Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/program_options/src/value_semantic.cpp @ 13

Last change on this file since 13 was 12, checked in by landauf, 17 years ago

added boost

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.begin() == '\'' && *s.rbegin() == '\'' ||
174            *s.begin() == '"' && *s.rbegin() == '"')
175            v = any(s.substr(1, s.size()-2));
176        else
177            v = any(s);
178    }
179
180#if !defined(BOOST_NO_STD_WSTRING)
181    BOOST_PROGRAM_OPTIONS_DECL
182    void validate(any& v, const vector<wstring>& xs, std::string*, int)
183    {
184        check_first_occurrence(v);
185        wstring s(get_single_string(xs));
186        if (*s.begin() == L'\'' && *s.rbegin() == L'\'' ||
187            *s.begin() == L'"' && *s.rbegin() == L'"')
188            v = any(s.substr(1, s.size()-2));
189        else
190            v = any(s);
191    }
192#endif
193
194    namespace validators {
195
196        BOOST_PROGRAM_OPTIONS_DECL
197        void check_first_occurrence(const boost::any& value)
198        {
199            if (!value.empty())
200                boost::throw_exception(
201                    multiple_occurrences("multiple_occurrences"));
202        }
203    }
204
205
206    invalid_option_value::
207    invalid_option_value(const std::string& bad_value)
208    : validation_error(string("invalid option value '")
209                       .append(bad_value).append("'"))
210    {}
211
212#ifndef BOOST_NO_STD_WSTRING
213
214    namespace
215    {
216        std::string convert_value(const std::wstring& s)
217        {
218            try {
219                return to_local_8_bit(s);
220            }
221            catch(const std::exception&) {
222                return "<unrepresentable unicode string>";
223            }
224        }
225    }
226
227    invalid_option_value::
228    invalid_option_value(const std::wstring& bad_value)
229    : validation_error(string("invalid option value '")
230                       .append(convert_value(bad_value))
231                       .append("'"))
232    {}
233#endif                       
234
235
236
237    void validation_error::set_option_name(const std::string& option_name)
238    {
239        m_option_name = option_name;
240    }
241
242    const char* validation_error::what() const throw()
243    {
244        if (!m_option_name.empty())
245        {
246            m_message = "in option '" + m_option_name + "': " 
247                + logic_error::what();
248            return m_message.c_str();
249
250        }
251        else
252        {
253            return logic_error::what();
254        }
255    }
256
257
258
259
260}}
Note: See TracBrowser for help on using the repository browser.