• 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

77.08
/libs/core/program_options/include/hpx/program_options/value_semantic.hpp
1
//  Copyright Vladimir Prus 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
#pragma once
8

9
#include <hpx/program_options/config.hpp>
10
#include <hpx/modules/datastructures.hpp>
11
#include <hpx/modules/format.hpp>
12
#include <hpx/program_options/errors.hpp>
13

14
#include <functional>
15
#include <limits>
16
#include <string>
17
#include <vector>
18

19
namespace hpx::program_options {
20

21
    /** Class which specifies how the option's value is to be parsed
22
        and converted into C++ types.
23
    */
24
    HPX_CXX_EXPORT class HPX_CORE_EXPORT value_semantic
25
    {
26
    public:
27
        /** Returns the name of the option. The name is only meaningful
28
            for automatic help message.
29
         */
30
        virtual std::string name() const = 0;
31

32
        /** The minimum number of tokens for this option that
33
            should be present on the command line. */
34
        virtual unsigned min_tokens() const noexcept = 0;
35

36
        /** The maximum number of tokens for this option that
37
            should be present on the command line. */
38
        virtual unsigned max_tokens() const noexcept = 0;
39

40
        /** Returns true if values from different sources should be composed.
41
            Otherwise, value from the first source is used and values from
42
            other sources are discarded.
43
        */
44
        virtual bool is_composing() const = 0;
45

46
        /** Returns true if value must be given. Non-optional value
47

48
        */
49
        virtual bool is_required() const = 0;
50

51
        /** Parses a group of tokens that specify a value of option.
52
            Stores the result in 'value_store', using whatever representation
53
            is desired. May be be called several times if value of the same
54
            option is specified more than once.
55
        */
56
        virtual void parse(hpx::any_nonser& value_store,
57
            std::vector<std::string> const& new_tokens, bool utf8) const = 0;
58

59
        /** Called to assign default value to 'value_store'. Returns
60
            true if default value is assigned, and false if no default
61
            value exists. */
62
        virtual bool apply_default(hpx::any_nonser& value_store) const = 0;
63

64
        /** Called when final value of an option is determined.
65
        */
66
        virtual void notify(hpx::any_nonser const& value_store) const = 0;
67

68
        virtual ~value_semantic() {}
69
    };
70

71
    /** Helper class which perform necessary character conversions in the
72
        'parse' method and forwards the data further.
73
    */
74
    HPX_CXX_EXPORT template <typename Char>
75
    class value_semantic_codecvt_helper
76
    {
77
        // Nothing here. Specializations to follow.
78
    };
79

80
    /** Helper conversion class for values that accept ascii
81
        strings as input.
82
        Overrides the 'parse' method and defines new 'xparse'
83
        method taking std::string. Depending on whether input
84
        to parse is ascii or UTF8, will pass it to xparse unmodified,
85
        or with UTF8->ascii conversion.
86
    */
87
    template <>
88
    class HPX_CORE_EXPORT
89
        value_semantic_codecvt_helper<char> : public value_semantic
90
    {
91
    private:    // base overrides
92
        void parse(hpx::any_nonser& value_store,
93
            std::vector<std::string> const& new_tokens,
94
            bool utf8) const override;
95

96
    protected:    // interface for derived classes.
97
        virtual void xparse(hpx::any_nonser& value_store,
98
            std::vector<std::string> const& new_tokens) const = 0;
99
    };
100

101
    /** Helper conversion class for values that accept ascii
102
        strings as input.
103
        Overrides the 'parse' method and defines new 'xparse'
104
        method taking std::wstring. Depending on whether input
105
        to parse is ascii or UTF8, will recode input to Unicode, or
106
        pass it unmodified.
107
    */
108
    template <>
109
    class HPX_CORE_EXPORT
110
        value_semantic_codecvt_helper<wchar_t> : public value_semantic
111
    {
112
    private:    // base overrides
113
        void parse(hpx::any_nonser& value_store,
114
            std::vector<std::string> const& new_tokens,
115
            bool utf8) const override;
116

117
    protected:    // interface for derived classes.
118
        virtual void xparse(hpx::any_nonser& value_store,
119
            std::vector<std::wstring> const& new_tokens) const = 0;
120
    };
121

122
    /** Class which specifies a simple handling of a value: the value will
123
        have string type and only one token is allowed. */
124
    HPX_CXX_EXPORT class HPX_CORE_EXPORT untyped_value
125
      : public value_semantic_codecvt_helper<char>
126
    {
127
    public:
128
        explicit untyped_value(bool zero_tokens = false)
129
          : m_zero_tokens(zero_tokens)
3,427✔
130
        {
131
        }
132

133
        std::string name() const override;
134

135
        unsigned min_tokens() const noexcept override;
136
        unsigned max_tokens() const noexcept override;
137

138
        bool is_composing() const noexcept override
×
139
        {
140
            return false;
×
141
        }
142

143
        bool is_required() const noexcept override
3,428✔
144
        {
145
            return false;
3,428✔
146
        }
147

148
        /** If 'value_store' is already initialized, or new_tokens
149
            has more than one element, throws. Otherwise, assigns
150
            the first string from 'new_tokens' to 'value_store', without
151
            any modifications.
152
         */
153
        void xparse(hpx::any_nonser& value_store,
154
            std::vector<std::string> const& new_tokens) const override;
155

156
        /** Does nothing. */
157
        bool apply_default(hpx::any_nonser&) const override
3,428✔
158
        {
159
            return false;
3,428✔
160
        }
161

162
        /** Does nothing. */
163
        void notify(hpx::any_nonser const&) const override {}
×
164

165
    private:
166
        bool m_zero_tokens;
167
    };
168

169
    /** Base class for all option that have a fixed type, and are
170
        willing to announce this type to the outside world.
171
        Any 'value_semantics' for which you want to find out the
172
        type can be dynamic_cast-ed to typed_value_base. If conversion
173
        succeeds, the 'type' method can be called.
174
    */
175
    HPX_CXX_EXPORT class typed_value_base
176
    {
177
    public:
178
        // Returns the type of the value described by this
179
        // object.
180
        virtual std::type_info const& value_type() const = 0;
181
        // Not really needed, since deletion from this
182
        // class is silly, but just in case.
183
        virtual ~typed_value_base() = default;
184
    };
185

186
    /** Class which handles value of a specific type. */
187
    HPX_CXX_EXPORT template <typename T, typename Char = char>
188
    class typed_value
189
      : public value_semantic_codecvt_helper<Char>
190
      , public typed_value_base
191
    {
192
    public:
193
        /** Ctor. The 'store_to' parameter tells where to store
194
            the value when it's known. The parameter can be NULL. */
195
        explicit typed_value(T* store_to)
1,913✔
196
          : m_store_to(store_to)
1,913✔
197
          , m_composing(false)
1,913✔
198
          , m_implicit(false)
1,913✔
199
          , m_multitoken(false)
1,913✔
200
          , m_zero_tokens(false)
1,913✔
201
          , m_required(false)
1,913✔
202
        {
203
        }
1,913✔
204

205
        /** Specifies default value, which will be used
206
            if none is explicitly specified. The type 'T' should
207
            provide operator<< for ostream.
208
        */
209
        typed_value* default_value(T const& v)
221✔
210
        {
211
            m_default_value = hpx::any_nonser(v);
223✔
212
            m_default_value_as_text = hpx::util::to_string(v);
221✔
213
            return this;
221✔
214
        }
215

216
        /** Specifies default value, which will be used
217
            if none is explicitly specified. Unlike the above overload,
218
            the type 'T' need not provide operator<< for ostream,
219
            but textual representation of default value must be provided
220
            by the user.
221
        */
222
        typed_value* default_value(T const& v, std::string const& textual)
×
223
        {
224
            m_default_value = hpx::any_nonser(v);
×
225
            m_default_value_as_text = textual;
×
226
            return this;
×
227
        }
228

229
        /** Specifies an implicit value, which will be used
230
            if the option is given, but without an adjacent value.
231
            Using this implies that an explicit value is optional,
232
        */
233
        typed_value* implicit_value(T const& v)
1,358✔
234
        {
235
            m_implicit_value = hpx::any_nonser(v);
1,358✔
236
            m_implicit_value_as_text = hpx::util::to_string(v);
1,358✔
237
            return this;
1,358✔
238
        }
239

240
        /** Specifies the name used to to the value in help message.  */
241
        typed_value* value_name(std::string const& name)
242
        {
243
            m_value_name = name;
244
            return this;
245
        }
246

247
        /** Specifies an implicit value, which will be used
248
            if the option is given, but without an adjacent value.
249
            Using this implies that an explicit value is optional, but if
250
            given, must be strictly adjacent to the option, i.e.: '-ovalue'
251
            or '--option=value'.  Giving '-o' or '--option' will cause the
252
            implicit value to be applied.
253
            Unlike the above overload, the type 'T' need not provide
254
            operator<< for ostream, but textual representation of default
255
            value must be provided by the user.
256
        */
257
        typed_value* implicit_value(T const& v, std::string const& textual)
258
        {
259
            m_implicit_value = hpx::any_nonser(v);
260
            m_implicit_value_as_text = textual;
261
            return this;
262
        }
263

264
        /** Specifies a function to be called when the final value
265
            is determined. */
266
        typed_value* notifier(std::function<void(T const&)> f)
267
        {
268
            m_notifier = f;
269
            return this;
270
        }
271

272
        /** Specifies that the value is composing. See the 'is_composing'
273
            method for explanation.
274
        */
275
        typed_value* composing() noexcept
276
        {
277
            m_composing = true;
873✔
278
            return this;
279
        }
280

281
        /** Specifies that the value can span multiple tokens.
282
        */
283
        typed_value* multitoken() noexcept
284
        {
285
            m_multitoken = true;
97✔
286
            return this;
287
        }
288

289
        /** Specifies that no tokens may be provided as the value of
290
            this option, which means that only presence of the option
291
            is significant. For such option to be useful, either the
292
            'validate' function should be specialized, or the
293
            'implicit_value' method should be also used. In most
294
            cases, you can use the 'bool_switch' function instead of
295
            using this method. */
296
        typed_value* zero_tokens() noexcept
297
        {
298
            m_zero_tokens = true;
×
299
            return this;
300
        }
301

302
        /** Specifies that the value must occur. */
303
        typed_value* required() noexcept
304
        {
305
            m_required = true;
306
            return this;
307
        }
308

309
    public:    // value semantic overrides
310
        std::string name() const override;
311

312
        bool is_composing() const noexcept override
18✔
313
        {
314
            return m_composing;
18✔
315
        }
316

317
        unsigned min_tokens() const noexcept override
36✔
318
        {
319
            if (m_zero_tokens || m_implicit_value.has_value())
36✔
320
            {
321
                return 0;
×
322
            }
323
            else
324
            {
325
                return 1;
326
            }
327
        }
328

329
        unsigned max_tokens() const noexcept override
36✔
330
        {
331
            if (m_multitoken)
36✔
332
            {
333
                return (std::numeric_limits<unsigned>::max)();
334
            }
335
            if (m_zero_tokens)
36✔
336
            {
337
                return 0;
338
            }
339
            return 1;
340
        }
341

36✔
342
        bool is_required() const noexcept override
343
        {
344
            return m_required;
345
        }
1,136✔
346

347
        /** Creates an instance of the 'validator' class and calls
1,136✔
348
            its operator() to perform the actual conversion. */
349
        void xparse(hpx::any_nonser& value_store,
350
            std::vector<std::basic_string<Char>> const& new_tokens)
351
            const override;
352

353
        /** If default value was specified via previous call to
354
            'default_value', stores that value into 'value_store'.
355
            Returns true if default value was stored.
356
        */
357
        bool apply_default(hpx::any_nonser& value_store) const override
358
        {
359
            if (!m_default_value.has_value())
360
            {
1,118✔
361
                return false;
362
            }
1,118✔
363

364
            value_store = m_default_value;
365
            return true;
366
        }
367

60✔
368
        /** If an address of variable to store value was specified
60✔
369
            when creating *this, stores the value there. Otherwise,
370
            does nothing. */
371
        void notify(hpx::any_nonser const& value_store) const override;
372

373
    public:    // typed_value_base overrides
374
        std::type_info const& value_type() const override
375
        {
376
            return typeid(T);
377
        }
×
378

379
    private:
×
380
        T* m_store_to;
381

382
        // Default value is stored as hpx::any_nonser and not
383
        // as boost::optional to avoid unnecessary instantiations.
384
        std::string m_value_name;
385
        hpx::any_nonser m_default_value;
386
        std::string m_default_value_as_text;
387
        hpx::any_nonser m_implicit_value;
388
        std::string m_implicit_value_as_text;
389
        bool m_composing, m_implicit, m_multitoken, m_zero_tokens, m_required;
390
        std::function<void(T const&)> m_notifier;
391
    };
392

393
    /** Creates a typed_value<T> instance. This function is the primary
394
        method to create value_semantic instance for a specific type, which
395
        can later be passed to 'option_description' constructor.
396
        The second overload is used when it's additionally desired to store the
397
        value of option into program variable.
398
    */
399
    HPX_CXX_EXPORT template <typename T>
400
    typed_value<T>* value();
401

402
    /** @overload
403
    */
404
    HPX_CXX_EXPORT template <typename T>
405
    typed_value<T>* value(T* v);
406

407
    /** Creates a typed_value<T> instance. This function is the primary
408
        method to create value_semantic instance for a specific type, which
409
        can later be passed to 'option_description' constructor.
410
    */
411
    HPX_CXX_EXPORT template <typename T>
412
    typed_value<T, wchar_t>* wvalue();
413

414
    /** @overload
415
    */
416
    HPX_CXX_EXPORT template <typename T>
417
    typed_value<T, wchar_t>* wvalue(T* v);
418

419
    /** Works the same way as the 'value<bool>' function, but the created
420
        value_semantic won't accept any explicit value. So, if the option
421
        is present on the command line, the value will be 'true'.
422
    */
423
    HPX_CXX_EXPORT HPX_CORE_EXPORT typed_value<bool>* bool_switch();
424

425
    /** @overload
426
    */
427
    HPX_CXX_EXPORT HPX_CORE_EXPORT typed_value<bool>* bool_switch(bool* v);
428
}    // namespace hpx::program_options
429

430
#include <hpx/program_options/detail/value_semantic.hpp>
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

© 2026 Coveralls, Inc