Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/program_options/src/value_semantic.cpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 7.3 KB
Line 
1// Copyright Vladimir Prus 2004.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt
4// or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#define BOOST_PROGRAM_OPTIONS_SOURCE
7#include <boost/program_options/config.hpp>
8#include <boost/program_options/value_semantic.hpp>
9#include <boost/program_options/detail/convert.hpp>
10
11#include <cctype>
12
13namespace boost { namespace program_options {
14
15    using namespace std;
16
17    void 
18    value_semantic_codecvt_helper<char>::
19    parse(boost::any& value_store, 
20          const std::vector<std::string>& new_tokens,
21          bool utf8) const
22    {
23        if (utf8) {
24#ifndef BOOST_NO_STD_WSTRING
25            // Need to convert to local encoding.
26            std::vector<string> local_tokens;
27            for (unsigned i = 0; i < new_tokens.size(); ++i) {
28                std::wstring w = from_utf8(new_tokens[i]);
29                local_tokens.push_back(to_local_8_bit(w));
30            }
31            xparse(value_store, local_tokens);
32#else
33            boost::throw_exception(
34                std::runtime_error("UTF-8 conversion not supported."));
35#endif
36        } else {
37            // Already in local encoding, pass unmodified
38            xparse(value_store, new_tokens);
39        }       
40    }
41
42#ifndef BOOST_NO_STD_WSTRING
43    void 
44    value_semantic_codecvt_helper<wchar_t>::
45    parse(boost::any& value_store, 
46          const std::vector<std::string>& new_tokens,
47          bool utf8) const
48    {
49        std::vector<wstring> tokens;
50        if (utf8) {
51            // Convert from utf8
52            for (unsigned i = 0; i < new_tokens.size(); ++i) {
53                tokens.push_back(from_utf8(new_tokens[i]));
54            }
55               
56        } else {
57            // Convert from local encoding
58            for (unsigned i = 0; i < new_tokens.size(); ++i) {
59                tokens.push_back(from_local_8_bit(new_tokens[i]));
60            }
61        }     
62
63        xparse(value_store, tokens); 
64    }
65#endif
66
67    BOOST_PROGRAM_OPTIONS_DECL std::string arg("arg");
68
69    std::string
70    untyped_value::name() const
71    {
72        return arg;
73    }
74   
75    unsigned 
76    untyped_value::min_tokens() const
77    {
78        if (m_zero_tokens)
79            return 0;
80        else
81            return 1;
82    }
83
84    unsigned 
85    untyped_value::max_tokens() const
86    {
87        if (m_zero_tokens)
88            return 0;
89        else
90            return 1;
91    }
92
93
94    void 
95    untyped_value::xparse(boost::any& value_store,
96                          const std::vector<std::string>& new_tokens) const
97    {
98        if (!value_store.empty()) 
99            boost::throw_exception(
100                multiple_occurrences("multiple_occurrences"));
101        if (new_tokens.size() > 1)
102            boost::throw_exception(multiple_values("multiple_values"));
103        value_store = new_tokens.empty() ? std::string("") : new_tokens.front();
104    }
105
106    BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
107    bool_switch()
108    {
109        return bool_switch(0);
110    }
111
112    BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
113    bool_switch(bool* v)
114    {
115        typed_value<bool>* r = new typed_value<bool>(v);
116        r->default_value(0);
117        r->zero_tokens();
118
119        return r;
120    }
121
122    /* Validates bool value.
123        Any of "1", "true", "yes", "on" will be converted to "1".<br>
124        Any of "0", "false", "no", "off" will be converted to "0".<br>
125        Case is ignored. Regardless of name passed, parameter will always
126        be optional.
127    */
128    BOOST_PROGRAM_OPTIONS_DECL void validate(any& v, const vector<string>& xs,
129                       bool*, int)
130    {
131        check_first_occurrence(v);
132        string s(get_single_string(xs, true));
133
134        for (size_t i = 0; i < s.size(); ++i)
135            s[i] = char(tolower(s[i]));
136
137        if (s.empty() || s == "on" || s == "yes" || s == "1" || s == "true")
138            v = any(true);
139        else if (s == "off" || s == "no" || s == "0" || s == "false")
140            v = any(false);
141        else
142            boost::throw_exception(validation_error(
143                                "'" + s + "' doesn't look like a bool value."));
144    }
145
146    // This is blatant copy-paste. However, templating this will cause a problem,
147    // since wstring can't be constructed/compared with char*. We'd need to
148    // create auxiliary 'widen' routine to convert from char* into
149    // needed string type, and that's more work.
150#if !defined(BOOST_NO_STD_WSTRING)
151    BOOST_PROGRAM_OPTIONS_DECL
152    void validate(any& v, const vector<wstring>& xs, bool*, int)
153    {
154        check_first_occurrence(v);
155        wstring s(get_single_string(xs, true));
156
157        for (size_t i = 0; i < s.size(); ++i)
158            s[i] = wchar_t(tolower(s[i]));
159
160        if (s.empty() || s == L"on" || s == L"yes" || s == L"1" || s == L"true")
161            v = any(true);
162        else if (s == L"off" || s == L"no" || s == L"0" || s == L"false")
163            v = any(false);
164        else
165            boost::throw_exception(validation_error("invalid bool value"));
166    }
167#endif
168    BOOST_PROGRAM_OPTIONS_DECL
169    void validate(any& v, const vector<string>& xs, std::string*, int)
170    {
171        check_first_occurrence(v);
172        string s(get_single_string(xs));
173        if (!s.empty() && (
174                (*s.begin() == '\'' && *s.rbegin() == '\'' ||
175                 *s.begin() == '"' && *s.rbegin() == '"')))
176        {
177            v = any(s.substr(1, s.size()-2));
178        }
179        else
180            v = any(s);
181    }
182
183#if !defined(BOOST_NO_STD_WSTRING)
184    BOOST_PROGRAM_OPTIONS_DECL
185    void validate(any& v, const vector<wstring>& xs, std::string*, int)
186    {
187        check_first_occurrence(v);
188        wstring s(get_single_string(xs));
189        if (*s.begin() == L'\'' && *s.rbegin() == L'\'' ||
190            *s.begin() == L'"' && *s.rbegin() == L'"')
191            v = any(s.substr(1, s.size()-2));
192        else
193            v = any(s);
194    }
195#endif
196
197    namespace validators {
198
199        BOOST_PROGRAM_OPTIONS_DECL
200        void check_first_occurrence(const boost::any& value)
201        {
202            if (!value.empty())
203                boost::throw_exception(
204                    multiple_occurrences("multiple_occurrences"));
205        }
206    }
207
208
209    invalid_option_value::
210    invalid_option_value(const std::string& bad_value)
211    : validation_error(string("invalid option value '")
212                       .append(bad_value).append("'"))
213    {}
214
215#ifndef BOOST_NO_STD_WSTRING
216
217    namespace
218    {
219        std::string convert_value(const std::wstring& s)
220        {
221            try {
222                return to_local_8_bit(s);
223            }
224            catch(const std::exception&) {
225                return "<unrepresentable unicode string>";
226            }
227        }
228    }
229
230    invalid_option_value::
231    invalid_option_value(const std::wstring& bad_value)
232    : validation_error(string("invalid option value '")
233                       .append(convert_value(bad_value))
234                       .append("'"))
235    {}
236#endif                       
237
238
239
240    void validation_error::set_option_name(const std::string& option_name)
241    {
242        m_option_name = option_name;
243    }
244
245    const char* validation_error::what() const throw()
246    {
247        if (!m_option_name.empty())
248        {
249            m_message = "in option '" + m_option_name + "': " 
250                + logic_error::what();
251            return m_message.c_str();
252
253        }
254        else
255        {
256            return logic_error::what();
257        }
258    }
259
260
261
262
263}}
Note: See TracBrowser for help on using the repository browser.