summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/libs/program_options/src/variables_map.cpp')
-rw-r--r--3rdParty/Boost/src/libs/program_options/src/variables_map.cpp231
1 files changed, 231 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp b/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp
new file mode 100644
index 0000000..29b1de9
--- /dev/null
+++ b/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp
@@ -0,0 +1,231 @@
+// Copyright Vladimir Prus 2002-2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/value_semantic.hpp>
+#include <boost/program_options/variables_map.hpp>
+
+#include <cassert>
+
+namespace boost { namespace program_options {
+
+ using namespace std;
+
+ // First, performs semantic actions for 'oa'.
+ // Then, stores in 'm' all options that are defined in 'desc'.
+ BOOST_PROGRAM_OPTIONS_DECL
+ void store(const parsed_options& options, variables_map& xm,
+ bool utf8)
+ {
+ // TODO: what if we have different definition
+ // for the same option name during different calls
+ // 'store'.
+ assert(options.description);
+ const options_description& desc = *options.description;
+
+ // We need to access map's operator[], not the overriden version
+ // variables_map. Ehmm.. messy.
+ std::map<std::string, variable_value>& m = xm;
+
+ std::set<std::string> new_final;
+
+ // Declared once, to please Intel in VC++ mode;
+ unsigned i;
+
+ // First, convert/store all given options
+ for (i = 0; i < options.options.size(); ++i) {
+
+ const string& name = options.options[i].string_key;
+ // Skip positional options without name
+ if (name.empty())
+ continue;
+
+ // Ignore unregistered option. The 'unregistered'
+ // field can be true only if user has explicitly asked
+ // to allow unregistered options. We can't store them
+ // to variables map (lacking any information about paring),
+ // so just ignore them.
+ if (options.options[i].unregistered)
+ continue;
+
+ // If option has final value, skip this assignment
+ if (xm.m_final.count(name))
+ continue;
+
+ const option_description& d = desc.find(name, false,
+ false, false);
+
+ variable_value& v = m[name];
+ if (v.defaulted()) {
+ // Explicit assignment here erases defaulted value
+ v = variable_value();
+ }
+
+ try {
+ d.semantic()->parse(v.value(), options.options[i].value, utf8);
+ }
+#ifndef BOOST_NO_EXCEPTIONS
+ catch(validation_error& e)
+ {
+ e.set_option_name(name);
+ throw;
+ }
+ catch(multiple_occurrences& e)
+ {
+ e.set_option_name(name);
+ throw;
+ }
+ catch(multiple_values& e)
+ {
+ e.set_option_name(name);
+ throw;
+ }
+#endif
+ v.m_value_semantic = d.semantic();
+
+ // The option is not composing, and the value is explicitly
+ // provided. Ignore values of this option for subsequent
+ // calls to 'store'. We store this to a temporary set,
+ // so that several assignment inside *this* 'store' call
+ // are allowed.
+ if (!d.semantic()->is_composing())
+ new_final.insert(name);
+ }
+ xm.m_final.insert(new_final.begin(), new_final.end());
+
+
+
+ // Second, apply default values and store required options.
+ const vector<shared_ptr<option_description> >& all = desc.options();
+ for(i = 0; i < all.size(); ++i)
+ {
+ const option_description& d = *all[i];
+ string key = d.key("");
+ // FIXME: this logic relies on knowledge of option_description
+ // internals.
+ // The 'key' is empty if options description contains '*'.
+ // In that
+ // case, default value makes no sense at all.
+ if (key.empty())
+ {
+ continue;
+ }
+ if (m.count(key) == 0) {
+
+ boost::any def;
+ if (d.semantic()->apply_default(def)) {
+ m[key] = variable_value(def, true);
+ m[key].m_value_semantic = d.semantic();
+ }
+ }
+
+ // add empty value if this is an required option
+ if (d.semantic()->is_required()) {
+ xm.m_required.insert(key);
+ }
+ }
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL
+ void store(const wparsed_options& options, variables_map& m)
+ {
+ store(options.utf8_encoded_options, m, true);
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL
+ void notify(variables_map& vm)
+ {
+ vm.notify();
+ }
+
+ abstract_variables_map::abstract_variables_map()
+ : m_next(0)
+ {}
+
+ abstract_variables_map::
+ abstract_variables_map(const abstract_variables_map* next)
+ : m_next(next)
+ {}
+
+ const variable_value&
+ abstract_variables_map::operator[](const std::string& name) const
+ {
+ const variable_value& v = get(name);
+ if (v.empty() && m_next)
+ return (*m_next)[name];
+ else if (v.defaulted() && m_next) {
+ const variable_value& v2 = (*m_next)[name];
+ if (!v2.empty() && !v2.defaulted())
+ return v2;
+ else return v;
+ } else {
+ return v;
+ }
+ }
+
+ void
+ abstract_variables_map::next(abstract_variables_map* next)
+ {
+ m_next = next;
+ }
+
+ variables_map::variables_map()
+ {}
+
+ variables_map::variables_map(const abstract_variables_map* next)
+ : abstract_variables_map(next)
+ {}
+
+ const variable_value&
+ variables_map::get(const std::string& name) const
+ {
+ static variable_value empty;
+ const_iterator i = this->find(name);
+ if (i == this->end())
+ return empty;
+ else
+ return i->second;
+ }
+
+ void
+ variables_map::notify()
+ {
+ // This checks if all required options occur
+ for (set<string>::const_iterator r = m_required.begin();
+ r != m_required.end();
+ ++r)
+ {
+ const string& opt = *r;
+ map<string, variable_value>::const_iterator iter = find(opt);
+ if (iter == end() || iter->second.empty())
+ {
+ boost::throw_exception(required_option(opt));
+
+ }
+ }
+
+ // Lastly, run notify actions.
+ for (map<string, variable_value>::iterator k = begin();
+ k != end();
+ ++k)
+ {
+ /* Users might wish to use variables_map to store their own values
+ that are not parsed, and therefore will not have value_semantics
+ defined. Do no crash on such values. In multi-module programs,
+ one module might add custom values, and the 'notify' function
+ will be called after that, so we check that value_sematics is
+ not NULL. See:
+ https://svn.boost.org/trac/boost/ticket/2782
+ */
+ if (k->second.m_value_semantic)
+ k->second.m_value_semantic->notify(k->second.value());
+ }
+ }
+
+}}