1*89c4ff92SAndroid Build Coastguard Worker /*
2*89c4ff92SAndroid Build Coastguard Worker
3*89c4ff92SAndroid Build Coastguard Worker Copyright (c) 2014, 2015, 2016, 2017 Jarryd Beck
4*89c4ff92SAndroid Build Coastguard Worker
5*89c4ff92SAndroid Build Coastguard Worker SPDX-License-Identifier: MIT
6*89c4ff92SAndroid Build Coastguard Worker
7*89c4ff92SAndroid Build Coastguard Worker Permission is hereby granted, free of charge, to any person obtaining a copy
8*89c4ff92SAndroid Build Coastguard Worker of this software and associated documentation files (the "Software"), to deal
9*89c4ff92SAndroid Build Coastguard Worker in the Software without restriction, including without limitation the rights
10*89c4ff92SAndroid Build Coastguard Worker to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11*89c4ff92SAndroid Build Coastguard Worker copies of the Software, and to permit persons to whom the Software is
12*89c4ff92SAndroid Build Coastguard Worker furnished to do so, subject to the following conditions:
13*89c4ff92SAndroid Build Coastguard Worker
14*89c4ff92SAndroid Build Coastguard Worker The above copyright notice and this permission notice shall be included in
15*89c4ff92SAndroid Build Coastguard Worker all copies or substantial portions of the Software.
16*89c4ff92SAndroid Build Coastguard Worker
17*89c4ff92SAndroid Build Coastguard Worker THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*89c4ff92SAndroid Build Coastguard Worker IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*89c4ff92SAndroid Build Coastguard Worker FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20*89c4ff92SAndroid Build Coastguard Worker AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*89c4ff92SAndroid Build Coastguard Worker LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*89c4ff92SAndroid Build Coastguard Worker OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23*89c4ff92SAndroid Build Coastguard Worker THE SOFTWARE.
24*89c4ff92SAndroid Build Coastguard Worker
25*89c4ff92SAndroid Build Coastguard Worker */
26*89c4ff92SAndroid Build Coastguard Worker
27*89c4ff92SAndroid Build Coastguard Worker #ifndef CXXOPTS_HPP_INCLUDED
28*89c4ff92SAndroid Build Coastguard Worker #define CXXOPTS_HPP_INCLUDED
29*89c4ff92SAndroid Build Coastguard Worker
30*89c4ff92SAndroid Build Coastguard Worker #include <cctype>
31*89c4ff92SAndroid Build Coastguard Worker #include <cstring>
32*89c4ff92SAndroid Build Coastguard Worker #include <exception>
33*89c4ff92SAndroid Build Coastguard Worker #include <iostream>
34*89c4ff92SAndroid Build Coastguard Worker #include <limits>
35*89c4ff92SAndroid Build Coastguard Worker #include <list>
36*89c4ff92SAndroid Build Coastguard Worker #include <map>
37*89c4ff92SAndroid Build Coastguard Worker #include <memory>
38*89c4ff92SAndroid Build Coastguard Worker #include <regex>
39*89c4ff92SAndroid Build Coastguard Worker #include <sstream>
40*89c4ff92SAndroid Build Coastguard Worker #include <string>
41*89c4ff92SAndroid Build Coastguard Worker #include <unordered_map>
42*89c4ff92SAndroid Build Coastguard Worker #include <unordered_set>
43*89c4ff92SAndroid Build Coastguard Worker #include <utility>
44*89c4ff92SAndroid Build Coastguard Worker #include <vector>
45*89c4ff92SAndroid Build Coastguard Worker
46*89c4ff92SAndroid Build Coastguard Worker #ifdef __cpp_lib_optional
47*89c4ff92SAndroid Build Coastguard Worker #include <optional>
48*89c4ff92SAndroid Build Coastguard Worker #define CXXOPTS_HAS_OPTIONAL
49*89c4ff92SAndroid Build Coastguard Worker #endif
50*89c4ff92SAndroid Build Coastguard Worker
51*89c4ff92SAndroid Build Coastguard Worker #if __cplusplus >= 201603L
52*89c4ff92SAndroid Build Coastguard Worker #define CXXOPTS_NODISCARD [[nodiscard]]
53*89c4ff92SAndroid Build Coastguard Worker #else
54*89c4ff92SAndroid Build Coastguard Worker #define CXXOPTS_NODISCARD
55*89c4ff92SAndroid Build Coastguard Worker #endif
56*89c4ff92SAndroid Build Coastguard Worker
57*89c4ff92SAndroid Build Coastguard Worker #ifndef CXXOPTS_VECTOR_DELIMITER
58*89c4ff92SAndroid Build Coastguard Worker #define CXXOPTS_VECTOR_DELIMITER ','
59*89c4ff92SAndroid Build Coastguard Worker #endif
60*89c4ff92SAndroid Build Coastguard Worker
61*89c4ff92SAndroid Build Coastguard Worker #define CXXOPTS__VERSION_MAJOR 3
62*89c4ff92SAndroid Build Coastguard Worker #define CXXOPTS__VERSION_MINOR 0
63*89c4ff92SAndroid Build Coastguard Worker #define CXXOPTS__VERSION_PATCH 0
64*89c4ff92SAndroid Build Coastguard Worker
65*89c4ff92SAndroid Build Coastguard Worker namespace cxxopts
66*89c4ff92SAndroid Build Coastguard Worker {
67*89c4ff92SAndroid Build Coastguard Worker static constexpr struct {
68*89c4ff92SAndroid Build Coastguard Worker uint8_t major, minor, patch;
69*89c4ff92SAndroid Build Coastguard Worker } version = {
70*89c4ff92SAndroid Build Coastguard Worker CXXOPTS__VERSION_MAJOR,
71*89c4ff92SAndroid Build Coastguard Worker CXXOPTS__VERSION_MINOR,
72*89c4ff92SAndroid Build Coastguard Worker CXXOPTS__VERSION_PATCH
73*89c4ff92SAndroid Build Coastguard Worker };
74*89c4ff92SAndroid Build Coastguard Worker } // namespace cxxopts
75*89c4ff92SAndroid Build Coastguard Worker
76*89c4ff92SAndroid Build Coastguard Worker //when we ask cxxopts to use Unicode, help strings are processed using ICU,
77*89c4ff92SAndroid Build Coastguard Worker //which results in the correct lengths being computed for strings when they
78*89c4ff92SAndroid Build Coastguard Worker //are formatted for the help output
79*89c4ff92SAndroid Build Coastguard Worker //it is necessary to make sure that <unicode/unistr.h> can be found by the
80*89c4ff92SAndroid Build Coastguard Worker //compiler, and that icu-uc is linked in to the binary.
81*89c4ff92SAndroid Build Coastguard Worker
82*89c4ff92SAndroid Build Coastguard Worker #ifdef CXXOPTS_USE_UNICODE
83*89c4ff92SAndroid Build Coastguard Worker #include <unicode/unistr.h>
84*89c4ff92SAndroid Build Coastguard Worker
85*89c4ff92SAndroid Build Coastguard Worker namespace cxxopts
86*89c4ff92SAndroid Build Coastguard Worker {
87*89c4ff92SAndroid Build Coastguard Worker typedef icu::UnicodeString String;
88*89c4ff92SAndroid Build Coastguard Worker
89*89c4ff92SAndroid Build Coastguard Worker inline
90*89c4ff92SAndroid Build Coastguard Worker String
toLocalString(std::string s)91*89c4ff92SAndroid Build Coastguard Worker toLocalString(std::string s)
92*89c4ff92SAndroid Build Coastguard Worker {
93*89c4ff92SAndroid Build Coastguard Worker return icu::UnicodeString::fromUTF8(std::move(s));
94*89c4ff92SAndroid Build Coastguard Worker }
95*89c4ff92SAndroid Build Coastguard Worker
96*89c4ff92SAndroid Build Coastguard Worker class UnicodeStringIterator : public
97*89c4ff92SAndroid Build Coastguard Worker std::iterator<std::forward_iterator_tag, int32_t>
98*89c4ff92SAndroid Build Coastguard Worker {
99*89c4ff92SAndroid Build Coastguard Worker public:
100*89c4ff92SAndroid Build Coastguard Worker
UnicodeStringIterator(const icu::UnicodeString * string,int32_t pos)101*89c4ff92SAndroid Build Coastguard Worker UnicodeStringIterator(const icu::UnicodeString* string, int32_t pos)
102*89c4ff92SAndroid Build Coastguard Worker : s(string)
103*89c4ff92SAndroid Build Coastguard Worker , i(pos)
104*89c4ff92SAndroid Build Coastguard Worker {
105*89c4ff92SAndroid Build Coastguard Worker }
106*89c4ff92SAndroid Build Coastguard Worker
107*89c4ff92SAndroid Build Coastguard Worker value_type
operator *() const108*89c4ff92SAndroid Build Coastguard Worker operator*() const
109*89c4ff92SAndroid Build Coastguard Worker {
110*89c4ff92SAndroid Build Coastguard Worker return s->char32At(i);
111*89c4ff92SAndroid Build Coastguard Worker }
112*89c4ff92SAndroid Build Coastguard Worker
113*89c4ff92SAndroid Build Coastguard Worker bool
operator ==(const UnicodeStringIterator & rhs) const114*89c4ff92SAndroid Build Coastguard Worker operator==(const UnicodeStringIterator& rhs) const
115*89c4ff92SAndroid Build Coastguard Worker {
116*89c4ff92SAndroid Build Coastguard Worker return s == rhs.s && i == rhs.i;
117*89c4ff92SAndroid Build Coastguard Worker }
118*89c4ff92SAndroid Build Coastguard Worker
119*89c4ff92SAndroid Build Coastguard Worker bool
operator !=(const UnicodeStringIterator & rhs) const120*89c4ff92SAndroid Build Coastguard Worker operator!=(const UnicodeStringIterator& rhs) const
121*89c4ff92SAndroid Build Coastguard Worker {
122*89c4ff92SAndroid Build Coastguard Worker return !(*this == rhs);
123*89c4ff92SAndroid Build Coastguard Worker }
124*89c4ff92SAndroid Build Coastguard Worker
125*89c4ff92SAndroid Build Coastguard Worker UnicodeStringIterator&
operator ++()126*89c4ff92SAndroid Build Coastguard Worker operator++()
127*89c4ff92SAndroid Build Coastguard Worker {
128*89c4ff92SAndroid Build Coastguard Worker ++i;
129*89c4ff92SAndroid Build Coastguard Worker return *this;
130*89c4ff92SAndroid Build Coastguard Worker }
131*89c4ff92SAndroid Build Coastguard Worker
132*89c4ff92SAndroid Build Coastguard Worker UnicodeStringIterator
operator +(int32_t v)133*89c4ff92SAndroid Build Coastguard Worker operator+(int32_t v)
134*89c4ff92SAndroid Build Coastguard Worker {
135*89c4ff92SAndroid Build Coastguard Worker return UnicodeStringIterator(s, i + v);
136*89c4ff92SAndroid Build Coastguard Worker }
137*89c4ff92SAndroid Build Coastguard Worker
138*89c4ff92SAndroid Build Coastguard Worker private:
139*89c4ff92SAndroid Build Coastguard Worker const icu::UnicodeString* s;
140*89c4ff92SAndroid Build Coastguard Worker int32_t i;
141*89c4ff92SAndroid Build Coastguard Worker };
142*89c4ff92SAndroid Build Coastguard Worker
143*89c4ff92SAndroid Build Coastguard Worker inline
144*89c4ff92SAndroid Build Coastguard Worker String&
stringAppend(String & s,String a)145*89c4ff92SAndroid Build Coastguard Worker stringAppend(String&s, String a)
146*89c4ff92SAndroid Build Coastguard Worker {
147*89c4ff92SAndroid Build Coastguard Worker return s.append(std::move(a));
148*89c4ff92SAndroid Build Coastguard Worker }
149*89c4ff92SAndroid Build Coastguard Worker
150*89c4ff92SAndroid Build Coastguard Worker inline
151*89c4ff92SAndroid Build Coastguard Worker String&
stringAppend(String & s,size_t n,UChar32 c)152*89c4ff92SAndroid Build Coastguard Worker stringAppend(String& s, size_t n, UChar32 c)
153*89c4ff92SAndroid Build Coastguard Worker {
154*89c4ff92SAndroid Build Coastguard Worker for (size_t i = 0; i != n; ++i)
155*89c4ff92SAndroid Build Coastguard Worker {
156*89c4ff92SAndroid Build Coastguard Worker s.append(c);
157*89c4ff92SAndroid Build Coastguard Worker }
158*89c4ff92SAndroid Build Coastguard Worker
159*89c4ff92SAndroid Build Coastguard Worker return s;
160*89c4ff92SAndroid Build Coastguard Worker }
161*89c4ff92SAndroid Build Coastguard Worker
162*89c4ff92SAndroid Build Coastguard Worker template <typename Iterator>
163*89c4ff92SAndroid Build Coastguard Worker String&
stringAppend(String & s,Iterator begin,Iterator end)164*89c4ff92SAndroid Build Coastguard Worker stringAppend(String& s, Iterator begin, Iterator end)
165*89c4ff92SAndroid Build Coastguard Worker {
166*89c4ff92SAndroid Build Coastguard Worker while (begin != end)
167*89c4ff92SAndroid Build Coastguard Worker {
168*89c4ff92SAndroid Build Coastguard Worker s.append(*begin);
169*89c4ff92SAndroid Build Coastguard Worker ++begin;
170*89c4ff92SAndroid Build Coastguard Worker }
171*89c4ff92SAndroid Build Coastguard Worker
172*89c4ff92SAndroid Build Coastguard Worker return s;
173*89c4ff92SAndroid Build Coastguard Worker }
174*89c4ff92SAndroid Build Coastguard Worker
175*89c4ff92SAndroid Build Coastguard Worker inline
176*89c4ff92SAndroid Build Coastguard Worker size_t
stringLength(const String & s)177*89c4ff92SAndroid Build Coastguard Worker stringLength(const String& s)
178*89c4ff92SAndroid Build Coastguard Worker {
179*89c4ff92SAndroid Build Coastguard Worker return s.length();
180*89c4ff92SAndroid Build Coastguard Worker }
181*89c4ff92SAndroid Build Coastguard Worker
182*89c4ff92SAndroid Build Coastguard Worker inline
183*89c4ff92SAndroid Build Coastguard Worker std::string
toUTF8String(const String & s)184*89c4ff92SAndroid Build Coastguard Worker toUTF8String(const String& s)
185*89c4ff92SAndroid Build Coastguard Worker {
186*89c4ff92SAndroid Build Coastguard Worker std::string result;
187*89c4ff92SAndroid Build Coastguard Worker s.toUTF8String(result);
188*89c4ff92SAndroid Build Coastguard Worker
189*89c4ff92SAndroid Build Coastguard Worker return result;
190*89c4ff92SAndroid Build Coastguard Worker }
191*89c4ff92SAndroid Build Coastguard Worker
192*89c4ff92SAndroid Build Coastguard Worker inline
193*89c4ff92SAndroid Build Coastguard Worker bool
empty(const String & s)194*89c4ff92SAndroid Build Coastguard Worker empty(const String& s)
195*89c4ff92SAndroid Build Coastguard Worker {
196*89c4ff92SAndroid Build Coastguard Worker return s.isEmpty();
197*89c4ff92SAndroid Build Coastguard Worker }
198*89c4ff92SAndroid Build Coastguard Worker }
199*89c4ff92SAndroid Build Coastguard Worker
200*89c4ff92SAndroid Build Coastguard Worker namespace std
201*89c4ff92SAndroid Build Coastguard Worker {
202*89c4ff92SAndroid Build Coastguard Worker inline
203*89c4ff92SAndroid Build Coastguard Worker cxxopts::UnicodeStringIterator
begin(const icu::UnicodeString & s)204*89c4ff92SAndroid Build Coastguard Worker begin(const icu::UnicodeString& s)
205*89c4ff92SAndroid Build Coastguard Worker {
206*89c4ff92SAndroid Build Coastguard Worker return cxxopts::UnicodeStringIterator(&s, 0);
207*89c4ff92SAndroid Build Coastguard Worker }
208*89c4ff92SAndroid Build Coastguard Worker
209*89c4ff92SAndroid Build Coastguard Worker inline
210*89c4ff92SAndroid Build Coastguard Worker cxxopts::UnicodeStringIterator
end(const icu::UnicodeString & s)211*89c4ff92SAndroid Build Coastguard Worker end(const icu::UnicodeString& s)
212*89c4ff92SAndroid Build Coastguard Worker {
213*89c4ff92SAndroid Build Coastguard Worker return cxxopts::UnicodeStringIterator(&s, s.length());
214*89c4ff92SAndroid Build Coastguard Worker }
215*89c4ff92SAndroid Build Coastguard Worker }
216*89c4ff92SAndroid Build Coastguard Worker
217*89c4ff92SAndroid Build Coastguard Worker //ifdef CXXOPTS_USE_UNICODE
218*89c4ff92SAndroid Build Coastguard Worker #else
219*89c4ff92SAndroid Build Coastguard Worker
220*89c4ff92SAndroid Build Coastguard Worker namespace cxxopts
221*89c4ff92SAndroid Build Coastguard Worker {
222*89c4ff92SAndroid Build Coastguard Worker typedef std::string String;
223*89c4ff92SAndroid Build Coastguard Worker
224*89c4ff92SAndroid Build Coastguard Worker template <typename T>
225*89c4ff92SAndroid Build Coastguard Worker T
toLocalString(T && t)226*89c4ff92SAndroid Build Coastguard Worker toLocalString(T&& t)
227*89c4ff92SAndroid Build Coastguard Worker {
228*89c4ff92SAndroid Build Coastguard Worker return std::forward<T>(t);
229*89c4ff92SAndroid Build Coastguard Worker }
230*89c4ff92SAndroid Build Coastguard Worker
231*89c4ff92SAndroid Build Coastguard Worker inline
232*89c4ff92SAndroid Build Coastguard Worker size_t
stringLength(const String & s)233*89c4ff92SAndroid Build Coastguard Worker stringLength(const String& s)
234*89c4ff92SAndroid Build Coastguard Worker {
235*89c4ff92SAndroid Build Coastguard Worker return s.length();
236*89c4ff92SAndroid Build Coastguard Worker }
237*89c4ff92SAndroid Build Coastguard Worker
238*89c4ff92SAndroid Build Coastguard Worker inline
239*89c4ff92SAndroid Build Coastguard Worker String&
stringAppend(String & s,const String & a)240*89c4ff92SAndroid Build Coastguard Worker stringAppend(String&s, const String& a)
241*89c4ff92SAndroid Build Coastguard Worker {
242*89c4ff92SAndroid Build Coastguard Worker return s.append(a);
243*89c4ff92SAndroid Build Coastguard Worker }
244*89c4ff92SAndroid Build Coastguard Worker
245*89c4ff92SAndroid Build Coastguard Worker inline
246*89c4ff92SAndroid Build Coastguard Worker String&
stringAppend(String & s,size_t n,char c)247*89c4ff92SAndroid Build Coastguard Worker stringAppend(String& s, size_t n, char c)
248*89c4ff92SAndroid Build Coastguard Worker {
249*89c4ff92SAndroid Build Coastguard Worker return s.append(n, c);
250*89c4ff92SAndroid Build Coastguard Worker }
251*89c4ff92SAndroid Build Coastguard Worker
252*89c4ff92SAndroid Build Coastguard Worker template <typename Iterator>
253*89c4ff92SAndroid Build Coastguard Worker String&
stringAppend(String & s,Iterator begin,Iterator end)254*89c4ff92SAndroid Build Coastguard Worker stringAppend(String& s, Iterator begin, Iterator end)
255*89c4ff92SAndroid Build Coastguard Worker {
256*89c4ff92SAndroid Build Coastguard Worker return s.append(begin, end);
257*89c4ff92SAndroid Build Coastguard Worker }
258*89c4ff92SAndroid Build Coastguard Worker
259*89c4ff92SAndroid Build Coastguard Worker template <typename T>
260*89c4ff92SAndroid Build Coastguard Worker std::string
toUTF8String(T && t)261*89c4ff92SAndroid Build Coastguard Worker toUTF8String(T&& t)
262*89c4ff92SAndroid Build Coastguard Worker {
263*89c4ff92SAndroid Build Coastguard Worker return std::forward<T>(t);
264*89c4ff92SAndroid Build Coastguard Worker }
265*89c4ff92SAndroid Build Coastguard Worker
266*89c4ff92SAndroid Build Coastguard Worker inline
267*89c4ff92SAndroid Build Coastguard Worker bool
empty(const std::string & s)268*89c4ff92SAndroid Build Coastguard Worker empty(const std::string& s)
269*89c4ff92SAndroid Build Coastguard Worker {
270*89c4ff92SAndroid Build Coastguard Worker return s.empty();
271*89c4ff92SAndroid Build Coastguard Worker }
272*89c4ff92SAndroid Build Coastguard Worker } // namespace cxxopts
273*89c4ff92SAndroid Build Coastguard Worker
274*89c4ff92SAndroid Build Coastguard Worker //ifdef CXXOPTS_USE_UNICODE
275*89c4ff92SAndroid Build Coastguard Worker #endif
276*89c4ff92SAndroid Build Coastguard Worker
277*89c4ff92SAndroid Build Coastguard Worker namespace cxxopts
278*89c4ff92SAndroid Build Coastguard Worker {
279*89c4ff92SAndroid Build Coastguard Worker namespace
280*89c4ff92SAndroid Build Coastguard Worker {
281*89c4ff92SAndroid Build Coastguard Worker #ifdef _WIN32
282*89c4ff92SAndroid Build Coastguard Worker const std::string LQUOTE("\'");
283*89c4ff92SAndroid Build Coastguard Worker const std::string RQUOTE("\'");
284*89c4ff92SAndroid Build Coastguard Worker #else
285*89c4ff92SAndroid Build Coastguard Worker const std::string LQUOTE("‘");
286*89c4ff92SAndroid Build Coastguard Worker const std::string RQUOTE("’");
287*89c4ff92SAndroid Build Coastguard Worker #endif
288*89c4ff92SAndroid Build Coastguard Worker } // namespace
289*89c4ff92SAndroid Build Coastguard Worker
290*89c4ff92SAndroid Build Coastguard Worker #if defined(__GNUC__)
291*89c4ff92SAndroid Build Coastguard Worker // GNU GCC with -Weffc++ will issue a warning regarding the upcoming class, we want to silence it:
292*89c4ff92SAndroid Build Coastguard Worker // warning: base class 'class std::enable_shared_from_this<cxxopts::Value>' has accessible non-virtual destructor
293*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
294*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic push
295*89c4ff92SAndroid Build Coastguard Worker // This will be ignored under other compilers like LLVM clang.
296*89c4ff92SAndroid Build Coastguard Worker #endif
297*89c4ff92SAndroid Build Coastguard Worker class Value : public std::enable_shared_from_this<Value>
298*89c4ff92SAndroid Build Coastguard Worker {
299*89c4ff92SAndroid Build Coastguard Worker public:
300*89c4ff92SAndroid Build Coastguard Worker
301*89c4ff92SAndroid Build Coastguard Worker virtual ~Value() = default;
302*89c4ff92SAndroid Build Coastguard Worker
303*89c4ff92SAndroid Build Coastguard Worker virtual
304*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
305*89c4ff92SAndroid Build Coastguard Worker clone() const = 0;
306*89c4ff92SAndroid Build Coastguard Worker
307*89c4ff92SAndroid Build Coastguard Worker virtual void
308*89c4ff92SAndroid Build Coastguard Worker parse(const std::string& text) const = 0;
309*89c4ff92SAndroid Build Coastguard Worker
310*89c4ff92SAndroid Build Coastguard Worker virtual void
311*89c4ff92SAndroid Build Coastguard Worker parse() const = 0;
312*89c4ff92SAndroid Build Coastguard Worker
313*89c4ff92SAndroid Build Coastguard Worker virtual bool
314*89c4ff92SAndroid Build Coastguard Worker has_default() const = 0;
315*89c4ff92SAndroid Build Coastguard Worker
316*89c4ff92SAndroid Build Coastguard Worker virtual bool
317*89c4ff92SAndroid Build Coastguard Worker is_container() const = 0;
318*89c4ff92SAndroid Build Coastguard Worker
319*89c4ff92SAndroid Build Coastguard Worker virtual bool
320*89c4ff92SAndroid Build Coastguard Worker has_implicit() const = 0;
321*89c4ff92SAndroid Build Coastguard Worker
322*89c4ff92SAndroid Build Coastguard Worker virtual std::string
323*89c4ff92SAndroid Build Coastguard Worker get_default_value() const = 0;
324*89c4ff92SAndroid Build Coastguard Worker
325*89c4ff92SAndroid Build Coastguard Worker virtual std::string
326*89c4ff92SAndroid Build Coastguard Worker get_implicit_value() const = 0;
327*89c4ff92SAndroid Build Coastguard Worker
328*89c4ff92SAndroid Build Coastguard Worker virtual std::shared_ptr<Value>
329*89c4ff92SAndroid Build Coastguard Worker default_value(const std::string& value) = 0;
330*89c4ff92SAndroid Build Coastguard Worker
331*89c4ff92SAndroid Build Coastguard Worker virtual std::shared_ptr<Value>
332*89c4ff92SAndroid Build Coastguard Worker implicit_value(const std::string& value) = 0;
333*89c4ff92SAndroid Build Coastguard Worker
334*89c4ff92SAndroid Build Coastguard Worker virtual std::shared_ptr<Value>
335*89c4ff92SAndroid Build Coastguard Worker no_implicit_value() = 0;
336*89c4ff92SAndroid Build Coastguard Worker
337*89c4ff92SAndroid Build Coastguard Worker virtual bool
338*89c4ff92SAndroid Build Coastguard Worker is_boolean() const = 0;
339*89c4ff92SAndroid Build Coastguard Worker };
340*89c4ff92SAndroid Build Coastguard Worker #if defined(__GNUC__)
341*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
342*89c4ff92SAndroid Build Coastguard Worker #endif
343*89c4ff92SAndroid Build Coastguard Worker class OptionException : public std::exception
344*89c4ff92SAndroid Build Coastguard Worker {
345*89c4ff92SAndroid Build Coastguard Worker public:
OptionException(std::string message)346*89c4ff92SAndroid Build Coastguard Worker explicit OptionException(std::string message)
347*89c4ff92SAndroid Build Coastguard Worker : m_message(std::move(message))
348*89c4ff92SAndroid Build Coastguard Worker {
349*89c4ff92SAndroid Build Coastguard Worker }
350*89c4ff92SAndroid Build Coastguard Worker
351*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
352*89c4ff92SAndroid Build Coastguard Worker const char*
what() const353*89c4ff92SAndroid Build Coastguard Worker what() const noexcept override
354*89c4ff92SAndroid Build Coastguard Worker {
355*89c4ff92SAndroid Build Coastguard Worker return m_message.c_str();
356*89c4ff92SAndroid Build Coastguard Worker }
357*89c4ff92SAndroid Build Coastguard Worker
358*89c4ff92SAndroid Build Coastguard Worker private:
359*89c4ff92SAndroid Build Coastguard Worker std::string m_message;
360*89c4ff92SAndroid Build Coastguard Worker };
361*89c4ff92SAndroid Build Coastguard Worker
362*89c4ff92SAndroid Build Coastguard Worker class OptionSpecException : public OptionException
363*89c4ff92SAndroid Build Coastguard Worker {
364*89c4ff92SAndroid Build Coastguard Worker public:
365*89c4ff92SAndroid Build Coastguard Worker
OptionSpecException(const std::string & message)366*89c4ff92SAndroid Build Coastguard Worker explicit OptionSpecException(const std::string& message)
367*89c4ff92SAndroid Build Coastguard Worker : OptionException(message)
368*89c4ff92SAndroid Build Coastguard Worker {
369*89c4ff92SAndroid Build Coastguard Worker }
370*89c4ff92SAndroid Build Coastguard Worker };
371*89c4ff92SAndroid Build Coastguard Worker
372*89c4ff92SAndroid Build Coastguard Worker class OptionParseException : public OptionException
373*89c4ff92SAndroid Build Coastguard Worker {
374*89c4ff92SAndroid Build Coastguard Worker public:
OptionParseException(const std::string & message)375*89c4ff92SAndroid Build Coastguard Worker explicit OptionParseException(const std::string& message)
376*89c4ff92SAndroid Build Coastguard Worker : OptionException(message)
377*89c4ff92SAndroid Build Coastguard Worker {
378*89c4ff92SAndroid Build Coastguard Worker }
379*89c4ff92SAndroid Build Coastguard Worker };
380*89c4ff92SAndroid Build Coastguard Worker
381*89c4ff92SAndroid Build Coastguard Worker class option_exists_error : public OptionSpecException
382*89c4ff92SAndroid Build Coastguard Worker {
383*89c4ff92SAndroid Build Coastguard Worker public:
option_exists_error(const std::string & option)384*89c4ff92SAndroid Build Coastguard Worker explicit option_exists_error(const std::string& option)
385*89c4ff92SAndroid Build Coastguard Worker : OptionSpecException("Option " + LQUOTE + option + RQUOTE + " already exists")
386*89c4ff92SAndroid Build Coastguard Worker {
387*89c4ff92SAndroid Build Coastguard Worker }
388*89c4ff92SAndroid Build Coastguard Worker };
389*89c4ff92SAndroid Build Coastguard Worker
390*89c4ff92SAndroid Build Coastguard Worker class invalid_option_format_error : public OptionSpecException
391*89c4ff92SAndroid Build Coastguard Worker {
392*89c4ff92SAndroid Build Coastguard Worker public:
invalid_option_format_error(const std::string & format)393*89c4ff92SAndroid Build Coastguard Worker explicit invalid_option_format_error(const std::string& format)
394*89c4ff92SAndroid Build Coastguard Worker : OptionSpecException("Invalid option format " + LQUOTE + format + RQUOTE)
395*89c4ff92SAndroid Build Coastguard Worker {
396*89c4ff92SAndroid Build Coastguard Worker }
397*89c4ff92SAndroid Build Coastguard Worker };
398*89c4ff92SAndroid Build Coastguard Worker
399*89c4ff92SAndroid Build Coastguard Worker class option_syntax_exception : public OptionParseException {
400*89c4ff92SAndroid Build Coastguard Worker public:
option_syntax_exception(const std::string & text)401*89c4ff92SAndroid Build Coastguard Worker explicit option_syntax_exception(const std::string& text)
402*89c4ff92SAndroid Build Coastguard Worker : OptionParseException("Argument " + LQUOTE + text + RQUOTE +
403*89c4ff92SAndroid Build Coastguard Worker " starts with a - but has incorrect syntax")
404*89c4ff92SAndroid Build Coastguard Worker {
405*89c4ff92SAndroid Build Coastguard Worker }
406*89c4ff92SAndroid Build Coastguard Worker };
407*89c4ff92SAndroid Build Coastguard Worker
408*89c4ff92SAndroid Build Coastguard Worker class option_not_exists_exception : public OptionParseException
409*89c4ff92SAndroid Build Coastguard Worker {
410*89c4ff92SAndroid Build Coastguard Worker public:
option_not_exists_exception(const std::string & option)411*89c4ff92SAndroid Build Coastguard Worker explicit option_not_exists_exception(const std::string& option)
412*89c4ff92SAndroid Build Coastguard Worker : OptionParseException("Option " + LQUOTE + option + RQUOTE + " does not exist")
413*89c4ff92SAndroid Build Coastguard Worker {
414*89c4ff92SAndroid Build Coastguard Worker }
415*89c4ff92SAndroid Build Coastguard Worker };
416*89c4ff92SAndroid Build Coastguard Worker
417*89c4ff92SAndroid Build Coastguard Worker class missing_argument_exception : public OptionParseException
418*89c4ff92SAndroid Build Coastguard Worker {
419*89c4ff92SAndroid Build Coastguard Worker public:
missing_argument_exception(const std::string & option)420*89c4ff92SAndroid Build Coastguard Worker explicit missing_argument_exception(const std::string& option)
421*89c4ff92SAndroid Build Coastguard Worker : OptionParseException(
422*89c4ff92SAndroid Build Coastguard Worker "Option " + LQUOTE + option + RQUOTE + " is missing an argument"
423*89c4ff92SAndroid Build Coastguard Worker )
424*89c4ff92SAndroid Build Coastguard Worker {
425*89c4ff92SAndroid Build Coastguard Worker }
426*89c4ff92SAndroid Build Coastguard Worker };
427*89c4ff92SAndroid Build Coastguard Worker
428*89c4ff92SAndroid Build Coastguard Worker class option_requires_argument_exception : public OptionParseException
429*89c4ff92SAndroid Build Coastguard Worker {
430*89c4ff92SAndroid Build Coastguard Worker public:
option_requires_argument_exception(const std::string & option)431*89c4ff92SAndroid Build Coastguard Worker explicit option_requires_argument_exception(const std::string& option)
432*89c4ff92SAndroid Build Coastguard Worker : OptionParseException(
433*89c4ff92SAndroid Build Coastguard Worker "Option " + LQUOTE + option + RQUOTE + " requires an argument"
434*89c4ff92SAndroid Build Coastguard Worker )
435*89c4ff92SAndroid Build Coastguard Worker {
436*89c4ff92SAndroid Build Coastguard Worker }
437*89c4ff92SAndroid Build Coastguard Worker };
438*89c4ff92SAndroid Build Coastguard Worker
439*89c4ff92SAndroid Build Coastguard Worker class option_not_has_argument_exception : public OptionParseException
440*89c4ff92SAndroid Build Coastguard Worker {
441*89c4ff92SAndroid Build Coastguard Worker public:
option_not_has_argument_exception(const std::string & option,const std::string & arg)442*89c4ff92SAndroid Build Coastguard Worker option_not_has_argument_exception
443*89c4ff92SAndroid Build Coastguard Worker (
444*89c4ff92SAndroid Build Coastguard Worker const std::string& option,
445*89c4ff92SAndroid Build Coastguard Worker const std::string& arg
446*89c4ff92SAndroid Build Coastguard Worker )
447*89c4ff92SAndroid Build Coastguard Worker : OptionParseException(
448*89c4ff92SAndroid Build Coastguard Worker "Option " + LQUOTE + option + RQUOTE +
449*89c4ff92SAndroid Build Coastguard Worker " does not take an argument, but argument " +
450*89c4ff92SAndroid Build Coastguard Worker LQUOTE + arg + RQUOTE + " given"
451*89c4ff92SAndroid Build Coastguard Worker )
452*89c4ff92SAndroid Build Coastguard Worker {
453*89c4ff92SAndroid Build Coastguard Worker }
454*89c4ff92SAndroid Build Coastguard Worker };
455*89c4ff92SAndroid Build Coastguard Worker
456*89c4ff92SAndroid Build Coastguard Worker class option_not_present_exception : public OptionParseException
457*89c4ff92SAndroid Build Coastguard Worker {
458*89c4ff92SAndroid Build Coastguard Worker public:
option_not_present_exception(const std::string & option)459*89c4ff92SAndroid Build Coastguard Worker explicit option_not_present_exception(const std::string& option)
460*89c4ff92SAndroid Build Coastguard Worker : OptionParseException("Option " + LQUOTE + option + RQUOTE + " not present")
461*89c4ff92SAndroid Build Coastguard Worker {
462*89c4ff92SAndroid Build Coastguard Worker }
463*89c4ff92SAndroid Build Coastguard Worker };
464*89c4ff92SAndroid Build Coastguard Worker
465*89c4ff92SAndroid Build Coastguard Worker class option_has_no_value_exception : public OptionException
466*89c4ff92SAndroid Build Coastguard Worker {
467*89c4ff92SAndroid Build Coastguard Worker public:
option_has_no_value_exception(const std::string & option)468*89c4ff92SAndroid Build Coastguard Worker explicit option_has_no_value_exception(const std::string& option)
469*89c4ff92SAndroid Build Coastguard Worker : OptionException(
470*89c4ff92SAndroid Build Coastguard Worker option.empty() ?
471*89c4ff92SAndroid Build Coastguard Worker ("Option " + LQUOTE + option + RQUOTE + " has no value") :
472*89c4ff92SAndroid Build Coastguard Worker "Option has no value")
473*89c4ff92SAndroid Build Coastguard Worker {
474*89c4ff92SAndroid Build Coastguard Worker }
475*89c4ff92SAndroid Build Coastguard Worker };
476*89c4ff92SAndroid Build Coastguard Worker
477*89c4ff92SAndroid Build Coastguard Worker class argument_incorrect_type : public OptionParseException
478*89c4ff92SAndroid Build Coastguard Worker {
479*89c4ff92SAndroid Build Coastguard Worker public:
argument_incorrect_type(const std::string & arg)480*89c4ff92SAndroid Build Coastguard Worker explicit argument_incorrect_type
481*89c4ff92SAndroid Build Coastguard Worker (
482*89c4ff92SAndroid Build Coastguard Worker const std::string& arg
483*89c4ff92SAndroid Build Coastguard Worker )
484*89c4ff92SAndroid Build Coastguard Worker : OptionParseException(
485*89c4ff92SAndroid Build Coastguard Worker "Argument " + LQUOTE + arg + RQUOTE + " failed to parse"
486*89c4ff92SAndroid Build Coastguard Worker )
487*89c4ff92SAndroid Build Coastguard Worker {
488*89c4ff92SAndroid Build Coastguard Worker }
489*89c4ff92SAndroid Build Coastguard Worker };
490*89c4ff92SAndroid Build Coastguard Worker
491*89c4ff92SAndroid Build Coastguard Worker class option_required_exception : public OptionParseException
492*89c4ff92SAndroid Build Coastguard Worker {
493*89c4ff92SAndroid Build Coastguard Worker public:
option_required_exception(const std::string & option)494*89c4ff92SAndroid Build Coastguard Worker explicit option_required_exception(const std::string& option)
495*89c4ff92SAndroid Build Coastguard Worker : OptionParseException(
496*89c4ff92SAndroid Build Coastguard Worker "Option " + LQUOTE + option + RQUOTE + " is required but not present"
497*89c4ff92SAndroid Build Coastguard Worker )
498*89c4ff92SAndroid Build Coastguard Worker {
499*89c4ff92SAndroid Build Coastguard Worker }
500*89c4ff92SAndroid Build Coastguard Worker };
501*89c4ff92SAndroid Build Coastguard Worker
502*89c4ff92SAndroid Build Coastguard Worker template <typename T>
throw_or_mimic(const std::string & text)503*89c4ff92SAndroid Build Coastguard Worker void throw_or_mimic(const std::string& text)
504*89c4ff92SAndroid Build Coastguard Worker {
505*89c4ff92SAndroid Build Coastguard Worker static_assert(std::is_base_of<std::exception, T>::value,
506*89c4ff92SAndroid Build Coastguard Worker "throw_or_mimic only works on std::exception and "
507*89c4ff92SAndroid Build Coastguard Worker "deriving classes");
508*89c4ff92SAndroid Build Coastguard Worker
509*89c4ff92SAndroid Build Coastguard Worker #ifndef CXXOPTS_NO_EXCEPTIONS
510*89c4ff92SAndroid Build Coastguard Worker // If CXXOPTS_NO_EXCEPTIONS is not defined, just throw
511*89c4ff92SAndroid Build Coastguard Worker throw T{text};
512*89c4ff92SAndroid Build Coastguard Worker #else
513*89c4ff92SAndroid Build Coastguard Worker // Otherwise manually instantiate the exception, print what() to stderr,
514*89c4ff92SAndroid Build Coastguard Worker // and exit
515*89c4ff92SAndroid Build Coastguard Worker T exception{text};
516*89c4ff92SAndroid Build Coastguard Worker std::cerr << exception.what() << std::endl;
517*89c4ff92SAndroid Build Coastguard Worker std::exit(EXIT_FAILURE);
518*89c4ff92SAndroid Build Coastguard Worker #endif
519*89c4ff92SAndroid Build Coastguard Worker }
520*89c4ff92SAndroid Build Coastguard Worker
521*89c4ff92SAndroid Build Coastguard Worker namespace values
522*89c4ff92SAndroid Build Coastguard Worker {
523*89c4ff92SAndroid Build Coastguard Worker namespace
524*89c4ff92SAndroid Build Coastguard Worker {
525*89c4ff92SAndroid Build Coastguard Worker std::basic_regex<char> integer_pattern
526*89c4ff92SAndroid Build Coastguard Worker ("(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)");
527*89c4ff92SAndroid Build Coastguard Worker std::basic_regex<char> truthy_pattern
528*89c4ff92SAndroid Build Coastguard Worker ("(t|T)(rue)?|1");
529*89c4ff92SAndroid Build Coastguard Worker std::basic_regex<char> falsy_pattern
530*89c4ff92SAndroid Build Coastguard Worker ("(f|F)(alse)?|0");
531*89c4ff92SAndroid Build Coastguard Worker } // namespace
532*89c4ff92SAndroid Build Coastguard Worker
533*89c4ff92SAndroid Build Coastguard Worker namespace detail
534*89c4ff92SAndroid Build Coastguard Worker {
535*89c4ff92SAndroid Build Coastguard Worker template <typename T, bool B>
536*89c4ff92SAndroid Build Coastguard Worker struct SignedCheck;
537*89c4ff92SAndroid Build Coastguard Worker
538*89c4ff92SAndroid Build Coastguard Worker template <typename T>
539*89c4ff92SAndroid Build Coastguard Worker struct SignedCheck<T, true>
540*89c4ff92SAndroid Build Coastguard Worker {
541*89c4ff92SAndroid Build Coastguard Worker template <typename U>
542*89c4ff92SAndroid Build Coastguard Worker void
operator ()cxxopts::values::detail::SignedCheck543*89c4ff92SAndroid Build Coastguard Worker operator()(bool negative, U u, const std::string& text)
544*89c4ff92SAndroid Build Coastguard Worker {
545*89c4ff92SAndroid Build Coastguard Worker if (negative)
546*89c4ff92SAndroid Build Coastguard Worker {
547*89c4ff92SAndroid Build Coastguard Worker if (u > static_cast<U>((std::numeric_limits<T>::min)()))
548*89c4ff92SAndroid Build Coastguard Worker {
549*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
550*89c4ff92SAndroid Build Coastguard Worker }
551*89c4ff92SAndroid Build Coastguard Worker }
552*89c4ff92SAndroid Build Coastguard Worker else
553*89c4ff92SAndroid Build Coastguard Worker {
554*89c4ff92SAndroid Build Coastguard Worker if (u > static_cast<U>((std::numeric_limits<T>::max)()))
555*89c4ff92SAndroid Build Coastguard Worker {
556*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
557*89c4ff92SAndroid Build Coastguard Worker }
558*89c4ff92SAndroid Build Coastguard Worker }
559*89c4ff92SAndroid Build Coastguard Worker }
560*89c4ff92SAndroid Build Coastguard Worker };
561*89c4ff92SAndroid Build Coastguard Worker
562*89c4ff92SAndroid Build Coastguard Worker template <typename T>
563*89c4ff92SAndroid Build Coastguard Worker struct SignedCheck<T, false>
564*89c4ff92SAndroid Build Coastguard Worker {
565*89c4ff92SAndroid Build Coastguard Worker template <typename U>
566*89c4ff92SAndroid Build Coastguard Worker void
operator ()cxxopts::values::detail::SignedCheck567*89c4ff92SAndroid Build Coastguard Worker operator()(bool, U, const std::string&) {}
568*89c4ff92SAndroid Build Coastguard Worker };
569*89c4ff92SAndroid Build Coastguard Worker
570*89c4ff92SAndroid Build Coastguard Worker template <typename T, typename U>
571*89c4ff92SAndroid Build Coastguard Worker void
check_signed_range(bool negative,U value,const std::string & text)572*89c4ff92SAndroid Build Coastguard Worker check_signed_range(bool negative, U value, const std::string& text)
573*89c4ff92SAndroid Build Coastguard Worker {
574*89c4ff92SAndroid Build Coastguard Worker SignedCheck<T, std::numeric_limits<T>::is_signed>()(negative, value, text);
575*89c4ff92SAndroid Build Coastguard Worker }
576*89c4ff92SAndroid Build Coastguard Worker } // namespace detail
577*89c4ff92SAndroid Build Coastguard Worker
578*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T>
579*89c4ff92SAndroid Build Coastguard Worker void
checked_negate(R & r,T && t,const std::string &,std::true_type)580*89c4ff92SAndroid Build Coastguard Worker checked_negate(R& r, T&& t, const std::string&, std::true_type)
581*89c4ff92SAndroid Build Coastguard Worker {
582*89c4ff92SAndroid Build Coastguard Worker // if we got to here, then `t` is a positive number that fits into
583*89c4ff92SAndroid Build Coastguard Worker // `R`. So to avoid MSVC C4146, we first cast it to `R`.
584*89c4ff92SAndroid Build Coastguard Worker // See https://github.com/jarro2783/cxxopts/issues/62 for more details.
585*89c4ff92SAndroid Build Coastguard Worker r = static_cast<R>(-static_cast<R>(t-1)-1);
586*89c4ff92SAndroid Build Coastguard Worker }
587*89c4ff92SAndroid Build Coastguard Worker
588*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T>
589*89c4ff92SAndroid Build Coastguard Worker void
checked_negate(R &,T &&,const std::string & text,std::false_type)590*89c4ff92SAndroid Build Coastguard Worker checked_negate(R&, T&&, const std::string& text, std::false_type)
591*89c4ff92SAndroid Build Coastguard Worker {
592*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
593*89c4ff92SAndroid Build Coastguard Worker }
594*89c4ff92SAndroid Build Coastguard Worker
595*89c4ff92SAndroid Build Coastguard Worker template <typename T>
596*89c4ff92SAndroid Build Coastguard Worker void
integer_parser(const std::string & text,T & value)597*89c4ff92SAndroid Build Coastguard Worker integer_parser(const std::string& text, T& value)
598*89c4ff92SAndroid Build Coastguard Worker {
599*89c4ff92SAndroid Build Coastguard Worker std::smatch match;
600*89c4ff92SAndroid Build Coastguard Worker std::regex_match(text, match, integer_pattern);
601*89c4ff92SAndroid Build Coastguard Worker
602*89c4ff92SAndroid Build Coastguard Worker if (match.length() == 0)
603*89c4ff92SAndroid Build Coastguard Worker {
604*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
605*89c4ff92SAndroid Build Coastguard Worker }
606*89c4ff92SAndroid Build Coastguard Worker
607*89c4ff92SAndroid Build Coastguard Worker if (match.length(4) > 0)
608*89c4ff92SAndroid Build Coastguard Worker {
609*89c4ff92SAndroid Build Coastguard Worker value = 0;
610*89c4ff92SAndroid Build Coastguard Worker return;
611*89c4ff92SAndroid Build Coastguard Worker }
612*89c4ff92SAndroid Build Coastguard Worker
613*89c4ff92SAndroid Build Coastguard Worker using US = typename std::make_unsigned<T>::type;
614*89c4ff92SAndroid Build Coastguard Worker
615*89c4ff92SAndroid Build Coastguard Worker constexpr bool is_signed = std::numeric_limits<T>::is_signed;
616*89c4ff92SAndroid Build Coastguard Worker const bool negative = match.length(1) > 0;
617*89c4ff92SAndroid Build Coastguard Worker const uint8_t base = match.length(2) > 0 ? 16 : 10;
618*89c4ff92SAndroid Build Coastguard Worker
619*89c4ff92SAndroid Build Coastguard Worker auto value_match = match[3];
620*89c4ff92SAndroid Build Coastguard Worker
621*89c4ff92SAndroid Build Coastguard Worker US result = 0;
622*89c4ff92SAndroid Build Coastguard Worker
623*89c4ff92SAndroid Build Coastguard Worker for (auto iter = value_match.first; iter != value_match.second; ++iter)
624*89c4ff92SAndroid Build Coastguard Worker {
625*89c4ff92SAndroid Build Coastguard Worker US digit = 0;
626*89c4ff92SAndroid Build Coastguard Worker
627*89c4ff92SAndroid Build Coastguard Worker if (*iter >= '0' && *iter <= '9')
628*89c4ff92SAndroid Build Coastguard Worker {
629*89c4ff92SAndroid Build Coastguard Worker digit = static_cast<US>(*iter - '0');
630*89c4ff92SAndroid Build Coastguard Worker }
631*89c4ff92SAndroid Build Coastguard Worker else if (base == 16 && *iter >= 'a' && *iter <= 'f')
632*89c4ff92SAndroid Build Coastguard Worker {
633*89c4ff92SAndroid Build Coastguard Worker digit = static_cast<US>(*iter - 'a' + 10);
634*89c4ff92SAndroid Build Coastguard Worker }
635*89c4ff92SAndroid Build Coastguard Worker else if (base == 16 && *iter >= 'A' && *iter <= 'F')
636*89c4ff92SAndroid Build Coastguard Worker {
637*89c4ff92SAndroid Build Coastguard Worker digit = static_cast<US>(*iter - 'A' + 10);
638*89c4ff92SAndroid Build Coastguard Worker }
639*89c4ff92SAndroid Build Coastguard Worker else
640*89c4ff92SAndroid Build Coastguard Worker {
641*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
642*89c4ff92SAndroid Build Coastguard Worker }
643*89c4ff92SAndroid Build Coastguard Worker
644*89c4ff92SAndroid Build Coastguard Worker const US next = static_cast<US>(result * base + digit);
645*89c4ff92SAndroid Build Coastguard Worker if (result > next)
646*89c4ff92SAndroid Build Coastguard Worker {
647*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
648*89c4ff92SAndroid Build Coastguard Worker }
649*89c4ff92SAndroid Build Coastguard Worker
650*89c4ff92SAndroid Build Coastguard Worker result = next;
651*89c4ff92SAndroid Build Coastguard Worker }
652*89c4ff92SAndroid Build Coastguard Worker
653*89c4ff92SAndroid Build Coastguard Worker detail::check_signed_range<T>(negative, result, text);
654*89c4ff92SAndroid Build Coastguard Worker
655*89c4ff92SAndroid Build Coastguard Worker if (negative)
656*89c4ff92SAndroid Build Coastguard Worker {
657*89c4ff92SAndroid Build Coastguard Worker checked_negate<T>(value, result, text, std::integral_constant<bool, is_signed>());
658*89c4ff92SAndroid Build Coastguard Worker }
659*89c4ff92SAndroid Build Coastguard Worker else
660*89c4ff92SAndroid Build Coastguard Worker {
661*89c4ff92SAndroid Build Coastguard Worker value = static_cast<T>(result);
662*89c4ff92SAndroid Build Coastguard Worker }
663*89c4ff92SAndroid Build Coastguard Worker }
664*89c4ff92SAndroid Build Coastguard Worker
665*89c4ff92SAndroid Build Coastguard Worker template <typename T>
stringstream_parser(const std::string & text,T & value)666*89c4ff92SAndroid Build Coastguard Worker void stringstream_parser(const std::string& text, T& value)
667*89c4ff92SAndroid Build Coastguard Worker {
668*89c4ff92SAndroid Build Coastguard Worker std::stringstream in(text);
669*89c4ff92SAndroid Build Coastguard Worker in >> value;
670*89c4ff92SAndroid Build Coastguard Worker if (!in) {
671*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
672*89c4ff92SAndroid Build Coastguard Worker }
673*89c4ff92SAndroid Build Coastguard Worker }
674*89c4ff92SAndroid Build Coastguard Worker
675*89c4ff92SAndroid Build Coastguard Worker inline
676*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,uint8_t & value)677*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, uint8_t& value)
678*89c4ff92SAndroid Build Coastguard Worker {
679*89c4ff92SAndroid Build Coastguard Worker integer_parser(text, value);
680*89c4ff92SAndroid Build Coastguard Worker }
681*89c4ff92SAndroid Build Coastguard Worker
682*89c4ff92SAndroid Build Coastguard Worker inline
683*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,int8_t & value)684*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, int8_t& value)
685*89c4ff92SAndroid Build Coastguard Worker {
686*89c4ff92SAndroid Build Coastguard Worker integer_parser(text, value);
687*89c4ff92SAndroid Build Coastguard Worker }
688*89c4ff92SAndroid Build Coastguard Worker
689*89c4ff92SAndroid Build Coastguard Worker inline
690*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,uint16_t & value)691*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, uint16_t& value)
692*89c4ff92SAndroid Build Coastguard Worker {
693*89c4ff92SAndroid Build Coastguard Worker integer_parser(text, value);
694*89c4ff92SAndroid Build Coastguard Worker }
695*89c4ff92SAndroid Build Coastguard Worker
696*89c4ff92SAndroid Build Coastguard Worker inline
697*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,int16_t & value)698*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, int16_t& value)
699*89c4ff92SAndroid Build Coastguard Worker {
700*89c4ff92SAndroid Build Coastguard Worker integer_parser(text, value);
701*89c4ff92SAndroid Build Coastguard Worker }
702*89c4ff92SAndroid Build Coastguard Worker
703*89c4ff92SAndroid Build Coastguard Worker inline
704*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,uint32_t & value)705*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, uint32_t& value)
706*89c4ff92SAndroid Build Coastguard Worker {
707*89c4ff92SAndroid Build Coastguard Worker integer_parser(text, value);
708*89c4ff92SAndroid Build Coastguard Worker }
709*89c4ff92SAndroid Build Coastguard Worker
710*89c4ff92SAndroid Build Coastguard Worker inline
711*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,int32_t & value)712*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, int32_t& value)
713*89c4ff92SAndroid Build Coastguard Worker {
714*89c4ff92SAndroid Build Coastguard Worker integer_parser(text, value);
715*89c4ff92SAndroid Build Coastguard Worker }
716*89c4ff92SAndroid Build Coastguard Worker
717*89c4ff92SAndroid Build Coastguard Worker inline
718*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,uint64_t & value)719*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, uint64_t& value)
720*89c4ff92SAndroid Build Coastguard Worker {
721*89c4ff92SAndroid Build Coastguard Worker integer_parser(text, value);
722*89c4ff92SAndroid Build Coastguard Worker }
723*89c4ff92SAndroid Build Coastguard Worker
724*89c4ff92SAndroid Build Coastguard Worker inline
725*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,int64_t & value)726*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, int64_t& value)
727*89c4ff92SAndroid Build Coastguard Worker {
728*89c4ff92SAndroid Build Coastguard Worker integer_parser(text, value);
729*89c4ff92SAndroid Build Coastguard Worker }
730*89c4ff92SAndroid Build Coastguard Worker
731*89c4ff92SAndroid Build Coastguard Worker inline
732*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,bool & value)733*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, bool& value)
734*89c4ff92SAndroid Build Coastguard Worker {
735*89c4ff92SAndroid Build Coastguard Worker std::smatch result;
736*89c4ff92SAndroid Build Coastguard Worker std::regex_match(text, result, truthy_pattern);
737*89c4ff92SAndroid Build Coastguard Worker
738*89c4ff92SAndroid Build Coastguard Worker if (!result.empty())
739*89c4ff92SAndroid Build Coastguard Worker {
740*89c4ff92SAndroid Build Coastguard Worker value = true;
741*89c4ff92SAndroid Build Coastguard Worker return;
742*89c4ff92SAndroid Build Coastguard Worker }
743*89c4ff92SAndroid Build Coastguard Worker
744*89c4ff92SAndroid Build Coastguard Worker std::regex_match(text, result, falsy_pattern);
745*89c4ff92SAndroid Build Coastguard Worker if (!result.empty())
746*89c4ff92SAndroid Build Coastguard Worker {
747*89c4ff92SAndroid Build Coastguard Worker value = false;
748*89c4ff92SAndroid Build Coastguard Worker return;
749*89c4ff92SAndroid Build Coastguard Worker }
750*89c4ff92SAndroid Build Coastguard Worker
751*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
752*89c4ff92SAndroid Build Coastguard Worker }
753*89c4ff92SAndroid Build Coastguard Worker
754*89c4ff92SAndroid Build Coastguard Worker inline
755*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,std::string & value)756*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, std::string& value)
757*89c4ff92SAndroid Build Coastguard Worker {
758*89c4ff92SAndroid Build Coastguard Worker value = text;
759*89c4ff92SAndroid Build Coastguard Worker }
760*89c4ff92SAndroid Build Coastguard Worker
761*89c4ff92SAndroid Build Coastguard Worker // The fallback parser. It uses the stringstream parser to parse all types
762*89c4ff92SAndroid Build Coastguard Worker // that have not been overloaded explicitly. It has to be placed in the
763*89c4ff92SAndroid Build Coastguard Worker // source code before all other more specialized templates.
764*89c4ff92SAndroid Build Coastguard Worker template <typename T>
765*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,T & value)766*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, T& value) {
767*89c4ff92SAndroid Build Coastguard Worker stringstream_parser(text, value);
768*89c4ff92SAndroid Build Coastguard Worker }
769*89c4ff92SAndroid Build Coastguard Worker
770*89c4ff92SAndroid Build Coastguard Worker template <typename T>
771*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,std::vector<T> & value)772*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, std::vector<T>& value)
773*89c4ff92SAndroid Build Coastguard Worker {
774*89c4ff92SAndroid Build Coastguard Worker std::stringstream in(text);
775*89c4ff92SAndroid Build Coastguard Worker std::string token;
776*89c4ff92SAndroid Build Coastguard Worker while(!in.eof() && std::getline(in, token, CXXOPTS_VECTOR_DELIMITER)) {
777*89c4ff92SAndroid Build Coastguard Worker T v;
778*89c4ff92SAndroid Build Coastguard Worker parse_value(token, v);
779*89c4ff92SAndroid Build Coastguard Worker value.emplace_back(std::move(v));
780*89c4ff92SAndroid Build Coastguard Worker }
781*89c4ff92SAndroid Build Coastguard Worker }
782*89c4ff92SAndroid Build Coastguard Worker
783*89c4ff92SAndroid Build Coastguard Worker #ifdef CXXOPTS_HAS_OPTIONAL
784*89c4ff92SAndroid Build Coastguard Worker template <typename T>
785*89c4ff92SAndroid Build Coastguard Worker void
parse_value(const std::string & text,std::optional<T> & value)786*89c4ff92SAndroid Build Coastguard Worker parse_value(const std::string& text, std::optional<T>& value)
787*89c4ff92SAndroid Build Coastguard Worker {
788*89c4ff92SAndroid Build Coastguard Worker T result;
789*89c4ff92SAndroid Build Coastguard Worker parse_value(text, result);
790*89c4ff92SAndroid Build Coastguard Worker value = std::move(result);
791*89c4ff92SAndroid Build Coastguard Worker }
792*89c4ff92SAndroid Build Coastguard Worker #endif
793*89c4ff92SAndroid Build Coastguard Worker
794*89c4ff92SAndroid Build Coastguard Worker inline
parse_value(const std::string & text,char & c)795*89c4ff92SAndroid Build Coastguard Worker void parse_value(const std::string& text, char& c)
796*89c4ff92SAndroid Build Coastguard Worker {
797*89c4ff92SAndroid Build Coastguard Worker if (text.length() != 1)
798*89c4ff92SAndroid Build Coastguard Worker {
799*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<argument_incorrect_type>(text);
800*89c4ff92SAndroid Build Coastguard Worker }
801*89c4ff92SAndroid Build Coastguard Worker
802*89c4ff92SAndroid Build Coastguard Worker c = text[0];
803*89c4ff92SAndroid Build Coastguard Worker }
804*89c4ff92SAndroid Build Coastguard Worker
805*89c4ff92SAndroid Build Coastguard Worker template <typename T>
806*89c4ff92SAndroid Build Coastguard Worker struct type_is_container
807*89c4ff92SAndroid Build Coastguard Worker {
808*89c4ff92SAndroid Build Coastguard Worker static constexpr bool value = false;
809*89c4ff92SAndroid Build Coastguard Worker };
810*89c4ff92SAndroid Build Coastguard Worker
811*89c4ff92SAndroid Build Coastguard Worker template <typename T>
812*89c4ff92SAndroid Build Coastguard Worker struct type_is_container<std::vector<T>>
813*89c4ff92SAndroid Build Coastguard Worker {
814*89c4ff92SAndroid Build Coastguard Worker static constexpr bool value = true;
815*89c4ff92SAndroid Build Coastguard Worker };
816*89c4ff92SAndroid Build Coastguard Worker
817*89c4ff92SAndroid Build Coastguard Worker template <typename T>
818*89c4ff92SAndroid Build Coastguard Worker class abstract_value : public Value
819*89c4ff92SAndroid Build Coastguard Worker {
820*89c4ff92SAndroid Build Coastguard Worker using Self = abstract_value<T>;
821*89c4ff92SAndroid Build Coastguard Worker
822*89c4ff92SAndroid Build Coastguard Worker public:
abstract_value()823*89c4ff92SAndroid Build Coastguard Worker abstract_value()
824*89c4ff92SAndroid Build Coastguard Worker : m_result(std::make_shared<T>())
825*89c4ff92SAndroid Build Coastguard Worker , m_store(m_result.get())
826*89c4ff92SAndroid Build Coastguard Worker {
827*89c4ff92SAndroid Build Coastguard Worker }
828*89c4ff92SAndroid Build Coastguard Worker
abstract_value(T * t)829*89c4ff92SAndroid Build Coastguard Worker explicit abstract_value(T* t)
830*89c4ff92SAndroid Build Coastguard Worker : m_store(t)
831*89c4ff92SAndroid Build Coastguard Worker {
832*89c4ff92SAndroid Build Coastguard Worker }
833*89c4ff92SAndroid Build Coastguard Worker
834*89c4ff92SAndroid Build Coastguard Worker ~abstract_value() override = default;
835*89c4ff92SAndroid Build Coastguard Worker
836*89c4ff92SAndroid Build Coastguard Worker abstract_value& operator=(const abstract_value&) = default;
837*89c4ff92SAndroid Build Coastguard Worker
abstract_value(const abstract_value & rhs)838*89c4ff92SAndroid Build Coastguard Worker abstract_value(const abstract_value& rhs)
839*89c4ff92SAndroid Build Coastguard Worker {
840*89c4ff92SAndroid Build Coastguard Worker if (rhs.m_result)
841*89c4ff92SAndroid Build Coastguard Worker {
842*89c4ff92SAndroid Build Coastguard Worker m_result = std::make_shared<T>();
843*89c4ff92SAndroid Build Coastguard Worker m_store = m_result.get();
844*89c4ff92SAndroid Build Coastguard Worker }
845*89c4ff92SAndroid Build Coastguard Worker else
846*89c4ff92SAndroid Build Coastguard Worker {
847*89c4ff92SAndroid Build Coastguard Worker m_store = rhs.m_store;
848*89c4ff92SAndroid Build Coastguard Worker }
849*89c4ff92SAndroid Build Coastguard Worker
850*89c4ff92SAndroid Build Coastguard Worker m_default = rhs.m_default;
851*89c4ff92SAndroid Build Coastguard Worker m_implicit = rhs.m_implicit;
852*89c4ff92SAndroid Build Coastguard Worker m_default_value = rhs.m_default_value;
853*89c4ff92SAndroid Build Coastguard Worker m_implicit_value = rhs.m_implicit_value;
854*89c4ff92SAndroid Build Coastguard Worker }
855*89c4ff92SAndroid Build Coastguard Worker
856*89c4ff92SAndroid Build Coastguard Worker void
parse(const std::string & text) const857*89c4ff92SAndroid Build Coastguard Worker parse(const std::string& text) const override
858*89c4ff92SAndroid Build Coastguard Worker {
859*89c4ff92SAndroid Build Coastguard Worker parse_value(text, *m_store);
860*89c4ff92SAndroid Build Coastguard Worker }
861*89c4ff92SAndroid Build Coastguard Worker
862*89c4ff92SAndroid Build Coastguard Worker bool
is_container() const863*89c4ff92SAndroid Build Coastguard Worker is_container() const override
864*89c4ff92SAndroid Build Coastguard Worker {
865*89c4ff92SAndroid Build Coastguard Worker return type_is_container<T>::value;
866*89c4ff92SAndroid Build Coastguard Worker }
867*89c4ff92SAndroid Build Coastguard Worker
868*89c4ff92SAndroid Build Coastguard Worker void
parse() const869*89c4ff92SAndroid Build Coastguard Worker parse() const override
870*89c4ff92SAndroid Build Coastguard Worker {
871*89c4ff92SAndroid Build Coastguard Worker parse_value(m_default_value, *m_store);
872*89c4ff92SAndroid Build Coastguard Worker }
873*89c4ff92SAndroid Build Coastguard Worker
874*89c4ff92SAndroid Build Coastguard Worker bool
has_default() const875*89c4ff92SAndroid Build Coastguard Worker has_default() const override
876*89c4ff92SAndroid Build Coastguard Worker {
877*89c4ff92SAndroid Build Coastguard Worker return m_default;
878*89c4ff92SAndroid Build Coastguard Worker }
879*89c4ff92SAndroid Build Coastguard Worker
880*89c4ff92SAndroid Build Coastguard Worker bool
has_implicit() const881*89c4ff92SAndroid Build Coastguard Worker has_implicit() const override
882*89c4ff92SAndroid Build Coastguard Worker {
883*89c4ff92SAndroid Build Coastguard Worker return m_implicit;
884*89c4ff92SAndroid Build Coastguard Worker }
885*89c4ff92SAndroid Build Coastguard Worker
886*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
default_value(const std::string & value)887*89c4ff92SAndroid Build Coastguard Worker default_value(const std::string& value) override
888*89c4ff92SAndroid Build Coastguard Worker {
889*89c4ff92SAndroid Build Coastguard Worker m_default = true;
890*89c4ff92SAndroid Build Coastguard Worker m_default_value = value;
891*89c4ff92SAndroid Build Coastguard Worker return shared_from_this();
892*89c4ff92SAndroid Build Coastguard Worker }
893*89c4ff92SAndroid Build Coastguard Worker
894*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
implicit_value(const std::string & value)895*89c4ff92SAndroid Build Coastguard Worker implicit_value(const std::string& value) override
896*89c4ff92SAndroid Build Coastguard Worker {
897*89c4ff92SAndroid Build Coastguard Worker m_implicit = true;
898*89c4ff92SAndroid Build Coastguard Worker m_implicit_value = value;
899*89c4ff92SAndroid Build Coastguard Worker return shared_from_this();
900*89c4ff92SAndroid Build Coastguard Worker }
901*89c4ff92SAndroid Build Coastguard Worker
902*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
no_implicit_value()903*89c4ff92SAndroid Build Coastguard Worker no_implicit_value() override
904*89c4ff92SAndroid Build Coastguard Worker {
905*89c4ff92SAndroid Build Coastguard Worker m_implicit = false;
906*89c4ff92SAndroid Build Coastguard Worker return shared_from_this();
907*89c4ff92SAndroid Build Coastguard Worker }
908*89c4ff92SAndroid Build Coastguard Worker
909*89c4ff92SAndroid Build Coastguard Worker std::string
get_default_value() const910*89c4ff92SAndroid Build Coastguard Worker get_default_value() const override
911*89c4ff92SAndroid Build Coastguard Worker {
912*89c4ff92SAndroid Build Coastguard Worker return m_default_value;
913*89c4ff92SAndroid Build Coastguard Worker }
914*89c4ff92SAndroid Build Coastguard Worker
915*89c4ff92SAndroid Build Coastguard Worker std::string
get_implicit_value() const916*89c4ff92SAndroid Build Coastguard Worker get_implicit_value() const override
917*89c4ff92SAndroid Build Coastguard Worker {
918*89c4ff92SAndroid Build Coastguard Worker return m_implicit_value;
919*89c4ff92SAndroid Build Coastguard Worker }
920*89c4ff92SAndroid Build Coastguard Worker
921*89c4ff92SAndroid Build Coastguard Worker bool
is_boolean() const922*89c4ff92SAndroid Build Coastguard Worker is_boolean() const override
923*89c4ff92SAndroid Build Coastguard Worker {
924*89c4ff92SAndroid Build Coastguard Worker return std::is_same<T, bool>::value;
925*89c4ff92SAndroid Build Coastguard Worker }
926*89c4ff92SAndroid Build Coastguard Worker
927*89c4ff92SAndroid Build Coastguard Worker const T&
get() const928*89c4ff92SAndroid Build Coastguard Worker get() const
929*89c4ff92SAndroid Build Coastguard Worker {
930*89c4ff92SAndroid Build Coastguard Worker if (m_store == nullptr)
931*89c4ff92SAndroid Build Coastguard Worker {
932*89c4ff92SAndroid Build Coastguard Worker return *m_result;
933*89c4ff92SAndroid Build Coastguard Worker }
934*89c4ff92SAndroid Build Coastguard Worker return *m_store;
935*89c4ff92SAndroid Build Coastguard Worker }
936*89c4ff92SAndroid Build Coastguard Worker
937*89c4ff92SAndroid Build Coastguard Worker protected:
938*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<T> m_result{};
939*89c4ff92SAndroid Build Coastguard Worker T* m_store{};
940*89c4ff92SAndroid Build Coastguard Worker
941*89c4ff92SAndroid Build Coastguard Worker bool m_default = false;
942*89c4ff92SAndroid Build Coastguard Worker bool m_implicit = false;
943*89c4ff92SAndroid Build Coastguard Worker
944*89c4ff92SAndroid Build Coastguard Worker std::string m_default_value{};
945*89c4ff92SAndroid Build Coastguard Worker std::string m_implicit_value{};
946*89c4ff92SAndroid Build Coastguard Worker };
947*89c4ff92SAndroid Build Coastguard Worker
948*89c4ff92SAndroid Build Coastguard Worker template <typename T>
949*89c4ff92SAndroid Build Coastguard Worker class standard_value : public abstract_value<T>
950*89c4ff92SAndroid Build Coastguard Worker {
951*89c4ff92SAndroid Build Coastguard Worker public:
952*89c4ff92SAndroid Build Coastguard Worker using abstract_value<T>::abstract_value;
953*89c4ff92SAndroid Build Coastguard Worker
954*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
955*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
clone() const956*89c4ff92SAndroid Build Coastguard Worker clone() const
957*89c4ff92SAndroid Build Coastguard Worker {
958*89c4ff92SAndroid Build Coastguard Worker return std::make_shared<standard_value<T>>(*this);
959*89c4ff92SAndroid Build Coastguard Worker }
960*89c4ff92SAndroid Build Coastguard Worker };
961*89c4ff92SAndroid Build Coastguard Worker
962*89c4ff92SAndroid Build Coastguard Worker template <>
963*89c4ff92SAndroid Build Coastguard Worker class standard_value<bool> : public abstract_value<bool>
964*89c4ff92SAndroid Build Coastguard Worker {
965*89c4ff92SAndroid Build Coastguard Worker public:
966*89c4ff92SAndroid Build Coastguard Worker ~standard_value() override = default;
967*89c4ff92SAndroid Build Coastguard Worker
standard_value()968*89c4ff92SAndroid Build Coastguard Worker standard_value()
969*89c4ff92SAndroid Build Coastguard Worker {
970*89c4ff92SAndroid Build Coastguard Worker set_default_and_implicit();
971*89c4ff92SAndroid Build Coastguard Worker }
972*89c4ff92SAndroid Build Coastguard Worker
standard_value(bool * b)973*89c4ff92SAndroid Build Coastguard Worker explicit standard_value(bool* b)
974*89c4ff92SAndroid Build Coastguard Worker : abstract_value(b)
975*89c4ff92SAndroid Build Coastguard Worker {
976*89c4ff92SAndroid Build Coastguard Worker set_default_and_implicit();
977*89c4ff92SAndroid Build Coastguard Worker }
978*89c4ff92SAndroid Build Coastguard Worker
979*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
clone() const980*89c4ff92SAndroid Build Coastguard Worker clone() const override
981*89c4ff92SAndroid Build Coastguard Worker {
982*89c4ff92SAndroid Build Coastguard Worker return std::make_shared<standard_value<bool>>(*this);
983*89c4ff92SAndroid Build Coastguard Worker }
984*89c4ff92SAndroid Build Coastguard Worker
985*89c4ff92SAndroid Build Coastguard Worker private:
986*89c4ff92SAndroid Build Coastguard Worker
987*89c4ff92SAndroid Build Coastguard Worker void
set_default_and_implicit()988*89c4ff92SAndroid Build Coastguard Worker set_default_and_implicit()
989*89c4ff92SAndroid Build Coastguard Worker {
990*89c4ff92SAndroid Build Coastguard Worker m_default = true;
991*89c4ff92SAndroid Build Coastguard Worker m_default_value = "false";
992*89c4ff92SAndroid Build Coastguard Worker m_implicit = true;
993*89c4ff92SAndroid Build Coastguard Worker m_implicit_value = "true";
994*89c4ff92SAndroid Build Coastguard Worker }
995*89c4ff92SAndroid Build Coastguard Worker };
996*89c4ff92SAndroid Build Coastguard Worker } // namespace values
997*89c4ff92SAndroid Build Coastguard Worker
998*89c4ff92SAndroid Build Coastguard Worker template <typename T>
999*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
value()1000*89c4ff92SAndroid Build Coastguard Worker value()
1001*89c4ff92SAndroid Build Coastguard Worker {
1002*89c4ff92SAndroid Build Coastguard Worker return std::make_shared<values::standard_value<T>>();
1003*89c4ff92SAndroid Build Coastguard Worker }
1004*89c4ff92SAndroid Build Coastguard Worker
1005*89c4ff92SAndroid Build Coastguard Worker template <typename T>
1006*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
value(T & t)1007*89c4ff92SAndroid Build Coastguard Worker value(T& t)
1008*89c4ff92SAndroid Build Coastguard Worker {
1009*89c4ff92SAndroid Build Coastguard Worker return std::make_shared<values::standard_value<T>>(&t);
1010*89c4ff92SAndroid Build Coastguard Worker }
1011*89c4ff92SAndroid Build Coastguard Worker
1012*89c4ff92SAndroid Build Coastguard Worker class OptionAdder;
1013*89c4ff92SAndroid Build Coastguard Worker
1014*89c4ff92SAndroid Build Coastguard Worker class OptionDetails
1015*89c4ff92SAndroid Build Coastguard Worker {
1016*89c4ff92SAndroid Build Coastguard Worker public:
OptionDetails(std::string short_,std::string long_,String desc,std::shared_ptr<const Value> val)1017*89c4ff92SAndroid Build Coastguard Worker OptionDetails
1018*89c4ff92SAndroid Build Coastguard Worker (
1019*89c4ff92SAndroid Build Coastguard Worker std::string short_,
1020*89c4ff92SAndroid Build Coastguard Worker std::string long_,
1021*89c4ff92SAndroid Build Coastguard Worker String desc,
1022*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<const Value> val
1023*89c4ff92SAndroid Build Coastguard Worker )
1024*89c4ff92SAndroid Build Coastguard Worker : m_short(std::move(short_))
1025*89c4ff92SAndroid Build Coastguard Worker , m_long(std::move(long_))
1026*89c4ff92SAndroid Build Coastguard Worker , m_desc(std::move(desc))
1027*89c4ff92SAndroid Build Coastguard Worker , m_value(std::move(val))
1028*89c4ff92SAndroid Build Coastguard Worker , m_count(0)
1029*89c4ff92SAndroid Build Coastguard Worker {
1030*89c4ff92SAndroid Build Coastguard Worker m_hash = std::hash<std::string>{}(m_long + m_short);
1031*89c4ff92SAndroid Build Coastguard Worker }
1032*89c4ff92SAndroid Build Coastguard Worker
OptionDetails(const OptionDetails & rhs)1033*89c4ff92SAndroid Build Coastguard Worker OptionDetails(const OptionDetails& rhs)
1034*89c4ff92SAndroid Build Coastguard Worker : m_desc(rhs.m_desc)
1035*89c4ff92SAndroid Build Coastguard Worker , m_count(rhs.m_count)
1036*89c4ff92SAndroid Build Coastguard Worker {
1037*89c4ff92SAndroid Build Coastguard Worker m_value = rhs.m_value->clone();
1038*89c4ff92SAndroid Build Coastguard Worker }
1039*89c4ff92SAndroid Build Coastguard Worker
1040*89c4ff92SAndroid Build Coastguard Worker OptionDetails(OptionDetails&& rhs) = default;
1041*89c4ff92SAndroid Build Coastguard Worker
1042*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1043*89c4ff92SAndroid Build Coastguard Worker const String&
description() const1044*89c4ff92SAndroid Build Coastguard Worker description() const
1045*89c4ff92SAndroid Build Coastguard Worker {
1046*89c4ff92SAndroid Build Coastguard Worker return m_desc;
1047*89c4ff92SAndroid Build Coastguard Worker }
1048*89c4ff92SAndroid Build Coastguard Worker
1049*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1050*89c4ff92SAndroid Build Coastguard Worker const Value&
value() const1051*89c4ff92SAndroid Build Coastguard Worker value() const {
1052*89c4ff92SAndroid Build Coastguard Worker return *m_value;
1053*89c4ff92SAndroid Build Coastguard Worker }
1054*89c4ff92SAndroid Build Coastguard Worker
1055*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1056*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value>
make_storage() const1057*89c4ff92SAndroid Build Coastguard Worker make_storage() const
1058*89c4ff92SAndroid Build Coastguard Worker {
1059*89c4ff92SAndroid Build Coastguard Worker return m_value->clone();
1060*89c4ff92SAndroid Build Coastguard Worker }
1061*89c4ff92SAndroid Build Coastguard Worker
1062*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1063*89c4ff92SAndroid Build Coastguard Worker const std::string&
short_name() const1064*89c4ff92SAndroid Build Coastguard Worker short_name() const
1065*89c4ff92SAndroid Build Coastguard Worker {
1066*89c4ff92SAndroid Build Coastguard Worker return m_short;
1067*89c4ff92SAndroid Build Coastguard Worker }
1068*89c4ff92SAndroid Build Coastguard Worker
1069*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1070*89c4ff92SAndroid Build Coastguard Worker const std::string&
long_name() const1071*89c4ff92SAndroid Build Coastguard Worker long_name() const
1072*89c4ff92SAndroid Build Coastguard Worker {
1073*89c4ff92SAndroid Build Coastguard Worker return m_long;
1074*89c4ff92SAndroid Build Coastguard Worker }
1075*89c4ff92SAndroid Build Coastguard Worker
1076*89c4ff92SAndroid Build Coastguard Worker size_t
hash() const1077*89c4ff92SAndroid Build Coastguard Worker hash() const
1078*89c4ff92SAndroid Build Coastguard Worker {
1079*89c4ff92SAndroid Build Coastguard Worker return m_hash;
1080*89c4ff92SAndroid Build Coastguard Worker }
1081*89c4ff92SAndroid Build Coastguard Worker
1082*89c4ff92SAndroid Build Coastguard Worker private:
1083*89c4ff92SAndroid Build Coastguard Worker std::string m_short{};
1084*89c4ff92SAndroid Build Coastguard Worker std::string m_long{};
1085*89c4ff92SAndroid Build Coastguard Worker String m_desc{};
1086*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<const Value> m_value{};
1087*89c4ff92SAndroid Build Coastguard Worker int m_count;
1088*89c4ff92SAndroid Build Coastguard Worker
1089*89c4ff92SAndroid Build Coastguard Worker size_t m_hash{};
1090*89c4ff92SAndroid Build Coastguard Worker };
1091*89c4ff92SAndroid Build Coastguard Worker
1092*89c4ff92SAndroid Build Coastguard Worker struct HelpOptionDetails
1093*89c4ff92SAndroid Build Coastguard Worker {
1094*89c4ff92SAndroid Build Coastguard Worker std::string s;
1095*89c4ff92SAndroid Build Coastguard Worker std::string l;
1096*89c4ff92SAndroid Build Coastguard Worker String desc;
1097*89c4ff92SAndroid Build Coastguard Worker bool has_default;
1098*89c4ff92SAndroid Build Coastguard Worker std::string default_value;
1099*89c4ff92SAndroid Build Coastguard Worker bool has_implicit;
1100*89c4ff92SAndroid Build Coastguard Worker std::string implicit_value;
1101*89c4ff92SAndroid Build Coastguard Worker std::string arg_help;
1102*89c4ff92SAndroid Build Coastguard Worker bool is_container;
1103*89c4ff92SAndroid Build Coastguard Worker bool is_boolean;
1104*89c4ff92SAndroid Build Coastguard Worker };
1105*89c4ff92SAndroid Build Coastguard Worker
1106*89c4ff92SAndroid Build Coastguard Worker struct HelpGroupDetails
1107*89c4ff92SAndroid Build Coastguard Worker {
1108*89c4ff92SAndroid Build Coastguard Worker std::string name{};
1109*89c4ff92SAndroid Build Coastguard Worker std::string description{};
1110*89c4ff92SAndroid Build Coastguard Worker std::vector<HelpOptionDetails> options{};
1111*89c4ff92SAndroid Build Coastguard Worker };
1112*89c4ff92SAndroid Build Coastguard Worker
1113*89c4ff92SAndroid Build Coastguard Worker class OptionValue
1114*89c4ff92SAndroid Build Coastguard Worker {
1115*89c4ff92SAndroid Build Coastguard Worker public:
1116*89c4ff92SAndroid Build Coastguard Worker void
parse(const std::shared_ptr<const OptionDetails> & details,const std::string & text)1117*89c4ff92SAndroid Build Coastguard Worker parse
1118*89c4ff92SAndroid Build Coastguard Worker (
1119*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<const OptionDetails>& details,
1120*89c4ff92SAndroid Build Coastguard Worker const std::string& text
1121*89c4ff92SAndroid Build Coastguard Worker )
1122*89c4ff92SAndroid Build Coastguard Worker {
1123*89c4ff92SAndroid Build Coastguard Worker ensure_value(details);
1124*89c4ff92SAndroid Build Coastguard Worker ++m_count;
1125*89c4ff92SAndroid Build Coastguard Worker m_value->parse(text);
1126*89c4ff92SAndroid Build Coastguard Worker m_long_name = &details->long_name();
1127*89c4ff92SAndroid Build Coastguard Worker }
1128*89c4ff92SAndroid Build Coastguard Worker
1129*89c4ff92SAndroid Build Coastguard Worker void
parse_default(const std::shared_ptr<const OptionDetails> & details)1130*89c4ff92SAndroid Build Coastguard Worker parse_default(const std::shared_ptr<const OptionDetails>& details)
1131*89c4ff92SAndroid Build Coastguard Worker {
1132*89c4ff92SAndroid Build Coastguard Worker ensure_value(details);
1133*89c4ff92SAndroid Build Coastguard Worker m_default = true;
1134*89c4ff92SAndroid Build Coastguard Worker m_long_name = &details->long_name();
1135*89c4ff92SAndroid Build Coastguard Worker m_value->parse();
1136*89c4ff92SAndroid Build Coastguard Worker }
1137*89c4ff92SAndroid Build Coastguard Worker
1138*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1139*89c4ff92SAndroid Build Coastguard Worker size_t
count() const1140*89c4ff92SAndroid Build Coastguard Worker count() const noexcept
1141*89c4ff92SAndroid Build Coastguard Worker {
1142*89c4ff92SAndroid Build Coastguard Worker return m_count;
1143*89c4ff92SAndroid Build Coastguard Worker }
1144*89c4ff92SAndroid Build Coastguard Worker
1145*89c4ff92SAndroid Build Coastguard Worker // TODO: maybe default options should count towards the number of arguments
1146*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1147*89c4ff92SAndroid Build Coastguard Worker bool
has_default() const1148*89c4ff92SAndroid Build Coastguard Worker has_default() const noexcept
1149*89c4ff92SAndroid Build Coastguard Worker {
1150*89c4ff92SAndroid Build Coastguard Worker return m_default;
1151*89c4ff92SAndroid Build Coastguard Worker }
1152*89c4ff92SAndroid Build Coastguard Worker
1153*89c4ff92SAndroid Build Coastguard Worker template <typename T>
1154*89c4ff92SAndroid Build Coastguard Worker const T&
as() const1155*89c4ff92SAndroid Build Coastguard Worker as() const
1156*89c4ff92SAndroid Build Coastguard Worker {
1157*89c4ff92SAndroid Build Coastguard Worker if (m_value == nullptr) {
1158*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_has_no_value_exception>(
1159*89c4ff92SAndroid Build Coastguard Worker m_long_name == nullptr ? "" : *m_long_name);
1160*89c4ff92SAndroid Build Coastguard Worker }
1161*89c4ff92SAndroid Build Coastguard Worker
1162*89c4ff92SAndroid Build Coastguard Worker #ifdef CXXOPTS_NO_RTTI
1163*89c4ff92SAndroid Build Coastguard Worker return static_cast<const values::standard_value<T>&>(*m_value).get();
1164*89c4ff92SAndroid Build Coastguard Worker #else
1165*89c4ff92SAndroid Build Coastguard Worker return dynamic_cast<const values::standard_value<T>&>(*m_value).get();
1166*89c4ff92SAndroid Build Coastguard Worker #endif
1167*89c4ff92SAndroid Build Coastguard Worker }
1168*89c4ff92SAndroid Build Coastguard Worker
1169*89c4ff92SAndroid Build Coastguard Worker private:
1170*89c4ff92SAndroid Build Coastguard Worker void
ensure_value(const std::shared_ptr<const OptionDetails> & details)1171*89c4ff92SAndroid Build Coastguard Worker ensure_value(const std::shared_ptr<const OptionDetails>& details)
1172*89c4ff92SAndroid Build Coastguard Worker {
1173*89c4ff92SAndroid Build Coastguard Worker if (m_value == nullptr)
1174*89c4ff92SAndroid Build Coastguard Worker {
1175*89c4ff92SAndroid Build Coastguard Worker m_value = details->make_storage();
1176*89c4ff92SAndroid Build Coastguard Worker }
1177*89c4ff92SAndroid Build Coastguard Worker }
1178*89c4ff92SAndroid Build Coastguard Worker
1179*89c4ff92SAndroid Build Coastguard Worker
1180*89c4ff92SAndroid Build Coastguard Worker const std::string* m_long_name = nullptr;
1181*89c4ff92SAndroid Build Coastguard Worker // Holding this pointer is safe, since OptionValue's only exist in key-value pairs,
1182*89c4ff92SAndroid Build Coastguard Worker // where the key has the string we point to.
1183*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<Value> m_value{};
1184*89c4ff92SAndroid Build Coastguard Worker size_t m_count = 0;
1185*89c4ff92SAndroid Build Coastguard Worker bool m_default = false;
1186*89c4ff92SAndroid Build Coastguard Worker };
1187*89c4ff92SAndroid Build Coastguard Worker
1188*89c4ff92SAndroid Build Coastguard Worker class KeyValue
1189*89c4ff92SAndroid Build Coastguard Worker {
1190*89c4ff92SAndroid Build Coastguard Worker public:
KeyValue(std::string key_,std::string value_)1191*89c4ff92SAndroid Build Coastguard Worker KeyValue(std::string key_, std::string value_)
1192*89c4ff92SAndroid Build Coastguard Worker : m_key(std::move(key_))
1193*89c4ff92SAndroid Build Coastguard Worker , m_value(std::move(value_))
1194*89c4ff92SAndroid Build Coastguard Worker {
1195*89c4ff92SAndroid Build Coastguard Worker }
1196*89c4ff92SAndroid Build Coastguard Worker
1197*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1198*89c4ff92SAndroid Build Coastguard Worker const std::string&
key() const1199*89c4ff92SAndroid Build Coastguard Worker key() const
1200*89c4ff92SAndroid Build Coastguard Worker {
1201*89c4ff92SAndroid Build Coastguard Worker return m_key;
1202*89c4ff92SAndroid Build Coastguard Worker }
1203*89c4ff92SAndroid Build Coastguard Worker
1204*89c4ff92SAndroid Build Coastguard Worker CXXOPTS_NODISCARD
1205*89c4ff92SAndroid Build Coastguard Worker const std::string&
value() const1206*89c4ff92SAndroid Build Coastguard Worker value() const
1207*89c4ff92SAndroid Build Coastguard Worker {
1208*89c4ff92SAndroid Build Coastguard Worker return m_value;
1209*89c4ff92SAndroid Build Coastguard Worker }
1210*89c4ff92SAndroid Build Coastguard Worker
1211*89c4ff92SAndroid Build Coastguard Worker template <typename T>
1212*89c4ff92SAndroid Build Coastguard Worker T
as() const1213*89c4ff92SAndroid Build Coastguard Worker as() const
1214*89c4ff92SAndroid Build Coastguard Worker {
1215*89c4ff92SAndroid Build Coastguard Worker T result;
1216*89c4ff92SAndroid Build Coastguard Worker values::parse_value(m_value, result);
1217*89c4ff92SAndroid Build Coastguard Worker return result;
1218*89c4ff92SAndroid Build Coastguard Worker }
1219*89c4ff92SAndroid Build Coastguard Worker
1220*89c4ff92SAndroid Build Coastguard Worker private:
1221*89c4ff92SAndroid Build Coastguard Worker std::string m_key;
1222*89c4ff92SAndroid Build Coastguard Worker std::string m_value;
1223*89c4ff92SAndroid Build Coastguard Worker };
1224*89c4ff92SAndroid Build Coastguard Worker
1225*89c4ff92SAndroid Build Coastguard Worker using ParsedHashMap = std::unordered_map<size_t, OptionValue>;
1226*89c4ff92SAndroid Build Coastguard Worker using NameHashMap = std::unordered_map<std::string, size_t>;
1227*89c4ff92SAndroid Build Coastguard Worker
1228*89c4ff92SAndroid Build Coastguard Worker class ParseResult
1229*89c4ff92SAndroid Build Coastguard Worker {
1230*89c4ff92SAndroid Build Coastguard Worker public:
1231*89c4ff92SAndroid Build Coastguard Worker
ParseResult()1232*89c4ff92SAndroid Build Coastguard Worker ParseResult() {}
1233*89c4ff92SAndroid Build Coastguard Worker
1234*89c4ff92SAndroid Build Coastguard Worker ParseResult(const ParseResult&) = default;
1235*89c4ff92SAndroid Build Coastguard Worker
ParseResult(NameHashMap && keys,ParsedHashMap && values,std::vector<KeyValue> sequential,std::vector<std::string> && unmatched_args)1236*89c4ff92SAndroid Build Coastguard Worker ParseResult(NameHashMap&& keys, ParsedHashMap&& values, std::vector<KeyValue> sequential, std::vector<std::string>&& unmatched_args)
1237*89c4ff92SAndroid Build Coastguard Worker : m_keys(std::move(keys))
1238*89c4ff92SAndroid Build Coastguard Worker , m_values(std::move(values))
1239*89c4ff92SAndroid Build Coastguard Worker , m_sequential(std::move(sequential))
1240*89c4ff92SAndroid Build Coastguard Worker , m_unmatched(std::move(unmatched_args))
1241*89c4ff92SAndroid Build Coastguard Worker {
1242*89c4ff92SAndroid Build Coastguard Worker }
1243*89c4ff92SAndroid Build Coastguard Worker
1244*89c4ff92SAndroid Build Coastguard Worker ParseResult& operator=(ParseResult&&) = default;
1245*89c4ff92SAndroid Build Coastguard Worker ParseResult& operator=(const ParseResult&) = default;
1246*89c4ff92SAndroid Build Coastguard Worker
1247*89c4ff92SAndroid Build Coastguard Worker size_t
count(const std::string & o) const1248*89c4ff92SAndroid Build Coastguard Worker count(const std::string& o) const
1249*89c4ff92SAndroid Build Coastguard Worker {
1250*89c4ff92SAndroid Build Coastguard Worker auto iter = m_keys.find(o);
1251*89c4ff92SAndroid Build Coastguard Worker if (iter == m_keys.end())
1252*89c4ff92SAndroid Build Coastguard Worker {
1253*89c4ff92SAndroid Build Coastguard Worker return 0;
1254*89c4ff92SAndroid Build Coastguard Worker }
1255*89c4ff92SAndroid Build Coastguard Worker
1256*89c4ff92SAndroid Build Coastguard Worker auto viter = m_values.find(iter->second);
1257*89c4ff92SAndroid Build Coastguard Worker
1258*89c4ff92SAndroid Build Coastguard Worker if (viter == m_values.end())
1259*89c4ff92SAndroid Build Coastguard Worker {
1260*89c4ff92SAndroid Build Coastguard Worker return 0;
1261*89c4ff92SAndroid Build Coastguard Worker }
1262*89c4ff92SAndroid Build Coastguard Worker
1263*89c4ff92SAndroid Build Coastguard Worker return viter->second.count();
1264*89c4ff92SAndroid Build Coastguard Worker }
1265*89c4ff92SAndroid Build Coastguard Worker
1266*89c4ff92SAndroid Build Coastguard Worker const OptionValue&
operator [](const std::string & option) const1267*89c4ff92SAndroid Build Coastguard Worker operator[](const std::string& option) const
1268*89c4ff92SAndroid Build Coastguard Worker {
1269*89c4ff92SAndroid Build Coastguard Worker auto iter = m_keys.find(option);
1270*89c4ff92SAndroid Build Coastguard Worker
1271*89c4ff92SAndroid Build Coastguard Worker if (iter == m_keys.end())
1272*89c4ff92SAndroid Build Coastguard Worker {
1273*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_not_present_exception>(option);
1274*89c4ff92SAndroid Build Coastguard Worker }
1275*89c4ff92SAndroid Build Coastguard Worker
1276*89c4ff92SAndroid Build Coastguard Worker auto viter = m_values.find(iter->second);
1277*89c4ff92SAndroid Build Coastguard Worker
1278*89c4ff92SAndroid Build Coastguard Worker if (viter == m_values.end())
1279*89c4ff92SAndroid Build Coastguard Worker {
1280*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_not_present_exception>(option);
1281*89c4ff92SAndroid Build Coastguard Worker }
1282*89c4ff92SAndroid Build Coastguard Worker
1283*89c4ff92SAndroid Build Coastguard Worker return viter->second;
1284*89c4ff92SAndroid Build Coastguard Worker }
1285*89c4ff92SAndroid Build Coastguard Worker
1286*89c4ff92SAndroid Build Coastguard Worker const std::vector<KeyValue>&
arguments() const1287*89c4ff92SAndroid Build Coastguard Worker arguments() const
1288*89c4ff92SAndroid Build Coastguard Worker {
1289*89c4ff92SAndroid Build Coastguard Worker return m_sequential;
1290*89c4ff92SAndroid Build Coastguard Worker }
1291*89c4ff92SAndroid Build Coastguard Worker
1292*89c4ff92SAndroid Build Coastguard Worker const std::vector<std::string>&
unmatched() const1293*89c4ff92SAndroid Build Coastguard Worker unmatched() const
1294*89c4ff92SAndroid Build Coastguard Worker {
1295*89c4ff92SAndroid Build Coastguard Worker return m_unmatched;
1296*89c4ff92SAndroid Build Coastguard Worker }
1297*89c4ff92SAndroid Build Coastguard Worker
1298*89c4ff92SAndroid Build Coastguard Worker private:
1299*89c4ff92SAndroid Build Coastguard Worker NameHashMap m_keys{};
1300*89c4ff92SAndroid Build Coastguard Worker ParsedHashMap m_values{};
1301*89c4ff92SAndroid Build Coastguard Worker std::vector<KeyValue> m_sequential{};
1302*89c4ff92SAndroid Build Coastguard Worker std::vector<std::string> m_unmatched{};
1303*89c4ff92SAndroid Build Coastguard Worker };
1304*89c4ff92SAndroid Build Coastguard Worker
1305*89c4ff92SAndroid Build Coastguard Worker struct Option
1306*89c4ff92SAndroid Build Coastguard Worker {
Optioncxxopts::Option1307*89c4ff92SAndroid Build Coastguard Worker Option
1308*89c4ff92SAndroid Build Coastguard Worker (
1309*89c4ff92SAndroid Build Coastguard Worker std::string opts,
1310*89c4ff92SAndroid Build Coastguard Worker std::string desc,
1311*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<const Value> value = ::cxxopts::value<bool>(),
1312*89c4ff92SAndroid Build Coastguard Worker std::string arg_help = ""
1313*89c4ff92SAndroid Build Coastguard Worker )
1314*89c4ff92SAndroid Build Coastguard Worker : opts_(std::move(opts))
1315*89c4ff92SAndroid Build Coastguard Worker , desc_(std::move(desc))
1316*89c4ff92SAndroid Build Coastguard Worker , value_(std::move(value))
1317*89c4ff92SAndroid Build Coastguard Worker , arg_help_(std::move(arg_help))
1318*89c4ff92SAndroid Build Coastguard Worker {
1319*89c4ff92SAndroid Build Coastguard Worker }
1320*89c4ff92SAndroid Build Coastguard Worker
1321*89c4ff92SAndroid Build Coastguard Worker std::string opts_;
1322*89c4ff92SAndroid Build Coastguard Worker std::string desc_;
1323*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<const Value> value_;
1324*89c4ff92SAndroid Build Coastguard Worker std::string arg_help_;
1325*89c4ff92SAndroid Build Coastguard Worker };
1326*89c4ff92SAndroid Build Coastguard Worker
1327*89c4ff92SAndroid Build Coastguard Worker using OptionMap = std::unordered_map<std::string, std::shared_ptr<OptionDetails>>;
1328*89c4ff92SAndroid Build Coastguard Worker using PositionalList = std::vector<std::string>;
1329*89c4ff92SAndroid Build Coastguard Worker using PositionalListIterator = PositionalList::const_iterator;
1330*89c4ff92SAndroid Build Coastguard Worker
1331*89c4ff92SAndroid Build Coastguard Worker class OptionParser
1332*89c4ff92SAndroid Build Coastguard Worker {
1333*89c4ff92SAndroid Build Coastguard Worker public:
OptionParser(const OptionMap & options,const PositionalList & positional,bool allow_unrecognised)1334*89c4ff92SAndroid Build Coastguard Worker OptionParser(const OptionMap& options, const PositionalList& positional, bool allow_unrecognised)
1335*89c4ff92SAndroid Build Coastguard Worker : m_options(options)
1336*89c4ff92SAndroid Build Coastguard Worker , m_positional(positional)
1337*89c4ff92SAndroid Build Coastguard Worker , m_allow_unrecognised(allow_unrecognised)
1338*89c4ff92SAndroid Build Coastguard Worker {
1339*89c4ff92SAndroid Build Coastguard Worker }
1340*89c4ff92SAndroid Build Coastguard Worker
1341*89c4ff92SAndroid Build Coastguard Worker ParseResult
1342*89c4ff92SAndroid Build Coastguard Worker parse(int argc, const char* const* argv);
1343*89c4ff92SAndroid Build Coastguard Worker
1344*89c4ff92SAndroid Build Coastguard Worker bool
1345*89c4ff92SAndroid Build Coastguard Worker consume_positional(const std::string& a, PositionalListIterator& next);
1346*89c4ff92SAndroid Build Coastguard Worker
1347*89c4ff92SAndroid Build Coastguard Worker void
1348*89c4ff92SAndroid Build Coastguard Worker checked_parse_arg
1349*89c4ff92SAndroid Build Coastguard Worker (
1350*89c4ff92SAndroid Build Coastguard Worker int argc,
1351*89c4ff92SAndroid Build Coastguard Worker const char* const* argv,
1352*89c4ff92SAndroid Build Coastguard Worker int& current,
1353*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<OptionDetails>& value,
1354*89c4ff92SAndroid Build Coastguard Worker const std::string& name
1355*89c4ff92SAndroid Build Coastguard Worker );
1356*89c4ff92SAndroid Build Coastguard Worker
1357*89c4ff92SAndroid Build Coastguard Worker void
1358*89c4ff92SAndroid Build Coastguard Worker add_to_option(OptionMap::const_iterator iter, const std::string& option, const std::string& arg);
1359*89c4ff92SAndroid Build Coastguard Worker
1360*89c4ff92SAndroid Build Coastguard Worker void
1361*89c4ff92SAndroid Build Coastguard Worker parse_option
1362*89c4ff92SAndroid Build Coastguard Worker (
1363*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<OptionDetails>& value,
1364*89c4ff92SAndroid Build Coastguard Worker const std::string& name,
1365*89c4ff92SAndroid Build Coastguard Worker const std::string& arg = ""
1366*89c4ff92SAndroid Build Coastguard Worker );
1367*89c4ff92SAndroid Build Coastguard Worker
1368*89c4ff92SAndroid Build Coastguard Worker void
1369*89c4ff92SAndroid Build Coastguard Worker parse_default(const std::shared_ptr<OptionDetails>& details);
1370*89c4ff92SAndroid Build Coastguard Worker
1371*89c4ff92SAndroid Build Coastguard Worker private:
1372*89c4ff92SAndroid Build Coastguard Worker
1373*89c4ff92SAndroid Build Coastguard Worker void finalise_aliases();
1374*89c4ff92SAndroid Build Coastguard Worker
1375*89c4ff92SAndroid Build Coastguard Worker const OptionMap& m_options;
1376*89c4ff92SAndroid Build Coastguard Worker const PositionalList& m_positional;
1377*89c4ff92SAndroid Build Coastguard Worker
1378*89c4ff92SAndroid Build Coastguard Worker std::vector<KeyValue> m_sequential{};
1379*89c4ff92SAndroid Build Coastguard Worker bool m_allow_unrecognised;
1380*89c4ff92SAndroid Build Coastguard Worker
1381*89c4ff92SAndroid Build Coastguard Worker ParsedHashMap m_parsed{};
1382*89c4ff92SAndroid Build Coastguard Worker NameHashMap m_keys{};
1383*89c4ff92SAndroid Build Coastguard Worker };
1384*89c4ff92SAndroid Build Coastguard Worker
1385*89c4ff92SAndroid Build Coastguard Worker class Options
1386*89c4ff92SAndroid Build Coastguard Worker {
1387*89c4ff92SAndroid Build Coastguard Worker public:
1388*89c4ff92SAndroid Build Coastguard Worker
Options(std::string program,std::string help_string="")1389*89c4ff92SAndroid Build Coastguard Worker explicit Options(std::string program, std::string help_string = "")
1390*89c4ff92SAndroid Build Coastguard Worker : m_program(std::move(program))
1391*89c4ff92SAndroid Build Coastguard Worker , m_help_string(toLocalString(std::move(help_string)))
1392*89c4ff92SAndroid Build Coastguard Worker , m_custom_help("[OPTION...]")
1393*89c4ff92SAndroid Build Coastguard Worker , m_positional_help("positional parameters")
1394*89c4ff92SAndroid Build Coastguard Worker , m_show_positional(false)
1395*89c4ff92SAndroid Build Coastguard Worker , m_allow_unrecognised(false)
1396*89c4ff92SAndroid Build Coastguard Worker , m_options(std::make_shared<OptionMap>())
1397*89c4ff92SAndroid Build Coastguard Worker {
1398*89c4ff92SAndroid Build Coastguard Worker }
1399*89c4ff92SAndroid Build Coastguard Worker
1400*89c4ff92SAndroid Build Coastguard Worker Options&
positional_help(std::string help_text)1401*89c4ff92SAndroid Build Coastguard Worker positional_help(std::string help_text)
1402*89c4ff92SAndroid Build Coastguard Worker {
1403*89c4ff92SAndroid Build Coastguard Worker m_positional_help = std::move(help_text);
1404*89c4ff92SAndroid Build Coastguard Worker return *this;
1405*89c4ff92SAndroid Build Coastguard Worker }
1406*89c4ff92SAndroid Build Coastguard Worker
1407*89c4ff92SAndroid Build Coastguard Worker Options&
custom_help(std::string help_text)1408*89c4ff92SAndroid Build Coastguard Worker custom_help(std::string help_text)
1409*89c4ff92SAndroid Build Coastguard Worker {
1410*89c4ff92SAndroid Build Coastguard Worker m_custom_help = std::move(help_text);
1411*89c4ff92SAndroid Build Coastguard Worker return *this;
1412*89c4ff92SAndroid Build Coastguard Worker }
1413*89c4ff92SAndroid Build Coastguard Worker
1414*89c4ff92SAndroid Build Coastguard Worker Options&
show_positional_help()1415*89c4ff92SAndroid Build Coastguard Worker show_positional_help()
1416*89c4ff92SAndroid Build Coastguard Worker {
1417*89c4ff92SAndroid Build Coastguard Worker m_show_positional = true;
1418*89c4ff92SAndroid Build Coastguard Worker return *this;
1419*89c4ff92SAndroid Build Coastguard Worker }
1420*89c4ff92SAndroid Build Coastguard Worker
1421*89c4ff92SAndroid Build Coastguard Worker Options&
allow_unrecognised_options()1422*89c4ff92SAndroid Build Coastguard Worker allow_unrecognised_options()
1423*89c4ff92SAndroid Build Coastguard Worker {
1424*89c4ff92SAndroid Build Coastguard Worker m_allow_unrecognised = true;
1425*89c4ff92SAndroid Build Coastguard Worker return *this;
1426*89c4ff92SAndroid Build Coastguard Worker }
1427*89c4ff92SAndroid Build Coastguard Worker
1428*89c4ff92SAndroid Build Coastguard Worker ParseResult
1429*89c4ff92SAndroid Build Coastguard Worker parse(int argc, const char* const* argv);
1430*89c4ff92SAndroid Build Coastguard Worker
1431*89c4ff92SAndroid Build Coastguard Worker OptionAdder
1432*89c4ff92SAndroid Build Coastguard Worker add_options(std::string group = "");
1433*89c4ff92SAndroid Build Coastguard Worker
1434*89c4ff92SAndroid Build Coastguard Worker void
1435*89c4ff92SAndroid Build Coastguard Worker add_options
1436*89c4ff92SAndroid Build Coastguard Worker (
1437*89c4ff92SAndroid Build Coastguard Worker const std::string& group,
1438*89c4ff92SAndroid Build Coastguard Worker std::initializer_list<Option> options
1439*89c4ff92SAndroid Build Coastguard Worker );
1440*89c4ff92SAndroid Build Coastguard Worker
1441*89c4ff92SAndroid Build Coastguard Worker void
1442*89c4ff92SAndroid Build Coastguard Worker add_option
1443*89c4ff92SAndroid Build Coastguard Worker (
1444*89c4ff92SAndroid Build Coastguard Worker const std::string& group,
1445*89c4ff92SAndroid Build Coastguard Worker const Option& option
1446*89c4ff92SAndroid Build Coastguard Worker );
1447*89c4ff92SAndroid Build Coastguard Worker
1448*89c4ff92SAndroid Build Coastguard Worker void
1449*89c4ff92SAndroid Build Coastguard Worker add_option
1450*89c4ff92SAndroid Build Coastguard Worker (
1451*89c4ff92SAndroid Build Coastguard Worker const std::string& group,
1452*89c4ff92SAndroid Build Coastguard Worker const std::string& s,
1453*89c4ff92SAndroid Build Coastguard Worker const std::string& l,
1454*89c4ff92SAndroid Build Coastguard Worker std::string desc,
1455*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<const Value>& value,
1456*89c4ff92SAndroid Build Coastguard Worker std::string arg_help
1457*89c4ff92SAndroid Build Coastguard Worker );
1458*89c4ff92SAndroid Build Coastguard Worker
1459*89c4ff92SAndroid Build Coastguard Worker //parse positional arguments into the given option
1460*89c4ff92SAndroid Build Coastguard Worker void
1461*89c4ff92SAndroid Build Coastguard Worker parse_positional(std::string option);
1462*89c4ff92SAndroid Build Coastguard Worker
1463*89c4ff92SAndroid Build Coastguard Worker void
1464*89c4ff92SAndroid Build Coastguard Worker parse_positional(std::vector<std::string> options);
1465*89c4ff92SAndroid Build Coastguard Worker
1466*89c4ff92SAndroid Build Coastguard Worker void
1467*89c4ff92SAndroid Build Coastguard Worker parse_positional(std::initializer_list<std::string> options);
1468*89c4ff92SAndroid Build Coastguard Worker
1469*89c4ff92SAndroid Build Coastguard Worker template <typename Iterator>
1470*89c4ff92SAndroid Build Coastguard Worker void
parse_positional(Iterator begin,Iterator end)1471*89c4ff92SAndroid Build Coastguard Worker parse_positional(Iterator begin, Iterator end) {
1472*89c4ff92SAndroid Build Coastguard Worker parse_positional(std::vector<std::string>{begin, end});
1473*89c4ff92SAndroid Build Coastguard Worker }
1474*89c4ff92SAndroid Build Coastguard Worker
1475*89c4ff92SAndroid Build Coastguard Worker std::string
1476*89c4ff92SAndroid Build Coastguard Worker help(const std::vector<std::string>& groups = {}) const;
1477*89c4ff92SAndroid Build Coastguard Worker
1478*89c4ff92SAndroid Build Coastguard Worker std::vector<std::string>
1479*89c4ff92SAndroid Build Coastguard Worker groups() const;
1480*89c4ff92SAndroid Build Coastguard Worker
1481*89c4ff92SAndroid Build Coastguard Worker const HelpGroupDetails&
1482*89c4ff92SAndroid Build Coastguard Worker group_help(const std::string& group) const;
1483*89c4ff92SAndroid Build Coastguard Worker
1484*89c4ff92SAndroid Build Coastguard Worker private:
1485*89c4ff92SAndroid Build Coastguard Worker
1486*89c4ff92SAndroid Build Coastguard Worker void
1487*89c4ff92SAndroid Build Coastguard Worker add_one_option
1488*89c4ff92SAndroid Build Coastguard Worker (
1489*89c4ff92SAndroid Build Coastguard Worker const std::string& option,
1490*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<OptionDetails>& details
1491*89c4ff92SAndroid Build Coastguard Worker );
1492*89c4ff92SAndroid Build Coastguard Worker
1493*89c4ff92SAndroid Build Coastguard Worker String
1494*89c4ff92SAndroid Build Coastguard Worker help_one_group(const std::string& group) const;
1495*89c4ff92SAndroid Build Coastguard Worker
1496*89c4ff92SAndroid Build Coastguard Worker void
1497*89c4ff92SAndroid Build Coastguard Worker generate_group_help
1498*89c4ff92SAndroid Build Coastguard Worker (
1499*89c4ff92SAndroid Build Coastguard Worker String& result,
1500*89c4ff92SAndroid Build Coastguard Worker const std::vector<std::string>& groups
1501*89c4ff92SAndroid Build Coastguard Worker ) const;
1502*89c4ff92SAndroid Build Coastguard Worker
1503*89c4ff92SAndroid Build Coastguard Worker void
1504*89c4ff92SAndroid Build Coastguard Worker generate_all_groups_help(String& result) const;
1505*89c4ff92SAndroid Build Coastguard Worker
1506*89c4ff92SAndroid Build Coastguard Worker std::string m_program{};
1507*89c4ff92SAndroid Build Coastguard Worker String m_help_string{};
1508*89c4ff92SAndroid Build Coastguard Worker std::string m_custom_help{};
1509*89c4ff92SAndroid Build Coastguard Worker std::string m_positional_help{};
1510*89c4ff92SAndroid Build Coastguard Worker bool m_show_positional;
1511*89c4ff92SAndroid Build Coastguard Worker bool m_allow_unrecognised;
1512*89c4ff92SAndroid Build Coastguard Worker
1513*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<OptionMap> m_options;
1514*89c4ff92SAndroid Build Coastguard Worker std::vector<std::string> m_positional{};
1515*89c4ff92SAndroid Build Coastguard Worker std::unordered_set<std::string> m_positional_set{};
1516*89c4ff92SAndroid Build Coastguard Worker
1517*89c4ff92SAndroid Build Coastguard Worker //mapping from groups to help options
1518*89c4ff92SAndroid Build Coastguard Worker std::map<std::string, HelpGroupDetails> m_help{};
1519*89c4ff92SAndroid Build Coastguard Worker
1520*89c4ff92SAndroid Build Coastguard Worker std::list<OptionDetails> m_option_list{};
1521*89c4ff92SAndroid Build Coastguard Worker std::unordered_map<std::string, decltype(m_option_list)::iterator> m_option_map{};
1522*89c4ff92SAndroid Build Coastguard Worker };
1523*89c4ff92SAndroid Build Coastguard Worker
1524*89c4ff92SAndroid Build Coastguard Worker class OptionAdder
1525*89c4ff92SAndroid Build Coastguard Worker {
1526*89c4ff92SAndroid Build Coastguard Worker public:
1527*89c4ff92SAndroid Build Coastguard Worker
OptionAdder(Options & options,std::string group)1528*89c4ff92SAndroid Build Coastguard Worker OptionAdder(Options& options, std::string group)
1529*89c4ff92SAndroid Build Coastguard Worker : m_options(options), m_group(std::move(group))
1530*89c4ff92SAndroid Build Coastguard Worker {
1531*89c4ff92SAndroid Build Coastguard Worker }
1532*89c4ff92SAndroid Build Coastguard Worker
1533*89c4ff92SAndroid Build Coastguard Worker OptionAdder&
1534*89c4ff92SAndroid Build Coastguard Worker operator()
1535*89c4ff92SAndroid Build Coastguard Worker (
1536*89c4ff92SAndroid Build Coastguard Worker const std::string& opts,
1537*89c4ff92SAndroid Build Coastguard Worker const std::string& desc,
1538*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<const Value>& value
1539*89c4ff92SAndroid Build Coastguard Worker = ::cxxopts::value<bool>(),
1540*89c4ff92SAndroid Build Coastguard Worker std::string arg_help = ""
1541*89c4ff92SAndroid Build Coastguard Worker );
1542*89c4ff92SAndroid Build Coastguard Worker
1543*89c4ff92SAndroid Build Coastguard Worker private:
1544*89c4ff92SAndroid Build Coastguard Worker Options& m_options;
1545*89c4ff92SAndroid Build Coastguard Worker std::string m_group;
1546*89c4ff92SAndroid Build Coastguard Worker };
1547*89c4ff92SAndroid Build Coastguard Worker
1548*89c4ff92SAndroid Build Coastguard Worker namespace
1549*89c4ff92SAndroid Build Coastguard Worker {
1550*89c4ff92SAndroid Build Coastguard Worker constexpr int OPTION_LONGEST = 30;
1551*89c4ff92SAndroid Build Coastguard Worker constexpr int OPTION_DESC_GAP = 2;
1552*89c4ff92SAndroid Build Coastguard Worker
1553*89c4ff92SAndroid Build Coastguard Worker std::basic_regex<char> option_matcher
1554*89c4ff92SAndroid Build Coastguard Worker ("--([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([[:alnum:]]+)");
1555*89c4ff92SAndroid Build Coastguard Worker
1556*89c4ff92SAndroid Build Coastguard Worker std::basic_regex<char> option_specifier
1557*89c4ff92SAndroid Build Coastguard Worker ("(([[:alnum:]]),)?[ ]*([[:alnum:]][-_[:alnum:]]*)?");
1558*89c4ff92SAndroid Build Coastguard Worker
1559*89c4ff92SAndroid Build Coastguard Worker String
format_option(const HelpOptionDetails & o)1560*89c4ff92SAndroid Build Coastguard Worker format_option
1561*89c4ff92SAndroid Build Coastguard Worker (
1562*89c4ff92SAndroid Build Coastguard Worker const HelpOptionDetails& o
1563*89c4ff92SAndroid Build Coastguard Worker )
1564*89c4ff92SAndroid Build Coastguard Worker {
1565*89c4ff92SAndroid Build Coastguard Worker const auto& s = o.s;
1566*89c4ff92SAndroid Build Coastguard Worker const auto& l = o.l;
1567*89c4ff92SAndroid Build Coastguard Worker
1568*89c4ff92SAndroid Build Coastguard Worker String result = " ";
1569*89c4ff92SAndroid Build Coastguard Worker
1570*89c4ff92SAndroid Build Coastguard Worker if (!s.empty())
1571*89c4ff92SAndroid Build Coastguard Worker {
1572*89c4ff92SAndroid Build Coastguard Worker result += "-" + toLocalString(s);
1573*89c4ff92SAndroid Build Coastguard Worker if (!l.empty())
1574*89c4ff92SAndroid Build Coastguard Worker {
1575*89c4ff92SAndroid Build Coastguard Worker result += ",";
1576*89c4ff92SAndroid Build Coastguard Worker }
1577*89c4ff92SAndroid Build Coastguard Worker }
1578*89c4ff92SAndroid Build Coastguard Worker else
1579*89c4ff92SAndroid Build Coastguard Worker {
1580*89c4ff92SAndroid Build Coastguard Worker result += " ";
1581*89c4ff92SAndroid Build Coastguard Worker }
1582*89c4ff92SAndroid Build Coastguard Worker
1583*89c4ff92SAndroid Build Coastguard Worker if (!l.empty())
1584*89c4ff92SAndroid Build Coastguard Worker {
1585*89c4ff92SAndroid Build Coastguard Worker result += " --" + toLocalString(l);
1586*89c4ff92SAndroid Build Coastguard Worker }
1587*89c4ff92SAndroid Build Coastguard Worker
1588*89c4ff92SAndroid Build Coastguard Worker auto arg = !o.arg_help.empty() ? toLocalString(o.arg_help) : "arg";
1589*89c4ff92SAndroid Build Coastguard Worker
1590*89c4ff92SAndroid Build Coastguard Worker if (!o.is_boolean)
1591*89c4ff92SAndroid Build Coastguard Worker {
1592*89c4ff92SAndroid Build Coastguard Worker if (o.has_implicit)
1593*89c4ff92SAndroid Build Coastguard Worker {
1594*89c4ff92SAndroid Build Coastguard Worker result += " [=" + arg + "(=" + toLocalString(o.implicit_value) + ")]";
1595*89c4ff92SAndroid Build Coastguard Worker }
1596*89c4ff92SAndroid Build Coastguard Worker else
1597*89c4ff92SAndroid Build Coastguard Worker {
1598*89c4ff92SAndroid Build Coastguard Worker result += " " + arg;
1599*89c4ff92SAndroid Build Coastguard Worker }
1600*89c4ff92SAndroid Build Coastguard Worker }
1601*89c4ff92SAndroid Build Coastguard Worker
1602*89c4ff92SAndroid Build Coastguard Worker return result;
1603*89c4ff92SAndroid Build Coastguard Worker }
1604*89c4ff92SAndroid Build Coastguard Worker
1605*89c4ff92SAndroid Build Coastguard Worker String
format_description(const HelpOptionDetails & o,size_t start,size_t width)1606*89c4ff92SAndroid Build Coastguard Worker format_description
1607*89c4ff92SAndroid Build Coastguard Worker (
1608*89c4ff92SAndroid Build Coastguard Worker const HelpOptionDetails& o,
1609*89c4ff92SAndroid Build Coastguard Worker size_t start,
1610*89c4ff92SAndroid Build Coastguard Worker size_t width
1611*89c4ff92SAndroid Build Coastguard Worker )
1612*89c4ff92SAndroid Build Coastguard Worker {
1613*89c4ff92SAndroid Build Coastguard Worker auto desc = o.desc;
1614*89c4ff92SAndroid Build Coastguard Worker
1615*89c4ff92SAndroid Build Coastguard Worker if (o.has_default && (!o.is_boolean || o.default_value != "false"))
1616*89c4ff92SAndroid Build Coastguard Worker {
1617*89c4ff92SAndroid Build Coastguard Worker if(!o.default_value.empty())
1618*89c4ff92SAndroid Build Coastguard Worker {
1619*89c4ff92SAndroid Build Coastguard Worker desc += toLocalString(" (default: " + o.default_value + ")");
1620*89c4ff92SAndroid Build Coastguard Worker }
1621*89c4ff92SAndroid Build Coastguard Worker else
1622*89c4ff92SAndroid Build Coastguard Worker {
1623*89c4ff92SAndroid Build Coastguard Worker desc += toLocalString(" (default: \"\")");
1624*89c4ff92SAndroid Build Coastguard Worker }
1625*89c4ff92SAndroid Build Coastguard Worker }
1626*89c4ff92SAndroid Build Coastguard Worker
1627*89c4ff92SAndroid Build Coastguard Worker String result;
1628*89c4ff92SAndroid Build Coastguard Worker
1629*89c4ff92SAndroid Build Coastguard Worker auto current = std::begin(desc);
1630*89c4ff92SAndroid Build Coastguard Worker auto startLine = current;
1631*89c4ff92SAndroid Build Coastguard Worker auto lastSpace = current;
1632*89c4ff92SAndroid Build Coastguard Worker
1633*89c4ff92SAndroid Build Coastguard Worker auto size = size_t{};
1634*89c4ff92SAndroid Build Coastguard Worker
1635*89c4ff92SAndroid Build Coastguard Worker while (current != std::end(desc))
1636*89c4ff92SAndroid Build Coastguard Worker {
1637*89c4ff92SAndroid Build Coastguard Worker if (*current == ' ')
1638*89c4ff92SAndroid Build Coastguard Worker {
1639*89c4ff92SAndroid Build Coastguard Worker lastSpace = current;
1640*89c4ff92SAndroid Build Coastguard Worker }
1641*89c4ff92SAndroid Build Coastguard Worker
1642*89c4ff92SAndroid Build Coastguard Worker if (*current == '\n')
1643*89c4ff92SAndroid Build Coastguard Worker {
1644*89c4ff92SAndroid Build Coastguard Worker startLine = current + 1;
1645*89c4ff92SAndroid Build Coastguard Worker lastSpace = startLine;
1646*89c4ff92SAndroid Build Coastguard Worker }
1647*89c4ff92SAndroid Build Coastguard Worker else if (size > width)
1648*89c4ff92SAndroid Build Coastguard Worker {
1649*89c4ff92SAndroid Build Coastguard Worker if (lastSpace == startLine)
1650*89c4ff92SAndroid Build Coastguard Worker {
1651*89c4ff92SAndroid Build Coastguard Worker stringAppend(result, startLine, current + 1);
1652*89c4ff92SAndroid Build Coastguard Worker stringAppend(result, "\n");
1653*89c4ff92SAndroid Build Coastguard Worker stringAppend(result, start, ' ');
1654*89c4ff92SAndroid Build Coastguard Worker startLine = current + 1;
1655*89c4ff92SAndroid Build Coastguard Worker lastSpace = startLine;
1656*89c4ff92SAndroid Build Coastguard Worker }
1657*89c4ff92SAndroid Build Coastguard Worker else
1658*89c4ff92SAndroid Build Coastguard Worker {
1659*89c4ff92SAndroid Build Coastguard Worker stringAppend(result, startLine, lastSpace);
1660*89c4ff92SAndroid Build Coastguard Worker stringAppend(result, "\n");
1661*89c4ff92SAndroid Build Coastguard Worker stringAppend(result, start, ' ');
1662*89c4ff92SAndroid Build Coastguard Worker startLine = lastSpace + 1;
1663*89c4ff92SAndroid Build Coastguard Worker lastSpace = startLine;
1664*89c4ff92SAndroid Build Coastguard Worker }
1665*89c4ff92SAndroid Build Coastguard Worker size = 0;
1666*89c4ff92SAndroid Build Coastguard Worker }
1667*89c4ff92SAndroid Build Coastguard Worker else
1668*89c4ff92SAndroid Build Coastguard Worker {
1669*89c4ff92SAndroid Build Coastguard Worker ++size;
1670*89c4ff92SAndroid Build Coastguard Worker }
1671*89c4ff92SAndroid Build Coastguard Worker
1672*89c4ff92SAndroid Build Coastguard Worker ++current;
1673*89c4ff92SAndroid Build Coastguard Worker }
1674*89c4ff92SAndroid Build Coastguard Worker
1675*89c4ff92SAndroid Build Coastguard Worker //append whatever is left
1676*89c4ff92SAndroid Build Coastguard Worker stringAppend(result, startLine, current);
1677*89c4ff92SAndroid Build Coastguard Worker
1678*89c4ff92SAndroid Build Coastguard Worker return result;
1679*89c4ff92SAndroid Build Coastguard Worker }
1680*89c4ff92SAndroid Build Coastguard Worker } // namespace
1681*89c4ff92SAndroid Build Coastguard Worker
1682*89c4ff92SAndroid Build Coastguard Worker inline
1683*89c4ff92SAndroid Build Coastguard Worker void
add_options(const std::string & group,std::initializer_list<Option> options)1684*89c4ff92SAndroid Build Coastguard Worker Options::add_options
1685*89c4ff92SAndroid Build Coastguard Worker (
1686*89c4ff92SAndroid Build Coastguard Worker const std::string &group,
1687*89c4ff92SAndroid Build Coastguard Worker std::initializer_list<Option> options
1688*89c4ff92SAndroid Build Coastguard Worker )
1689*89c4ff92SAndroid Build Coastguard Worker {
1690*89c4ff92SAndroid Build Coastguard Worker OptionAdder option_adder(*this, group);
1691*89c4ff92SAndroid Build Coastguard Worker for (const auto &option: options)
1692*89c4ff92SAndroid Build Coastguard Worker {
1693*89c4ff92SAndroid Build Coastguard Worker option_adder(option.opts_, option.desc_, option.value_, option.arg_help_);
1694*89c4ff92SAndroid Build Coastguard Worker }
1695*89c4ff92SAndroid Build Coastguard Worker }
1696*89c4ff92SAndroid Build Coastguard Worker
1697*89c4ff92SAndroid Build Coastguard Worker inline
1698*89c4ff92SAndroid Build Coastguard Worker OptionAdder
add_options(std::string group)1699*89c4ff92SAndroid Build Coastguard Worker Options::add_options(std::string group)
1700*89c4ff92SAndroid Build Coastguard Worker {
1701*89c4ff92SAndroid Build Coastguard Worker return OptionAdder(*this, std::move(group));
1702*89c4ff92SAndroid Build Coastguard Worker }
1703*89c4ff92SAndroid Build Coastguard Worker
1704*89c4ff92SAndroid Build Coastguard Worker inline
1705*89c4ff92SAndroid Build Coastguard Worker OptionAdder&
operator ()(const std::string & opts,const std::string & desc,const std::shared_ptr<const Value> & value,std::string arg_help)1706*89c4ff92SAndroid Build Coastguard Worker OptionAdder::operator()
1707*89c4ff92SAndroid Build Coastguard Worker (
1708*89c4ff92SAndroid Build Coastguard Worker const std::string& opts,
1709*89c4ff92SAndroid Build Coastguard Worker const std::string& desc,
1710*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<const Value>& value,
1711*89c4ff92SAndroid Build Coastguard Worker std::string arg_help
1712*89c4ff92SAndroid Build Coastguard Worker )
1713*89c4ff92SAndroid Build Coastguard Worker {
1714*89c4ff92SAndroid Build Coastguard Worker std::match_results<const char*> result;
1715*89c4ff92SAndroid Build Coastguard Worker std::regex_match(opts.c_str(), result, option_specifier);
1716*89c4ff92SAndroid Build Coastguard Worker
1717*89c4ff92SAndroid Build Coastguard Worker if (result.empty())
1718*89c4ff92SAndroid Build Coastguard Worker {
1719*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<invalid_option_format_error>(opts);
1720*89c4ff92SAndroid Build Coastguard Worker }
1721*89c4ff92SAndroid Build Coastguard Worker
1722*89c4ff92SAndroid Build Coastguard Worker const auto& short_match = result[2];
1723*89c4ff92SAndroid Build Coastguard Worker const auto& long_match = result[3];
1724*89c4ff92SAndroid Build Coastguard Worker
1725*89c4ff92SAndroid Build Coastguard Worker if (!short_match.length() && !long_match.length())
1726*89c4ff92SAndroid Build Coastguard Worker {
1727*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<invalid_option_format_error>(opts);
1728*89c4ff92SAndroid Build Coastguard Worker } else if (long_match.length() == 1 && short_match.length())
1729*89c4ff92SAndroid Build Coastguard Worker {
1730*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<invalid_option_format_error>(opts);
1731*89c4ff92SAndroid Build Coastguard Worker }
1732*89c4ff92SAndroid Build Coastguard Worker
1733*89c4ff92SAndroid Build Coastguard Worker auto option_names = []
1734*89c4ff92SAndroid Build Coastguard Worker (
1735*89c4ff92SAndroid Build Coastguard Worker const std::sub_match<const char*>& short_,
1736*89c4ff92SAndroid Build Coastguard Worker const std::sub_match<const char*>& long_
1737*89c4ff92SAndroid Build Coastguard Worker )
1738*89c4ff92SAndroid Build Coastguard Worker {
1739*89c4ff92SAndroid Build Coastguard Worker if (long_.length() == 1)
1740*89c4ff92SAndroid Build Coastguard Worker {
1741*89c4ff92SAndroid Build Coastguard Worker return std::make_tuple(long_.str(), short_.str());
1742*89c4ff92SAndroid Build Coastguard Worker }
1743*89c4ff92SAndroid Build Coastguard Worker return std::make_tuple(short_.str(), long_.str());
1744*89c4ff92SAndroid Build Coastguard Worker }(short_match, long_match);
1745*89c4ff92SAndroid Build Coastguard Worker
1746*89c4ff92SAndroid Build Coastguard Worker m_options.add_option
1747*89c4ff92SAndroid Build Coastguard Worker (
1748*89c4ff92SAndroid Build Coastguard Worker m_group,
1749*89c4ff92SAndroid Build Coastguard Worker std::get<0>(option_names),
1750*89c4ff92SAndroid Build Coastguard Worker std::get<1>(option_names),
1751*89c4ff92SAndroid Build Coastguard Worker desc,
1752*89c4ff92SAndroid Build Coastguard Worker value,
1753*89c4ff92SAndroid Build Coastguard Worker std::move(arg_help)
1754*89c4ff92SAndroid Build Coastguard Worker );
1755*89c4ff92SAndroid Build Coastguard Worker
1756*89c4ff92SAndroid Build Coastguard Worker return *this;
1757*89c4ff92SAndroid Build Coastguard Worker }
1758*89c4ff92SAndroid Build Coastguard Worker
1759*89c4ff92SAndroid Build Coastguard Worker inline
1760*89c4ff92SAndroid Build Coastguard Worker void
parse_default(const std::shared_ptr<OptionDetails> & details)1761*89c4ff92SAndroid Build Coastguard Worker OptionParser::parse_default(const std::shared_ptr<OptionDetails>& details)
1762*89c4ff92SAndroid Build Coastguard Worker {
1763*89c4ff92SAndroid Build Coastguard Worker // TODO: remove the duplicate code here
1764*89c4ff92SAndroid Build Coastguard Worker auto& store = m_parsed[details->hash()];
1765*89c4ff92SAndroid Build Coastguard Worker store.parse_default(details);
1766*89c4ff92SAndroid Build Coastguard Worker }
1767*89c4ff92SAndroid Build Coastguard Worker
1768*89c4ff92SAndroid Build Coastguard Worker inline
1769*89c4ff92SAndroid Build Coastguard Worker void
parse_option(const std::shared_ptr<OptionDetails> & value,const std::string &,const std::string & arg)1770*89c4ff92SAndroid Build Coastguard Worker OptionParser::parse_option
1771*89c4ff92SAndroid Build Coastguard Worker (
1772*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<OptionDetails>& value,
1773*89c4ff92SAndroid Build Coastguard Worker const std::string& /*name*/,
1774*89c4ff92SAndroid Build Coastguard Worker const std::string& arg
1775*89c4ff92SAndroid Build Coastguard Worker )
1776*89c4ff92SAndroid Build Coastguard Worker {
1777*89c4ff92SAndroid Build Coastguard Worker auto hash = value->hash();
1778*89c4ff92SAndroid Build Coastguard Worker auto& result = m_parsed[hash];
1779*89c4ff92SAndroid Build Coastguard Worker result.parse(value, arg);
1780*89c4ff92SAndroid Build Coastguard Worker
1781*89c4ff92SAndroid Build Coastguard Worker m_sequential.emplace_back(value->long_name(), arg);
1782*89c4ff92SAndroid Build Coastguard Worker }
1783*89c4ff92SAndroid Build Coastguard Worker
1784*89c4ff92SAndroid Build Coastguard Worker inline
1785*89c4ff92SAndroid Build Coastguard Worker void
checked_parse_arg(int argc,const char * const * argv,int & current,const std::shared_ptr<OptionDetails> & value,const std::string & name)1786*89c4ff92SAndroid Build Coastguard Worker OptionParser::checked_parse_arg
1787*89c4ff92SAndroid Build Coastguard Worker (
1788*89c4ff92SAndroid Build Coastguard Worker int argc,
1789*89c4ff92SAndroid Build Coastguard Worker const char* const* argv,
1790*89c4ff92SAndroid Build Coastguard Worker int& current,
1791*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<OptionDetails>& value,
1792*89c4ff92SAndroid Build Coastguard Worker const std::string& name
1793*89c4ff92SAndroid Build Coastguard Worker )
1794*89c4ff92SAndroid Build Coastguard Worker {
1795*89c4ff92SAndroid Build Coastguard Worker if (current + 1 >= argc)
1796*89c4ff92SAndroid Build Coastguard Worker {
1797*89c4ff92SAndroid Build Coastguard Worker if (value->value().has_implicit())
1798*89c4ff92SAndroid Build Coastguard Worker {
1799*89c4ff92SAndroid Build Coastguard Worker parse_option(value, name, value->value().get_implicit_value());
1800*89c4ff92SAndroid Build Coastguard Worker }
1801*89c4ff92SAndroid Build Coastguard Worker else
1802*89c4ff92SAndroid Build Coastguard Worker {
1803*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<missing_argument_exception>(name);
1804*89c4ff92SAndroid Build Coastguard Worker }
1805*89c4ff92SAndroid Build Coastguard Worker }
1806*89c4ff92SAndroid Build Coastguard Worker else
1807*89c4ff92SAndroid Build Coastguard Worker {
1808*89c4ff92SAndroid Build Coastguard Worker if (value->value().has_implicit())
1809*89c4ff92SAndroid Build Coastguard Worker {
1810*89c4ff92SAndroid Build Coastguard Worker parse_option(value, name, value->value().get_implicit_value());
1811*89c4ff92SAndroid Build Coastguard Worker }
1812*89c4ff92SAndroid Build Coastguard Worker else
1813*89c4ff92SAndroid Build Coastguard Worker {
1814*89c4ff92SAndroid Build Coastguard Worker parse_option(value, name, argv[current + 1]);
1815*89c4ff92SAndroid Build Coastguard Worker ++current;
1816*89c4ff92SAndroid Build Coastguard Worker }
1817*89c4ff92SAndroid Build Coastguard Worker }
1818*89c4ff92SAndroid Build Coastguard Worker }
1819*89c4ff92SAndroid Build Coastguard Worker
1820*89c4ff92SAndroid Build Coastguard Worker inline
1821*89c4ff92SAndroid Build Coastguard Worker void
add_to_option(OptionMap::const_iterator iter,const std::string & option,const std::string & arg)1822*89c4ff92SAndroid Build Coastguard Worker OptionParser::add_to_option(OptionMap::const_iterator iter, const std::string& option, const std::string& arg)
1823*89c4ff92SAndroid Build Coastguard Worker {
1824*89c4ff92SAndroid Build Coastguard Worker parse_option(iter->second, option, arg);
1825*89c4ff92SAndroid Build Coastguard Worker }
1826*89c4ff92SAndroid Build Coastguard Worker
1827*89c4ff92SAndroid Build Coastguard Worker inline
1828*89c4ff92SAndroid Build Coastguard Worker bool
consume_positional(const std::string & a,PositionalListIterator & next)1829*89c4ff92SAndroid Build Coastguard Worker OptionParser::consume_positional(const std::string& a, PositionalListIterator& next)
1830*89c4ff92SAndroid Build Coastguard Worker {
1831*89c4ff92SAndroid Build Coastguard Worker while (next != m_positional.end())
1832*89c4ff92SAndroid Build Coastguard Worker {
1833*89c4ff92SAndroid Build Coastguard Worker auto iter = m_options.find(*next);
1834*89c4ff92SAndroid Build Coastguard Worker if (iter != m_options.end())
1835*89c4ff92SAndroid Build Coastguard Worker {
1836*89c4ff92SAndroid Build Coastguard Worker auto& result = m_parsed[iter->second->hash()];
1837*89c4ff92SAndroid Build Coastguard Worker if (!iter->second->value().is_container())
1838*89c4ff92SAndroid Build Coastguard Worker {
1839*89c4ff92SAndroid Build Coastguard Worker if (result.count() == 0)
1840*89c4ff92SAndroid Build Coastguard Worker {
1841*89c4ff92SAndroid Build Coastguard Worker add_to_option(iter, *next, a);
1842*89c4ff92SAndroid Build Coastguard Worker ++next;
1843*89c4ff92SAndroid Build Coastguard Worker return true;
1844*89c4ff92SAndroid Build Coastguard Worker }
1845*89c4ff92SAndroid Build Coastguard Worker ++next;
1846*89c4ff92SAndroid Build Coastguard Worker continue;
1847*89c4ff92SAndroid Build Coastguard Worker }
1848*89c4ff92SAndroid Build Coastguard Worker add_to_option(iter, *next, a);
1849*89c4ff92SAndroid Build Coastguard Worker return true;
1850*89c4ff92SAndroid Build Coastguard Worker }
1851*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_not_exists_exception>(*next);
1852*89c4ff92SAndroid Build Coastguard Worker }
1853*89c4ff92SAndroid Build Coastguard Worker
1854*89c4ff92SAndroid Build Coastguard Worker return false;
1855*89c4ff92SAndroid Build Coastguard Worker }
1856*89c4ff92SAndroid Build Coastguard Worker
1857*89c4ff92SAndroid Build Coastguard Worker inline
1858*89c4ff92SAndroid Build Coastguard Worker void
parse_positional(std::string option)1859*89c4ff92SAndroid Build Coastguard Worker Options::parse_positional(std::string option)
1860*89c4ff92SAndroid Build Coastguard Worker {
1861*89c4ff92SAndroid Build Coastguard Worker parse_positional(std::vector<std::string>{std::move(option)});
1862*89c4ff92SAndroid Build Coastguard Worker }
1863*89c4ff92SAndroid Build Coastguard Worker
1864*89c4ff92SAndroid Build Coastguard Worker inline
1865*89c4ff92SAndroid Build Coastguard Worker void
parse_positional(std::vector<std::string> options)1866*89c4ff92SAndroid Build Coastguard Worker Options::parse_positional(std::vector<std::string> options)
1867*89c4ff92SAndroid Build Coastguard Worker {
1868*89c4ff92SAndroid Build Coastguard Worker m_positional = std::move(options);
1869*89c4ff92SAndroid Build Coastguard Worker
1870*89c4ff92SAndroid Build Coastguard Worker m_positional_set.insert(m_positional.begin(), m_positional.end());
1871*89c4ff92SAndroid Build Coastguard Worker }
1872*89c4ff92SAndroid Build Coastguard Worker
1873*89c4ff92SAndroid Build Coastguard Worker inline
1874*89c4ff92SAndroid Build Coastguard Worker void
parse_positional(std::initializer_list<std::string> options)1875*89c4ff92SAndroid Build Coastguard Worker Options::parse_positional(std::initializer_list<std::string> options)
1876*89c4ff92SAndroid Build Coastguard Worker {
1877*89c4ff92SAndroid Build Coastguard Worker parse_positional(std::vector<std::string>(options));
1878*89c4ff92SAndroid Build Coastguard Worker }
1879*89c4ff92SAndroid Build Coastguard Worker
1880*89c4ff92SAndroid Build Coastguard Worker inline
1881*89c4ff92SAndroid Build Coastguard Worker ParseResult
parse(int argc,const char * const * argv)1882*89c4ff92SAndroid Build Coastguard Worker Options::parse(int argc, const char* const* argv)
1883*89c4ff92SAndroid Build Coastguard Worker {
1884*89c4ff92SAndroid Build Coastguard Worker OptionParser parser(*m_options, m_positional, m_allow_unrecognised);
1885*89c4ff92SAndroid Build Coastguard Worker
1886*89c4ff92SAndroid Build Coastguard Worker return parser.parse(argc, argv);
1887*89c4ff92SAndroid Build Coastguard Worker }
1888*89c4ff92SAndroid Build Coastguard Worker
1889*89c4ff92SAndroid Build Coastguard Worker inline ParseResult
parse(int argc,const char * const * argv)1890*89c4ff92SAndroid Build Coastguard Worker OptionParser::parse(int argc, const char* const* argv)
1891*89c4ff92SAndroid Build Coastguard Worker {
1892*89c4ff92SAndroid Build Coastguard Worker int current = 1;
1893*89c4ff92SAndroid Build Coastguard Worker bool consume_remaining = false;
1894*89c4ff92SAndroid Build Coastguard Worker PositionalListIterator next_positional = m_positional.begin();
1895*89c4ff92SAndroid Build Coastguard Worker
1896*89c4ff92SAndroid Build Coastguard Worker std::vector<std::string> unmatched;
1897*89c4ff92SAndroid Build Coastguard Worker
1898*89c4ff92SAndroid Build Coastguard Worker while (current != argc)
1899*89c4ff92SAndroid Build Coastguard Worker {
1900*89c4ff92SAndroid Build Coastguard Worker if (strcmp(argv[current], "--") == 0)
1901*89c4ff92SAndroid Build Coastguard Worker {
1902*89c4ff92SAndroid Build Coastguard Worker consume_remaining = true;
1903*89c4ff92SAndroid Build Coastguard Worker ++current;
1904*89c4ff92SAndroid Build Coastguard Worker break;
1905*89c4ff92SAndroid Build Coastguard Worker }
1906*89c4ff92SAndroid Build Coastguard Worker
1907*89c4ff92SAndroid Build Coastguard Worker std::match_results<const char*> result;
1908*89c4ff92SAndroid Build Coastguard Worker std::regex_match(argv[current], result, option_matcher);
1909*89c4ff92SAndroid Build Coastguard Worker
1910*89c4ff92SAndroid Build Coastguard Worker if (result.empty())
1911*89c4ff92SAndroid Build Coastguard Worker {
1912*89c4ff92SAndroid Build Coastguard Worker //not a flag
1913*89c4ff92SAndroid Build Coastguard Worker
1914*89c4ff92SAndroid Build Coastguard Worker // but if it starts with a `-`, then it's an error
1915*89c4ff92SAndroid Build Coastguard Worker if (argv[current][0] == '-' && argv[current][1] != '\0') {
1916*89c4ff92SAndroid Build Coastguard Worker if (!m_allow_unrecognised) {
1917*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_syntax_exception>(argv[current]);
1918*89c4ff92SAndroid Build Coastguard Worker }
1919*89c4ff92SAndroid Build Coastguard Worker }
1920*89c4ff92SAndroid Build Coastguard Worker
1921*89c4ff92SAndroid Build Coastguard Worker //if true is returned here then it was consumed, otherwise it is
1922*89c4ff92SAndroid Build Coastguard Worker //ignored
1923*89c4ff92SAndroid Build Coastguard Worker if (consume_positional(argv[current], next_positional))
1924*89c4ff92SAndroid Build Coastguard Worker {
1925*89c4ff92SAndroid Build Coastguard Worker }
1926*89c4ff92SAndroid Build Coastguard Worker else
1927*89c4ff92SAndroid Build Coastguard Worker {
1928*89c4ff92SAndroid Build Coastguard Worker unmatched.push_back(argv[current]);
1929*89c4ff92SAndroid Build Coastguard Worker }
1930*89c4ff92SAndroid Build Coastguard Worker //if we return from here then it was parsed successfully, so continue
1931*89c4ff92SAndroid Build Coastguard Worker }
1932*89c4ff92SAndroid Build Coastguard Worker else
1933*89c4ff92SAndroid Build Coastguard Worker {
1934*89c4ff92SAndroid Build Coastguard Worker //short or long option?
1935*89c4ff92SAndroid Build Coastguard Worker if (result[4].length() != 0)
1936*89c4ff92SAndroid Build Coastguard Worker {
1937*89c4ff92SAndroid Build Coastguard Worker const std::string& s = result[4];
1938*89c4ff92SAndroid Build Coastguard Worker
1939*89c4ff92SAndroid Build Coastguard Worker for (std::size_t i = 0; i != s.size(); ++i)
1940*89c4ff92SAndroid Build Coastguard Worker {
1941*89c4ff92SAndroid Build Coastguard Worker std::string name(1, s[i]);
1942*89c4ff92SAndroid Build Coastguard Worker auto iter = m_options.find(name);
1943*89c4ff92SAndroid Build Coastguard Worker
1944*89c4ff92SAndroid Build Coastguard Worker if (iter == m_options.end())
1945*89c4ff92SAndroid Build Coastguard Worker {
1946*89c4ff92SAndroid Build Coastguard Worker if (m_allow_unrecognised)
1947*89c4ff92SAndroid Build Coastguard Worker {
1948*89c4ff92SAndroid Build Coastguard Worker continue;
1949*89c4ff92SAndroid Build Coastguard Worker }
1950*89c4ff92SAndroid Build Coastguard Worker //error
1951*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_not_exists_exception>(name);
1952*89c4ff92SAndroid Build Coastguard Worker }
1953*89c4ff92SAndroid Build Coastguard Worker
1954*89c4ff92SAndroid Build Coastguard Worker auto value = iter->second;
1955*89c4ff92SAndroid Build Coastguard Worker
1956*89c4ff92SAndroid Build Coastguard Worker if (i + 1 == s.size())
1957*89c4ff92SAndroid Build Coastguard Worker {
1958*89c4ff92SAndroid Build Coastguard Worker //it must be the last argument
1959*89c4ff92SAndroid Build Coastguard Worker checked_parse_arg(argc, argv, current, value, name);
1960*89c4ff92SAndroid Build Coastguard Worker }
1961*89c4ff92SAndroid Build Coastguard Worker else if (value->value().has_implicit())
1962*89c4ff92SAndroid Build Coastguard Worker {
1963*89c4ff92SAndroid Build Coastguard Worker parse_option(value, name, value->value().get_implicit_value());
1964*89c4ff92SAndroid Build Coastguard Worker }
1965*89c4ff92SAndroid Build Coastguard Worker else
1966*89c4ff92SAndroid Build Coastguard Worker {
1967*89c4ff92SAndroid Build Coastguard Worker //error
1968*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_requires_argument_exception>(name);
1969*89c4ff92SAndroid Build Coastguard Worker }
1970*89c4ff92SAndroid Build Coastguard Worker }
1971*89c4ff92SAndroid Build Coastguard Worker }
1972*89c4ff92SAndroid Build Coastguard Worker else if (result[1].length() != 0)
1973*89c4ff92SAndroid Build Coastguard Worker {
1974*89c4ff92SAndroid Build Coastguard Worker const std::string& name = result[1];
1975*89c4ff92SAndroid Build Coastguard Worker
1976*89c4ff92SAndroid Build Coastguard Worker auto iter = m_options.find(name);
1977*89c4ff92SAndroid Build Coastguard Worker
1978*89c4ff92SAndroid Build Coastguard Worker if (iter == m_options.end())
1979*89c4ff92SAndroid Build Coastguard Worker {
1980*89c4ff92SAndroid Build Coastguard Worker if (m_allow_unrecognised)
1981*89c4ff92SAndroid Build Coastguard Worker {
1982*89c4ff92SAndroid Build Coastguard Worker // keep unrecognised options in argument list, skip to next argument
1983*89c4ff92SAndroid Build Coastguard Worker unmatched.push_back(argv[current]);
1984*89c4ff92SAndroid Build Coastguard Worker ++current;
1985*89c4ff92SAndroid Build Coastguard Worker continue;
1986*89c4ff92SAndroid Build Coastguard Worker }
1987*89c4ff92SAndroid Build Coastguard Worker //error
1988*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_not_exists_exception>(name);
1989*89c4ff92SAndroid Build Coastguard Worker }
1990*89c4ff92SAndroid Build Coastguard Worker
1991*89c4ff92SAndroid Build Coastguard Worker auto opt = iter->second;
1992*89c4ff92SAndroid Build Coastguard Worker
1993*89c4ff92SAndroid Build Coastguard Worker //equals provided for long option?
1994*89c4ff92SAndroid Build Coastguard Worker if (result[2].length() != 0)
1995*89c4ff92SAndroid Build Coastguard Worker {
1996*89c4ff92SAndroid Build Coastguard Worker //parse the option given
1997*89c4ff92SAndroid Build Coastguard Worker
1998*89c4ff92SAndroid Build Coastguard Worker parse_option(opt, name, result[3]);
1999*89c4ff92SAndroid Build Coastguard Worker }
2000*89c4ff92SAndroid Build Coastguard Worker else
2001*89c4ff92SAndroid Build Coastguard Worker {
2002*89c4ff92SAndroid Build Coastguard Worker //parse the next argument
2003*89c4ff92SAndroid Build Coastguard Worker checked_parse_arg(argc, argv, current, opt, name);
2004*89c4ff92SAndroid Build Coastguard Worker }
2005*89c4ff92SAndroid Build Coastguard Worker }
2006*89c4ff92SAndroid Build Coastguard Worker
2007*89c4ff92SAndroid Build Coastguard Worker }
2008*89c4ff92SAndroid Build Coastguard Worker
2009*89c4ff92SAndroid Build Coastguard Worker ++current;
2010*89c4ff92SAndroid Build Coastguard Worker }
2011*89c4ff92SAndroid Build Coastguard Worker
2012*89c4ff92SAndroid Build Coastguard Worker for (auto& opt : m_options)
2013*89c4ff92SAndroid Build Coastguard Worker {
2014*89c4ff92SAndroid Build Coastguard Worker auto& detail = opt.second;
2015*89c4ff92SAndroid Build Coastguard Worker const auto& value = detail->value();
2016*89c4ff92SAndroid Build Coastguard Worker
2017*89c4ff92SAndroid Build Coastguard Worker auto& store = m_parsed[detail->hash()];
2018*89c4ff92SAndroid Build Coastguard Worker
2019*89c4ff92SAndroid Build Coastguard Worker if(value.has_default() && !store.count() && !store.has_default()){
2020*89c4ff92SAndroid Build Coastguard Worker parse_default(detail);
2021*89c4ff92SAndroid Build Coastguard Worker }
2022*89c4ff92SAndroid Build Coastguard Worker }
2023*89c4ff92SAndroid Build Coastguard Worker
2024*89c4ff92SAndroid Build Coastguard Worker if (consume_remaining)
2025*89c4ff92SAndroid Build Coastguard Worker {
2026*89c4ff92SAndroid Build Coastguard Worker while (current < argc)
2027*89c4ff92SAndroid Build Coastguard Worker {
2028*89c4ff92SAndroid Build Coastguard Worker if (!consume_positional(argv[current], next_positional)) {
2029*89c4ff92SAndroid Build Coastguard Worker break;
2030*89c4ff92SAndroid Build Coastguard Worker }
2031*89c4ff92SAndroid Build Coastguard Worker ++current;
2032*89c4ff92SAndroid Build Coastguard Worker }
2033*89c4ff92SAndroid Build Coastguard Worker
2034*89c4ff92SAndroid Build Coastguard Worker //adjust argv for any that couldn't be swallowed
2035*89c4ff92SAndroid Build Coastguard Worker while (current != argc) {
2036*89c4ff92SAndroid Build Coastguard Worker unmatched.push_back(argv[current]);
2037*89c4ff92SAndroid Build Coastguard Worker ++current;
2038*89c4ff92SAndroid Build Coastguard Worker }
2039*89c4ff92SAndroid Build Coastguard Worker }
2040*89c4ff92SAndroid Build Coastguard Worker
2041*89c4ff92SAndroid Build Coastguard Worker finalise_aliases();
2042*89c4ff92SAndroid Build Coastguard Worker
2043*89c4ff92SAndroid Build Coastguard Worker ParseResult parsed(std::move(m_keys), std::move(m_parsed), std::move(m_sequential), std::move(unmatched));
2044*89c4ff92SAndroid Build Coastguard Worker return parsed;
2045*89c4ff92SAndroid Build Coastguard Worker }
2046*89c4ff92SAndroid Build Coastguard Worker
2047*89c4ff92SAndroid Build Coastguard Worker inline
2048*89c4ff92SAndroid Build Coastguard Worker void
finalise_aliases()2049*89c4ff92SAndroid Build Coastguard Worker OptionParser::finalise_aliases()
2050*89c4ff92SAndroid Build Coastguard Worker {
2051*89c4ff92SAndroid Build Coastguard Worker for (auto& option: m_options)
2052*89c4ff92SAndroid Build Coastguard Worker {
2053*89c4ff92SAndroid Build Coastguard Worker auto& detail = *option.second;
2054*89c4ff92SAndroid Build Coastguard Worker auto hash = detail.hash();
2055*89c4ff92SAndroid Build Coastguard Worker m_keys[detail.short_name()] = hash;
2056*89c4ff92SAndroid Build Coastguard Worker m_keys[detail.long_name()] = hash;
2057*89c4ff92SAndroid Build Coastguard Worker
2058*89c4ff92SAndroid Build Coastguard Worker m_parsed.emplace(hash, OptionValue());
2059*89c4ff92SAndroid Build Coastguard Worker }
2060*89c4ff92SAndroid Build Coastguard Worker }
2061*89c4ff92SAndroid Build Coastguard Worker
2062*89c4ff92SAndroid Build Coastguard Worker inline
2063*89c4ff92SAndroid Build Coastguard Worker void
add_option(const std::string & group,const Option & option)2064*89c4ff92SAndroid Build Coastguard Worker Options::add_option
2065*89c4ff92SAndroid Build Coastguard Worker (
2066*89c4ff92SAndroid Build Coastguard Worker const std::string& group,
2067*89c4ff92SAndroid Build Coastguard Worker const Option& option
2068*89c4ff92SAndroid Build Coastguard Worker )
2069*89c4ff92SAndroid Build Coastguard Worker {
2070*89c4ff92SAndroid Build Coastguard Worker add_options(group, {option});
2071*89c4ff92SAndroid Build Coastguard Worker }
2072*89c4ff92SAndroid Build Coastguard Worker
2073*89c4ff92SAndroid Build Coastguard Worker inline
2074*89c4ff92SAndroid Build Coastguard Worker void
add_option(const std::string & group,const std::string & s,const std::string & l,std::string desc,const std::shared_ptr<const Value> & value,std::string arg_help)2075*89c4ff92SAndroid Build Coastguard Worker Options::add_option
2076*89c4ff92SAndroid Build Coastguard Worker (
2077*89c4ff92SAndroid Build Coastguard Worker const std::string& group,
2078*89c4ff92SAndroid Build Coastguard Worker const std::string& s,
2079*89c4ff92SAndroid Build Coastguard Worker const std::string& l,
2080*89c4ff92SAndroid Build Coastguard Worker std::string desc,
2081*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<const Value>& value,
2082*89c4ff92SAndroid Build Coastguard Worker std::string arg_help
2083*89c4ff92SAndroid Build Coastguard Worker )
2084*89c4ff92SAndroid Build Coastguard Worker {
2085*89c4ff92SAndroid Build Coastguard Worker auto stringDesc = toLocalString(std::move(desc));
2086*89c4ff92SAndroid Build Coastguard Worker auto option = std::make_shared<OptionDetails>(s, l, stringDesc, value);
2087*89c4ff92SAndroid Build Coastguard Worker
2088*89c4ff92SAndroid Build Coastguard Worker if (!s.empty())
2089*89c4ff92SAndroid Build Coastguard Worker {
2090*89c4ff92SAndroid Build Coastguard Worker add_one_option(s, option);
2091*89c4ff92SAndroid Build Coastguard Worker }
2092*89c4ff92SAndroid Build Coastguard Worker
2093*89c4ff92SAndroid Build Coastguard Worker if (!l.empty())
2094*89c4ff92SAndroid Build Coastguard Worker {
2095*89c4ff92SAndroid Build Coastguard Worker add_one_option(l, option);
2096*89c4ff92SAndroid Build Coastguard Worker }
2097*89c4ff92SAndroid Build Coastguard Worker
2098*89c4ff92SAndroid Build Coastguard Worker m_option_list.push_front(*option.get());
2099*89c4ff92SAndroid Build Coastguard Worker auto iter = m_option_list.begin();
2100*89c4ff92SAndroid Build Coastguard Worker m_option_map[s] = iter;
2101*89c4ff92SAndroid Build Coastguard Worker m_option_map[l] = iter;
2102*89c4ff92SAndroid Build Coastguard Worker
2103*89c4ff92SAndroid Build Coastguard Worker //add the help details
2104*89c4ff92SAndroid Build Coastguard Worker auto& options = m_help[group];
2105*89c4ff92SAndroid Build Coastguard Worker
2106*89c4ff92SAndroid Build Coastguard Worker options.options.emplace_back(HelpOptionDetails{s, l, stringDesc,
2107*89c4ff92SAndroid Build Coastguard Worker value->has_default(), value->get_default_value(),
2108*89c4ff92SAndroid Build Coastguard Worker value->has_implicit(), value->get_implicit_value(),
2109*89c4ff92SAndroid Build Coastguard Worker std::move(arg_help),
2110*89c4ff92SAndroid Build Coastguard Worker value->is_container(),
2111*89c4ff92SAndroid Build Coastguard Worker value->is_boolean()});
2112*89c4ff92SAndroid Build Coastguard Worker }
2113*89c4ff92SAndroid Build Coastguard Worker
2114*89c4ff92SAndroid Build Coastguard Worker inline
2115*89c4ff92SAndroid Build Coastguard Worker void
add_one_option(const std::string & option,const std::shared_ptr<OptionDetails> & details)2116*89c4ff92SAndroid Build Coastguard Worker Options::add_one_option
2117*89c4ff92SAndroid Build Coastguard Worker (
2118*89c4ff92SAndroid Build Coastguard Worker const std::string& option,
2119*89c4ff92SAndroid Build Coastguard Worker const std::shared_ptr<OptionDetails>& details
2120*89c4ff92SAndroid Build Coastguard Worker )
2121*89c4ff92SAndroid Build Coastguard Worker {
2122*89c4ff92SAndroid Build Coastguard Worker auto in = m_options->emplace(option, details);
2123*89c4ff92SAndroid Build Coastguard Worker
2124*89c4ff92SAndroid Build Coastguard Worker if (!in.second)
2125*89c4ff92SAndroid Build Coastguard Worker {
2126*89c4ff92SAndroid Build Coastguard Worker throw_or_mimic<option_exists_error>(option);
2127*89c4ff92SAndroid Build Coastguard Worker }
2128*89c4ff92SAndroid Build Coastguard Worker }
2129*89c4ff92SAndroid Build Coastguard Worker
2130*89c4ff92SAndroid Build Coastguard Worker inline
2131*89c4ff92SAndroid Build Coastguard Worker String
help_one_group(const std::string & g) const2132*89c4ff92SAndroid Build Coastguard Worker Options::help_one_group(const std::string& g) const
2133*89c4ff92SAndroid Build Coastguard Worker {
2134*89c4ff92SAndroid Build Coastguard Worker using OptionHelp = std::vector<std::pair<String, String>>;
2135*89c4ff92SAndroid Build Coastguard Worker
2136*89c4ff92SAndroid Build Coastguard Worker auto group = m_help.find(g);
2137*89c4ff92SAndroid Build Coastguard Worker if (group == m_help.end())
2138*89c4ff92SAndroid Build Coastguard Worker {
2139*89c4ff92SAndroid Build Coastguard Worker return "";
2140*89c4ff92SAndroid Build Coastguard Worker }
2141*89c4ff92SAndroid Build Coastguard Worker
2142*89c4ff92SAndroid Build Coastguard Worker OptionHelp format;
2143*89c4ff92SAndroid Build Coastguard Worker
2144*89c4ff92SAndroid Build Coastguard Worker size_t longest = 0;
2145*89c4ff92SAndroid Build Coastguard Worker
2146*89c4ff92SAndroid Build Coastguard Worker String result;
2147*89c4ff92SAndroid Build Coastguard Worker
2148*89c4ff92SAndroid Build Coastguard Worker if (!g.empty())
2149*89c4ff92SAndroid Build Coastguard Worker {
2150*89c4ff92SAndroid Build Coastguard Worker result += toLocalString(" " + g + " options:\n");
2151*89c4ff92SAndroid Build Coastguard Worker }
2152*89c4ff92SAndroid Build Coastguard Worker
2153*89c4ff92SAndroid Build Coastguard Worker for (const auto& o : group->second.options)
2154*89c4ff92SAndroid Build Coastguard Worker {
2155*89c4ff92SAndroid Build Coastguard Worker if (m_positional_set.find(o.l) != m_positional_set.end() &&
2156*89c4ff92SAndroid Build Coastguard Worker !m_show_positional)
2157*89c4ff92SAndroid Build Coastguard Worker {
2158*89c4ff92SAndroid Build Coastguard Worker continue;
2159*89c4ff92SAndroid Build Coastguard Worker }
2160*89c4ff92SAndroid Build Coastguard Worker
2161*89c4ff92SAndroid Build Coastguard Worker auto s = format_option(o);
2162*89c4ff92SAndroid Build Coastguard Worker longest = (std::max)(longest, stringLength(s));
2163*89c4ff92SAndroid Build Coastguard Worker format.push_back(std::make_pair(s, String()));
2164*89c4ff92SAndroid Build Coastguard Worker }
2165*89c4ff92SAndroid Build Coastguard Worker
2166*89c4ff92SAndroid Build Coastguard Worker longest = (std::min)(longest, static_cast<size_t>(OPTION_LONGEST));
2167*89c4ff92SAndroid Build Coastguard Worker
2168*89c4ff92SAndroid Build Coastguard Worker //widest allowed description
2169*89c4ff92SAndroid Build Coastguard Worker auto allowed = size_t{76} - longest - OPTION_DESC_GAP;
2170*89c4ff92SAndroid Build Coastguard Worker
2171*89c4ff92SAndroid Build Coastguard Worker auto fiter = format.begin();
2172*89c4ff92SAndroid Build Coastguard Worker for (const auto& o : group->second.options)
2173*89c4ff92SAndroid Build Coastguard Worker {
2174*89c4ff92SAndroid Build Coastguard Worker if (m_positional_set.find(o.l) != m_positional_set.end() &&
2175*89c4ff92SAndroid Build Coastguard Worker !m_show_positional)
2176*89c4ff92SAndroid Build Coastguard Worker {
2177*89c4ff92SAndroid Build Coastguard Worker continue;
2178*89c4ff92SAndroid Build Coastguard Worker }
2179*89c4ff92SAndroid Build Coastguard Worker
2180*89c4ff92SAndroid Build Coastguard Worker auto d = format_description(o, longest + OPTION_DESC_GAP, allowed);
2181*89c4ff92SAndroid Build Coastguard Worker
2182*89c4ff92SAndroid Build Coastguard Worker result += fiter->first;
2183*89c4ff92SAndroid Build Coastguard Worker if (stringLength(fiter->first) > longest)
2184*89c4ff92SAndroid Build Coastguard Worker {
2185*89c4ff92SAndroid Build Coastguard Worker result += '\n';
2186*89c4ff92SAndroid Build Coastguard Worker result += toLocalString(std::string(longest + OPTION_DESC_GAP, ' '));
2187*89c4ff92SAndroid Build Coastguard Worker }
2188*89c4ff92SAndroid Build Coastguard Worker else
2189*89c4ff92SAndroid Build Coastguard Worker {
2190*89c4ff92SAndroid Build Coastguard Worker result += toLocalString(std::string(longest + OPTION_DESC_GAP -
2191*89c4ff92SAndroid Build Coastguard Worker stringLength(fiter->first),
2192*89c4ff92SAndroid Build Coastguard Worker ' '));
2193*89c4ff92SAndroid Build Coastguard Worker }
2194*89c4ff92SAndroid Build Coastguard Worker result += d;
2195*89c4ff92SAndroid Build Coastguard Worker result += '\n';
2196*89c4ff92SAndroid Build Coastguard Worker
2197*89c4ff92SAndroid Build Coastguard Worker ++fiter;
2198*89c4ff92SAndroid Build Coastguard Worker }
2199*89c4ff92SAndroid Build Coastguard Worker
2200*89c4ff92SAndroid Build Coastguard Worker return result;
2201*89c4ff92SAndroid Build Coastguard Worker }
2202*89c4ff92SAndroid Build Coastguard Worker
2203*89c4ff92SAndroid Build Coastguard Worker inline
2204*89c4ff92SAndroid Build Coastguard Worker void
generate_group_help(String & result,const std::vector<std::string> & print_groups) const2205*89c4ff92SAndroid Build Coastguard Worker Options::generate_group_help
2206*89c4ff92SAndroid Build Coastguard Worker (
2207*89c4ff92SAndroid Build Coastguard Worker String& result,
2208*89c4ff92SAndroid Build Coastguard Worker const std::vector<std::string>& print_groups
2209*89c4ff92SAndroid Build Coastguard Worker ) const
2210*89c4ff92SAndroid Build Coastguard Worker {
2211*89c4ff92SAndroid Build Coastguard Worker for (size_t i = 0; i != print_groups.size(); ++i)
2212*89c4ff92SAndroid Build Coastguard Worker {
2213*89c4ff92SAndroid Build Coastguard Worker const String& group_help_text = help_one_group(print_groups[i]);
2214*89c4ff92SAndroid Build Coastguard Worker if (empty(group_help_text))
2215*89c4ff92SAndroid Build Coastguard Worker {
2216*89c4ff92SAndroid Build Coastguard Worker continue;
2217*89c4ff92SAndroid Build Coastguard Worker }
2218*89c4ff92SAndroid Build Coastguard Worker result += group_help_text;
2219*89c4ff92SAndroid Build Coastguard Worker if (i < print_groups.size() - 1)
2220*89c4ff92SAndroid Build Coastguard Worker {
2221*89c4ff92SAndroid Build Coastguard Worker result += '\n';
2222*89c4ff92SAndroid Build Coastguard Worker }
2223*89c4ff92SAndroid Build Coastguard Worker }
2224*89c4ff92SAndroid Build Coastguard Worker }
2225*89c4ff92SAndroid Build Coastguard Worker
2226*89c4ff92SAndroid Build Coastguard Worker inline
2227*89c4ff92SAndroid Build Coastguard Worker void
generate_all_groups_help(String & result) const2228*89c4ff92SAndroid Build Coastguard Worker Options::generate_all_groups_help(String& result) const
2229*89c4ff92SAndroid Build Coastguard Worker {
2230*89c4ff92SAndroid Build Coastguard Worker std::vector<std::string> all_groups;
2231*89c4ff92SAndroid Build Coastguard Worker all_groups.reserve(m_help.size());
2232*89c4ff92SAndroid Build Coastguard Worker
2233*89c4ff92SAndroid Build Coastguard Worker for (const auto& group : m_help)
2234*89c4ff92SAndroid Build Coastguard Worker {
2235*89c4ff92SAndroid Build Coastguard Worker all_groups.push_back(group.first);
2236*89c4ff92SAndroid Build Coastguard Worker }
2237*89c4ff92SAndroid Build Coastguard Worker
2238*89c4ff92SAndroid Build Coastguard Worker generate_group_help(result, all_groups);
2239*89c4ff92SAndroid Build Coastguard Worker }
2240*89c4ff92SAndroid Build Coastguard Worker
2241*89c4ff92SAndroid Build Coastguard Worker inline
2242*89c4ff92SAndroid Build Coastguard Worker std::string
help(const std::vector<std::string> & help_groups) const2243*89c4ff92SAndroid Build Coastguard Worker Options::help(const std::vector<std::string>& help_groups) const
2244*89c4ff92SAndroid Build Coastguard Worker {
2245*89c4ff92SAndroid Build Coastguard Worker String result = m_help_string + "\nUsage:\n " +
2246*89c4ff92SAndroid Build Coastguard Worker toLocalString(m_program) + " " + toLocalString(m_custom_help);
2247*89c4ff92SAndroid Build Coastguard Worker
2248*89c4ff92SAndroid Build Coastguard Worker if (!m_positional.empty() && !m_positional_help.empty()) {
2249*89c4ff92SAndroid Build Coastguard Worker result += " " + toLocalString(m_positional_help);
2250*89c4ff92SAndroid Build Coastguard Worker }
2251*89c4ff92SAndroid Build Coastguard Worker
2252*89c4ff92SAndroid Build Coastguard Worker result += "\n\n";
2253*89c4ff92SAndroid Build Coastguard Worker
2254*89c4ff92SAndroid Build Coastguard Worker if (help_groups.empty())
2255*89c4ff92SAndroid Build Coastguard Worker {
2256*89c4ff92SAndroid Build Coastguard Worker generate_all_groups_help(result);
2257*89c4ff92SAndroid Build Coastguard Worker }
2258*89c4ff92SAndroid Build Coastguard Worker else
2259*89c4ff92SAndroid Build Coastguard Worker {
2260*89c4ff92SAndroid Build Coastguard Worker generate_group_help(result, help_groups);
2261*89c4ff92SAndroid Build Coastguard Worker }
2262*89c4ff92SAndroid Build Coastguard Worker
2263*89c4ff92SAndroid Build Coastguard Worker return toUTF8String(result);
2264*89c4ff92SAndroid Build Coastguard Worker }
2265*89c4ff92SAndroid Build Coastguard Worker
2266*89c4ff92SAndroid Build Coastguard Worker inline
2267*89c4ff92SAndroid Build Coastguard Worker std::vector<std::string>
groups() const2268*89c4ff92SAndroid Build Coastguard Worker Options::groups() const
2269*89c4ff92SAndroid Build Coastguard Worker {
2270*89c4ff92SAndroid Build Coastguard Worker std::vector<std::string> g;
2271*89c4ff92SAndroid Build Coastguard Worker
2272*89c4ff92SAndroid Build Coastguard Worker std::transform(
2273*89c4ff92SAndroid Build Coastguard Worker m_help.begin(),
2274*89c4ff92SAndroid Build Coastguard Worker m_help.end(),
2275*89c4ff92SAndroid Build Coastguard Worker std::back_inserter(g),
2276*89c4ff92SAndroid Build Coastguard Worker [] (const std::map<std::string, HelpGroupDetails>::value_type& pair)
2277*89c4ff92SAndroid Build Coastguard Worker {
2278*89c4ff92SAndroid Build Coastguard Worker return pair.first;
2279*89c4ff92SAndroid Build Coastguard Worker }
2280*89c4ff92SAndroid Build Coastguard Worker );
2281*89c4ff92SAndroid Build Coastguard Worker
2282*89c4ff92SAndroid Build Coastguard Worker return g;
2283*89c4ff92SAndroid Build Coastguard Worker }
2284*89c4ff92SAndroid Build Coastguard Worker
2285*89c4ff92SAndroid Build Coastguard Worker inline
2286*89c4ff92SAndroid Build Coastguard Worker const HelpGroupDetails&
group_help(const std::string & group) const2287*89c4ff92SAndroid Build Coastguard Worker Options::group_help(const std::string& group) const
2288*89c4ff92SAndroid Build Coastguard Worker {
2289*89c4ff92SAndroid Build Coastguard Worker return m_help.at(group);
2290*89c4ff92SAndroid Build Coastguard Worker }
2291*89c4ff92SAndroid Build Coastguard Worker
2292*89c4ff92SAndroid Build Coastguard Worker } // namespace cxxopts
2293*89c4ff92SAndroid Build Coastguard Worker
2294*89c4ff92SAndroid Build Coastguard Worker #endif //CXXOPTS_HPP_INCLUDED
2295