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