Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/program_options/src/variables_map.cpp @ 13

Last change on this file since 13 was 12, checked in by landauf, 17 years ago

added boost

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