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