| // Copyright Vladimir Prus 2004. |
| // Distributed under the Boost Software License, Version 1.0. |
| // (See accompanying file LICENSE_1_0.txt |
| // or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| #ifndef BOOST_VALUE_SEMANTIC_HPP_VP_2004_02_24 |
| #define BOOST_VALUE_SEMANTIC_HPP_VP_2004_02_24 |
| |
| #include <boost/program_options/config.hpp> |
| #include <boost/program_options/errors.hpp> |
| |
| #include <boost/any.hpp> |
| #include <boost/function/function1.hpp> |
| #include <boost/lexical_cast.hpp> |
| |
| |
| #include <string> |
| #include <vector> |
| #include <typeinfo> |
| |
| namespace boost { namespace program_options { |
| |
| /** Class which specifies how the option's value is to be parsed |
| and converted into C++ types. |
| */ |
| class BOOST_PROGRAM_OPTIONS_DECL value_semantic { |
| public: |
| /** Returns the name of the option. The name is only meaningful |
| for automatic help message. |
| */ |
| virtual std::string name() const = 0; |
| |
| /** The minimum number of tokens for this option that |
| should be present on the command line. */ |
| virtual unsigned min_tokens() const = 0; |
| |
| /** The maximum number of tokens for this option that |
| should be present on the command line. */ |
| virtual unsigned max_tokens() const = 0; |
| |
| /** Returns true if values from different sources should be composed. |
| Otherwise, value from the first source is used and values from |
| other sources are discarded. |
| */ |
| virtual bool is_composing() const = 0; |
| |
| /** Returns true if value must be given. Non-optional value |
| |
| */ |
| virtual bool is_required() const = 0; |
| |
| /** Parses a group of tokens that specify a value of option. |
| Stores the result in 'value_store', using whatever representation |
| is desired. May be be called several times if value of the same |
| option is specified more than once. |
| */ |
| virtual void parse(boost::any& value_store, |
| const std::vector<std::string>& new_tokens, |
| bool utf8) const |
| = 0; |
| |
| /** Called to assign default value to 'value_store'. Returns |
| true if default value is assigned, and false if no default |
| value exists. */ |
| virtual bool apply_default(boost::any& value_store) const = 0; |
| |
| /** Called when final value of an option is determined. |
| */ |
| virtual void notify(const boost::any& value_store) const = 0; |
| |
| virtual ~value_semantic() {} |
| }; |
| |
| /** Helper class which perform necessary character conversions in the |
| 'parse' method and forwards the data further. |
| */ |
| template<class charT> |
| class value_semantic_codecvt_helper { |
| // Nothing here. Specializations to follow. |
| }; |
| |
| /** Helper conversion class for values that accept ascii |
| strings as input. |
| Overrides the 'parse' method and defines new 'xparse' |
| method taking std::string. Depending on whether input |
| to parse is ascii or UTF8, will pass it to xparse unmodified, |
| or with UTF8->ascii conversion. |
| */ |
| template<> |
| class BOOST_PROGRAM_OPTIONS_DECL |
| value_semantic_codecvt_helper<char> : public value_semantic { |
| private: // base overrides |
| void parse(boost::any& value_store, |
| const std::vector<std::string>& new_tokens, |
| bool utf8) const; |
| protected: // interface for derived classes. |
| virtual void xparse(boost::any& value_store, |
| const std::vector<std::string>& new_tokens) |
| const = 0; |
| }; |
| |
| /** Helper conversion class for values that accept ascii |
| strings as input. |
| Overrides the 'parse' method and defines new 'xparse' |
| method taking std::wstring. Depending on whether input |
| to parse is ascii or UTF8, will recode input to Unicode, or |
| pass it unmodified. |
| */ |
| template<> |
| class BOOST_PROGRAM_OPTIONS_DECL |
| value_semantic_codecvt_helper<wchar_t> : public value_semantic { |
| private: // base overrides |
| void parse(boost::any& value_store, |
| const std::vector<std::string>& new_tokens, |
| bool utf8) const; |
| protected: // interface for derived classes. |
| #if !defined(BOOST_NO_STD_WSTRING) |
| virtual void xparse(boost::any& value_store, |
| const std::vector<std::wstring>& new_tokens) |
| const = 0; |
| #endif |
| }; |
| |
| /** Class which specifies a simple handling of a value: the value will |
| have string type and only one token is allowed. */ |
| class BOOST_PROGRAM_OPTIONS_DECL |
| untyped_value : public value_semantic_codecvt_helper<char> { |
| public: |
| untyped_value(bool zero_tokens = false) |
| : m_zero_tokens(zero_tokens) |
| {} |
| |
| std::string name() const; |
| |
| unsigned min_tokens() const; |
| unsigned max_tokens() const; |
| |
| bool is_composing() const { return false; } |
| |
| bool is_required() const { return false; } |
| |
| /** If 'value_store' is already initialized, or new_tokens |
| has more than one elements, throws. Otherwise, assigns |
| the first string from 'new_tokens' to 'value_store', without |
| any modifications. |
| */ |
| void xparse(boost::any& value_store, |
| const std::vector<std::string>& new_tokens) const; |
| |
| /** Does nothing. */ |
| bool apply_default(boost::any&) const { return false; } |
| |
| /** Does nothing. */ |
| void notify(const boost::any&) const {} |
| private: |
| bool m_zero_tokens; |
| }; |
| |
| /** Base class for all option that have a fixed type, and are |
| willing to announce this type to the outside world. |
| Any 'value_semantics' for which you want to find out the |
| type can be dynamic_cast-ed to typed_value_base. If conversion |
| succeeds, the 'type' method can be called. |
| */ |
| class typed_value_base |
| { |
| public: |
| // Returns the type of the value described by this |
| // object. |
| virtual const std::type_info& value_type() const = 0; |
| // Not really needed, since deletion from this |
| // class is silly, but just in case. |
| virtual ~typed_value_base() {} |
| }; |
| |
| |
| /** Class which handles value of a specific type. */ |
| template<class T, class charT = char> |
| class typed_value : public value_semantic_codecvt_helper<charT>, |
| public typed_value_base |
| { |
| public: |
| /** Ctor. The 'store_to' parameter tells where to store |
| the value when it's known. The parameter can be NULL. */ |
| typed_value(T* store_to) |
| : m_store_to(store_to), m_composing(false), |
| m_multitoken(false), m_zero_tokens(false), |
| m_required(false) |
| {} |
| |
| /** Specifies default value, which will be used |
| if none is explicitly specified. The type 'T' should |
| provide operator<< for ostream. |
| */ |
| typed_value* default_value(const T& v) |
| { |
| m_default_value = boost::any(v); |
| m_default_value_as_text = boost::lexical_cast<std::string>(v); |
| return this; |
| } |
| |
| /** Specifies default value, which will be used |
| if none is explicitly specified. Unlike the above overload, |
| the type 'T' need not provide operator<< for ostream, |
| but textual representation of default value must be provided |
| by the user. |
| */ |
| typed_value* default_value(const T& v, const std::string& textual) |
| { |
| m_default_value = boost::any(v); |
| m_default_value_as_text = textual; |
| return this; |
| } |
| |
| /** Specifies an implicit value, which will be used |
| if the option is given, but without an adjacent value. |
| Using this implies that an explicit value is optional, but if |
| given, must be strictly adjacent to the option, i.e.: '-ovalue' |
| or '--option=value'. Giving '-o' or '--option' will cause the |
| implicit value to be applied. |
| */ |
| typed_value* implicit_value(const T &v) |
| { |
| m_implicit_value = boost::any(v); |
| m_implicit_value_as_text = |
| boost::lexical_cast<std::string>(v); |
| return this; |
| } |
| |
| /** Specifies an implicit value, which will be used |
| if the option is given, but without an adjacent value. |
| Using this implies that an explicit value is optional, but if |
| given, must be strictly adjacent to the option, i.e.: '-ovalue' |
| or '--option=value'. Giving '-o' or '--option' will cause the |
| implicit value to be applied. |
| Unlike the above overload, the type 'T' need not provide |
| operator<< for ostream, but textual representation of default |
| value must be provided by the user. |
| */ |
| typed_value* implicit_value(const T &v, const std::string& textual) |
| { |
| m_implicit_value = boost::any(v); |
| m_implicit_value_as_text = textual; |
| return this; |
| } |
| |
| /** Specifies a function to be called when the final value |
| is determined. */ |
| typed_value* notifier(function1<void, const T&> f) |
| { |
| m_notifier = f; |
| return this; |
| } |
| |
| /** Specifies that the value is composing. See the 'is_composing' |
| method for explanation. |
| */ |
| typed_value* composing() |
| { |
| m_composing = true; |
| return this; |
| } |
| |
| /** Specifies that the value can span multiple tokens. */ |
| typed_value* multitoken() |
| { |
| m_multitoken = true; |
| return this; |
| } |
| |
| typed_value* zero_tokens() |
| { |
| m_zero_tokens = true; |
| return this; |
| } |
| |
| /** Specifies that the value must occur. */ |
| typed_value* required() |
| { |
| m_required = true; |
| return this; |
| } |
| |
| public: // value semantic overrides |
| |
| std::string name() const; |
| |
| bool is_composing() const { return m_composing; } |
| |
| unsigned min_tokens() const |
| { |
| if (m_zero_tokens || !m_implicit_value.empty()) { |
| return 0; |
| } else { |
| return 1; |
| } |
| } |
| |
| unsigned max_tokens() const { |
| if (m_multitoken) { |
| return 32000; |
| } else if (m_zero_tokens) { |
| return 0; |
| } else { |
| return 1; |
| } |
| } |
| |
| bool is_required() const { return m_required; } |
| |
| /** Creates an instance of the 'validator' class and calls |
| its operator() to perform the actual conversion. */ |
| void xparse(boost::any& value_store, |
| const std::vector< std::basic_string<charT> >& new_tokens) |
| const; |
| |
| /** If default value was specified via previous call to |
| 'default_value', stores that value into 'value_store'. |
| Returns true if default value was stored. |
| */ |
| virtual bool apply_default(boost::any& value_store) const |
| { |
| if (m_default_value.empty()) { |
| return false; |
| } else { |
| value_store = m_default_value; |
| return true; |
| } |
| } |
| |
| /** If an address of variable to store value was specified |
| when creating *this, stores the value there. Otherwise, |
| does nothing. */ |
| void notify(const boost::any& value_store) const; |
| |
| public: // typed_value_base overrides |
| |
| const std::type_info& value_type() const |
| { |
| return typeid(T); |
| } |
| |
| |
| private: |
| T* m_store_to; |
| |
| // Default value is stored as boost::any and not |
| // as boost::optional to avoid unnecessary instantiations. |
| boost::any m_default_value; |
| std::string m_default_value_as_text; |
| boost::any m_implicit_value; |
| std::string m_implicit_value_as_text; |
| bool m_composing, m_implicit, m_multitoken, m_zero_tokens, m_required; |
| boost::function1<void, const T&> m_notifier; |
| }; |
| |
| |
| /** Creates a typed_value<T> instance. This function is the primary |
| method to create value_semantic instance for a specific type, which |
| can later be passed to 'option_description' constructor. |
| The second overload is used when it's additionally desired to store the |
| value of option into program variable. |
| */ |
| template<class T> |
| typed_value<T>* |
| value(); |
| |
| /** @overload |
| */ |
| template<class T> |
| typed_value<T>* |
| value(T* v); |
| |
| /** Creates a typed_value<T> instance. This function is the primary |
| method to create value_semantic instance for a specific type, which |
| can later be passed to 'option_description' constructor. |
| */ |
| template<class T> |
| typed_value<T, wchar_t>* |
| wvalue(); |
| |
| /** @overload |
| */ |
| template<class T> |
| typed_value<T, wchar_t>* |
| wvalue(T* v); |
| |
| /** Works the same way as the 'value<bool>' function, but the created |
| value_semantic won't accept any explicit value. So, if the option |
| is present on the command line, the value will be 'true'. |
| */ |
| BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* |
| bool_switch(); |
| |
| /** @overload |
| */ |
| BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* |
| bool_switch(bool* v); |
| |
| }} |
| |
| #include "boost/program_options/detail/value_semantic.hpp" |
| |
| #endif |
| |