-
Notifications
You must be signed in to change notification settings - Fork 35
/
flags.cc
76 lines (70 loc) · 1.8 KB
/
flags.cc
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
#include "libpstack/flags.h"
#include <cassert>
namespace pstack {
Flags &
Flags::add( const char *name, int flag, const char *metavar, const char *help, Cb cb) {
if (flag == LONGONLY)
flag = --longVal;
longOptions.push_back({name, metavar != nullptr ? 1 : 0, nullptr, int(flag)});
assert(data.find(flag) == data.end());
auto &datum = data[flag];
datum.helptext = help;
datum.metavar = metavar;
datum.callback = std::move(cb);
return *this;
}
const Flags &
Flags::done()
{
shortOptions = "";
for (auto &opt : longOptions) {
if (opt.val > 0) {
shortOptions += char(opt.val);
if (opt.has_arg != 0)
shortOptions += ':';
}
}
longOptions.push_back({nullptr, 0, nullptr, 0});
return *this;
}
std::ostream &
Flags::dump(std::ostream &os) const
{
for (const auto &opt : longOptions) {
if (opt.name == nullptr)
continue;
const auto &datum = data.at(opt.val);
os << " [";
if (opt.val > 0)
os << "-" << char(opt.val) << "|";
os << "--" << opt.name;
if (opt.has_arg != 0)
os << " <" << datum.metavar << ">";
os << "]\n " << datum.helptext << "\n";
}
return os;
}
const Flags &
Flags::parse(int argc, char **argv) const
{
for (;;) {
int optidx = 0;
int c = getopt_long(argc, argv, shortOptions.c_str(), longOptions.data(), &optidx);
if (c == -1)
break;
if (c == '?') {
dump(std::clog);
throw std::runtime_error(std::string("unknown command line option "));
}
data.at(c).callback(optarg);
}
return *this;
}
const Flags &
Flags::parse(int argc, char **argv)
{
done();
const Flags &f = *this;
return f.parse(argc, argv);
}
}