card: fix compile warning
[android/external-libkmsxx.git] / kms++util / src / opts.cpp
1 #include <algorithm>
3 #include <unistd.h>
4 #include <getopt.h>
6 #include <kms++util/opts.h>
8 using namespace std;
10 Option::Option(const string& str, function<void()> func)
11         : m_void_func(func)
12 {
13         parse(str);
14 }
16 Option::Option(const string& str, function<void(const string)> func)
17         : m_func(func)
18 {
19         parse(str);
20 }
22 void Option::parse(const string& str)
23 {
24         auto iend = str.end();
25         if (*(iend - 1) == '=') {
26                 iend--;
27                 m_has_arg = 1;
28         } else if (*(iend - 1) == '?') {
29                 iend--;
30                 m_has_arg = 2;
31         } else {
32                 m_has_arg = 0;
33         }
35         auto isplit = find(str.begin(), iend, '|');
37         if (isplit != str.begin())
38                 m_short = str[0];
39         else
40                 m_short = 0;
42         if (isplit != iend)
43                 m_long = string(isplit + 1, iend);
44 }
46 OptionSet::OptionSet(initializer_list<Option> il)
47         : m_opts(il)
48 {
49 }
51 void OptionSet::parse(int argc, char** argv)
52 {
53         string shortopts = ":";
54         vector<struct option> longopts;
56         for (unsigned opt_idx = 0; opt_idx < m_opts.size(); ++opt_idx) {
57                 const Option& o = m_opts[opt_idx];
59                 if (o.m_short != 0) {
60                         shortopts.push_back(o.m_short);
61                         if (o.m_has_arg == 1)
62                                 shortopts.push_back(':');
63                         else if (o.m_has_arg == 2)
64                                 shortopts.append("::");
65                 }
67                 if (!o.m_long.empty()) {
68                         struct option copt;
69                         copt.name = o.m_long.c_str();
70                         copt.has_arg = o.m_has_arg;
71                         copt.flag = 0;
72                         copt.val = opt_idx + 1000;
73                         longopts.push_back(copt);
74                 }
75         }
77         longopts.push_back(option {});
79         while (1) {
80                 int long_idx = 0;
81                 int c = getopt_long(argc, argv, shortopts.c_str(),
82                                     longopts.data(), &long_idx);
83                 if (c == -1)
84                         break;
86                 if (c == '?')
87                         throw std::invalid_argument(string("Unrecognized option ") + argv[optind - 1]);
89                 if (c == ':') {
90                         const Option& o = find_opt(optopt);
91                         if (optopt < 256)
92                                 throw std::invalid_argument(string("Missing argument to -") + o.m_short);
93                         else
94                                 throw std::invalid_argument(string("Missing argument to --") + o.m_long);
95                 }
97                 string sarg = { optarg ?: "" };
99                 const Option& opt = find_opt(c);
101                 if (opt.m_func)
102                         opt.m_func(sarg);
103                 else
104                         opt.m_void_func();
105         }
107         for (int i = optind; i < argc; ++i)
108                 m_params.push_back(argv[i]);
111 const Option& OptionSet::find_opt(int c)
113         if (c < 256)
114                 return *find_if(m_opts.begin(), m_opts.end(), [c](const Option& o) { return o.m_short == c; });
115         else
116                 return m_opts[c - 1000];