436 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			436 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // 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> | ||
|  | #include <limits> | ||
|  | 
 | ||
|  | 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 the option should only take adjacent token, | ||
|  |             not one from further command-line arguments. | ||
|  |         */ | ||
|  |         virtual bool adjacent_tokens_only() 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 adjacent_tokens_only() const { return false; } | ||
|  | 
 | ||
|  |         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; | ||
|  |     }; | ||
|  | 
 | ||
|  | #ifndef BOOST_NO_RTTI | ||
|  |     /** 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() {} | ||
|  |     }; | ||
|  | #endif | ||
|  | 
 | ||
|  | 
 | ||
|  |     /** Class which handles value of a specific type. */ | ||
|  |     template<class T, class charT = char> | ||
|  |     class typed_value : public value_semantic_codecvt_helper<charT> | ||
|  | #ifndef BOOST_NO_RTTI | ||
|  |                       , public typed_value_base | ||
|  | #endif | ||
|  |     { | ||
|  |     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_implicit(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 the name used to to the value in help message.  */ | ||
|  |         typed_value* value_name(const std::string& name) | ||
|  |         { | ||
|  |             m_value_name = name; | ||
|  |             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; | ||
|  |         } | ||
|  | 
 | ||
|  |         /** Specifies that no tokens may be provided as the value of | ||
|  |             this option, which means that only presense of the option | ||
|  |             is significant. For such option to be useful, either the | ||
|  |             'validate' function should be specialized, or the  | ||
|  |             'implicit_value' method should be also used. In most | ||
|  |             cases, you can use the 'bool_switch' function instead of | ||
|  |             using this method. */ | ||
|  |         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 std::numeric_limits<unsigned>::max BOOST_PREVENT_MACRO_SUBSTITUTION(); | ||
|  |             } else if (m_zero_tokens) { | ||
|  |                 return 0; | ||
|  |             } else { | ||
|  |                 return 1; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         bool adjacent_tokens_only() const { return !m_implicit_value.empty(); } | ||
|  | 
 | ||
|  |         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 | ||
|  |          | ||
|  | #ifndef BOOST_NO_RTTI | ||
|  |         const std::type_info& value_type() const | ||
|  |         { | ||
|  |             return typeid(T); | ||
|  |         } | ||
|  | #endif | ||
|  |          | ||
|  | 
 | ||
|  |     private: | ||
|  |         T* m_store_to; | ||
|  |          | ||
|  |         // Default value is stored as boost::any and not | ||
|  |         // as boost::optional to avoid unnecessary instantiations. | ||
|  |         std::string m_value_name; | ||
|  |         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 | ||
|  | 
 |