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 // Declared here so can be used to provide context for exceptions
43 string original_token
;
45 #ifndef BOOST_NO_EXCEPTIONS
50 // First, convert/store all given options
51 for (i
= 0; i
< options
.options
.size(); ++i
) {
53 option_name
= options
.options
[i
].string_key
;
54 // Skip positional options without name
55 if (option_name
.empty())
58 // Ignore unregistered option. The 'unregistered'
59 // field can be true only if user has explicitly asked
60 // to allow unregistered options. We can't store them
61 // to variables map (lacking any information about paring),
62 // so just ignore them.
63 if (options
.options
[i
].unregistered
)
66 // If option has final value, skip this assignment
67 if (xm
.m_final
.count(option_name
))
70 original_token
= options
.options
[i
].original_tokens
.size() ?
71 options
.options
[i
].original_tokens
[0] : "";
72 const option_description
& d
= desc
.find(option_name
, false,
75 variable_value
& v
= m
[option_name
];
77 // Explicit assignment here erases defaulted value
81 d
.semantic()->parse(v
.value(), options
.options
[i
].value
, utf8
);
83 v
.m_value_semantic
= d
.semantic();
85 // The option is not composing, and the value is explicitly
86 // provided. Ignore values of this option for subsequent
87 // calls to 'store'. We store this to a temporary set,
88 // so that several assignment inside *this* 'store' call
90 if (!d
.semantic()->is_composing())
91 new_final
.insert(option_name
);
94 #ifndef BOOST_NO_EXCEPTIONS
95 catch(error_with_option_name
& e
)
97 // add context and rethrow
98 e
.add_context(option_name
, original_token
, options
.m_options_prefix
);
102 xm
.m_final
.insert(new_final
.begin(), new_final
.end());
106 // Second, apply default values and store required options.
107 const vector
<shared_ptr
<option_description
> >& all
= desc
.options();
108 for(i
= 0; i
< all
.size(); ++i
)
110 const option_description
& d
= *all
[i
];
111 string key
= d
.key("");
112 // FIXME: this logic relies on knowledge of option_description
114 // The 'key' is empty if options description contains '*'.
116 // case, default value makes no sense at all.
121 if (m
.count(key
) == 0) {
124 if (d
.semantic()->apply_default(def
)) {
125 m
[key
] = variable_value(def
, true);
126 m
[key
].m_value_semantic
= d
.semantic();
130 // add empty value if this is an required option
131 if (d
.semantic()->is_required()) {
133 // For option names specified in multiple ways, e.g. on the command line,
134 // config file etc, the following precedence rules apply:
135 // "--" > ("-" or "/") > ""
136 // Precedence is set conveniently by a single call to length()
137 string canonical_name
= d
.canonical_display_name(options
.m_options_prefix
);
138 if (canonical_name
.length() > xm
.m_required
[key
].length())
139 xm
.m_required
[key
] = canonical_name
;
144 BOOST_PROGRAM_OPTIONS_DECL
145 void store(const wparsed_options
& options
, variables_map
& m
)
147 store(options
.utf8_encoded_options
, m
, true);
150 BOOST_PROGRAM_OPTIONS_DECL
151 void notify(variables_map
& vm
)
156 abstract_variables_map::abstract_variables_map()
160 abstract_variables_map::
161 abstract_variables_map(const abstract_variables_map
* next
)
165 const variable_value
&
166 abstract_variables_map::operator[](const std::string
& name
) const
168 const variable_value
& v
= get(name
);
169 if (v
.empty() && m_next
)
170 return (*m_next
)[name
];
171 else if (v
.defaulted() && m_next
) {
172 const variable_value
& v2
= (*m_next
)[name
];
173 if (!v2
.empty() && !v2
.defaulted())
182 abstract_variables_map::next(abstract_variables_map
* next
)
187 variables_map::variables_map()
190 variables_map::variables_map(const abstract_variables_map
* next
)
191 : abstract_variables_map(next
)
194 void variables_map::clear()
196 std::map
<std::string
, variable_value
>::clear();
201 const variable_value
&
202 variables_map::get(const std::string
& name
) const
204 static variable_value empty
;
205 const_iterator i
= this->find(name
);
206 if (i
== this->end())
213 variables_map::notify()
215 // This checks if all required options occur
216 for (map
<string
, string
>::const_iterator r
= m_required
.begin();
217 r
!= m_required
.end();
220 const string
& opt
= r
->first
;
221 const string
& display_opt
= r
->second
;
222 map
<string
, variable_value
>::const_iterator iter
= find(opt
);
223 if (iter
== end() || iter
->second
.empty())
225 boost::throw_exception(required_option(display_opt
));
230 // Lastly, run notify actions.
231 for (map
<string
, variable_value
>::iterator k
= begin();
235 /* Users might wish to use variables_map to store their own values
236 that are not parsed, and therefore will not have value_semantics
237 defined. Do not crash on such values. In multi-module programs,
238 one module might add custom values, and the 'notify' function
239 will be called after that, so we check that value_sematics is
241 https://svn.boost.org/trac/boost/ticket/2782
243 if (k
->second
.m_value_semantic
)
244 k
->second
.m_value_semantic
->notify(k
->second
.value());