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

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

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

6.47
/libs/core/program_options/src/value_semantic.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. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
#include <hpx/program_options/config.hpp>
8
#include <hpx/modules/datastructures.hpp>
9
#include <hpx/program_options/detail/cmdline.hpp>
10
#include <hpx/program_options/detail/convert.hpp>
11
#include <hpx/program_options/value_semantic.hpp>
12

13
#include <cctype>
14
#include <cstddef>
15
#include <map>
16
#include <set>
17
#include <string>
18
#include <vector>
19

20
namespace hpx::program_options {
21

22
    namespace {
×
23

24
        std::string convert_value(std::wstring const& s)
25
        {
26
            try
×
27
            {
28
                return detail::to_local_8_bit(s);
29
            }
30
            catch (std::exception const&)
×
31
            {
32
                return "<unrepresentable unicode string>";
33
            }
34
        }
35
    }    // namespace
×
36

37
    void value_semantic_codecvt_helper<char>::parse(
38
        hpx::any_nonser& value_store,
39
        std::vector<std::string> const& new_tokens, bool utf8) const
×
40
    {
41
        if (utf8)
×
42
        {
43
            // Need to convert to local encoding.
×
44
            std::vector<std::string> local_tokens;
×
45
            for (auto const& new_token : new_tokens)
46
            {
47
                std::wstring w = detail::from_utf8(new_token);
48
                local_tokens.emplace_back(detail::to_local_8_bit(w));
483✔
49
            }
50
            xparse(value_store, local_tokens);
51
        }
52
        else
483✔
53
        {
54
            // Already in local encoding, pass unmodified
55
            xparse(value_store, new_tokens);
×
56
        }
×
57
    }
58

×
59
    void value_semantic_codecvt_helper<wchar_t>::parse(
×
60
        hpx::any_nonser& value_store,
61
        std::vector<std::string> const& new_tokens, bool utf8) const
×
62
    {
×
63
        std::vector<std::wstring> tokens;
64
        if (utf8)
65
        {
66
            // Convert from utf8
483✔
67
            for (auto const& new_token : new_tokens)
68
            {
483✔
69
                tokens.emplace_back(detail::from_utf8(new_token));
70
            }
×
71
        }
72
        else
73
        {
74
            // Convert from local encoding
×
75
            for (auto const& new_token : new_tokens)
×
76
            {
77
                tokens.emplace_back(detail::from_local_8_bit(new_token));
78
            }
×
79
        }
80

×
81
        xparse(value_store, tokens);
82
    }
83

84
    std::string arg("arg");
85

86
    std::string untyped_value::name() const
×
87
    {
88
        return arg;
×
89
    }
90

91
    unsigned untyped_value::min_tokens() const noexcept
92
    {
×
93
        if (m_zero_tokens)
×
94
            return 0;
95
        else
96
            return 1;
97
    }
×
98

99
    unsigned untyped_value::max_tokens() const noexcept
×
100
    {
101
        return min_tokens();
102
    }
×
103

104
    void untyped_value::xparse(hpx::any_nonser& value_store,
×
105
        std::vector<std::string> const& new_tokens) const
106
    {
107
        if (value_store.has_value())
×
108
            throw multiple_occurrences();
109
        if (new_tokens.size() > 1)
110
            throw multiple_values();
×
111
        value_store = new_tokens.empty() ? std::string() : new_tokens.front();
112
    }
×
113

114
    typed_value<bool>* bool_switch()
115
    {
×
116
        return bool_switch(nullptr);
117
    }
118

×
119
    typed_value<bool>* bool_switch(bool* v)
×
120
    {
×
121
        auto* r = new typed_value(v);
×
122
        r->default_value(false);
×
123
        r->zero_tokens();
×
124

125
        return r;
×
126
    }
127

×
128
    /* Validates bool value.
129
        hpx::any_nonser of "1", "true", "yes", "on" will be converted to "1".
130
        hpx::any_nonser of "0", "false", "no", "off" will be converted to "0".
×
131
        Case is ignored. The 'xs' vector can either be empty, in which
132
        case the value is 'true', or can contain explicit value.
×
133
    */
×
134
    void validate(
135
        hpx::any_nonser& v, std::vector<std::string> const& xs, bool*, int)
136
    {
×
137
        check_first_occurrence(v);
138
        std::string s(get_single_string(xs, true));
139

140
        for (char& i : s)
141
        {
142
            i = static_cast<char>(std::tolower(i));
143
        }
144

145
        if (s.empty() || s == "on" || s == "yes" || s == "1" || s == "true")
×
146
        {
147
            v = hpx::any_nonser(true);
148
        }
×
149
        else if (s == "off" || s == "no" || s == "0" || s == "false")
×
150
        {
151
            v = hpx::any_nonser(false);
×
152
        }
153
        else
×
154
        {
155
            throw invalid_bool_value(s);
156
        }
×
157
    }
158

×
159
    // This is blatant copy-paste. However, templating this will cause a problem,
160
    // since wstring can't be constructed/compared with char*. We'd need to
×
161
    // create auxiliary 'widen' routine to convert from char* into
162
    // needed string type, and that's more work.
×
163
    void validate(
164
        hpx::any_nonser& v, std::vector<std::wstring> const& xs, bool*, int)
165
    {
166
        check_first_occurrence(v);
×
167
        std::wstring s(get_single_string(xs, true));
168

×
169
        for (wchar_t& i : s)
170
        {
171
            i = static_cast<wchar_t>(tolower(i));
172
        }
173

174
        if (s.empty() || s == L"on" || s == L"yes" || s == L"1" || s == L"true")
175
        {
×
176
            v = hpx::any_nonser(true);
177
        }
178
        else if (s == L"off" || s == L"no" || s == L"0" || s == L"false")
×
179
        {
×
180
            v = hpx::any_nonser(false);
181
        }
×
182
        else
183
        {
×
184
            throw invalid_bool_value(convert_value(s));
185
        }
186
    }
×
187

188
    void validate(hpx::any_nonser& v, std::vector<std::string> const& xs,
×
189
        std::string*, int)
190
    {
×
191
        check_first_occurrence(v);
192
        v = hpx::any_nonser(get_single_string(xs));
×
193
    }
194

195
    void validate(hpx::any_nonser& v, std::vector<std::wstring> const& xs,
196
        std::string*, int)
×
197
    {
198
        check_first_occurrence(v);
×
199
        v = hpx::any_nonser(get_single_string(xs));
200
    }
201

465✔
202
    namespace validators {
203

204
        void check_first_occurrence(hpx::any_nonser const& value)
465✔
205
        {
930✔
206
            if (value.has_value())
465✔
207
                throw multiple_occurrences();
208
        }
209
    }    // namespace validators
×
210

211
    invalid_option_value::invalid_option_value(std::string const& bad_value)
212
      : validation_error(validation_error::invalid_option_value)
×
213
    {
×
214
        set_substitute("value", bad_value);
×
215
    }
216

217
    invalid_option_value::invalid_option_value(std::wstring const& bad_value)
218
      : validation_error(validation_error::invalid_option_value)
219
    {
483✔
220
        set_substitute("value", convert_value(bad_value));
221
    }
483✔
222

×
223
    invalid_bool_value::invalid_bool_value(std::string const& bad_value)
483✔
224
      : validation_error(validation_error::invalid_bool_value)
225
    {
226
        set_substitute("value", bad_value);
×
227
    }
×
228

229
    void ambiguous_option::substitute_placeholders(
×
230
        std::string const& original_error_template) const
×
231
    {
232
        // For short forms, all alternatives must be identical, by
×
233
        //      definition, to the specified option, so we don't need to
×
234
        //      display alternatives
235
        if (m_option_style == command_line_style::allow_dash_for_short ||
×
236
            m_option_style == command_line_style::allow_slash_for_short)
×
237
        {
238
            error_with_option_name::substitute_placeholders(
×
239
                original_error_template);
×
240
            return;
241
        }
×
242

×
243
        std::string error_template = original_error_template;
244
        // remove duplicates using std::set
×
245
        std::set<std::string> alternatives_set(
246
            m_alternatives.begin(), m_alternatives.end());
×
247
        std::vector<std::string> const alternatives_vec(
248
            alternatives_set.begin(), alternatives_set.end());
×
249

×
250
        error_template += " and matches ";
251
        // Being very cautious: should be > 1 alternative!
252
        if (alternatives_vec.size() > 1)
253
        {
×
254
            for (std::size_t i = 0; i < alternatives_vec.size() - 1; ++i)
255
                error_template += "'%prefix%" + alternatives_vec[i] + "', ";
×
256
            error_template += "and ";
×
257
        }
×
258

×
259
        // there is a programming error if multiple options have the same name...
×
260
        if (m_alternatives.size() > 1 && alternatives_vec.size() == 1)
261
            error_template += "different versions of ";
×
262

263
        error_template += "'%prefix%" + alternatives_vec.back() + "'";
264

×
265
        // use inherited logic
266
        error_with_option_name::substitute_placeholders(error_template);
×
267
    }
268

269
    std::string validation_error::get_template(kind_t kind)
×
270
    {
271
        // Initially, store the message in 'const char*' variable,
272
        // to avoid conversion to std::string in all cases.
273
        char const* msg;
274
        switch (kind)
×
275
        {
276
        case invalid_bool_value:
×
277
            msg = "the argument ('%value%') for option '%canonical_option%' is "
×
278
                  "invalid. Valid choices are 'on|off', 'yes|no', '1|0' and "
279
                  "'true|false'";
280
            break;
281
        case invalid_option_value:
282
            msg = "the argument ('%value%') for option '%canonical_option%' is "
×
283
                  "invalid";
284
            break;
×
285
        case multiple_values_not_allowed:
286
            msg = "option '%canonical_option%' only takes a single argument";
287
            break;
288
        case at_least_one_value_required:
289
            msg = "option '%canonical_option%' requires at least one argument";
×
290
            break;
291
        // currently unused
×
292
        case invalid_option:
293
            msg = "option '%canonical_option%' is not valid";
×
294
            break;
295
        default:
×
296
            msg = "unknown error";
297
            break;
298
        }
299
        return msg;
×
300
    }
301
}    // 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