~ubuntu-branches/ubuntu/vivid/bino/vivid-proposed

« back to all changes in this revision

Viewing changes to src/base/opt.h

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Schaal
  • Date: 2011-09-09 14:23:54 UTC
  • Revision ID: james.westby@ubuntu.com-20110909142354-m1a9a4523i7ddb02
Tags: upstream-1.2.0
ImportĀ upstreamĀ versionĀ 1.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of bino, a 3D video player.
 
3
 *
 
4
 * Copyright (C) 2006-2007, 2009-2011
 
5
 * Martin Lambers <marlam@marlam.de>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 3 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#ifndef OPT_H
 
22
#define OPT_H
 
23
 
 
24
#include <sstream>
 
25
#include <vector>
 
26
#include <string>
 
27
#include <cctype>
 
28
#include <cstdio>
 
29
#include <stdint.h>
 
30
 
 
31
 
 
32
/**
 
33
 * \brief Command line parsing
 
34
 *
 
35
 * This module allows quick and easy command line parsing.
 
36
 *
 
37
 * A set of useful default option types is provided, and you can implement your own.
 
38
 *
 
39
 * The idea is to build a vector of the options you want to support,
 
40
 * and the call the opt::parse() function to parse your command line.
 
41
 *
 
42
 * An example:
 
43
 *
 
44
 * opt::info version("version", '\0', opt::optional);
 
45
 * opt::flag verbose("verbose", 'v', opt::optional);
 
46
 * opt::val<int> width("width", 'w', opt::required, 1, 100, 50);
 
47
 *
 
48
 * std::vector<opt::option *> options;
 
49
 * options.push_back(&version);
 
50
 * options.push_back(&verbose);
 
51
 * options.push_back(&width);
 
52
 *
 
53
 * std::vector<std::string> arguments;
 
54
 * opt::parse(argc, argv, options, 1, -1, arguments);
 
55
 */
 
56
 
 
57
namespace opt
 
