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