xref: /aosp_15_r20/external/armnn/third-party/cxxopts/cxxopts.hpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
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