• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #856

28 Dec 2022 02:00AM UTC coverage: 86.602% (+0.05%) from 86.55%
#856

push

StellarBot
Merge #6119

6119: Update CMakeLists.txt r=hkaiser a=khuck

updating the default APEX version


Co-authored-by: Kevin Huck <khuck@cs.uoregon.edu>

174566 of 201573 relevant lines covered (86.6%)

1876093.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.17
/libs/core/program_options/src/variables_map.cpp
1
//  Copyright Vladimir Prus 2002-2004.
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0.
5
//  (See accompanying file LICENSE_1_0.txt
6
//  or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/program_options/config.hpp>
9
#include <hpx/assert.hpp>
10
#include <hpx/datastructures/any.hpp>
11
#include <hpx/program_options/options_description.hpp>
12
#include <hpx/program_options/parsers.hpp>
13
#include <hpx/program_options/value_semantic.hpp>
14
#include <hpx/program_options/variables_map.hpp>
15

16
#include <cstddef>
17
#include <map>
18
#include <memory>
19
#include <set>
20
#include <string>
21
#include <vector>
22

23
namespace hpx::program_options {
24

25
    // First, performs semantic actions for 'oa'. Then, stores in 'm' all
26
    // options that are defined in 'desc'.
27
    HPX_CORE_EXPORT
28
    void store(parsed_options const& options, variables_map& xm, bool utf8)
4,311✔
29
    {
30
        // TODO: what if we have different definition for the same option name
31
        // during different calls 'store'.
32
        HPX_ASSERT(options.description);
4,311✔
33
        options_description const& desc = *options.description;
4,311✔
34

35
        // We need to access map's operator[], not the overridden version
36
        // variables_map. Ehmm.. messy.
37
        std::map<std::string, variable_value>& m = xm;
4,311✔
38

39
        std::set<std::string> new_final;
4,311✔
40

41
        // Declared once, to please Intel in VC++ mode;
42
        std::size_t i;
43

44
        // Declared here so can be used to provide context for exceptions
45
        std::string option_name;
4,311✔
46
        std::string original_token;
4,311✔
47

48
        try
49
        {
50
            // First, convert/store all given options
51
            for (i = 0; i < options.options.size(); ++i)
19,359✔
52
            {
53
                auto const& opts = options.options[i];
15,054✔
54
                option_name = opts.string_key;
15,054✔
55
                // Skip positional options without name
56
                if (option_name.empty())
15,054✔
57
                    continue;
423✔
58

59
                // Ignore unregistered option. The 'unregistered' field can be
60
                // true only if user has explicitly asked to allow unregistered
61
                // options. We can't store them to variables map (lacking any
62
                // information about paring), so just ignore them.
63
                if (opts.unregistered)
14,631✔
64
                    continue;
615✔
65

66
                // If option has final value, skip this assignment
67
                if (xm.m_final.count(option_name))
14,016✔
68
                    continue;
1✔
69

70
                original_token = !opts.original_tokens.empty() ?
28,030✔
71
                    opts.original_tokens[0] :
13,980✔
72
                    "";
35✔
73
                option_description const& d =
14,015✔
74
                    desc.find(option_name, false, false, false);
14,015✔
75

76
                variable_value& v = m[option_name];
14,015✔
77
                if (v.defaulted())
14,015✔
78
                {
79
                    // Explicit assignment here erases defaulted value
80
                    v = variable_value();
2✔
81
                }
2✔
82

83
                d.semantic()->parse(v.value(), opts.value, utf8);
14,015✔
84

85
                v.m_value_semantic = d.semantic();
14,009✔
86

87
                // The option is not composing, and the value is explicitly
88
                // provided. Ignore values of this option for subsequent calls
89
                // to 'store'. We store this to a temporary set, so that several
90
                // assignment inside *this* 'store' call are allowed.
91
                if (!d.semantic()->is_composing())
14,009✔
92
                    new_final.insert(option_name);
11,723✔
93
            }
14,009✔
94
        }
4,311✔
95
        catch (error_with_option_name& e)
96
        {
97
            // add context and rethrow
98
            e.add_context(
12✔
99
                option_name, original_token, options.m_options_prefix);
6✔
100
            throw;
6✔
101
        }
6✔
102

103
        xm.m_final.insert(new_final.begin(), new_final.end());
4,305✔
104

105
        // Second, apply default values and store required options.
106
        std::vector<std::shared_ptr<option_description>> const& all =
4,305✔
107
            desc.options();
4,305✔
108
        for (i = 0; i < all.size(); ++i)
189,420✔
109
        {
110
            option_description const& d = *all[i];
185,115✔
111
            std::string key = d.key("");
185,115✔
112
            // FIXME: this logic relies on knowledge of option_description
113
            // internals. The 'key' is empty if options description contains
114
            // '*'. In that case, default value makes no sense at all.
115
            if (key.empty())
185,115✔
116
            {
117
                continue;
×
118
            }
119
            if (m.count(key) == 0)
185,115✔
120
            {
121
                hpx::any_nonser def;
172,315✔
122
                if (d.semantic()->apply_default(def))
172,315✔
123
                {
124
                    m[key] = variable_value(def, true);
5,550✔
125
                    m[key].m_value_semantic = d.semantic();
5,550✔
126
                }
5,550✔
127
            }
172,315✔
128

129
            // add empty value if this is an required option
130
            if (d.semantic()->is_required())
185,115✔
131
            {
132
                // For option names specified in multiple ways, e.g. on the
133
                // command line, config file etc, the following precedence rules
134
                // apply: "--"  >  ("-" or "/")  >  ""
135
                // Precedence is set conveniently by a single call to length()
136
                std::string canonical_name =
137
                    d.canonical_display_name(options.m_options_prefix);
15✔
138
                if (canonical_name.length() > xm.m_required[key].length())
15✔
139
                    xm.m_required[key] = canonical_name;
11✔
140
            }
15✔
141
        }
185,115✔
142
    }
4,323✔
143

144
    void store(wparsed_options const& options, variables_map& m)
3✔
145
    {
146
        store(options.utf8_encoded_options, m, true);
3✔
147
    }
3✔
148

149
    void notify(variables_map& vm)
4,281✔
150
    {
151
        vm.notify();
4,281✔
152
    }
4,281✔
153

154
    abstract_variables_map::abstract_variables_map()
4,314✔
155
      : m_next(nullptr)
4,314✔
156
    {
4,314✔
157
    }
4,314✔
158

159
    abstract_variables_map::abstract_variables_map(
×
160
        abstract_variables_map const* next)
161
      : m_next(next)
×
162
    {
×
163
    }
×
164

165
    variable_value const& abstract_variables_map::operator[](
16,894✔
166
        std::string const& name) const
167
    {
168
        variable_value const& v = get(name);
16,894✔
169
        if (v.empty() && m_next)
16,894✔
170
            return (*m_next)[name];
×
171
        else if (v.defaulted() && m_next)
16,894✔
172
        {
173
            variable_value const& v2 = (*m_next)[name];
×
174
            if (!v2.empty() && !v2.defaulted())
×
175
                return v2;
×
176
            else
177
                return v;
×
178
        }
179
        else
180
        {
181
            return v;
16,894✔
182
        }
183
    }
16,894✔
184

185
    void abstract_variables_map::next(abstract_variables_map* next)
×
186
    {
187
        m_next = next;
×
188
    }
×
189

190
    variables_map::variables_map() {}
4,314✔
191

192
    variables_map::variables_map(abstract_variables_map const* next)
×
193
      : abstract_variables_map(next)
×
194
    {
×
195
    }
×
196

197
    void variables_map::clear()
×
198
    {
199
        std::map<std::string, variable_value>::clear();
×
200
        m_final.clear();
×
201
        m_required.clear();
×
202
    }
×
203

204
    variable_value const& variables_map::get(std::string const& name) const
16,894✔
205
    {
206
        static variable_value empty;
16,894✔
207
        const_iterator i = this->find(name);
16,894✔
208
        if (i == this->end())
16,894✔
209
            return empty;
×
210
        else
211
            return i->second;
16,894✔
212
    }
16,894✔
213

214
    void variables_map::notify()
4,281✔
215
    {
216
        // This checks if all required options occur
217
        for (std::map<std::string, std::string>::const_iterator r =
4,286✔
218
                 m_required.begin();
4,281✔
219
             r != m_required.end(); ++r)
4,286✔
220
        {
221
            std::string const& opt = r->first;
6✔
222
            std::string const& display_opt = r->second;
6✔
223
            std::map<std::string, variable_value>::const_iterator iter =
224
                find(opt);
6✔
225
            if (iter == end() || iter->second.empty())
6✔
226
            {
227
                throw required_option(display_opt);
1✔
228
            }
229
        }
5✔
230

231
        // Lastly, run notify actions.
232
        for (auto& k : *this)
22,578✔
233
        {
234
            /* Users might wish to use variables_map to store their own values
235
               that are not parsed, and therefore will not have value_semantics
236
               defined. Do not crash on such values. In multi-module programs,
237
               one module might add custom values, and the 'notify' function
238
               will be called after that, so we check that value_sematics is
239
               not NULL. See:
240
                   https://svn.boost.org/trac/boost/ticket/2782
241
            */
242
            if (k.second.m_value_semantic)
18,298✔
243
                k.second.m_value_semantic->notify(k.second.value());
18,298✔
244
        }
245
    }
4,280✔
246
}    // namespace hpx::program_options
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc