source: NonGTP/Boost/boost/program_options/detail/config_file.hpp @ 857

Revision 857, 5.8 KB checked in by igarcia, 18 years ago (diff)
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#ifndef BOOST_CONFIG_FILE_VP_2003_01_02
8#define BOOST_CONFIG_FILE_VP_2003_01_02
9
10#include <iosfwd>
11#include <string>
12#include <set>
13
14#include <boost/noncopyable.hpp>
15#include <boost/program_options/config.hpp>
16#include <boost/program_options/option.hpp>
17#include <boost/program_options/eof_iterator.hpp>
18
19#include <boost/detail/workaround.hpp>
20#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202))
21#include <boost/program_options/detail/convert.hpp>
22#endif
23
24#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
25#include <istream> // std::getline
26#endif
27
28#include <boost/static_assert.hpp>
29#include <boost/type_traits/is_same.hpp>
30#include <boost/shared_ptr.hpp>
31
32
33
34namespace boost { namespace program_options { namespace detail {
35
36    /** Standalone parser for config files in ini-line format.
37        The parser is a model of single-pass lvalue iterator, and
38        default constructor creates past-the-end-iterator. The typical usage is:
39        config_file_iterator i(is, ... set of options ...), e;
40        for(; i !=e; ++i) {
41            *i;
42        }
43       
44        Syntax conventions:
45
46        - config file can not contain positional options
47        - '#' is comment character: it is ignored together with
48          the rest of the line.
49        - variable assignments are in the form
50          name '=' value.
51          spaces around '=' are trimmed.
52        - Section names are given in brackets.
53
54         The actual option name is constructed by combining current section
55         name and specified option name, with dot between. If section_name
56         already contains dot at the end, new dot is not inserted. For example:
57         @verbatim
58         [gui.accessibility]
59         visual_bell=yes
60         @endverbatim
61         will result in option "gui.accessibility.visual_bell" with value
62         "yes" been returned.
63
64         TODO: maybe, we should just accept a pointer to options_description
65         class.
66     */   
67    class common_config_file_iterator
68        : public eof_iterator<common_config_file_iterator, option>
69    {
70    public:
71        common_config_file_iterator() { found_eof(); }
72        common_config_file_iterator(
73            const std::set<std::string>& allowed_options);
74
75        virtual ~common_config_file_iterator() {}
76
77    public: // Method required by eof_iterator
78       
79        void get();
80       
81    protected: // Stubs for derived classes
82
83        // Obtains next line from the config file
84        // Note: really, this design is a bit ugly
85        // The most clean thing would be to pass 'line_iterator' to
86        // constructor of this class, but to avoid templating this class
87        // we'd need polymorphic iterator, which does not exist yet.
88        virtual bool getline(std::string&) { return false; }
89       
90    private:
91        /** Adds another allowed option. If the 'name' ends with
92            '*', then all options with the same prefix are
93            allowed. For example, if 'name' is 'foo*', then 'foo1' and
94            'foo_bar' are allowed. */
95        void add_option(const char* name);
96
97        // Returns true if 's' is a registered option name.
98        bool allowed_option(const std::string& s) const;
99
100        // That's probably too much data for iterator, since
101        // it will be copied, but let's not bother for now.
102        std::set<std::string> allowed_options;
103        // Invariant: no element is prefix of other element.
104        std::set<std::string> allowed_prefixes;
105        std::string m_prefix;
106    };
107
108    template<class charT>
109    class basic_config_file_iterator : public common_config_file_iterator {
110    public:
111        basic_config_file_iterator()
112        {
113            found_eof();
114        }
115
116        /** Creates a config file parser for the specified stream.           
117        */
118        basic_config_file_iterator(std::basic_istream<charT>& is,
119                                   const std::set<std::string>& allowed_options);
120
121    private: // base overrides
122
123        bool getline(std::string&);
124
125    private: // internal data
126        shared_ptr<std::basic_istream<charT> > is;
127    };
128   
129    typedef basic_config_file_iterator<char> config_file_iterator;
130    typedef basic_config_file_iterator<wchar_t> wconfig_file_iterator;
131
132
133    struct null_deleter
134    {
135        void operator()(void const *) const {}
136    };
137
138
139    template<class charT>
140    basic_config_file_iterator<charT>::
141    basic_config_file_iterator(std::basic_istream<charT>& is,
142                               const std::set<std::string>& allowed_options)
143    : common_config_file_iterator(allowed_options)
144    {
145        this->is.reset(&is, null_deleter());                 
146        get();
147    }
148
149    // Specializing this function for wchar_t causes problems on
150    // borland and vc7, as well as on metrowerks. On the first two
151    // I don't know a workaround, so make use of 'to_internal' to
152    // avoid specialization.
153    template<class charT>
154    bool
155    basic_config_file_iterator<charT>::getline(std::string& s)
156    {
157        std::basic_string<charT> in;
158        if (std::getline(*is, in)) {
159            s = to_internal(in);
160            return true;
161        } else {
162            return false;
163        }
164    }
165
166    // Specialization is needed to workaround getline bug on Comeau.
167#if BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4303)) || \
168        (defined(__sgi) && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(741)))
169    template<>
170    bool
171    basic_config_file_iterator<wchar_t>::getline(std::string& s);
172#endif
173
174   
175
176}}}
177
178#endif
Note: See TracBrowser for help on using the repository browser.