aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/getopt/small/last_getopt_opt.cpp
blob: 9c53312de8b5e03cd95bf4591077f0b0a9f8e0dc (plain) (blame)
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
#include "last_getopt_opt.h"

#include <util/stream/format.h>
#include <util/string/escape.h>
#include <util/generic/ylimits.h>
#include <util/generic/utility.h>
#include <util/generic/algorithm.h>
#include <ctype.h>

namespace NLastGetopt {
    static const TStringBuf ExcludedShortNameChars = "= -\t\n";
    static const TStringBuf ExcludedLongNameChars = "= \t\n";

    bool TOpt::NameIs(const TString& name) const {
        for (const auto& next : LongNames_) {
            if (next == name)
                return true;
        }
        return false;
    }

    bool TOpt::CharIs(char c) const {
        for (auto next : Chars_) {
            if (next == c)
                return true;
        }
        return false;
    }

    char TOpt::GetChar() const {
        if (Chars_.empty())
            ythrow TConfException() << "no char for option " << this->ToShortString();
        return Chars_.at(0);
    }

    char TOpt::GetCharOr0() const {
        if (Chars_.empty())
            return 0;
        return GetChar();
    }

    TString TOpt::GetName() const {
        if (LongNames_.empty())
            ythrow TConfException() << "no name for option " << this->ToShortString();
        return LongNames_.at(0);
    }

    bool TOpt::IsAllowedShortName(unsigned char c) {
        return isprint(c) && TStringBuf::npos == ExcludedShortNameChars.find(c);
    }

    TOpt& TOpt::AddShortName(unsigned char c) {
        if (!IsAllowedShortName(c))
            throw TUsageException() << "option char '" << c << "' is not allowed";
        Chars_.push_back(c);
        return *this;
    }

    bool TOpt::IsAllowedLongName(const TString& name, unsigned char* out) {
        for (size_t i = 0; i != name.size(); ++i) {
            const unsigned char c = name[i];
            if (!isprint(c) || TStringBuf::npos != ExcludedLongNameChars.find(c)) {
                if (nullptr != out)
                    *out = c;
                return false;
            }
        }
        return true;
    }

    TOpt& TOpt::AddLongName(const TString& name) {
        unsigned char c = 0;
        if (!IsAllowedLongName(name, &c))
            throw TUsageException() << "option char '" << c
                                     << "' in long '" << name << "' is not allowed";
        LongNames_.push_back(name);
        return *this;
    }

    namespace NPrivate {
        TString OptToString(char c);

        TString OptToString(const TString& longOption);
    }

    TString TOpt::ToShortString() const {
        if (!LongNames_.empty())
            return NPrivate::OptToString(LongNames_.front());
        if (!Chars_.empty())
            return NPrivate::OptToString(Chars_.front());
        return "?";
    }

    void TOpt::FireHandlers(const TOptsParser* parser) const {
        for (const auto& handler : Handlers_) {
            handler->HandleOpt(parser);
        }
    }

    TOpt& TOpt::IfPresentDisableCompletionFor(const TOpt& opt) {
        if (opt.GetLongNames()) {
            IfPresentDisableCompletionFor(opt.GetName());
        } else {
            IfPresentDisableCompletionFor(opt.GetChar());
        }
        return *this;
    }
}