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_VARIABLES_MAP_VP_2003_05_19
8 #define BOOST_VARIABLES_MAP_VP_2003_05_19
9 
10 #include <boost/program_options/config.hpp>
11 
12 #include <boost/any.hpp>
13 #include <boost/shared_ptr.hpp>
14 
15 #include <string>
16 #include <map>
17 #include <set>
18 
19 #if defined(BOOST_MSVC)
20 #   pragma warning (push)
21 #   pragma warning (disable:4251) // 'boost::program_options::variable_value::v' : class 'boost::any' needs to have dll-interface to be used by clients of class 'boost::program_options::variable_value
22 #endif
23 
24 namespace boost { namespace program_options {
25 
26     template<class charT>
27     class basic_parsed_options;
28 
29     class value_semantic;
30     class variables_map;
31 
32     // forward declaration
33 
34     /** Stores in 'm' all options that are defined in 'options'.
35         If 'm' already has a non-defaulted value of an option, that value
36         is not changed, even if 'options' specify some value.
37     */
38     BOOST_PROGRAM_OPTIONS_DECL
39     void store(const basic_parsed_options<char>& options, variables_map& m,
40                     bool utf8 = false);
41 
42     /** Stores in 'm' all options that are defined in 'options'.
43         If 'm' already has a non-defaulted value of an option, that value
44         is not changed, even if 'options' specify some value.
45         This is wide character variant.
46     */
47     BOOST_PROGRAM_OPTIONS_DECL
48     void store(const basic_parsed_options<wchar_t>& options,
49                     variables_map& m);
50 
51 
52     /** Runs all 'notify' function for options in 'm'. */
53     BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& m);
54 
55     /** Class holding value of option. Contains details about how the
56         value is set and allows to conveniently obtain the value.
57     */
58     class BOOST_PROGRAM_OPTIONS_DECL variable_value {
59     public:
variable_value()60         variable_value() : m_defaulted(false) {}
variable_value(const boost::any & xv,bool xdefaulted)61         variable_value(const boost::any& xv, bool xdefaulted)
62         : v(xv), m_defaulted(xdefaulted)
63         {}
64 
65         /** If stored value if of type T, returns that value. Otherwise,
66             throws boost::bad_any_cast exception. */
67        template<class T>
as() const68        const T& as() const {
69            return boost::any_cast<const T&>(v);
70        }
71        /** @overload */
72        template<class T>
as()73        T& as() {
74            return boost::any_cast<T&>(v);
75        }
76 
77         /// Returns true if no value is stored.
78         bool empty() const;
79         /** Returns true if the value was not explicitly
80             given, but has default value. */
81         bool defaulted() const;
82         /** Returns the contained value. */
83         const boost::any& value() const;
84 
85         /** Returns the contained value. */
86         boost::any& value();
87     private:
88         boost::any v;
89         bool m_defaulted;
90         // Internal reference to value semantic. We need to run
91         // notifications when *final* values of options are known, and
92         // they are known only after all sources are stored. By that
93         // time options_description for the first source might not
94         // be easily accessible, so we need to store semantic here.
95         shared_ptr<const value_semantic> m_value_semantic;
96 
97         friend BOOST_PROGRAM_OPTIONS_DECL
98         void store(const basic_parsed_options<char>& options,
99               variables_map& m, bool);
100 
101         friend class BOOST_PROGRAM_OPTIONS_DECL variables_map;
102     };
103 
104     /** Implements string->string mapping with convenient value casting
105         facilities. */
106     class BOOST_PROGRAM_OPTIONS_DECL abstract_variables_map {
107     public:
108         abstract_variables_map();
109         abstract_variables_map(const abstract_variables_map* next);
110 
~abstract_variables_map()111         virtual ~abstract_variables_map() {}
112 
113         /** Obtains the value of variable 'name', from *this and
114             possibly from the chain of variable maps.
115 
116             - if there's no value in *this.
117                 - if there's next variable map, returns value from it
118                 - otherwise, returns empty value
119 
120             - if there's defaulted value
121                 - if there's next variable map, which has a non-defaulted
122                   value, return that
123                 - otherwise, return value from *this
124 
125             - if there's a non-defaulted value, returns it.
126         */
127         const variable_value& operator[](const std::string& name) const;
128 
129         /** Sets next variable map, which will be used to find
130            variables not found in *this. */
131         void next(abstract_variables_map* next);
132 
133     private:
134         /** Returns value of variable 'name' stored in *this, or
135             empty value otherwise. */
136         virtual const variable_value& get(const std::string& name) const = 0;
137 
138         const abstract_variables_map* m_next;
139     };
140 
141     /** Concrete variables map which store variables in real map.
142 
143         This class is derived from std::map<std::string, variable_value>,
144         so you can use all map operators to examine its content.
145     */
146     class BOOST_PROGRAM_OPTIONS_DECL variables_map : public abstract_variables_map,
147                                public std::map<std::string, variable_value>
148     {
149     public:
150         variables_map();
151         variables_map(const abstract_variables_map* next);
152 
153         // Resolve conflict between inherited operators.
operator [](const std::string & name) const154         const variable_value& operator[](const std::string& name) const
155         { return abstract_variables_map::operator[](name); }
156 
157         // Override to clear some extra fields.
158         void clear();
159 
160         void notify();
161 
162     private:
163         /** Implementation of abstract_variables_map::get
164             which does 'find' in *this. */
165         const variable_value& get(const std::string& name) const;
166 
167         /** Names of option with 'final' values \-- which should not
168             be changed by subsequence assignments. */
169         std::set<std::string> m_final;
170 
171         friend BOOST_PROGRAM_OPTIONS_DECL
172         void store(const basic_parsed_options<char>& options,
173                           variables_map& xm,
174                           bool utf8);
175 
176         /** Names of required options, filled by parser which has
177             access to options_description.
178             The map values are the "canonical" names for each corresponding option.
179             This is useful in creating diagnostic messages when the option is absent. */
180         std::map<std::string, std::string> m_required;
181     };
182 
183 
184     /*
185      * Templates/inlines
186      */
187 
188     inline bool
empty() const189     variable_value::empty() const
190     {
191         return v.empty();
192     }
193 
194     inline bool
defaulted() const195     variable_value::defaulted() const
196     {
197         return m_defaulted;
198     }
199 
200     inline
201     const boost::any&
value() const202     variable_value::value() const
203     {
204         return v;
205     }
206 
207     inline
208     boost::any&
value()209     variable_value::value()
210     {
211         return v;
212     }
213 
214 }}
215 
216 #if defined(BOOST_MSVC)
217 #   pragma warning (pop)
218 #endif
219 
220 #endif
221