You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
207 lines
6.7 KiB
207 lines
6.7 KiB
// 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) |
|
|
|
// This file defines template functions that are declared in |
|
// ../value_semantic.hpp. |
|
|
|
#include <boost/throw_exception.hpp> |
|
|
|
namespace boost { namespace program_options { |
|
|
|
extern BOOST_PROGRAM_OPTIONS_DECL std::string arg; |
|
|
|
template<class T, class charT> |
|
std::string |
|
typed_value<T, charT>::name() const |
|
{ |
|
if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) { |
|
std::string msg = "[=arg(=" + m_implicit_value_as_text + ")]"; |
|
if (!m_default_value.empty() && !m_default_value_as_text.empty()) |
|
msg += " (=" + m_default_value_as_text + ")"; |
|
return msg; |
|
} |
|
else if (!m_default_value.empty() && !m_default_value_as_text.empty()) { |
|
return arg + " (=" + m_default_value_as_text + ")"; |
|
} else { |
|
return arg; |
|
} |
|
} |
|
|
|
template<class T, class charT> |
|
void |
|
typed_value<T, charT>::notify(const boost::any& value_store) const |
|
{ |
|
const T* value = boost::any_cast<T>(&value_store); |
|
if (m_store_to) { |
|
*m_store_to = *value; |
|
} |
|
if (m_notifier) { |
|
m_notifier(*value); |
|
} |
|
} |
|
|
|
namespace validators { |
|
/* If v.size() > 1, throw validation_error. |
|
If v.size() == 1, return v.front() |
|
Otherwise, returns a reference to a statically allocated |
|
empty string if 'allow_empty' and throws validation_error |
|
otherwise. */ |
|
template<class charT> |
|
const std::basic_string<charT>& get_single_string( |
|
const std::vector<std::basic_string<charT> >& v, |
|
bool allow_empty = false) |
|
{ |
|
static std::basic_string<charT> empty; |
|
if (v.size() > 1) |
|
boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed)); |
|
else if (v.size() == 1) |
|
return v.front(); |
|
else if (!allow_empty) |
|
boost::throw_exception(validation_error(validation_error::at_least_one_value_required)); |
|
return empty; |
|
} |
|
|
|
/* Throws multiple_occurrences if 'value' is not empty. */ |
|
BOOST_PROGRAM_OPTIONS_DECL void |
|
check_first_occurrence(const boost::any& value); |
|
} |
|
|
|
using namespace validators; |
|
|
|
/** Validates 's' and updates 'v'. |
|
@pre 'v' is either empty or in the state assigned by the previous |
|
invocation of 'validate'. |
|
The target type is specified via a parameter which has the type of |
|
pointer to the desired type. This is workaround for compilers without |
|
partial template ordering, just like the last 'long/int' parameter. |
|
*/ |
|
template<class T, class charT> |
|
void validate(boost::any& v, |
|
const std::vector< std::basic_string<charT> >& xs, |
|
T*, long) |
|
{ |
|
validators::check_first_occurrence(v); |
|
std::basic_string<charT> s(validators::get_single_string(xs)); |
|
try { |
|
v = any(lexical_cast<T>(s)); |
|
} |
|
catch(const bad_lexical_cast&) { |
|
boost::throw_exception(invalid_option_value(s)); |
|
} |
|
} |
|
|
|
BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, |
|
const std::vector<std::string>& xs, |
|
bool*, |
|
int); |
|
|
|
#if !defined(BOOST_NO_STD_WSTRING) |
|
BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, |
|
const std::vector<std::wstring>& xs, |
|
bool*, |
|
int); |
|
#endif |
|
// For some reason, this declaration, which is require by the standard, |
|
// cause gcc 3.2 to not generate code to specialization defined in |
|
// value_semantic.cpp |
|
#if ! ( ( BOOST_WORKAROUND(__GNUC__, <= 3) &&\ |
|
BOOST_WORKAROUND(__GNUC_MINOR__, < 3) ) || \ |
|
( BOOST_WORKAROUND(BOOST_MSVC, == 1310) ) \ |
|
) |
|
BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, |
|
const std::vector<std::string>& xs, |
|
std::string*, |
|
int); |
|
|
|
#if !defined(BOOST_NO_STD_WSTRING) |
|
BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, |
|
const std::vector<std::wstring>& xs, |
|
std::string*, |
|
int); |
|
#endif |
|
#endif |
|
|
|
/** Validates sequences. Allows multiple values per option occurrence |
|
and multiple occurrences. */ |
|
template<class T, class charT> |
|
void validate(boost::any& v, |
|
const std::vector<std::basic_string<charT> >& s, |
|
std::vector<T>*, |
|
int) |
|
{ |
|
if (v.empty()) { |
|
v = boost::any(std::vector<T>()); |
|
} |
|
std::vector<T>* tv = boost::any_cast< std::vector<T> >(&v); |
|
assert(NULL != tv); |
|
for (unsigned i = 0; i < s.size(); ++i) |
|
{ |
|
try { |
|
/* We call validate so that if user provided |
|
a validator for class T, we use it even |
|
when parsing vector<T>. */ |
|
boost::any a; |
|
std::vector<std::basic_string<charT> > cv; |
|
cv.push_back(s[i]); |
|
validate(a, cv, (T*)0, 0); |
|
tv->push_back(boost::any_cast<T>(a)); |
|
} |
|
catch(const bad_lexical_cast& /*e*/) { |
|
boost::throw_exception(invalid_option_value(s[i])); |
|
} |
|
} |
|
} |
|
|
|
template<class T, class charT> |
|
void |
|
typed_value<T, charT>:: |
|
xparse(boost::any& value_store, |
|
const std::vector<std::basic_string<charT> >& new_tokens) const |
|
{ |
|
// If no tokens were given, and the option accepts an implicit |
|
// value, then assign the implicit value as the stored value; |
|
// otherwise, validate the user-provided token(s). |
|
if (new_tokens.empty() && !m_implicit_value.empty()) |
|
value_store = m_implicit_value; |
|
else |
|
validate(value_store, new_tokens, (T*)0, 0); |
|
} |
|
|
|
template<class T> |
|
typed_value<T>* |
|
value() |
|
{ |
|
// Explicit qualification is vc6 workaround. |
|
return boost::program_options::value<T>(0); |
|
} |
|
|
|
template<class T> |
|
typed_value<T>* |
|
value(T* v) |
|
{ |
|
typed_value<T>* r = new typed_value<T>(v); |
|
|
|
return r; |
|
} |
|
|
|
template<class T> |
|
typed_value<T, wchar_t>* |
|
wvalue() |
|
{ |
|
return wvalue<T>(0); |
|
} |
|
|
|
template<class T> |
|
typed_value<T, wchar_t>* |
|
wvalue(T* v) |
|
{ |
|
typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v); |
|
|
|
return r; |
|
} |
|
|
|
|
|
|
|
}}
|
|
|