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

source code of boost/boost/program_options/value_semantic.hpp