value_semantic.hpp 6.8 KB

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