]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/program_options/src/variables_map.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / program_options / src / variables_map.cpp
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 #include <boost/program_options/parsers.hpp>
10 #include <boost/program_options/options_description.hpp>
11 #include <boost/program_options/value_semantic.hpp>
12 #include <boost/program_options/variables_map.hpp>
13
14 #include <cassert>
15
16 namespace boost { namespace program_options {
17
18 using namespace std;
19
20 // First, performs semantic actions for 'oa'.
21 // Then, stores in 'm' all options that are defined in 'desc'.
22 BOOST_PROGRAM_OPTIONS_DECL
23 void store(const parsed_options& options, variables_map& xm,
24 bool utf8)
25 {
26 // TODO: what if we have different definition
27 // for the same option name during different calls
28 // 'store'.
29 assert(options.description);
30 const options_description& desc = *options.description;
31
32 // We need to access map's operator[], not the overriden version
33 // variables_map. Ehmm.. messy.
34 std::map<std::string, variable_value>& m = xm;
35
36 std::set<std::string> new_final;
37
38 // Declared once, to please Intel in VC++ mode;
39 unsigned i;
40
41 // Declared here so can be used to provide context for exceptions
42 string option_name;
43 string original_token;
44
45 try
46 {
47
48 // First, convert/store all given options
49 for (i = 0; i < options.options.size(); ++i) {
50
51 option_name = options.options[i].string_key;
52 original_token = options.options[i].original_tokens.size() ?
53 options.options[i].original_tokens[0] :
54 option_name;
55 // Skip positional options without name
56 if (option_name.empty())
57 continue;
58
59 // Ignore unregistered option. The 'unregistered'
60 // field can be true only if user has explicitly asked
61 // to allow unregistered options. We can't store them
62 // to variables map (lacking any information about paring),
63 // so just ignore them.
64 if (options.options[i].unregistered)
65 continue;
66
67 // If option has final value, skip this assignment
68 if (xm.m_final.count(option_name))
69 continue;
70
71 string original_token = options.options[i].original_tokens.size() ?
72 options.options[i].original_tokens[0] : "";
73 const option_description& d = desc.find(option_name, false,
74 false, false);
75
76 variable_value& v = m[option_name];
77 if (v.defaulted()) {
78 // Explicit assignment here erases defaulted value
79 v = variable_value();
80 }
81
82 d.semantic()->parse(v.value(), options.options[i].value, utf8);
83
84 v.m_value_semantic = d.semantic();
85
86 // The option is not composing, and the value is explicitly
87 // provided. Ignore values of this option for subsequent
88 // calls to 'store'. We store this to a temporary set,
89 // so that several assignment inside *this* 'store' call
90 // are allowed.
91 if (!d.semantic()->is_composing())
92 new_final.insert(option_name);
93 }
94 }
95 #ifndef BOOST_NO_EXCEPTIONS
96 catch(error_with_option_name& e)
97 {
98 // add context and rethrow
99 e.add_context(option_name, original_token, options.m_options_prefix);
100 throw;
101 }
102 #endif
103 xm.m_final.insert(new_final.begin(), new_final.end());
104
105
106
107 // Second, apply default values and store required options.
108 const vector<shared_ptr<option_description> >& all = desc.options();
109 for(i = 0; i < all.size(); ++i)
110 {
111 const option_description& d = *all[i];
112 string key = d.key("");
113 // FIXME: this logic relies on knowledge of option_description
114 // internals.
115 // The 'key' is empty if options description contains '*'.
116 // In that
117 // case, default value makes no sense at all.
118 if (key.empty())
119 {
120 continue;
121 }
122 if (m.count(key) == 0) {
123
124 boost::any def;
125 if (d.semantic()->apply_default(def)) {
126 m[key] = variable_value(def, true);
127 m[key].m_value_semantic = d.semantic();
128 }
129 }
130
131 // add empty value if this is an required option
132 if (d.semantic()->is_required()) {
133
134 // For option names specified in multiple ways, e.g. on the command line,
135 // config file etc, the following precedence rules apply:
136 // "--" > ("-" or "/") > ""
137 // Precedence is set conveniently by a single call to length()
138 string canonical_name = d.canonical_display_name(options.m_options_prefix);
139 if (canonical_name.length() > xm.m_required[key].length())
140 xm.m_required[key] = canonical_name;
141 }
142 }
143 }
144
145 BOOST_PROGRAM_OPTIONS_DECL
146 void store(const wparsed_options& options, variables_map& m)
147 {
148 store(options.utf8_encoded_options, m, true);
149 }
150
151 BOOST_PROGRAM_OPTIONS_DECL
152 void notify(variables_map& vm)
153 {
154 vm.notify();
155 }
156
157 abstract_variables_map::abstract_variables_map()
158 : m_next(0)
159 {}
160
161 abstract_variables_map::
162 abstract_variables_map(const abstract_variables_map* next)
163 : m_next(next)
164 {}
165
166 const variable_value&
167 abstract_variables_map::operator[](const std::string& name) const
168 {
169 const variable_value& v = get(name);
170 if (v.empty() && m_next)
171 return (*m_next)[name];
172 else if (v.defaulted() && m_next) {
173 const variable_value& v2 = (*m_next)[name];
174 if (!v2.empty() && !v2.defaulted())
175 return v2;
176 else return v;
177 } else {
178 return v;
179 }
180 }
181
182 void
183 abstract_variables_map::next(abstract_variables_map* next)
184 {
185 m_next = next;
186 }
187
188 variables_map::variables_map()
189 {}
190
191 variables_map::variables_map(const abstract_variables_map* next)
192 : abstract_variables_map(next)
193 {}
194
195 void variables_map::clear()
196 {
197 std::map<std::string, variable_value>::clear();
198 m_final.clear();
199 m_required.clear();
200 }
201
202 const variable_value&
203 variables_map::get(const std::string& name) const
204 {
205 static variable_value empty;
206 const_iterator i = this->find(name);
207 if (i == this->end())
208 return empty;
209 else
210 return i->second;
211 }
212
213 void
214 variables_map::notify()
215 {
216 // This checks if all required options occur
217 for (map<string, string>::const_iterator r = m_required.begin();
218 r != m_required.end();
219 ++r)
220 {
221 const string& opt = r->first;
222 const string& display_opt = r->second;
223 map<string, variable_value>::const_iterator iter = find(opt);
224 if (iter == end() || iter->second.empty())
225 {
226 boost::throw_exception(required_option(display_opt));
227
228 }
229 }
230
231 // Lastly, run notify actions.
232 for (map<string, variable_value>::iterator k = begin();
233 k != end();
234 ++k)
235 {
236 /* Users might wish to use variables_map to store their own values
237 that are not parsed, and therefore will not have value_semantics
238 defined. Do not crash on such values. In multi-module programs,
239 one module might add custom values, and the 'notify' function
240 will be called after that, so we check that value_sematics is
241 not NULL. See:
242 https://svn.boost.org/trac/boost/ticket/2782
243 */
244 if (k->second.m_value_semantic)
245 k->second.m_value_semantic->notify(k->second.value());
246 }
247 }
248
249 }}