// 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 #include #include #include #include #include #include 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; /** 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& 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 value_semantic_codecvt_helper { // Nothing here. Specializations to follow. }; template<> class BOOST_PROGRAM_OPTIONS_DECL value_semantic_codecvt_helper : public value_semantic { private: // base overrides void parse(boost::any& value_store, const std::vector& new_tokens, bool utf8) const; protected: // interface for derived classes. virtual void xparse(boost::any& value_store, const std::vector& new_tokens) const = 0; }; template<> class BOOST_PROGRAM_OPTIONS_DECL value_semantic_codecvt_helper : public value_semantic { private: // base overrides void parse(boost::any& value_store, const std::vector& 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& 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 { 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; } /** 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& 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; }; /** Class which handles value of a specific type. */ template class typed_value : public value_semantic_codecvt_helper { 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) {} /** 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(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 a function to be called when the final value is determined. */ typed_value* notifier(function1 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; } public: // value semantic overrides std::string name() const; bool is_composing() const { return m_composing; } unsigned min_tokens() const { if (m_zero_tokens) { return 0; } else { return 1; } } unsigned max_tokens() const { if (m_multitoken) { return 32000; } else if (m_zero_tokens) { return 0; } else { return 1; } } /** Creates an instance of the 'validator' class and calls its operator() to perform athe ctual conversion. */ void xparse(boost::any& value_store, const std::vector< std::basic_string >& 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; 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; bool m_composing, m_implicit, m_multitoken, m_zero_tokens; boost::function1 m_notifier; }; /** Creates a typed_value 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 typed_value* value(); /** @overload */ template typed_value* value(T* v); /** Creates a typed_value 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 typed_value* wvalue(); /** @overload */ template typed_value* wvalue(T* v); /** Works the same way as the 'value' 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_switch(); /** @overload */ BOOST_PROGRAM_OPTIONS_DECL typed_value* bool_switch(bool* v); }} #include "boost/program_options/detail/value_semantic.hpp" #endif