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 
17 
18 #include <string>
19 #include <vector>
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         /** Parses a group of tokens that specify a value of option.
48             Stores the result in 'value_store', using whatever representation
49             is desired. May be be called several times if value of the same
50             option is specified more than once.
51         */
52         virtual void parse(boost::any& value_store,
53                            const std::vector<std::string>& new_tokens,
54                            bool utf8) const
55             = 0;
56 
57         /** Called to assign default value to 'value_store'. Returns
58             true if default value is assigned, and false if no default
59             value exists. */
60         virtual bool apply_default(boost::any& value_store) const = 0;
61 
62         /** Called when final value of an option is determined.
63         */
64         virtual void notify(const boost::any& value_store) const = 0;
65 
~value_semantic()66         virtual ~value_semantic() {}
67     };
68 
69     /** Helper class which perform necessary character conversions in the
70         'parse' method and forwards the data further.
71     */
72     template<class charT>
73     class value_semantic_codecvt_helper {
74         // Nothing here. Specializations to follow.
75     };
76 
77     template<>
78     class BOOST_PROGRAM_OPTIONS_DECL
79     value_semantic_codecvt_helper<char> : public value_semantic {
80     private: // base overrides
81         void parse(boost::any& value_store,
82                    const std::vector<std::string>& new_tokens,
83                    bool utf8) const;
84     protected: // interface for derived classes.
85         virtual void xparse(boost::any& value_store,
86                             const std::vector<std::string>& new_tokens)
87             const = 0;
88     };
89 
90     template<>
91     class BOOST_PROGRAM_OPTIONS_DECL
92     value_semantic_codecvt_helper<wchar_t> : public value_semantic {
93     private: // base overrides
94         void parse(boost::any& value_store,
95                    const std::vector<std::string>& new_tokens,
96                    bool utf8) const;
97     protected: // interface for derived classes.
98 #if !defined(BOOST_NO_STD_WSTRING)
99         virtual void xparse(boost::any& value_store,
100                             const std::vector<std::wstring>& new_tokens)
101             const = 0;
102 #endif
103     };
104     /** Class which specifies a simple handling of a value: the value will
105         have string type and only one token is allowed. */
106     class BOOST_PROGRAM_OPTIONS_DECL
107     untyped_value : public value_semantic_codecvt_helper<char>  {
108     public:
untyped_value(bool zero_tokens=false)109         untyped_value(bool zero_tokens = false)
110         : m_zero_tokens(zero_tokens)
111         {}
112 
113         std::string name() const;
114 
115         unsigned min_tokens() const;
116         unsigned max_tokens() const;
117 
is_composing() const118         bool is_composing() const { return false; }
119 
120         /** If 'value_store' is already initialized, or new_tokens
121             has more than one elements, throws. Otherwise, assigns
122             the first string from 'new_tokens' to 'value_store', without
123             any modifications.
124          */
125         void xparse(boost::any& value_store,
126                     const std::vector<std::string>& new_tokens) const;
127 
128         /** Does nothing. */
apply_default(boost::any &) const129         bool apply_default(boost::any&) const { return false; }
130 
131         /** Does nothing. */
notify(const boost::any &) const132         void notify(const boost::any&) const {}
133     private:
134         bool m_zero_tokens;
135     };
136 
137     /** Class which handles value of a specific type. */
138     template<class T, class charT = char>
139     class typed_value : public value_semantic_codecvt_helper<charT>  {
140     public:
141         /** Ctor. The 'store_to' parameter tells where to store
142             the value when it's known. The parameter can be NULL. */
typed_value(T * store_to)143         typed_value(T* store_to)
144         : m_store_to(store_to), m_composing(false),
145           m_multitoken(false), m_zero_tokens(false)
146         {}
147 
148         /** Specifies default value, which will be used
149             if none is explicitly specified. The type 'T' should
150             provide operator<< for ostream.
151         */
default_value(const T & v)152         typed_value* default_value(const T& v)
153         {
154             m_default_value = boost::any(v);
155             m_default_value_as_text = boost::lexical_cast<std::string>(v);
156             return this;
157         }
158 
159         /** Specifies default value, which will be used
160             if none is explicitly specified. Unlike the above overload,
161             the type 'T' need not provide operator<< for ostream,
162             but textual representation of default value must be provided
163             by the user.
164         */
default_value(const T & v,const std::string & textual)165         typed_value* default_value(const T& v, const std::string& textual)
166         {
167             m_default_value = boost::any(v);
168             m_default_value_as_text = textual;
169             return this;
170         }
171 
172         /** Specifies a function to be called when the final value
173             is determined. */
notifier(function1<void,const T &> f)174         typed_value* notifier(function1<void, const T&> f)
175         {
176             m_notifier = f;
177             return this;
178         }
179 
180         /** Specifies that the value is composing. See the 'is_composing'
181             method for explanation.
182         */
composing()183         typed_value* composing()
184         {
185             m_composing = true;
186             return this;
187         }
188 
189         /** Specifies that the value can span multiple tokens. */
multitoken()190         typed_value* multitoken()
191         {
192             m_multitoken = true;
193             return this;
194         }
195 
zero_tokens()196         typed_value* zero_tokens()
197         {
198             m_zero_tokens = true;
199             return this;
200         }
201 
202 
203     public: // value semantic overrides
204 
205         std::string name() const;
206 
is_composing() const207         bool is_composing() const { return m_composing; }
208 
min_tokens() const209         unsigned min_tokens() const
210         {
211             if (m_zero_tokens) {
212                 return 0;
213             } else {
214                 return 1;
215             }
216         }
217 
max_tokens() const218         unsigned max_tokens() const {
219             if (m_multitoken) {
220                 return 32000;
221             } else if (m_zero_tokens) {
222                 return 0;
223             } else {
224                 return 1;
225             }
226         }
227 
228 
229         /** Creates an instance of the 'validator' class and calls
230             its operator() to perform athe ctual conversion. */
231         void xparse(boost::any& value_store,
232                     const std::vector< std::basic_string<charT> >& new_tokens)
233             const;
234 
235         /** If default value was specified via previous call to
236             'default_value', stores that value into 'value_store'.
237             Returns true if default value was stored.
238         */
apply_default(boost::any & value_store) const239         virtual bool apply_default(boost::any& value_store) const
240         {
241             if (m_default_value.empty()) {
242                 return false;
243             } else {
244                 value_store = m_default_value;
245                 return true;
246             }
247         }
248 
249         /** If an address of variable to store value was specified
250             when creating *this, stores the value there. Otherwise,
251             does nothing. */
252         void notify(const boost::any& value_store) const;
253 
254 
255     private:
256         T* m_store_to;
257 
258         // Default value is stored as boost::any and not
259         // as boost::optional to avoid unnecessary instantiations.
260         boost::any m_default_value;
261         std::string m_default_value_as_text;
262         bool m_composing, m_implicit, m_multitoken, m_zero_tokens;
263         boost::function1<void, const T&> m_notifier;
264     };
265 
266 
267     /** Creates a typed_value<T> instance. This function is the primary
268         method to create value_semantic instance for a specific type, which
269         can later be passed to 'option_description' constructor.
270         The second overload is used when it's additionally desired to store the
271         value of option into program variable.
272     */
273     template<class T>
274     typed_value<T>*
275     value();
276 
277     /** @overload
278     */
279     template<class T>
280     typed_value<T>*
281     value(T* v);
282 
283     /** Creates a typed_value<T> instance. This function is the primary
284         method to create value_semantic instance for a specific type, which
285         can later be passed to 'option_description' constructor.
286     */
287     template<class T>
288     typed_value<T, wchar_t>*
289     wvalue();
290 
291     /** @overload
292     */
293     template<class T>
294     typed_value<T, wchar_t>*
295     wvalue(T* v);
296 
297     /** Works the same way as the 'value<bool>' function, but the created
298         value_semantic won't accept any explicit value. So, if the option
299         is present on the command line, the value will be 'true'.
300     */
301     BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
302     bool_switch();
303 
304     /** @overload
305     */
306     BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
307     bool_switch(bool* v);
308 
309 }}
310 
311 #include "boost/program_options/detail/value_semantic.hpp"
312 
313 #endif
314 
315