| 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 | // First, convert/store all given options |
|---|
| 42 | for (i = 0; i < options.options.size(); ++i) { |
|---|
| 43 | |
|---|
| 44 | const string& name = options.options[i].string_key; |
|---|
| 45 | // Skip positional options without name |
|---|
| 46 | if (name.empty()) |
|---|
| 47 | continue; |
|---|
| 48 | |
|---|
| 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) |
|---|
| 55 | continue; |
|---|
| 56 | |
|---|
| 57 | // If option has final value, skip this assignment |
|---|
| 58 | if (xm.m_final.count(name)) |
|---|
| 59 | continue; |
|---|
| 60 | |
|---|
| 61 | // Ignore options which are not described |
|---|
| 62 | //TODO: consider this. |
|---|
| 63 | //if (desc.count(name) == 0) |
|---|
| 64 | // continue; |
|---|
| 65 | |
|---|
| 66 | const option_description& d = desc.find(name, false); |
|---|
| 67 | |
|---|
| 68 | variable_value& v = m[name]; |
|---|
| 69 | if (v.defaulted()) { |
|---|
| 70 | // Explicit assignment here erases defaulted value |
|---|
| 71 | v = variable_value(); |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | try { |
|---|
| 75 | d.semantic()->parse(v.value(), options.options[i].value, utf8); |
|---|
| 76 | } |
|---|
| 77 | catch(validation_error& e) |
|---|
| 78 | { |
|---|
| 79 | e.set_option_name(name); |
|---|
| 80 | throw; |
|---|
| 81 | } |
|---|
| 82 | v.m_value_semantic = d.semantic(); |
|---|
| 83 | |
|---|
| 84 | // The option is not composing, and the value is explicitly |
|---|
| 85 | // provided. Ignore values of this option for subsequent |
|---|
| 86 | // calls to 'store'. We store this to a temporary set, |
|---|
| 87 | // so that several assignment inside *this* 'store' call |
|---|
| 88 | // are allowed. |
|---|
| 89 | if (!d.semantic()->is_composing()) |
|---|
| 90 | new_final.insert(name); |
|---|
| 91 | } |
|---|
| 92 | xm.m_final.insert(new_final.begin(), new_final.end()); |
|---|
| 93 | |
|---|
| 94 | |
|---|
| 95 | |
|---|
| 96 | // Second, apply default values. |
|---|
| 97 | const vector<shared_ptr<option_description> >& all = desc.options(); |
|---|
| 98 | for(i = 0; i < all.size(); ++i) |
|---|
| 99 | { |
|---|
| 100 | const option_description& d = *all[i]; |
|---|
| 101 | string key = d.key(""); |
|---|
| 102 | // FIXME: this logic relies on knowledge of option_description |
|---|
| 103 | // internals. |
|---|
| 104 | // The 'key' is empty if options description contains '*'. |
|---|
| 105 | // In that |
|---|
| 106 | // case, default value makes no sense at all. |
|---|
| 107 | if (key.empty()) |
|---|
| 108 | { |
|---|
| 109 | continue; |
|---|
| 110 | } |
|---|
| 111 | if (m.count(key) == 0) { |
|---|
| 112 | |
|---|
| 113 | boost::any def; |
|---|
| 114 | if (d.semantic()->apply_default(def)) { |
|---|
| 115 | m[key] = variable_value(def, true); |
|---|
| 116 | m[key].m_value_semantic = d.semantic(); |
|---|
| 117 | } |
|---|
| 118 | } |
|---|
| 119 | } |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | BOOST_PROGRAM_OPTIONS_DECL |
|---|
| 123 | void store(const wparsed_options& options, variables_map& m) |
|---|
| 124 | { |
|---|
| 125 | store(options.utf8_encoded_options, m, true); |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | BOOST_PROGRAM_OPTIONS_DECL |
|---|
| 129 | void notify(variables_map& vm) |
|---|
| 130 | { |
|---|
| 131 | // Lastly, run notify actions. |
|---|
| 132 | for (map<string, variable_value>::iterator k = vm.begin(); |
|---|
| 133 | k != vm.end(); |
|---|
| 134 | ++k) |
|---|
| 135 | { |
|---|
| 136 | k->second.m_value_semantic->notify(k->second.value()); |
|---|
| 137 | } |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | abstract_variables_map::abstract_variables_map() |
|---|
| 141 | : m_next(0) |
|---|
| 142 | {} |
|---|
| 143 | |
|---|
| 144 | abstract_variables_map:: |
|---|
| 145 | abstract_variables_map(const abstract_variables_map* next) |
|---|
| 146 | : m_next(next) |
|---|
| 147 | {} |
|---|
| 148 | |
|---|
| 149 | const variable_value& |
|---|
| 150 | abstract_variables_map::operator[](const std::string& name) const |
|---|
| 151 | { |
|---|
| 152 | const variable_value& v = get(name); |
|---|
| 153 | if (v.empty() && m_next) |
|---|
| 154 | return (*m_next)[name]; |
|---|
| 155 | else if (v.defaulted() && m_next) { |
|---|
| 156 | const variable_value& v2 = (*m_next)[name]; |
|---|
| 157 | if (!v2.empty() && !v2.defaulted()) |
|---|
| 158 | return v2; |
|---|
| 159 | else return v; |
|---|
| 160 | } else { |
|---|
| 161 | return v; |
|---|
| 162 | } |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | void |
|---|
| 166 | abstract_variables_map::next(abstract_variables_map* next) |
|---|
| 167 | { |
|---|
| 168 | m_next = next; |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | variables_map::variables_map() |
|---|
| 172 | {} |
|---|
| 173 | |
|---|
| 174 | variables_map::variables_map(const abstract_variables_map* next) |
|---|
| 175 | : abstract_variables_map(next) |
|---|
| 176 | {} |
|---|
| 177 | |
|---|
| 178 | const variable_value& |
|---|
| 179 | variables_map::get(const std::string& name) const |
|---|
| 180 | { |
|---|
| 181 | static variable_value empty; |
|---|
| 182 | const_iterator i = this->find(name); |
|---|
| 183 | if (i == this->end()) |
|---|
| 184 | return empty; |
|---|
| 185 | else |
|---|
| 186 | return i->second; |
|---|
| 187 | } |
|---|
| 188 | }} |
|---|