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 | |
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: |
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 | |
138 | bool is_composing() const { return false; } |
139 | |
140 | 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. */ |
151 | bool apply_default(boost::any&) const { return false; } |
152 | |
153 | /** Does nothing. */ |
154 | 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. |
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. */ |
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 | */ |
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 | */ |
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 | */ |
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. */ |
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 | */ |
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. */ |
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 | */ |
266 | typed_value* composing() |
267 | { |
268 | m_composing = true; |
269 | return this; |
270 | } |
271 | |
272 | /** Specifies that the value can span multiple tokens. |
273 | */ |
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. */ |
287 | typed_value* zero_tokens() |
288 | { |
289 | m_zero_tokens = true; |
290 | return this; |
291 | } |
292 | |
293 | /** Specifies that the value must occur. */ |
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 | |
304 | bool is_composing() const { return m_composing; } |
305 | |
306 | 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 | |
315 | 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 | |
325 | 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 | */ |
337 | 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 |
355 | 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 | |