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)
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>
16
namespace boost { namespace program_options {
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,
26
// TODO: what if we have different definition
27
// for the same option name during different calls
29
assert(options.description);
30
const options_description& desc = *options.description;
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;
36
std::set<std::string> new_final;
38
// Declared once, to please Intel in VC++ mode;
41
// First, convert/store all given options
42
for (i = 0; i < options.options.size(); ++i) {
44
const string& name = options.options[i].string_key;
45
// Skip positional options without name
49
// Ignore unregistered option. The 'unregistered'
50
// field can be true only if user has explicitly asked
51
// to allow unregistered options. We can't store them
52
// to variables map (lacking any information about paring),
53
// so just ignore them.
54
if (options.options[i].unregistered)
57
// If option has final value, skip this assignment
58
if (xm.m_final.count(name))
61
const option_description& d = desc.find(name, false,
64
variable_value& v = m[name];
66
// Explicit assignment here erases defaulted value
71
d.semantic()->parse(v.value(), options.options[i].value, utf8);
73
#ifndef BOOST_NO_EXCEPTIONS
74
catch(validation_error& e)
76
e.set_option_name(name);
79
catch(multiple_occurrences& e)
81
e.set_option_name(name);
84
catch(multiple_values& e)
86
e.set_option_name(name);
90
v.m_value_semantic = d.semantic();
92
// The option is not composing, and the value is explicitly
93
// provided. Ignore values of this option for subsequent
94
// calls to 'store'. We store this to a temporary set,
95
// so that several assignment inside *this* 'store' call
97
if (!d.semantic()->is_composing())
98
new_final.insert(name);
100
xm.m_final.insert(new_final.begin(), new_final.end());
104
// Second, apply default values and store required options.
105
const vector<shared_ptr<option_description> >& all = desc.options();
106
for(i = 0; i < all.size(); ++i)
108
const option_description& d = *all[i];
109
string key = d.key("");
110
// FIXME: this logic relies on knowledge of option_description
112
// The 'key' is empty if options description contains '*'.
114
// case, default value makes no sense at all.
119
if (m.count(key) == 0) {
122
if (d.semantic()->apply_default(def)) {
123
m[key] = variable_value(def, true);
124
m[key].m_value_semantic = d.semantic();
128
// add empty value if this is an required option
129
if (d.semantic()->is_required()) {
130
xm.m_required.insert(key);
135
BOOST_PROGRAM_OPTIONS_DECL
136
void store(const wparsed_options& options, variables_map& m)
138
store(options.utf8_encoded_options, m, true);
141
BOOST_PROGRAM_OPTIONS_DECL
142
void notify(variables_map& vm)
147
abstract_variables_map::abstract_variables_map()
151
abstract_variables_map::
152
abstract_variables_map(const abstract_variables_map* next)
156
const variable_value&
157
abstract_variables_map::operator[](const std::string& name) const
159
const variable_value& v = get(name);
160
if (v.empty() && m_next)
161
return (*m_next)[name];
162
else if (v.defaulted() && m_next) {
163
const variable_value& v2 = (*m_next)[name];
164
if (!v2.empty() && !v2.defaulted())
173
abstract_variables_map::next(abstract_variables_map* next)
178
variables_map::variables_map()
181
variables_map::variables_map(const abstract_variables_map* next)
182
: abstract_variables_map(next)
185
const variable_value&
186
variables_map::get(const std::string& name) const
188
static variable_value empty;
189
const_iterator i = this->find(name);
190
if (i == this->end())
197
variables_map::notify()
199
// This checks if all required options occur
200
for (set<string>::const_iterator r = m_required.begin();
201
r != m_required.end();
204
const string& opt = *r;
205
map<string, variable_value>::const_iterator iter = find(opt);
206
if (iter == end() || iter->second.empty())
208
boost::throw_exception(required_option(opt));
213
// Lastly, run notify actions.
214
for (map<string, variable_value>::iterator k = begin();
218
/* Users might wish to use variables_map to store their own values
219
that are not parsed, and therefore will not have value_semantics
220
defined. Do no crash on such values. In multi-module programs,
221
one module might add custom values, and the 'notify' function
222
will be called after that, so we check that value_sematics is
224
https://svn.boost.org/trac/boost/ticket/2782
226
if (k->second.m_value_semantic)
227
k->second.m_value_semantic->notify(k->second.value());