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