58
{
 
59
    /**
 
60
     * \brief Option policy
 
61
     *
 
62
     * Policy of an option.
 
63
     */
 
64
    enum option_policy
 
65
    {
 
66
        optional = 0,       /** The option is optional. */
 
67
        required = 1        /** The option is mandatory. */
 
68
    };
 
69
 
 
70
    /**
 
71
     * \brief Option interface
 
72
     *
 
73
     * The interface for options.\n
 
74
     * You can implement your own options by implementing this interface.\n
 
75
     * If the option takes arguments, you should also implement the two
 
76
     * functions value() and values().\n
 
77
     * The function value() should return the parsed argument of the last occurence
 
78
     * of the option, whereas the function values() should return the parsed arguments
 
79
     * of all occurences of the option in a vector. An empty vector indicates that
 
80
     * the option was not given on the command line.\n
 
81
     */
 
82
    class option
 
83
    {
 
84
    private:
 
85
        std::string _longname;
 
86
        char _shortname;
 
87
        option_policy _policy;
 
88
 
 
89
    public:
 
90
        /**
 
91
         * \brief Constructor
 
92
         * \param longname      Long name of the option, or "".
 
93
         * \param shortname     Short name of the option, or '\0'.
 
94
         * \param mandatory     Whether this option is mandatory or optional.
 
95
         */
 
96
        option(const std::string &longname, char shortname, option_policy policy)
 
97
            : _longname(longname), _shortname(shortname), _policy(policy)
 
98
        {
 
99
        }
 
100
 
 
101
        const std::string &longname() const
 
102
        {
 
103
            return _longname;
 
104
        }
 
105
 
 
106
        char shortname() const
 
107
        {
 
108
            return _shortname;
 
109
        }
 
110
 
 
111
        opt::option_policy policy() const
 
112
        {
 
113
            return _policy;
 
114
        }
 
115
 
 
116
        /**
 
117
         * \brief Argument policy
 
118
         *
 
119
         * Argument policy of an option.
 
120
         */
 
121
        enum argument_policy
 
122
        {
 
123
            no_argument = 0,            /** The option takes no argument. */
 
124
            required_argument = 1,      /** The option requires an argument. */
 
125
            optional_argument = 2       /** The option accepts an optional argument. */
 
126
        };
 
127
 
 
128
        /**
 
129
         * \brief Return the argument policy of this option.
 
130
         * \return The argument policy.
 
131
         */
 
132
        virtual enum argument_policy argument_policy() const = 0;
 
133
 
 
134
        /**
 
135
         * \brief Parse an argument to this option (if applicable).
 
136
         * \param argument      The argument. Empty if there is no argument.
 
137
         * \return              Success (true) or failure (false).
 
138
         */
 
139
        virtual bool parse_argument(const std::string &argument) = 0;
 
140
    };
 
141
 
 
142
    /**
 
143
     * \brief Parse the command line.
 
144
     * \param argc              The standard argc parameter.
 
145
     * \param argv              The standard argv parameter.
 
146
     * \param options           A vector with pointers to options.
 
147
     * \param min_arguments     Minimum number of arguments, or -1 if there is no limit.
 
148
     * \param max_arguments     Maximum number of arguments, or -1 if there is no limit.
 
149
     * \param arguments         A vector in which the arguments will be stored.
 
150
     * \return                  Success (true) or failure (false).
 
151
     *
 
152
     * This function parses the command line. It uses GNU's getopt_long()
 
153
     * internally and thus has the same features:\n
 
154
     * - allows abbreviation of long options to their shortest unambiguous prefix
 
155
     * - allows mixing of arguments and options
 
156
     * - space between short option and argument is optional
 
157
     * - arguments to long options can be given with an optional '=' character
 
158
     * - the special argument '--' separates options from arguments
 
159
     * - ...and so on
 
160
     */
 
161
    bool parse(int argc, char *argv[],
 
162
            std::vector<option *> &options,
 
163
            int min_arguments, int max_arguments,
 
164
            std::vector<std::string> &arguments);
 
165
 
 
166
    /**
 
167
     * \brief An option type for informational options.
 
168
     *
 
169
     * This option type is for options such as --help and --version. When such an
 
170
     * option is found, the parser will not test for the presence of mandatory
 
171
     * options or arguments, so that 'prg --help' and 'prg --version' always work.
 
172
     *
 
173
     * The value() function will return whether this option was seen.
 
174
     */
 
175
    class info : public option
 
176
    {
 
177
    private:
 
178
        bool _seen;
 
179
 
 
180
    public:
 
181
        info(const std::string &longname, char shortname, enum option_policy policy)
 
182
            : option(longname, shortname, policy), _seen(false)
 
183
        {
 
184
        }
 
185
 
 
186
        enum argument_policy argument_policy() const
 
187
        {
 
188
            return no_argument;
 
189
        }
 
190
 
 
191
        bool parse_argument(const std::string &)
 
192
        {
 
193
            _seen = true;
 
194
            return true;
 
195
        }
 
196
 
 
197
        bool value() const
 
198
        {
 
199
            return _seen;
 
200
        }
 
201
    };
 
202
 
 
203
    /**
 
204
     * \brief An option type for flags.
 
205
     *
 
206
     * This option type provides flags. A flag may have no argument, in which
 
207
     * case a default argument is assumed, or it may have one of the arguments "true",
 
208
     * "on", "yes" to set the flag, or "false", "off", "no" to unset the flag.
 
209
     */
 
210
    class flag : public option
 
211
    {
 
212
    private:
 
213
        const bool _default_value;
 
214
        const bool _default_argument;
 
215
        std::vector<bool> _values;
 
216
 
 
217
    public:
 
218
        flag(const std::string &longname, char shortname, enum option_policy policy,
 
219
                bool default_value = false, bool default_argument = true)
 
220
            : option(longname, shortname, policy),
 
221
            _default_value(default_value), _default_argument(default_argument)
 
222
        {
 
223
        }
 
224
 
 
225
        enum argument_policy argument_policy() const
 
226
        {
 
227
            return optional_argument;
 
228
        }
 
229
 
 
230
        bool parse_argument(const std::string &argument)
 
231
        {
 
232
            if (argument.empty())
 
233
            {
 
234
                _values.push_back(_default_argument);
 
235
                return true;
 
236
            }
 
237
            else if (argument.compare("on") == 0 || argument.compare("true") == 0 || argument.compare("yes") == 0)
 
238
            {
 
239
                _values.push_back(true);
 
240
                return true;
 
241
            }
 
242
            else if (argument.compare("off") == 0 || argument.compare("false") == 0 || argument.compare("no") == 0)
 
243
            {
 
244
                _values.push_back(false);
 
245
                return true;
 
246
            }
 
247
            else
 
248
            {
 
249
                return false;
 
250
            }
 
251
        }
 
252
 
 
253
        bool value() const
 
254
        {
 
255
            return (_values.size() > 0 ? _values.back() : _default_value);
 
256
        }
 
257
 
 
258
        const std::vector<bool> &values() const
 
259
        {
 
260
            return _values;
 
261
        }
 
262
    };
 
263
 
 
264
    /**
 
265
     * \brief An option type for values.
 
266
     *
 
267
     * This option type allows to parse a value of arbitrary type.\n
 
268
     * The number of allowed values can optionally be restricted:\n
 
269
     * - If a lower and higher bound are given, then only values within this range
 
270
     *   are allowed. Other values will be rejected. The bounds
 
271
     *   are inclusive by default, but can be made exclusive (useful
 
272
     *   for floating point data).
 
273
     * - If a vector of allowed values is given, only these values
 
274
     *   will be allowed, and all other values will be rejected.
 
275
     *
 
276
     * Note that if this option type is used with type std::string,
 
277
     * then the string must not contain spaces. If you need to parse strings with spaces,
 
278
     * use option_string.
 
279
     */
 
280
    template<typename T>
 
281
    class val : public option
 
282
    {
 
283
    private:
 
284
        enum restriction_policy
 
285
        {
 
286
            none,
 
287
            bounds,
 
288
            allowed_values
 
289
        };
 
290
        const restriction_policy _restriction_policy;
 
291
        const T _lower_bound;
 
292
        const bool _lower_bound_inclusive;
 
293
        const T _higher_bound;
 
294
        const bool _higher_bound_inclusive;
 
295
        const std::vector<T> _allowed_values;
 
296
        const T _default_value;
 
297
        std::vector<T> _values;
 
298
 
 
299
    public:
 
300
        val(const std::string &longname, char shortname, enum option_policy policy,
 
301
                const T &lower_bound, const T &higher_bound, const T &default_value = T())
 
302
            : option(longname, shortname, policy),
 
303
            _restriction_policy(bounds),
 
304
            _lower_bound(lower_bound), _lower_bound_inclusive(true),
 
305
            _higher_bound(higher_bound), _higher_bound_inclusive(true),
 
306
            _allowed_values(),
 
307
            _default_value(default_value)
 
308
        {
 
309
        }
 
310
        val(const std::string &longname, char shortname, enum option_policy policy,
 
311
                const T &lower_bound, bool lower_bound_inclusive,
 
312
                const T &higher_bound, bool higher_bound_inclusive,
 
313
                const T &default_value = T())
 
314
            : option(longname, shortname, policy),
 
315
            _restriction_policy(bounds),
 
316
            _lower_bound(lower_bound), _lower_bound_inclusive(lower_bound_inclusive),
 
317
            _higher_bound(higher_bound), _higher_bound_inclusive(higher_bound_inclusive),
 
318
            _allowed_values(),
 
319
            _default_value(default_value)
 
320
        {
 
321
        }
 
322
        val(const std::string &longname, char shortname, enum option_policy policy,
 
323
                const std::vector<T> &allowed_values, const T &default_value = T())
 
324
            : option(longname, shortname, policy),
 
325
            _restriction_policy(val::allowed_values),
 
326
            _lower_bound(), _lower_bound_inclusive(),
 
327
            _higher_bound(), _higher_bound_inclusive(),
 
328
            _allowed_values(allowed_values),
 
329
            _default_value(default_value)
 
330
        {
 
331
        }
 
332
        val(const std::string &longname, char shortname, enum option_policy policy,
 
333
                const T &default_value = T())
 
334
            : option(longname, shortname, policy),
 
335
            _restriction_policy(none),
 
336
            _lower_bound(), _lower_bound_inclusive(),
 
337
            _higher_bound(), _higher_bound_inclusive(),
 
338
            _allowed_values(),
 
339
            _default_value(default_value)
 
340
        {
 
341
        }
 
342
 
 
343
        enum argument_policy argument_policy() const
 
344
        {
 
345
            return required_argument;
 
346
        }
 
347
 
 
348
        bool parse_argument(const std::string &argument)
 
349
        {
 
350
            T v;
 
351
            std::istringstream is(argument);
 
352
            bool ok = false;
 
353
 
 
354
            is >> v;
 
355
            if (!is.fail() && is.eof())
 
356
            {
 
357
                if (_restriction_policy == allowed_values)
 
358
                {
 
359
                    for (size_t i = 0; i < _allowed_values.size(); i++)
 
360
                    {
 
361
                        if (_allowed_values[i] <= v && _allowed_values[i] >= v)
 
362
                        {
 
363
                            ok = true;
 
364
                            break;
 
365
                        }
 
366
                    }
 
367
                }
 
368
                else if (_restriction_policy == bounds)
 
369
                {
 
370
                    ok = (((_lower_bound_inclusive && v >= _lower_bound)
 
371
                                || (!_lower_bound_inclusive && v > _lower_bound))
 
372
                            && ((_higher_bound_inclusive && v <= _higher_bound)
 
373
                                || (!_higher_bound_inclusive && v < _higher_bound)));
 
374
                }
 
375
                else // _restriction_policy == none
 
376
                {
 
377
                    ok = true;
 
378
                }
 
379
                if (ok)
 
380
                {
 
381
                    _values.push_back(v);
 
382
                }
 
383
            }
 
384
            return ok;
 
385
        }
 
386
 
 
387
        const T &value() const
 
388
        {
 
389
            return (_values.size() > 0 ? _values.back() : _default_value);
 
390
        }
 
391
 
 
392
        const std::vector<T> &values() const
 
393
        {
 
394
            return _values;
 
395
        }
 
396
    };
 
397
 
 
398
    template<typename T>
 
399
    class tuple : public option
 
400
    {
 
401
    private:
 
402
        enum restriction_policy
 
403
        {
 
404
            none,
 
405
            bounds,
 
406
            allowed_values
 
407
        };
 
408
        const std::string _separator;
 
409
        const bool _size_is_fixed;
 
410
        const size_t _fixed_size;
 
411
        const restriction_policy _restriction_policy;
 
412
        const T _lower_bound;
 
413
        const bool _lower_bound_inclusive;
 
414
        const T _higher_bound;
 
415
        const bool _higher_bound_inclusive;
 
416
        const std::vector<T> _allowed_values;
 
417
        const std::vector<T> _default_value;
 
418
        std::vector<std::vector<T> > _values;
 
419
 
 
420
    public:
 
421
        tuple(const std::string &longname, char shortname, enum option_policy policy,
 
422
                const T &lower_bound, const T &higher_bound,
 
423
                const std::vector<T> &default_value = std::vector<T>(),
 
424
                int fixed_size = -1, const std::string &separator = ",")
 
425
            : option(longname, shortname, policy),
 
426
            _separator(separator), _size_is_fixed(fixed_size >= 0), _fixed_size(fixed_size),
 
427
            _restriction_policy(bounds),
 
428
            _lower_bound(lower_bound), _lower_bound_inclusive(true),
 
429
            _higher_bound(higher_bound), _higher_bound_inclusive(true),
 
430
            _allowed_values(),
 
431
            _default_value(default_value)
 
432
        {
 
433
        }
 
434
        tuple(const std::string &longname, char shortname, enum option_policy policy,
 
435
                const T &lower_bound, bool lower_bound_inclusive,
 
436
                const T &higher_bound, bool higher_bound_inclusive,
 
437
                const std::vector<T> &default_value = std::vector<T>(),
 
438
                int fixed_size = -1, const std::string &separator = ",")
 
439
            : option(longname, shortname, policy),
 
440
            _separator(separator), _size_is_fixed(fixed_size >= 0), _fixed_size(fixed_size),
 
441
            _restriction_policy(bounds),
 
442
            _lower_bound(lower_bound), _lower_bound_inclusive(lower_bound_inclusive),
 
443
            _higher_bound(higher_bound), _higher_bound_inclusive(higher_bound_inclusive),
 
444
            _allowed_values(),
 
445
            _default_value(default_value)
 
446
        {
 
447
        }
 
448
        tuple(const std::string &longname, char shortname, enum option_policy policy,
 
449
                const std::vector<T> &allowed_values,
 
450
                const std::vector<T> &default_value,
 
451
                int fixed_size = -1, const std::string &separator = ",")
 
452
            : option(longname, shortname, policy),
 
453
            _separator(separator), _size_is_fixed(fixed_size >= 0), _fixed_size(fixed_size),
 
454
            _restriction_policy(tuple::allowed_values),
 
455
            _lower_bound(), _lower_bound_inclusive(),
 
456
            _higher_bound(), _higher_bound_inclusive(),
 
457
            _allowed_values(allowed_values),
 
458
            _default_value(default_value)
 
459
        {
 
460
        }
 
461
        tuple(const std::string &longname, char shortname, enum option_policy policy,
 
462
                const std::vector<T> &default_value = std::vector<T>(),
 
463
                int fixed_size = -1, const std::string &separator = ",")
 
464
            : option(longname, shortname, policy),
 
465
            _separator(separator), _size_is_fixed(fixed_size >= 0), _fixed_size(fixed_size),
 
466
            _restriction_policy(none),
 
467
            _lower_bound(), _lower_bound_inclusive(),
 
468
            _higher_bound(), _higher_bound_inclusive(),
 
469
            _allowed_values(),
 
470
            _default_value(default_value)
 
471
        {
 
472
        }
 
473
 
 
474
        enum argument_policy argument_policy() const
 
475
        {
 
476
            return required_argument;
 
477
        }
 
478
 
 
479
        bool parse_argument(const std::string &argument)
 
480
        {
 
481
            std::istringstream is(argument);
 
482
            std::vector<T> vv;
 
483
            if (argument.length() > 0)
 
484
            {
 
485
                do
 
486
                {
 
487
                    T v;
 
488
                    is >> v;
 
489
                    if (is.fail())
 
490
                    {
 
491
                        return false;
 
492
                    }
 
493
                    vv.push_back(v);
 
494
                    if (!is.eof())
 
495
                    {
 
496
                        for (size_t i = 0; i < _separator.length(); i++)
 
497
                        {
 
498
                            char c;
 
499
                            is.get(c);
 
500
                            if (is.fail() || c != _separator[i])
 
501
                            {
 
502
                                return false;
 
503
                            }
 
504
                        }
 
505
                    }
 
506
                }
 
507
                while (!is.eof());
 
508
            }
 
509
            if (_size_is_fixed && vv.size() != _fixed_size)
 
510
            {
 
511
                return false;
 
512
            }
 
513
            if (_restriction_policy == allowed_values)
 
514
            {
 
515
                bool ok = false;
 
516
                for (size_t i = 0; i < _allowed_values.size(); i++)
 
517
                {
 
518
                    for (size_t j = 0; j < vv.size(); j++)
 
519
                    {
 
520
                        if (_allowed_values[i] <= vv[j] && _allowed_values[i] >= vv[j])
 
521
                        {
 
522
                            ok = true;
 
523
                            break;
 
524
                        }
 
525
                    }
 
526
                    if (ok)
 
527
                    {
 
528
                        break;
 
529
                    }
 
530
                }
 
531
                if (!ok)
 
532
                {
 
533
                    return false;
 
534
                }
 
535
            }
 
536
            else if (_restriction_policy == bounds)
 
537
            {
 
538
                for (size_t i = 0; i < vv.size(); i++)
 
539
                {
 
540
                    if ((_lower_bound_inclusive && vv[i] < _lower_bound)
 
541
                            || (!_lower_bound_inclusive && vv[i] <= _lower_bound)
 
542
                            || (_higher_bound_inclusive && vv[i] > _higher_bound)
 
543
                            || (!_higher_bound_inclusive && vv[i] >= _higher_bound))
 
544
                    {
 
545
                        return false;
 
546
                    }
 
547
                }
 
548
            }
 
549
            _values.push_back(vv);
 
550
            return true;
 
551
        }
 
552
 
 
553
        const std::vector<T> &value() const
 
554
        {
 
555
            return (_values.size() > 0 ? _values.back() : _default_value);
 
556
        }
 
557
 
 
558
        const std::vector<std::vector<T> > &values() const
 
559
        {
 
560
            return _values;
 
561
        }
 
562
    };
 
563
 
 
564
    /**
 
565
     * \brief An option type for strings.
 
566
     *
 
567
     * This option type allows to parse arbitrary strings, including spaces.
 
568
     * Optionally, a list of allowed strings can be given, and also a list
 
569
     * of allowed control characters. By default, the string must not contain
 
570
     * control characters.
 
571
     */
 
572
    class string : public option
 
573
    {
 
574
    private:
 
575
        const std::string _allowed_control_chars;
 
576
        const std::vector<std::string> _allowed_values;
 
577
        const std::string _default_value;
 
578
        std::vector<std::string> _values;
 
579
 
 
580
    public:
 
581
        string(const std::string &longname, char shortname, enum option_policy policy,
 
582
                const std::vector<std::string> allowed_values,
 
583
                const std::string &default_value = "")
 
584
            : option(longname, shortname, policy),
 
585
            _allowed_control_chars(""),
 
586
            _allowed_values(allowed_values),
 
587
            _default_value(default_value)
 
588
        {
 
589
        }
 
590
        string(const std::string &longname, char shortname, enum option_policy policy,
 
591
                const std::string &allowed_control_chars,
 
592
                const std::string &default_value)
 
593
            : option(longname, shortname, policy),
 
594
            _allowed_control_chars(allowed_control_chars),
 
595
            _allowed_values(),
 
596
            _default_value(default_value)
 
597
        {
 
598
        }
 
599
        string(const std::string &longname, char shortname, enum option_policy policy,
 
600
                const std::string &default_value = "")
 
601
            : option(longname, shortname, policy),
 
602
            _allowed_control_chars(""),
 
603
            _allowed_values(),
 
604
            _default_value(default_value)
 
605
        {
 
606
        }
 
607
 
 
608
        enum argument_policy argument_policy() const
 
609
        {
 
610
            return required_argument;
 
611
        }
 
612
 
 
613
        bool parse_argument(const std::string &argument)
 
614
        {
 
615
            bool ok;
 
616
            if (_allowed_values.size() > 0)
 
617
            {
 
618
                ok = false;
 
619
                for (size_t i = 0; i < _allowed_values.size(); i++)
 
620
                {
 
621
                    if (argument.compare(_allowed_values[i]) == 0)
 
622
                    {
 
623
                        ok = true;
 
624
                        break;
 
625
                    }
 
626
                }
 
627
            }
 
628
            else
 
629
            {
 
630
                ok = true;
 
631
                for (size_t i = 0; i < argument.length(); i++)
 
632
                {
 
633
                    char c = argument[i];
 
634
                    if (std::iscntrl(c) && _allowed_control_chars.find(c) == std::string::npos)
 
635
                    {
 
636
                        ok = false;
 
637
                        break;
 
638
                    }
 
639
                }
 
640
            }
 
641
            if (ok)
 
642
            {
 
643
                _values.push_back(argument);
 
644
            }
 
645
            return ok;
 
646
        }
 
647
 
 
648
        const std::string &value() const
 
649
        {
 
650
            return (_values.size() > 0 ? _values.back() : _default_value);
 
651
        }
 
652
 
 
653
        const std::vector<std::string> &values() const
 
654
        {
 
655
            return _values;
 
656
        }
 
657
    };
 
658
 
 
659
    /**
 
660
     * \brief An option type for colors.
 
661
     *
 
662
     * This option type accepts colors in the format [AA]RRGGBB. If the alpha
 
663
     * part is omitted, it is set to 255.
 
664
     * Color values are returned in uint32_t BGRA format.
 
665
     */
 
666
    class color : public option
 
667
    {
 
668
    private:
 
669
        uint32_t _default_value;
 
670
        std::vector<uint32_t> _values;
 
671
 
 
672
    public:
 
673
        color(const std::string &longname, char shortname, option_policy policy,
 
674
                uint32_t default_value = 0u)
 
675
            : option(longname, shortname, policy),
 
676
            _default_value(default_value)
 
677
        {
 
678
        }
 
679
 
 
680
        virtual enum argument_policy argument_policy() const
 
681
        {
 
682
            return required_argument;
 
683
        }
 
684
 
 
685
        virtual bool parse_argument(const std::string &argument)
 
686
        {
 
687
            unsigned int a = 255u, r, g, b;
 
688
            if (argument.length() != 8 && argument.length() != 6)
 
689
            {
 
690
                return false;
 
691
            }
 
692
            else if (argument.length() == 8 && std::sscanf(argument.c_str(), "%2x%2x%2x%2x", &a, &r, &g, &b) != 4)
 
693
            {
 
694
                return false;
 
695
            }
 
696
            else if (argument.length() == 6 && std::sscanf(argument.c_str(), "%2x%2x%2x", &r, &g, &b) != 3)
 
697
            {
 
698
                return false;
 
699
            }
 
700
            _values.push_back((a << 24u) | (r << 16u) | (g << 8u) | b);
 
701
            return true;
 
702
        }
 
703
 
 
704
        uint32_t value() const
 
705
        {
 
706
            return (_values.size() > 0 ? _values.back() : _default_value);
 
707
        }
 
708
 
 
709
        const std::vector<uint32_t> &values() const
 
710
        {
 
711
            return _values;
 
712
        }
 
713
    };
 
714
}
 
715
 
 
716
#endif