value_semantic.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  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. #ifndef BOOST_VALUE_SEMANTIC_HPP_VP_2004_02_24
  6. #define BOOST_VALUE_SEMANTIC_HPP_VP_2004_02_24
  7. #include <boost/program_options/config.hpp>
  8. #include <boost/program_options/errors.hpp>
  9. #include <boost/any.hpp>
  10. #include <boost/function/function1.hpp>
  11. #include <boost/lexical_cast.hpp>
  12. #include <string>
  13. #include <vector>
  14. #include <typeinfo>
  15. #include <limits>
  16. namespace boost { namespace program_options {
  17. /** Class which specifies how the option's value is to be parsed
  18. and converted into C++ types.
  19. */
  20. class BOOST_PROGRAM_OPTIONS_DECL value_semantic {
  21. public:
  22. /** Returns the name of the option. The name is only meaningful
  23. for automatic help message.
  24. */
  25. virtual std::string name() const = 0;
  26. /** The minimum number of tokens for this option that
  27. should be present on the command line. */
  28. virtual unsigned min_tokens() const = 0;
  29. /** The maximum number of tokens for this option that
  30. should be present on the command line. */
  31. virtual unsigned max_tokens() const = 0;
  32. /** Returns true if values from different sources should be composed.
  33. Otherwise, value from the first source is used and values from
  34. other sources are discarded.
  35. */
  36. virtual bool is_composing() const = 0;
  37. /** Returns true if value must be given. Non-optional value
  38. */
  39. virtual bool is_required() const = 0;
  40. /** Parses a group of tokens that specify a value of option.
  41. Stores the result in 'value_store', using whatever representation
  42. is desired. May be be called several times if value of the same
  43. option is specified more than once.
  44. */
  45. virtual void parse(boost::any& value_store,
  46. const std::vector<std::string>& new_tokens,
  47. bool utf8) const
  48. = 0;
  49. /** Called to assign default value to 'value_store'. Returns
  50. true if default value is assigned, and false if no default
  51. value exists. */
  52. virtual bool apply_default(boost::any& value_store) const = 0;
  53. /** Called when final value of an option is determined.
  54. */
  55. virtual void notify(const boost::any& value_store) const = 0;
  56. virtual ~value_semantic() {}
  57. };
  58. /** Helper class which perform necessary character conversions in the
  59. 'parse' method and forwards the data further.
  60. */
  61. template<class charT>
  62. class value_semantic_codecvt_helper {
  63. // Nothing here. Specializations to follow.
  64. };
  65. /** Helper conversion class for values that accept ascii
  66. strings as input.
  67. Overrides the 'parse' method and defines new 'xparse'
  68. method taking std::string. Depending on whether input
  69. to parse is ascii or UTF8, will pass it to xparse unmodified,
  70. or with UTF8->ascii conversion.
  71. */
  72. template<>
  73. class BOOST_PROGRAM_OPTIONS_DECL
  74. value_semantic_codecvt_helper<char> : public value_semantic {
  75. private: // base overrides
  76. void parse(boost::any& value_store,
  77. const std::vector<std::string>& new_tokens,
  78. bool utf8) const;
  79. protected: // interface for derived classes.
  80. virtual void xparse(boost::any& value_store,
  81. const std::vector<std::string>& new_tokens)
  82. const = 0;
  83. };
  84. /** Helper conversion class for values that accept ascii
  85. strings as input.
  86. Overrides the 'parse' method and defines new 'xparse'
  87. method taking std::wstring. Depending on whether input
  88. to parse is ascii or UTF8, will recode input to Unicode, or
  89. pass it unmodified.
  90. */
  91. template<>
  92. class BOOST_PROGRAM_OPTIONS_DECL
  93. value_semantic_codecvt_helper<wchar_t> : public value_semantic {
  94. private: // base overrides
  95. void parse(boost::any& value_store,
  96. const std::vector<std::string>& new_tokens,
  97. bool utf8) const;
  98. protected: // interface for derived classes.
  99. #if !defined(BOOST_NO_STD_WSTRING)
  100. virtual void xparse(boost::any& value_store,
  101. const std::vector<std::wstring>& new_tokens)
  102. const = 0;
  103. #endif
  104. };
  105. /** Class which specifies a simple handling of a value: the value will
  106. have string type and only one token is allowed. */
  107. class BOOST_PROGRAM_OPTIONS_DECL
  108. untyped_value : public value_semantic_codecvt_helper<char> {
  109. public:
  110. untyped_value(bool zero_tokens = false)
  111. : m_zero_tokens(zero_tokens)
  112. {}
  113. std::string name() const;
  114. unsigned min_tokens() const;
  115. unsigned max_tokens() const;
  116. bool is_composing() const { return false; }
  117. bool is_required() const { return false; }
  118. /** If 'value_store' is already initialized, or new_tokens
  119. has more than one elements, throws. Otherwise, assigns
  120. the first string from 'new_tokens' to 'value_store', without
  121. any modifications.
  122. */
  123. void xparse(boost::any& value_store,
  124. const std::vector<std::string>& new_tokens) const;
  125. /** Does nothing. */
  126. bool apply_default(boost::any&) const { return false; }
  127. /** Does nothing. */
  128. void notify(const boost::any&) const {}
  129. private:
  130. bool m_zero_tokens;
  131. };
  132. #ifndef BOOST_NO_RTTI
  133. /** Base class for all option that have a fixed type, and are
  134. willing to announce this type to the outside world.
  135. Any 'value_semantics' for which you want to find out the
  136. type can be dynamic_cast-ed to typed_value_base. If conversion
  137. succeeds, the 'type' method can be called.
  138. */
  139. class typed_value_base
  140. {
  141. public:
  142. // Returns the type of the value described by this
  143. // object.
  144. virtual const std::type_info& value_type() const = 0;
  145. // Not really needed, since deletion from this
  146. // class is silly, but just in case.
  147. virtual ~typed_value_base() {}
  148. };
  149. #endif
  150. /** Class which handles value of a specific type. */
  151. template<class T, class charT = char>
  152. class typed_value : public value_semantic_codecvt_helper<charT>
  153. #ifndef BOOST_NO_RTTI
  154. , public typed_value_base
  155. #endif
  156. {
  157. public:
  158. /** Ctor. The 'store_to' parameter tells where to store
  159. the value when it's known. The parameter can be NULL. */
  160. typed_value(T* store_to)
  161. : m_store_to(store_to), m_composing(false),
  162. m_implicit(false), m_multitoken(false),
  163. m_zero_tokens(false), m_required(false)
  164. {}
  165. /** Specifies default value, which will be used
  166. if none is explicitly specified. The type 'T' should
  167. provide operator<< for ostream.
  168. */
  169. typed_value* default_value(const T& v)
  170. {
  171. m_default_value = boost::any(v);
  172. m_default_value_as_text = boost::lexical_cast<std::string>(v);
  173. return this;
  174. }
  175. /** Specifies default value, which will be used
  176. if none is explicitly specified. Unlike the above overload,
  177. the type 'T' need not provide operator<< for ostream,
  178. but textual representation of default value must be provided
  179. by the user.
  180. */
  181. typed_value* default_value(const T& v, const std::string& textual)
  182. {
  183. m_default_value = boost::any(v);
  184. m_default_value_as_text = textual;
  185. return this;
  186. }
  187. /** Specifies an implicit value, which will be used
  188. if the option is given, but without an adjacent value.
  189. Using this implies that an explicit value is optional,
  190. */
  191. typed_value* implicit_value(const T &v)
  192. {
  193. m_implicit_value = boost::any(v);
  194. m_implicit_value_as_text =
  195. boost::lexical_cast<std::string>(v);
  196. return this;
  197. }
  198. /** Specifies the name used to to the value in help message. */
  199. typed_value* value_name(const std::string& name)
  200. {
  201. m_value_name = name;
  202. return this;
  203. }
  204. /** Specifies an implicit value, which will be used
  205. if the option is given, but without an adjacent value.
  206. Using this implies that an explicit value is optional, but if
  207. given, must be strictly adjacent to the option, i.e.: '-ovalue'
  208. or '--option=value'. Giving '-o' or '--option' will cause the
  209. implicit value to be applied.
  210. Unlike the above overload, the type 'T' need not provide
  211. operator<< for ostream, but textual representation of default
  212. value must be provided by the user.
  213. */
  214. typed_value* implicit_value(const T &v, const std::string& textual)
  215. {
  216. m_implicit_value = boost::any(v);
  217. m_implicit_value_as_text = textual;
  218. return this;
  219. }
  220. /** Specifies a function to be called when the final value
  221. is determined. */
  222. typed_value* notifier(function1<void, const T&> f)
  223. {
  224. m_notifier = f;
  225. return this;
  226. }
  227. /** Specifies that the value is composing. See the 'is_composing'
  228. method for explanation.
  229. */
  230. typed_value* composing()
  231. {
  232. m_composing = true;
  233. return this;
  234. }
  235. /** Specifies that the value can span multiple tokens.
  236. */
  237. typed_value* multitoken()
  238. {
  239. m_multitoken = true;
  240. return this;
  241. }
  242. /** Specifies that no tokens may be provided as the value of
  243. this option, which means that only presense of the option
  244. is significant. For such option to be useful, either the
  245. 'validate' function should be specialized, or the
  246. 'implicit_value' method should be also used. In most
  247. cases, you can use the 'bool_switch' function instead of
  248. using this method. */
  249. typed_value* zero_tokens()
  250. {
  251. m_zero_tokens = true;
  252. return this;
  253. }
  254. /** Specifies that the value must occur. */
  255. typed_value* required()
  256. {
  257. m_required = true;
  258. return this;
  259. }
  260. public: // value semantic overrides
  261. std::string name() const;
  262. bool is_composing() const { return m_composing; }
  263. unsigned min_tokens() const
  264. {
  265. if (m_zero_tokens || !m_implicit_value.empty()) {
  266. return 0;
  267. } else {
  268. return 1;
  269. }
  270. }
  271. unsigned max_tokens() const {
  272. if (m_multitoken) {
  273. return std::numeric_limits<unsigned>::max BOOST_PREVENT_MACRO_SUBSTITUTION();
  274. } else if (m_zero_tokens) {
  275. return 0;
  276. } else {
  277. return 1;
  278. }
  279. }
  280. bool is_required() const { return m_required; }
  281. /** Creates an instance of the 'validator' class and calls
  282. its operator() to perform the actual conversion. */
  283. void xparse(boost::any& value_store,
  284. const std::vector< std::basic_string<charT> >& new_tokens)
  285. const;
  286. /** If default value was specified via previous call to
  287. 'default_value', stores that value into 'value_store'.
  288. Returns true if default value was stored.
  289. */
  290. virtual bool apply_default(boost::any& value_store) const
  291. {
  292. if (m_default_value.empty()) {
  293. return false;
  294. } else {
  295. value_store = m_default_value;
  296. return true;
  297. }
  298. }
  299. /** If an address of variable to store value was specified
  300. when creating *this, stores the value there. Otherwise,
  301. does nothing. */
  302. void notify(const boost::any& value_store) const;
  303. public: // typed_value_base overrides
  304. #ifndef BOOST_NO_RTTI
  305. const std::type_info& value_type() const
  306. {
  307. return typeid(T);
  308. }
  309. #endif
  310. private:
  311. T* m_store_to;
  312. // Default value is stored as boost::any and not
  313. // as boost::optional to avoid unnecessary instantiations.
  314. std::string m_value_name;
  315. boost::any m_default_value;
  316. std::string m_default_value_as_text;
  317. boost::any m_implicit_value;
  318. std::string m_implicit_value_as_text;
  319. bool m_composing, m_implicit, m_multitoken, m_zero_tokens, m_required;
  320. boost::function1<void, const T&> m_notifier;
  321. };
  322. /** Creates a typed_value<T> instance. This function is the primary
  323. method to create value_semantic instance for a specific type, which
  324. can later be passed to 'option_description' constructor.
  325. The second overload is used when it's additionally desired to store the
  326. value of option into program variable.
  327. */
  328. template<class T>
  329. typed_value<T>*
  330. value();
  331. /** @overload
  332. */
  333. template<class T>
  334. typed_value<T>*
  335. value(T* v);
  336. /** Creates a typed_value<T> instance. This function is the primary
  337. method to create value_semantic instance for a specific type, which
  338. can later be passed to 'option_description' constructor.
  339. */
  340. template<class T>
  341. typed_value<T, wchar_t>*
  342. wvalue();
  343. /** @overload
  344. */
  345. template<class T>
  346. typed_value<T, wchar_t>*
  347. wvalue(T* v);
  348. /** Works the same way as the 'value<bool>' function, but the created
  349. value_semantic won't accept any explicit value. So, if the option
  350. is present on the command line, the value will be 'true'.
  351. */
  352. BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
  353. bool_switch();
  354. /** @overload
  355. */
  356. BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
  357. bool_switch(bool* v);
  358. }}
  359. #include "boost/program_options/detail/value_semantic.hpp"
  360. #endif