Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/program_options/src/variables_map.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 5.9 KB
Line 
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
16namespace 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}}
Note: See TracBrowser for help on using the repository browser.