Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:14

0001 // Copyright Vladimir Prus 2002-2004.
0002 // Distributed under the Boost Software License, Version 1.0.
0003 // (See accompanying file LICENSE_1_0.txt
0004 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 
0007 #ifndef BOOST_CONFIG_FILE_VP_2003_01_02
0008 #define BOOST_CONFIG_FILE_VP_2003_01_02
0009 
0010 #include <iosfwd>
0011 #include <string>
0012 #include <set>
0013 
0014 #include <boost/noncopyable.hpp>
0015 #include <boost/program_options/config.hpp>
0016 #include <boost/program_options/option.hpp>
0017 #include <boost/program_options/eof_iterator.hpp>
0018 
0019 #include <boost/detail/workaround.hpp>
0020 #include <boost/program_options/detail/convert.hpp>
0021 
0022 #if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
0023 #include <istream> // std::getline
0024 #endif
0025 
0026 #include <boost/static_assert.hpp>
0027 #include <boost/type_traits/is_same.hpp>
0028 #include <boost/shared_ptr.hpp>
0029 
0030 #ifdef BOOST_MSVC
0031 # pragma warning(push)
0032 # pragma warning(disable: 4251) // class XYZ needs to have dll-interface to be used by clients of class XYZ
0033 #endif
0034 
0035 
0036 
0037 namespace boost { namespace program_options { namespace detail {
0038 
0039     /** Standalone parser for config files in ini-line format.
0040         The parser is a model of single-pass lvalue iterator, and
0041         default constructor creates past-the-end-iterator. The typical usage is:
0042         config_file_iterator i(is, ... set of options ...), e;
0043         for(; i !=e; ++i) {
0044             *i;
0045         }
0046         
0047         Syntax conventions:
0048 
0049         - config file can not contain positional options
0050         - '#' is comment character: it is ignored together with
0051           the rest of the line.
0052         - variable assignments are in the form
0053           name '=' value.
0054           spaces around '=' are trimmed.
0055         - Section names are given in brackets. 
0056 
0057          The actual option name is constructed by combining current section
0058          name and specified option name, with dot between. If section_name 
0059          already contains dot at the end, new dot is not inserted. For example:
0060          @verbatim
0061          [gui.accessibility]
0062          visual_bell=yes
0063          @endverbatim
0064          will result in option "gui.accessibility.visual_bell" with value
0065          "yes" been returned.
0066 
0067          TODO: maybe, we should just accept a pointer to options_description
0068          class.
0069      */    
0070     class BOOST_PROGRAM_OPTIONS_DECL common_config_file_iterator
0071         : public eof_iterator<common_config_file_iterator, option>
0072     {
0073     public:
0074         common_config_file_iterator() { found_eof(); }
0075         common_config_file_iterator(
0076             const std::set<std::string>& allowed_options,
0077             bool allow_unregistered = false);
0078 
0079         BOOST_DEFAULTED_FUNCTION(virtual ~common_config_file_iterator(), {})
0080 
0081     public: // Method required by eof_iterator
0082         
0083         void get();
0084         
0085 #if BOOST_WORKAROUND(_MSC_VER, <= 1900)
0086         void decrement() {}
0087         void advance(difference_type) {}
0088 #endif
0089 
0090     protected: // Stubs for derived classes
0091 
0092         // Obtains next line from the config file
0093         // Note: really, this design is a bit ugly
0094         // The most clean thing would be to pass 'line_iterator' to
0095         // constructor of this class, but to avoid templating this class
0096         // we'd need polymorphic iterator, which does not exist yet.
0097         virtual bool getline(std::string&) { return false; }
0098         
0099     private:
0100         /** Adds another allowed option. If the 'name' ends with
0101             '*', then all options with the same prefix are
0102             allowed. For example, if 'name' is 'foo*', then 'foo1' and
0103             'foo_bar' are allowed. */
0104         void add_option(const char* name);
0105 
0106         // Returns true if 's' is a registered option name.
0107         bool allowed_option(const std::string& s) const; 
0108 
0109         // That's probably too much data for iterator, since
0110         // it will be copied, but let's not bother for now.
0111         std::set<std::string> allowed_options;
0112         // Invariant: no element is prefix of other element.
0113         std::set<std::string> allowed_prefixes;
0114         std::string m_prefix;
0115         bool m_allow_unregistered;
0116     };
0117 
0118     template<class charT>
0119     class basic_config_file_iterator : public common_config_file_iterator {
0120     public:
0121         basic_config_file_iterator()
0122         {
0123             found_eof();
0124         }
0125 
0126         /** Creates a config file parser for the specified stream.            
0127         */
0128         basic_config_file_iterator(std::basic_istream<charT>& is, 
0129                                    const std::set<std::string>& allowed_options,
0130                                    bool allow_unregistered = false); 
0131 
0132     private: // base overrides
0133 
0134         bool getline(std::string&);
0135 
0136     private: // internal data
0137         shared_ptr<std::basic_istream<charT> > is;
0138     };
0139     
0140     typedef basic_config_file_iterator<char> config_file_iterator;
0141     typedef basic_config_file_iterator<wchar_t> wconfig_file_iterator;
0142 
0143 
0144     struct null_deleter
0145     {
0146         void operator()(void const *) const {}
0147     };
0148 
0149 
0150     template<class charT>
0151     basic_config_file_iterator<charT>::
0152     basic_config_file_iterator(std::basic_istream<charT>& is, 
0153                                const std::set<std::string>& allowed_options,
0154                                bool allow_unregistered)
0155     : common_config_file_iterator(allowed_options, allow_unregistered)
0156     {
0157         this->is.reset(&is, null_deleter());                 
0158         get();
0159     }
0160 
0161     // Specializing this function for wchar_t causes problems on
0162     // borland and vc7, as well as on metrowerks. On the first two
0163     // I don't know a workaround, so make use of 'to_internal' to
0164     // avoid specialization.
0165     template<class charT>
0166     bool
0167     basic_config_file_iterator<charT>::getline(std::string& s)
0168     {
0169         std::basic_string<charT> in;
0170         if (std::getline(*is, in)) {
0171             s = to_internal(in);
0172             return true;
0173         } else {
0174             return false;
0175         }
0176     }
0177 
0178     // Specialization is needed to workaround getline bug on Comeau.
0179 #if BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4303)) || \
0180         (defined(__sgi) && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(741)))
0181     template<>
0182     bool
0183     basic_config_file_iterator<wchar_t>::getline(std::string& s);
0184 #endif
0185 
0186     
0187 
0188 }}}
0189 
0190 #ifdef BOOST_MSVC
0191 # pragma warning(pop)
0192 #endif
0193 
0194 #endif