Chris@16
|
1 // Copyright Vladimir Prus 2004.
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
3 // (See accompanying file LICENSE_1_0.txt
|
Chris@16
|
4 // or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 // This file defines template functions that are declared in
|
Chris@16
|
7 // ../value_semantic.hpp.
|
Chris@16
|
8
|
Chris@16
|
9 #include <boost/throw_exception.hpp>
|
Chris@16
|
10
|
Chris@16
|
11 namespace boost { namespace program_options {
|
Chris@16
|
12
|
Chris@16
|
13 extern BOOST_PROGRAM_OPTIONS_DECL std::string arg;
|
Chris@16
|
14
|
Chris@16
|
15 template<class T, class charT>
|
Chris@16
|
16 std::string
|
Chris@16
|
17 typed_value<T, charT>::name() const
|
Chris@16
|
18 {
|
Chris@16
|
19 std::string const& var = (m_value_name.empty() ? arg : m_value_name);
|
Chris@16
|
20 if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) {
|
Chris@16
|
21 std::string msg = "[=" + var + "(=" + m_implicit_value_as_text + ")]";
|
Chris@16
|
22 if (!m_default_value.empty() && !m_default_value_as_text.empty())
|
Chris@16
|
23 msg += " (=" + m_default_value_as_text + ")";
|
Chris@16
|
24 return msg;
|
Chris@16
|
25 }
|
Chris@16
|
26 else if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
|
Chris@16
|
27 return var + " (=" + m_default_value_as_text + ")";
|
Chris@16
|
28 } else {
|
Chris@16
|
29 return var;
|
Chris@16
|
30 }
|
Chris@16
|
31 }
|
Chris@16
|
32
|
Chris@16
|
33 template<class T, class charT>
|
Chris@16
|
34 void
|
Chris@16
|
35 typed_value<T, charT>::notify(const boost::any& value_store) const
|
Chris@16
|
36 {
|
Chris@16
|
37 const T* value = boost::any_cast<T>(&value_store);
|
Chris@16
|
38 if (m_store_to) {
|
Chris@16
|
39 *m_store_to = *value;
|
Chris@16
|
40 }
|
Chris@16
|
41 if (m_notifier) {
|
Chris@16
|
42 m_notifier(*value);
|
Chris@16
|
43 }
|
Chris@16
|
44 }
|
Chris@16
|
45
|
Chris@16
|
46 namespace validators {
|
Chris@16
|
47 /* If v.size() > 1, throw validation_error.
|
Chris@16
|
48 If v.size() == 1, return v.front()
|
Chris@16
|
49 Otherwise, returns a reference to a statically allocated
|
Chris@16
|
50 empty string if 'allow_empty' and throws validation_error
|
Chris@16
|
51 otherwise. */
|
Chris@16
|
52 template<class charT>
|
Chris@16
|
53 const std::basic_string<charT>& get_single_string(
|
Chris@16
|
54 const std::vector<std::basic_string<charT> >& v,
|
Chris@16
|
55 bool allow_empty = false)
|
Chris@16
|
56 {
|
Chris@16
|
57 static std::basic_string<charT> empty;
|
Chris@16
|
58 if (v.size() > 1)
|
Chris@16
|
59 boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed));
|
Chris@16
|
60 else if (v.size() == 1)
|
Chris@16
|
61 return v.front();
|
Chris@16
|
62 else if (!allow_empty)
|
Chris@16
|
63 boost::throw_exception(validation_error(validation_error::at_least_one_value_required));
|
Chris@16
|
64 return empty;
|
Chris@16
|
65 }
|
Chris@16
|
66
|
Chris@16
|
67 /* Throws multiple_occurrences if 'value' is not empty. */
|
Chris@16
|
68 BOOST_PROGRAM_OPTIONS_DECL void
|
Chris@16
|
69 check_first_occurrence(const boost::any& value);
|
Chris@16
|
70 }
|
Chris@16
|
71
|
Chris@16
|
72 using namespace validators;
|
Chris@16
|
73
|
Chris@16
|
74 /** Validates 's' and updates 'v'.
|
Chris@16
|
75 @pre 'v' is either empty or in the state assigned by the previous
|
Chris@16
|
76 invocation of 'validate'.
|
Chris@16
|
77 The target type is specified via a parameter which has the type of
|
Chris@16
|
78 pointer to the desired type. This is workaround for compilers without
|
Chris@16
|
79 partial template ordering, just like the last 'long/int' parameter.
|
Chris@16
|
80 */
|
Chris@16
|
81 template<class T, class charT>
|
Chris@16
|
82 void validate(boost::any& v,
|
Chris@16
|
83 const std::vector< std::basic_string<charT> >& xs,
|
Chris@16
|
84 T*, long)
|
Chris@16
|
85 {
|
Chris@16
|
86 validators::check_first_occurrence(v);
|
Chris@16
|
87 std::basic_string<charT> s(validators::get_single_string(xs));
|
Chris@16
|
88 try {
|
Chris@16
|
89 v = any(lexical_cast<T>(s));
|
Chris@16
|
90 }
|
Chris@16
|
91 catch(const bad_lexical_cast&) {
|
Chris@16
|
92 boost::throw_exception(invalid_option_value(s));
|
Chris@16
|
93 }
|
Chris@16
|
94 }
|
Chris@16
|
95
|
Chris@16
|
96 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
|
Chris@16
|
97 const std::vector<std::string>& xs,
|
Chris@16
|
98 bool*,
|
Chris@16
|
99 int);
|
Chris@16
|
100
|
Chris@16
|
101 #if !defined(BOOST_NO_STD_WSTRING)
|
Chris@16
|
102 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
|
Chris@16
|
103 const std::vector<std::wstring>& xs,
|
Chris@16
|
104 bool*,
|
Chris@16
|
105 int);
|
Chris@16
|
106 #endif
|
Chris@16
|
107 // For some reason, this declaration, which is require by the standard,
|
Chris@101
|
108 // cause msvc 7.1 to not generate code to specialization defined in
|
Chris@16
|
109 // value_semantic.cpp
|
Chris@101
|
110 #if ! ( BOOST_WORKAROUND(BOOST_MSVC, == 1310) )
|
Chris@16
|
111 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
|
Chris@16
|
112 const std::vector<std::string>& xs,
|
Chris@16
|
113 std::string*,
|
Chris@16
|
114 int);
|
Chris@16
|
115
|
Chris@16
|
116 #if !defined(BOOST_NO_STD_WSTRING)
|
Chris@16
|
117 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v,
|
Chris@16
|
118 const std::vector<std::wstring>& xs,
|
Chris@16
|
119 std::string*,
|
Chris@16
|
120 int);
|
Chris@16
|
121 #endif
|
Chris@16
|
122 #endif
|
Chris@16
|
123
|
Chris@16
|
124 /** Validates sequences. Allows multiple values per option occurrence
|
Chris@16
|
125 and multiple occurrences. */
|
Chris@16
|
126 template<class T, class charT>
|
Chris@16
|
127 void validate(boost::any& v,
|
Chris@16
|
128 const std::vector<std::basic_string<charT> >& s,
|
Chris@16
|
129 std::vector<T>*,
|
Chris@16
|
130 int)
|
Chris@16
|
131 {
|
Chris@16
|
132 if (v.empty()) {
|
Chris@16
|
133 v = boost::any(std::vector<T>());
|
Chris@16
|
134 }
|
Chris@16
|
135 std::vector<T>* tv = boost::any_cast< std::vector<T> >(&v);
|
Chris@16
|
136 assert(NULL != tv);
|
Chris@16
|
137 for (unsigned i = 0; i < s.size(); ++i)
|
Chris@16
|
138 {
|
Chris@16
|
139 try {
|
Chris@16
|
140 /* We call validate so that if user provided
|
Chris@16
|
141 a validator for class T, we use it even
|
Chris@16
|
142 when parsing vector<T>. */
|
Chris@16
|
143 boost::any a;
|
Chris@16
|
144 std::vector<std::basic_string<charT> > cv;
|
Chris@16
|
145 cv.push_back(s[i]);
|
Chris@16
|
146 validate(a, cv, (T*)0, 0);
|
Chris@16
|
147 tv->push_back(boost::any_cast<T>(a));
|
Chris@16
|
148 }
|
Chris@16
|
149 catch(const bad_lexical_cast& /*e*/) {
|
Chris@16
|
150 boost::throw_exception(invalid_option_value(s[i]));
|
Chris@16
|
151 }
|
Chris@16
|
152 }
|
Chris@16
|
153 }
|
Chris@16
|
154
|
Chris@16
|
155 template<class T, class charT>
|
Chris@16
|
156 void
|
Chris@16
|
157 typed_value<T, charT>::
|
Chris@16
|
158 xparse(boost::any& value_store,
|
Chris@16
|
159 const std::vector<std::basic_string<charT> >& new_tokens) const
|
Chris@16
|
160 {
|
Chris@16
|
161 // If no tokens were given, and the option accepts an implicit
|
Chris@16
|
162 // value, then assign the implicit value as the stored value;
|
Chris@16
|
163 // otherwise, validate the user-provided token(s).
|
Chris@16
|
164 if (new_tokens.empty() && !m_implicit_value.empty())
|
Chris@16
|
165 value_store = m_implicit_value;
|
Chris@16
|
166 else
|
Chris@16
|
167 validate(value_store, new_tokens, (T*)0, 0);
|
Chris@16
|
168 }
|
Chris@16
|
169
|
Chris@16
|
170 template<class T>
|
Chris@16
|
171 typed_value<T>*
|
Chris@16
|
172 value()
|
Chris@16
|
173 {
|
Chris@16
|
174 // Explicit qualification is vc6 workaround.
|
Chris@16
|
175 return boost::program_options::value<T>(0);
|
Chris@16
|
176 }
|
Chris@16
|
177
|
Chris@16
|
178 template<class T>
|
Chris@16
|
179 typed_value<T>*
|
Chris@16
|
180 value(T* v)
|
Chris@16
|
181 {
|
Chris@16
|
182 typed_value<T>* r = new typed_value<T>(v);
|
Chris@16
|
183
|
Chris@16
|
184 return r;
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 template<class T>
|
Chris@16
|
188 typed_value<T, wchar_t>*
|
Chris@16
|
189 wvalue()
|
Chris@16
|
190 {
|
Chris@16
|
191 return wvalue<T>(0);
|
Chris@16
|
192 }
|
Chris@16
|
193
|
Chris@16
|
194 template<class T>
|
Chris@16
|
195 typed_value<T, wchar_t>*
|
Chris@16
|
196 wvalue(T* v)
|
Chris@16
|
197 {
|
Chris@16
|
198 typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v);
|
Chris@16
|
199
|
Chris@16
|
200 return r;
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203
|
Chris@16
|
204
|
Chris@16
|
205 }}
|