Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/program_options/src/config_file.cpp @ 12

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

added boost

File size: 5.5 KB
Line 
1// Copyright Vladimir Prus 2002-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
7#define BOOST_PROGRAM_OPTIONS_SOURCE
8#include <boost/program_options/config.hpp>
9
10#include <boost/program_options/detail/config_file.hpp>
11#include <boost/program_options/errors.hpp>
12#include <boost/program_options/detail/convert.hpp>
13#include <boost/throw_exception.hpp>
14
15#include <iostream>
16#include <fstream>
17#include <cassert>
18
19namespace boost { namespace program_options { namespace detail {
20
21    using namespace std;
22
23    common_config_file_iterator::common_config_file_iterator(
24        const std::set<std::string>& allowed_options)
25    : allowed_options(allowed_options)
26    {
27        for(std::set<std::string>::const_iterator i = allowed_options.begin();
28            i != allowed_options.end(); 
29            ++i)
30        {
31            add_option(i->c_str());
32        }
33    }
34
35    void
36    common_config_file_iterator::add_option(const char* name)
37    {
38        string s(name);
39        assert(!s.empty());
40        if (*s.rbegin() == '*') {
41            s.resize(s.size()-1);
42            bool bad_prefixes(false);
43            // If 's' is a prefix of one of allowed suffix, then
44            // lower_bound will return that element.
45            // If some element is prefix of 's', then lower_bound will
46            // return the next element.
47            set<string>::iterator i = allowed_prefixes.lower_bound(s);
48            if (i != allowed_prefixes.end()) {
49                if (i->find(s) == 0)
50                    bad_prefixes = true;                   
51            }
52            if (i != allowed_prefixes.begin()) {
53                --i;
54                if (s.find(*i) == 0)
55                    bad_prefixes = true;
56            }
57            if (bad_prefixes)
58                boost::throw_exception(error("bad prefixes"));
59            allowed_prefixes.insert(s);
60        }
61    }
62
63    namespace {
64        string trim_ws(const string& s)
65        {
66            string::size_type n, n2;
67            n = s.find_first_not_of(" \t\r\n");
68            if (n == string::npos)
69                return string();
70            else {
71                n2 = s.find_last_not_of(" \t\r\n");
72                return s.substr(n, n2-n+1);
73            }
74        }
75    }
76
77
78    void common_config_file_iterator::get()
79    {
80        string s;
81        string::size_type n;
82        bool found = false;
83
84        while(this->getline(s)) {
85
86            // strip '#' comments and whitespace
87            if ((n = s.find('#')) != string::npos)
88                s = s.substr(0, n);
89            s = trim_ws(s);
90
91            if (!s.empty()) {
92                // Handle section name
93                if (*s.begin() == '[' && *s.rbegin() == ']') {
94                    m_prefix = s.substr(1, s.size()-2);
95                    if (*m_prefix.rbegin() != '.')
96                        m_prefix += '.';
97                }
98                else if ((n = s.find('=')) != string::npos) {
99
100                    string name = m_prefix + trim_ws(s.substr(0, n));
101                    string value = trim_ws(s.substr(n+1));
102
103                    if (!allowed_option(name))
104                        boost::throw_exception(unknown_option(name));
105                                       
106                    if (value.empty())
107                        boost::throw_exception(invalid_syntax(s, "no value given"));
108                   
109                    found = true;
110                    this->value().string_key = name;
111                    this->value().value.clear();
112                    this->value().value.push_back(value);
113                    break;
114
115                } else {
116                    boost::throw_exception(invalid_syntax(s, "unrecognized line"));
117                }
118            }
119        }
120        if (!found)
121            found_eof();
122    }
123
124
125    bool 
126    common_config_file_iterator::allowed_option(const std::string& s) const
127    {
128        set<string>::const_iterator i = allowed_options.find(s);
129        if (i != allowed_options.end())
130            return true;       
131        // If s is "pa" where "p" is allowed prefix then
132        // lower_bound should find the element after "p".
133        // This depends on 'allowed_prefixes' invariant.
134        i = allowed_prefixes.lower_bound(s);
135        if (i != allowed_prefixes.begin() && s.find(*--i) == 0)
136            return true;
137        return false;
138    }
139
140#if BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4303)) || \
141        (defined(__sgi) && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(741)))
142    template<>
143    bool
144    basic_config_file_iterator<wchar_t>::getline(std::string& s)
145    {
146        std::wstring ws;
147        // On Comeau, using two-argument version causes
148        // call to some internal function with std::wstring, and '\n'
149        // (not L'\n') and compile can't resolve that call.
150
151        if (std::getline(*is, ws, L'\n')) {
152            s = to_utf8(ws);
153            return true;
154        } else {
155            return false;
156        }           
157    }
158#endif   
159
160}}}
161
162#if 0
163using boost::program_options::config_file;
164
165#include <sstream>
166#include <cassert>
167
168int main()
169{
170    try {
171        stringstream s(
172            "a = 1\n"
173            "b = 2\n");
174
175        config_file cf(s);
176        cf.add_option("a");
177        cf.add_option("b");
178
179        assert(++cf);
180        assert(cf.name() == "a");
181        assert(cf.value() == "1");
182        assert(++cf);
183        assert(cf.name() == "b");
184        assert(cf.value() == "2");
185        assert(!++cf);
186    }
187    catch(exception& e)
188    {
189        cout << e.what() << "\n";
190    }
191}
192#endif
Note: See TracBrowser for help on using the repository browser.