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 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 | |