summaryrefslogtreecommitdiff
path: root/src/parameters_parser.hh
blob: 2ba77c76fb5734f2f0eb235bfa7bec3216c2a426 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifndef parameters_parser_hh_INCLUDED
#define parameters_parser_hh_INCLUDED

#include "string.hh"
#include "memoryview.hh"
#include "exception.hh"

#include <unordered_map>

namespace Kakoune
{

using ParameterList = memoryview<String>;

struct unknown_option : public runtime_error
{
    unknown_option(const String& name)
        : runtime_error("unknown option '" + name + "'") {}
};

struct missing_option_value: public runtime_error
{
    missing_option_value(const String& name)
        : runtime_error("missing value for option '" + name + "'") {}
};

// ParameterParser provides tools to parse command parameters.
// There are 3 types of parameters:
//  * unnamed options, which are accessed by position (ignoring named ones)
//  * named boolean options, which are enabled using '-name' syntax
//  * named string options,  which are defined using '-name value' syntax
struct ParametersParser
{
    // the options defines named options, if they map to true, then
    // they are understood as string options, else they are understood as
    // boolean option.
    ParametersParser(const ParameterList& params,
                     std::unordered_map<String, bool> options);

    // check if a named option (either string or boolean) is specified
    bool has_option(const String& name) const;

    // get a string option value, returns an empty string if the option
    // is not defined
    const String& option_value(const String& name) const;

    // positional parameters count
    size_t positional_count() const;

    struct iterator
    {
    public:
        typedef String            value_type;
        typedef const value_type* pointer;
        typedef const value_type& reference;
        typedef size_t            difference_type;
        typedef std::forward_iterator_tag iterator_category;

        iterator(const ParametersParser& parser, size_t index)
            : m_parser(parser), m_index(index) {}

        const String& operator*() const
        {
            assert(m_parser.m_positional[m_index]);
            return m_parser.m_params[m_index];
        }

        const String* operator->() const
        {
            assert(m_parser.m_positional[m_index]);
            return &m_parser.m_params[m_index];
        }

        iterator& operator++()
        {
           while (m_index < m_parser.m_positional.size() and
                  not m_parser.m_positional[++m_index]) {}
           return *this;
        }

        bool operator==(const iterator& other) const
        {
            return &m_parser == &other.m_parser and m_index == other.m_index;
        }

        bool operator!=(const iterator& other) const
        {
            return &m_parser != &other.m_parser or m_index != other.m_index;
        }

        bool operator<(const iterator& other) const
        {
            assert(&m_parser == &other.m_parser);
            return m_index < other.m_index;
        }

    private:
        const ParametersParser& m_parser;
        size_t                  m_index;
    };

    // access positional parameter by index
    const String& operator[] (size_t index) const;
    // positional parameter begin
    iterator begin() const;
    // positional parameter end
    iterator end() const;

private:
    ParameterList     m_params;
    std::vector<bool> m_positional;
    std::unordered_map<String, bool> m_options;
};

}

#endif // parameters_parser_hh_INCLUDED