1 // Copyright Vladimir Prus 2004.
\r
2 // Distributed under the Boost Software License, Version 1.0.
\r
3 // (See accompanying file LICENSE_1_0.txt
\r
4 // or copy at http://www.boost.org/LICENSE_1_0.txt)
\r
6 // This file defines template functions that are declared in
\r
7 // ../value_semantic.hpp.
\r
9 #include <boost/throw_exception.hpp>
\r
11 namespace boost { namespace program_options {
\r
13 extern BOOST_PROGRAM_OPTIONS_DECL std::string arg;
\r
15 template<class T, class charT>
\r
17 typed_value<T, charT>::name() const
\r
19 if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) {
\r
20 std::string msg = "[=arg(=" + m_implicit_value_as_text + ")]";
\r
21 if (!m_default_value.empty() && !m_default_value_as_text.empty())
\r
22 msg += " (=" + m_default_value_as_text + ")";
\r
25 else if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
\r
26 return arg + " (=" + m_default_value_as_text + ")";
\r
32 template<class T, class charT>
\r
34 typed_value<T, charT>::notify(const boost::any& value_store) const
\r
36 const T* value = boost::any_cast<T>(&value_store);
\r
38 *m_store_to = *value;
\r
45 namespace validators {
\r
46 /* If v.size() > 1, throw validation_error.
\r
47 If v.size() == 1, return v.front()
\r
48 Otherwise, returns a reference to a statically allocated
\r
49 empty string if 'allow_empty' and throws validation_error
\r
51 template<class charT>
\r
52 const std::basic_string<charT>& get_single_string(
\r
53 const std::vector<std::basic_string<charT> >& v,
\r
54 bool allow_empty = false)
\r
56 static std::basic_string<charT> empty;
\r
58 boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed));
\r
59 else if (v.size() == 1)
\r
61 else if (!allow_empty)
\r
62 boost::throw_exception(validation_error(validation_error::at_least_one_value_required));
\r
66 /* Throws multiple_occurrences if 'value' is not empty. */
\r
67 BOOST_PROGRAM_OPTIONS_DECL void
\r
68 check_first_occurrence(const boost::any& value);
\r
71 using namespace validators;
\r
73 /** Validates 's' and updates 'v'.
\r
74 @pre 'v' is either empty or in the state assigned by the previous
\r
75 invocation of 'validate'.
\r
76 The target type is specified via a parameter which has the type of
\r
77 pointer to the desired type. This is workaround for compilers without
\r
78 partial template ordering, just like the last 'long/int' parameter.
\r
80 template<class T, class charT>
\r
81 void validate(boost::any& v,
\r
82 const std::vector< std::basic_string<charT> >& xs,
\r
85 validators::check_first_occurrence(v);
\r
86 std::basic_string<charT> s(validators::get_single_string(xs));
\r
88 v = any(lexical_cast<T>(s));
\r
90 catch(const bad_lexical_cast&) {
\r
91 boost::throw_exception(invalid_option_value(s));
\r
95 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
\r
96 const std::vector<std::string>& xs,
\r
100 #if !defined(BOOST_NO_STD_WSTRING)
\r
101 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
\r
102 const std::vector<std::wstring>& xs,
\r
106 // For some reason, this declaration, which is require by the standard,
\r
107 // cause gcc 3.2 to not generate code to specialization defined in
\r
108 // value_semantic.cpp
\r
109 #if ! ( ( BOOST_WORKAROUND(__GNUC__, <= 3) &&\
\r
110 BOOST_WORKAROUND(__GNUC_MINOR__, < 3) ) || \
\r
111 ( BOOST_WORKAROUND(BOOST_MSVC, == 1310) ) \
\r
113 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
\r
114 const std::vector<std::string>& xs,
\r
118 #if !defined(BOOST_NO_STD_WSTRING)
\r
119 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
\r
120 const std::vector<std::wstring>& xs,
\r
126 /** Validates sequences. Allows multiple values per option occurrence
\r
127 and multiple occurrences. */
\r
128 template<class T, class charT>
\r
129 void validate(boost::any& v,
\r
130 const std::vector<std::basic_string<charT> >& s,
\r
135 v = boost::any(std::vector<T>());
\r
137 std::vector<T>* tv = boost::any_cast< std::vector<T> >(&v);
\r
138 assert(NULL != tv);
\r
139 for (unsigned i = 0; i < s.size(); ++i)
\r
142 /* We call validate so that if user provided
\r
143 a validator for class T, we use it even
\r
144 when parsing vector<T>. */
\r
146 std::vector<std::basic_string<charT> > v;
\r
148 validate(a, v, (T*)0, 0);
\r
149 tv->push_back(boost::any_cast<T>(a));
\r
151 catch(const bad_lexical_cast& /*e*/) {
\r
152 boost::throw_exception(invalid_option_value(s[i]));
\r
157 template<class T, class charT>
\r
159 typed_value<T, charT>::
\r
160 xparse(boost::any& value_store,
\r
161 const std::vector<std::basic_string<charT> >& new_tokens) const
\r
163 // If no tokens were given, and the option accepts an implicit
\r
164 // value, then assign the implicit value as the stored value;
\r
165 // otherwise, validate the user-provided token(s).
\r
166 if (new_tokens.empty() && !m_implicit_value.empty())
\r
167 value_store = m_implicit_value;
\r
169 validate(value_store, new_tokens, (T*)0, 0);
\r
176 // Explicit qualification is vc6 workaround.
\r
177 return boost::program_options::value<T>(0);
\r
184 typed_value<T>* r = new typed_value<T>(v);
\r
190 typed_value<T, wchar_t>*
\r
193 return wvalue<T>(0);
\r
197 typed_value<T, wchar_t>*
\r
200 typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v);
\r