value_semantic.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // Copyright Vladimir Prus 2004.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt
  4. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // This file defines template functions that are declared in
  6. // ../value_semantic.hpp.
  7. #include <boost/throw_exception.hpp>
  8. // forward declaration
  9. namespace boost { template<class T> class optional; }
  10. namespace boost { namespace program_options {
  11. extern BOOST_PROGRAM_OPTIONS_DECL std::string arg;
  12. template<class T, class charT>
  13. std::string
  14. typed_value<T, charT>::name() const
  15. {
  16. std::string const& var = (m_value_name.empty() ? arg : m_value_name);
  17. if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) {
  18. std::string msg = "[=" + var + "(=" + m_implicit_value_as_text + ")]";
  19. if (!m_default_value.empty() && !m_default_value_as_text.empty())
  20. msg += " (=" + m_default_value_as_text + ")";
  21. return msg;
  22. }
  23. else if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
  24. return var + " (=" + m_default_value_as_text + ")";
  25. } else {
  26. return var;
  27. }
  28. }
  29. template<class T, class charT>
  30. void
  31. typed_value<T, charT>::notify(const boost::any& value_store) const
  32. {
  33. const T* value = boost::any_cast<T>(&value_store);
  34. if (m_store_to) {
  35. *m_store_to = *value;
  36. }
  37. if (m_notifier) {
  38. m_notifier(*value);
  39. }
  40. }
  41. namespace validators {
  42. /* If v.size() > 1, throw validation_error.
  43. If v.size() == 1, return v.front()
  44. Otherwise, returns a reference to a statically allocated
  45. empty string if 'allow_empty' and throws validation_error
  46. otherwise. */
  47. template<class charT>
  48. const std::basic_string<charT>& get_single_string(
  49. const std::vector<std::basic_string<charT> >& v,
  50. bool allow_empty = false)
  51. {
  52. static std::basic_string<charT> empty;
  53. if (v.size() > 1)
  54. boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed));
  55. else if (v.size() == 1)
  56. return v.front();
  57. else if (!allow_empty)
  58. boost::throw_exception(validation_error(validation_error::at_least_one_value_required));
  59. return empty;
  60. }
  61. /* Throws multiple_occurrences if 'value' is not empty. */
  62. BOOST_PROGRAM_OPTIONS_DECL void
  63. check_first_occurrence(const boost::any& value);
  64. }
  65. using namespace validators;
  66. /** Validates 's' and updates 'v'.
  67. @pre 'v' is either empty or in the state assigned by the previous
  68. invocation of 'validate'.
  69. The target type is specified via a parameter which has the type of
  70. pointer to the desired type. This is workaround for compilers without
  71. partial template ordering, just like the last 'long/int' parameter.
  72. */
  73. template<class T, class charT>
  74. void validate(boost::any& v,
  75. const std::vector< std::basic_string<charT> >& xs,
  76. T*, long)
  77. {
  78. validators::check_first_occurrence(v);
  79. std::basic_string<charT> s(validators::get_single_string(xs));
  80. try {
  81. v = any(lexical_cast<T>(s));
  82. }
  83. catch(const bad_lexical_cast&) {
  84. boost::throw_exception(invalid_option_value(s));
  85. }
  86. }
  87. BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
  88. const std::vector<std::string>& xs,
  89. bool*,
  90. int);
  91. #if !defined(BOOST_NO_STD_WSTRING)
  92. BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
  93. const std::vector<std::wstring>& xs,
  94. bool*,
  95. int);
  96. #endif
  97. // For some reason, this declaration, which is require by the standard,
  98. // cause msvc 7.1 to not generate code to specialization defined in
  99. // value_semantic.cpp
  100. #if ! ( BOOST_WORKAROUND(BOOST_MSVC, == 1310) )
  101. BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
  102. const std::vector<std::string>& xs,
  103. std::string*,
  104. int);
  105. #if !defined(BOOST_NO_STD_WSTRING)
  106. BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
  107. const std::vector<std::wstring>& xs,
  108. std::string*,
  109. int);
  110. #endif
  111. #endif
  112. /** Validates sequences. Allows multiple values per option occurrence
  113. and multiple occurrences. */
  114. template<class T, class charT>
  115. void validate(boost::any& v,
  116. const std::vector<std::basic_string<charT> >& s,
  117. std::vector<T>*,
  118. int)
  119. {
  120. if (v.empty()) {
  121. v = boost::any(std::vector<T>());
  122. }
  123. std::vector<T>* tv = boost::any_cast< std::vector<T> >(&v);
  124. assert(NULL != tv);
  125. for (unsigned i = 0; i < s.size(); ++i)
  126. {
  127. try {
  128. /* We call validate so that if user provided
  129. a validator for class T, we use it even
  130. when parsing vector<T>. */
  131. boost::any a;
  132. std::vector<std::basic_string<charT> > cv;
  133. cv.push_back(s[i]);
  134. validate(a, cv, (T*)0, 0);
  135. tv->push_back(boost::any_cast<T>(a));
  136. }
  137. catch(const bad_lexical_cast& /*e*/) {
  138. boost::throw_exception(invalid_option_value(s[i]));
  139. }
  140. }
  141. }
  142. /** Validates optional arguments. */
  143. template<class T, class charT>
  144. void validate(boost::any& v,
  145. const std::vector<std::basic_string<charT> >& s,
  146. boost::optional<T>*,
  147. int)
  148. {
  149. validators::check_first_occurrence(v);
  150. validators::get_single_string(s);
  151. boost::any a;
  152. validate(a, s, (T*)0, 0);
  153. v = boost::any(boost::optional<T>(boost::any_cast<T>(a)));
  154. }
  155. template<class T, class charT>
  156. void
  157. typed_value<T, charT>::
  158. xparse(boost::any& value_store,
  159. const std::vector<std::basic_string<charT> >& new_tokens) const
  160. {
  161. // If no tokens were given, and the option accepts an implicit
  162. // value, then assign the implicit value as the stored value;
  163. // otherwise, validate the user-provided token(s).
  164. if (new_tokens.empty() && !m_implicit_value.empty())
  165. value_store = m_implicit_value;
  166. else
  167. validate(value_store, new_tokens, (T*)0, 0);
  168. }
  169. template<class T>
  170. typed_value<T>*
  171. value()
  172. {
  173. // Explicit qualification is vc6 workaround.
  174. return boost::program_options::value<T>(0);
  175. }
  176. template<class T>
  177. typed_value<T>*
  178. value(T* v)
  179. {
  180. typed_value<T>* r = new typed_value<T>(v);
  181. return r;
  182. }
  183. template<class T>
  184. typed_value<T, wchar_t>*
  185. wvalue()
  186. {
  187. return wvalue<T>(0);
  188. }
  189. template<class T>
  190. typed_value<T, wchar_t>*
  191. wvalue(T* v)
  192. {
  193. typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v);
  194. return r;
  195. }
  196. }}