Coverage Report

Created: 2025-06-13 06:29

/src/gdal/apps/argparse/argparse.hpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
  __ _ _ __ __ _ _ __   __ _ _ __ ___  ___
3
 / _` | '__/ _` | '_ \ / _` | '__/ __|/ _ \ Argument Parser for Modern C++
4
| (_| | | | (_| | |_) | (_| | |  \__ \  __/ http://github.com/p-ranav/argparse
5
 \__,_|_|  \__, | .__/ \__,_|_|  |___/\___|
6
           |___/|_|
7
8
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9
SPDX-License-Identifier: MIT
10
Copyright (c) 2019-2022 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>
11
and other contributors.
12
13
Permission is hereby  granted, free of charge, to any  person obtaining a copy
14
of this software and associated  documentation files (the "Software"), to deal
15
in the Software  without restriction, including without  limitation the rights
16
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
17
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
18
furnished to do so, subject to the following conditions:
19
20
The above copyright notice and this permission notice shall be included in all
21
copies or substantial portions of the Software.
22
23
THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
24
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
25
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
26
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
27
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
29
SOFTWARE.
30
*/
31
#pragma once
32
33
#include <cerrno>
34
35
#ifndef ARGPARSE_MODULE_USE_STD_MODULE
36
#include <algorithm>
37
#include <any>
38
#include <array>
39
#include <set>
40
#include <charconv>
41
#include <cstdlib>
42
#include <functional>
43
#include <iomanip>
44
#include <iostream>
45
#include <iterator>
46
#include <limits>
47
#include <list>
48
#include <map>
49
#include <numeric>
50
#include <optional>
51
#include <sstream>
52
#include <stdexcept>
53
#include <string>
54
#include <string_view>
55
#include <tuple>
56
#include <type_traits>
57
#include <utility>
58
#include <variant>
59
#include <vector>
60
#endif
61
62
#ifndef ARGPARSE_CUSTOM_STRTOF
63
#define ARGPARSE_CUSTOM_STRTOF strtof
64
#endif
65
66
#ifndef ARGPARSE_CUSTOM_STRTOD
67
#define ARGPARSE_CUSTOM_STRTOD strtod
68
#endif
69
70
#ifndef ARGPARSE_CUSTOM_STRTOLD
71
#define ARGPARSE_CUSTOM_STRTOLD strtold
72
#endif
73
74
namespace argparse {
75
76
namespace details { // namespace for helper methods
77
78
template <typename T, typename = void>
79
struct HasContainerTraits : std::false_type {};
80
81
template <> struct HasContainerTraits<std::string> : std::false_type {};
82
83
template <> struct HasContainerTraits<std::string_view> : std::false_type {};
84
85
template <typename T>
86
struct HasContainerTraits<
87
    T, std::void_t<typename T::value_type, decltype(std::declval<T>().begin()),
88
                   decltype(std::declval<T>().end()),
89
                   decltype(std::declval<T>().size())>> : std::true_type {};
90
91
template <typename T>
92
inline constexpr bool IsContainer = HasContainerTraits<T>::value;
93
94
template <typename T, typename = void>
95
struct HasStreamableTraits : std::false_type {};
96
97
template <typename T>
98
struct HasStreamableTraits<
99
    T,
100
    std::void_t<decltype(std::declval<std::ostream &>() << std::declval<T>())>>
101
    : std::true_type {};
102
103
template <typename T>
104
inline constexpr bool IsStreamable = HasStreamableTraits<T>::value;
105
106
constexpr std::size_t repr_max_container_size = 5;
107
108
0
template <typename T> std::string repr(T const &val) {
109
0
  if constexpr (std::is_same_v<T, bool>) {
110
0
    return val ? "true" : "false";
111
0
  } else if constexpr (std::is_convertible_v<T, std::string_view>) {
112
0
    return '"' + std::string{std::string_view{val}} + '"';
113
  } else if constexpr (IsContainer<T>) {
114
    std::stringstream out;
115
    out << "{";
116
    const auto size = val.size();
117
    if (size > 1) {
118
      out << repr(*val.begin());
119
      std::for_each(
120
          std::next(val.begin()),
121
          std::next(
122
              val.begin(),
123
              static_cast<typename T::iterator::difference_type>(
124
                  std::min<std::size_t>(size, repr_max_container_size) - 1)),
125
          [&out](const auto &v) { out << " " << repr(v); });
126
      if (size <= repr_max_container_size) {
127
        out << " ";
128
      } else {
129
        out << "...";
130
      }
131
    }
132
    if (size > 0) {
133
      out << repr(*std::prev(val.end()));
134
    }
135
    out << "}";
136
    return out.str();
137
0
  } else if constexpr (IsStreamable<T>) {
138
0
    std::stringstream out;
139
0
    out << val;
140
0
    return out.str();
141
  } else {
142
    return "<not representable>";
143
  }
144
0
}
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > gdal_argparse::details::repr<bool>(bool const&)
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > gdal_argparse::details::repr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > gdal_argparse::details::repr<double>(double const&)
145
146
namespace {
147
148
template <typename T> constexpr bool standard_signed_integer = false;
149
template <> constexpr bool standard_signed_integer<signed char> = true;
150
template <> constexpr bool standard_signed_integer<short int> = true;
151
template <> constexpr bool standard_signed_integer<int> = true;
152
template <> constexpr bool standard_signed_integer<long int> = true;
153
template <> constexpr bool standard_signed_integer<long long int> = true;
154
155
template <typename T> constexpr bool standard_unsigned_integer = false;
156
template <> constexpr bool standard_unsigned_integer<unsigned char> = true;
157
template <> constexpr bool standard_unsigned_integer<unsigned short int> = true;
158
template <> constexpr bool standard_unsigned_integer<unsigned int> = true;
159
template <> constexpr bool standard_unsigned_integer<unsigned long int> = true;
160
template <>
161
constexpr bool standard_unsigned_integer<unsigned long long int> = true;
162
163
} // namespace
164
165
constexpr int radix_2 = 2;
166
constexpr int radix_8 = 8;
167
constexpr int radix_10 = 10;
168
constexpr int radix_16 = 16;
169
170
template <typename T>
171
constexpr bool standard_integer =
172
    standard_signed_integer<T> || standard_unsigned_integer<T>;
173
174
template <class F, class Tuple, class Extra, std::size_t... I>
175
constexpr decltype(auto)
176
apply_plus_one_impl(F &&f, Tuple &&t, Extra &&x,
177
                    std::index_sequence<I...> /*unused*/) {
178
  return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...,
179
                     std::forward<Extra>(x));
180
}
181
182
template <class F, class Tuple, class Extra>
183
constexpr decltype(auto) apply_plus_one(F &&f, Tuple &&t, Extra &&x) {
184
  return details::apply_plus_one_impl(
185
      std::forward<F>(f), std::forward<Tuple>(t), std::forward<Extra>(x),
186
      std::make_index_sequence<
187
          std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
188
}
189
190
0
constexpr auto pointer_range(std::string_view s) noexcept {
191
0
  return std::tuple(s.data(), s.data() + s.size());
192
0
}
193
194
template <class CharT, class Traits>
195
constexpr bool starts_with(std::basic_string_view<CharT, Traits> prefix,
196
0
                           std::basic_string_view<CharT, Traits> s) noexcept {
197
0
  return s.substr(0, prefix.size()) == prefix;
198
0
}
199
200
enum class chars_format {
201
  scientific = 0xf1,
202
  fixed = 0xf2,
203
  hex = 0xf4,
204
  binary = 0xf8,
205
  general = fixed | scientific
206
};
207
208
struct ConsumeBinaryPrefixResult {
209
  bool is_binary;
210
  std::string_view rest;
211
};
212
213
constexpr auto consume_binary_prefix(std::string_view s)
214
0
    -> ConsumeBinaryPrefixResult {
215
0
  if (starts_with(std::string_view{"0b"}, s) ||
216
0
      starts_with(std::string_view{"0B"}, s)) {
217
0
    s.remove_prefix(2);
218
0
    return {true, s};
219
0
  }
220
0
  return {false, s};
221
0
}
222
223
struct ConsumeHexPrefixResult {
224
  bool is_hexadecimal;
225
  std::string_view rest;
226
};
227
228
using namespace std::literals;
229
230
constexpr auto consume_hex_prefix(std::string_view s)
231
0
    -> ConsumeHexPrefixResult {
232
0
  if (starts_with("0x"sv, s) || starts_with("0X"sv, s)) {
233
0
    s.remove_prefix(2);
234
0
    return {true, s};
235
0
  }
236
0
  return {false, s};
237
0
}
238
239
template <class T, auto Param>
240
0
inline auto do_from_chars(std::string_view s) -> T {
241
0
  T x{0};
242
0
  auto [first, last] = pointer_range(s);
243
0
  auto [ptr, ec] = std::from_chars(first, last, x, Param);
244
0
  if (ec == std::errc()) {
245
0
    if (ptr == last) {
246
0
      return x;
247
0
    }
248
0
    throw std::invalid_argument{"pattern '" + std::string(s) +
249
0
                                "' does not match to the end"};
250
0
  }
251
0
  if (ec == std::errc::invalid_argument) {
252
0
    throw std::invalid_argument{"pattern '" + std::string(s) + "' not found"};
253
0
  }
254
0
  if (ec == std::errc::result_out_of_range) {
255
0
    throw std::range_error{"'" + std::string(s) + "' not representable"};
256
0
  }
257
0
  return x; // unreachable
258
0
}
Unexecuted instantiation: _ZN13gdal_argparse7details13do_from_charsIiTnDaLi10EEET_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEE
Unexecuted instantiation: _ZN13gdal_argparse7details13do_from_charsIiTnDaLi16EEET_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEE
Unexecuted instantiation: _ZN13gdal_argparse7details13do_from_charsIiTnDaLi2EEET_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEE
Unexecuted instantiation: _ZN13gdal_argparse7details13do_from_charsIiTnDaLi8EEET_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEE
Unexecuted instantiation: _ZN13gdal_argparse7details13do_from_charsIxTnDaLi10EEET_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEE
259
260
template <class T, auto Param = 0> struct parse_number {
261
0
  auto operator()(std::string_view s) -> T {
262
0
    return do_from_chars<T, Param>(s);
263
0
  }
Unexecuted instantiation: gdal_argparse::details::parse_number<int, 10>::operator()(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: gdal_argparse::details::parse_number<long long, 10>::operator()(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
264
};
265
266
template <class T> struct parse_number<T, radix_2> {
267
  auto operator()(std::string_view s) -> T {
268
    if (auto [ok, rest] = consume_binary_prefix(s); ok) {
269
      return do_from_chars<T, radix_2>(rest);
270
    }
271
    throw std::invalid_argument{"pattern not found"};
272
  }
273
};
274
275
template <class T> struct parse_number<T, radix_16> {
276
  auto operator()(std::string_view s) -> T {
277
    if (starts_with("0x"sv, s) || starts_with("0X"sv, s)) {
278
      if (auto [ok, rest] = consume_hex_prefix(s); ok) {
279
        try {
280
          return do_from_chars<T, radix_16>(rest);
281
        } catch (const std::invalid_argument &err) {
282
          throw std::invalid_argument("Failed to parse '" + std::string(s) +
283
                                      "' as hexadecimal: " + err.what());
284
        } catch (const std::range_error &err) {
285
          throw std::range_error("Failed to parse '" + std::string(s) +
286
                                 "' as hexadecimal: " + err.what());
287
        }
288
      }
289
    } else {
290
      // Allow passing hex numbers without prefix
291
      // Shape 'x' already has to be specified
292
      try {
293
        return do_from_chars<T, radix_16>(s);
294
      } catch (const std::invalid_argument &err) {
295
        throw std::invalid_argument("Failed to parse '" + std::string(s) +
296
                                    "' as hexadecimal: " + err.what());
297
      } catch (const std::range_error &err) {
298
        throw std::range_error("Failed to parse '" + std::string(s) +
299
                               "' as hexadecimal: " + err.what());
300
      }
301
    }
302
303
    throw std::invalid_argument{"pattern '" + std::string(s) +
304
                                "' not identified as hexadecimal"};
305
  }
306
};
307
308
template <class T> struct parse_number<T> {
309
0
  auto operator()(std::string_view s) -> T {
310
0
    auto [ok, rest] = consume_hex_prefix(s);
311
0
    if (ok) {
312
0
      try {
313
0
        return do_from_chars<T, radix_16>(rest);
314
0
      } catch (const std::invalid_argument &err) {
315
0
        throw std::invalid_argument("Failed to parse '" + std::string(s) +
316
0
                                    "' as hexadecimal: " + err.what());
317
0
      } catch (const std::range_error &err) {
318
0
        throw std::range_error("Failed to parse '" + std::string(s) +
319
0
                               "' as hexadecimal: " + err.what());
320
0
      }
321
0
    }
322
323
0
    auto [ok_binary, rest_binary] = consume_binary_prefix(s);
324
0
    if (ok_binary) {
325
0
      try {
326
0
        return do_from_chars<T, radix_2>(rest_binary);
327
0
      } catch (const std::invalid_argument &err) {
328
0
        throw std::invalid_argument("Failed to parse '" + std::string(s) +
329
0
                                    "' as binary: " + err.what());
330
0
      } catch (const std::range_error &err) {
331
0
        throw std::range_error("Failed to parse '" + std::string(s) +
332
0
                               "' as binary: " + err.what());
333
0
      }
334
0
    }
335
336
0
    if (starts_with("0"sv, s)) {
337
0
      try {
338
0
        return do_from_chars<T, radix_8>(rest);
339
0
      } catch (const std::invalid_argument &err) {
340
0
        throw std::invalid_argument("Failed to parse '" + std::string(s) +
341
0
                                    "' as octal: " + err.what());
342
0
      } catch (const std::range_error &err) {
343
0
        throw std::range_error("Failed to parse '" + std::string(s) +
344
0
                               "' as octal: " + err.what());
345
0
      }
346
0
    }
347
348
0
    try {
349
0
      return do_from_chars<T, radix_10>(rest);
350
0
    } catch (const std::invalid_argument &err) {
351
0
      throw std::invalid_argument("Failed to parse '" + std::string(s) +
352
0
                                  "' as decimal integer: " + err.what());
353
0
    } catch (const std::range_error &err) {
354
0
      throw std::range_error("Failed to parse '" + std::string(s) +
355
0
                             "' as decimal integer: " + err.what());
356
0
    }
357
0
  }
358
};
359
360
namespace {
361
362
template <class T> inline const auto generic_strtod = nullptr;
363
template <> inline const auto generic_strtod<float> = ARGPARSE_CUSTOM_STRTOF;
364
template <> inline const auto generic_strtod<double> = ARGPARSE_CUSTOM_STRTOD;
365
template <>
366
inline const auto generic_strtod<long double> = ARGPARSE_CUSTOM_STRTOLD;
367
368
} // namespace
369
370
0
template <class T> inline auto do_strtod(std::string const &s) -> T {
371
0
  if (isspace(static_cast<unsigned char>(s[0])) || s[0] == '+') {
372
0
    throw std::invalid_argument{"pattern '" + s + "' not found"};
373
0
  }
374
375
0
  auto [first, last] = pointer_range(s);
376
0
  char *ptr;
377
378
0
  errno = 0;
379
0
  auto x = generic_strtod<T>(first, &ptr);
380
0
  if (errno == 0) {
381
0
    if (ptr == last) {
382
0
      return x;
383
0
    }
384
0
    throw std::invalid_argument{"pattern '" + s +
385
0
                                "' does not match to the end"};
386
0
  }
387
0
  if (errno == ERANGE) {
388
0
    throw std::range_error{"'" + s + "' not representable"};
389
0
  }
390
0
  return x; // unreachable
391
0
}
392
393
template <class T> struct parse_number<T, chars_format::general> {
394
0
  auto operator()(std::string const &s) -> T {
395
0
    if (auto r = consume_hex_prefix(s); r.is_hexadecimal) {
396
0
      throw std::invalid_argument{
397
0
          "chars_format::general does not parse hexfloat"};
398
0
    }
399
0
    if (auto r = consume_binary_prefix(s); r.is_binary) {
400
0
      throw std::invalid_argument{
401
0
          "chars_format::general does not parse binfloat"};
402
0
    }
403
404
0
    try {
405
0
      return do_strtod<T>(s);
406
0
    } catch (const std::invalid_argument &err) {
407
0
      throw std::invalid_argument("Failed to parse '" + s +
408
0
                                  "' as number: " + err.what());
409
0
    } catch (const std::range_error &err) {
410
0
      throw std::range_error("Failed to parse '" + s +
411
0
                             "' as number: " + err.what());
412
0
    }
413
0
  }
414
};
415
416
template <class T> struct parse_number<T, chars_format::hex> {
417
  auto operator()(std::string const &s) -> T {
418
    if (auto r = consume_hex_prefix(s); !r.is_hexadecimal) {
419
      throw std::invalid_argument{"chars_format::hex parses hexfloat"};
420
    }
421
    if (auto r = consume_binary_prefix(s); r.is_binary) {
422
      throw std::invalid_argument{"chars_format::hex does not parse binfloat"};
423
    }
424
425
    try {
426
      return do_strtod<T>(s);
427
    } catch (const std::invalid_argument &err) {
428
      throw std::invalid_argument("Failed to parse '" + s +
429
                                  "' as hexadecimal: " + err.what());
430
    } catch (const std::range_error &err) {
431
      throw std::range_error("Failed to parse '" + s +
432
                             "' as hexadecimal: " + err.what());
433
    }
434
  }
435
};
436
437
template <class T> struct parse_number<T, chars_format::binary> {
438
  auto operator()(std::string const &s) -> T {
439
    if (auto r = consume_hex_prefix(s); r.is_hexadecimal) {
440
      throw std::invalid_argument{
441
          "chars_format::binary does not parse hexfloat"};
442
    }
443
    if (auto r = consume_binary_prefix(s); !r.is_binary) {
444
      throw std::invalid_argument{"chars_format::binary parses binfloat"};
445
    }
446
447
    return do_strtod<T>(s);
448
  }
449
};
450
451
template <class T> struct parse_number<T, chars_format::scientific> {
452
  auto operator()(std::string const &s) -> T {
453
    if (auto r = consume_hex_prefix(s); r.is_hexadecimal) {
454
      throw std::invalid_argument{
455
          "chars_format::scientific does not parse hexfloat"};
456
    }
457
    if (auto r = consume_binary_prefix(s); r.is_binary) {
458
      throw std::invalid_argument{
459
          "chars_format::scientific does not parse binfloat"};
460
    }
461
    if (s.find_first_of("eE") == std::string::npos) {
462
      throw std::invalid_argument{
463
          "chars_format::scientific requires exponent part"};
464
    }
465
466
    try {
467
      return do_strtod<T>(s);
468
    } catch (const std::invalid_argument &err) {
469
      throw std::invalid_argument("Failed to parse '" + s +
470
                                  "' as scientific notation: " + err.what());
471
    } catch (const std::range_error &err) {
472
      throw std::range_error("Failed to parse '" + s +
473
                             "' as scientific notation: " + err.what());
474
    }
475
  }
476
};
477
478
template <class T> struct parse_number<T, chars_format::fixed> {
479
  auto operator()(std::string const &s) -> T {
480
    if (auto r = consume_hex_prefix(s); r.is_hexadecimal) {
481
      throw std::invalid_argument{
482
          "chars_format::fixed does not parse hexfloat"};
483
    }
484
    if (auto r = consume_binary_prefix(s); r.is_binary) {
485
      throw std::invalid_argument{
486
          "chars_format::fixed does not parse binfloat"};
487
    }
488
    if (s.find_first_of("eE") != std::string::npos) {
489
      throw std::invalid_argument{
490
          "chars_format::fixed does not parse exponent part"};
491
    }
492
493
    try {
494
      return do_strtod<T>(s);
495
    } catch (const std::invalid_argument &err) {
496
      throw std::invalid_argument("Failed to parse '" + s +
497
                                  "' as fixed notation: " + err.what());
498
    } catch (const std::range_error &err) {
499
      throw std::range_error("Failed to parse '" + s +
500
                             "' as fixed notation: " + err.what());
501
    }
502
  }
503
};
504
505
template <typename StrIt>
506
0
std::string join(StrIt first, StrIt last, const std::string &separator) {
507
0
  if (first == last) {
508
0
    return "";
509
0
  }
510
0
  std::stringstream value;
511
0
  value << *first;
512
0
  ++first;
513
0
  while (first != last) {
514
0
    value << separator << *first;
515
0
    ++first;
516
0
  }
517
0
  return value.str();
518
0
}
519
520
template <typename T> struct can_invoke_to_string {
521
  template <typename U>
522
  static auto test(int)
523
      -> decltype(std::to_string(std::declval<U>()), std::true_type{});
524
525
  template <typename U> static auto test(...) -> std::false_type;
526
527
  static constexpr bool value = decltype(test<T>(0))::value;
528
};
529
530
template <typename T> struct IsChoiceTypeSupported {
531
  using CleanType = typename std::decay<T>::type;
532
  static const bool value = std::is_integral<CleanType>::value ||
533
                            std::is_same<CleanType, std::string>::value ||
534
                            std::is_same<CleanType, std::string_view>::value ||
535
                            std::is_same<CleanType, const char *>::value;
536
};
537
538
template <typename StringType>
539
std::size_t get_levenshtein_distance(const StringType &s1,
540
0
                                     const StringType &s2) {
541
0
  std::vector<std::vector<std::size_t>> dp(
542
0
      s1.size() + 1, std::vector<std::size_t>(s2.size() + 1, 0));
543
544
0
  for (std::size_t i = 0; i <= s1.size(); ++i) {
545
0
    for (std::size_t j = 0; j <= s2.size(); ++j) {
546
0
      if (i == 0) {
547
0
        dp[i][j] = j;
548
0
      } else if (j == 0) {
549
0
        dp[i][j] = i;
550
0
      } else if (s1[i - 1] == s2[j - 1]) {
551
0
        dp[i][j] = dp[i - 1][j - 1];
552
0
      } else {
553
0
        dp[i][j] = 1 + std::min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]});
554
0
      }
555
0
    }
556
0
  }
557
558
0
  return dp[s1.size()][s2.size()];
559
0
}
560
561
template <typename ValueType>
562
std::string get_most_similar_string(const std::map<std::string, ValueType> &map,
563
0
                                    const std::string &input) {
564
0
  std::string most_similar{};
565
0
  std::size_t min_distance = std::numeric_limits<std::size_t>::max();
566
567
0
  for (const auto &entry : map) {
568
0
    std::size_t distance = get_levenshtein_distance(entry.first, input);
569
0
    if (distance < min_distance) {
570
0
      min_distance = distance;
571
0
      most_similar = entry.first;
572
0
    }
573
0
  }
574
575
0
  return most_similar;
576
0
}
577
578
} // namespace details
579
580
enum class nargs_pattern { optional, any, at_least_one };
581
582
enum class default_arguments : unsigned int {
583
  none = 0,
584
  help = 1,
585
  version = 2,
586
  all = help | version,
587
};
588
589
inline default_arguments operator&(const default_arguments &a,
590
0
                                   const default_arguments &b) {
591
0
  return static_cast<default_arguments>(
592
0
      static_cast<std::underlying_type<default_arguments>::type>(a) &
593
0
      static_cast<std::underlying_type<default_arguments>::type>(b));
594
0
}
595
596
class ArgumentParser;
597
598
class Argument {
599
  friend class ArgumentParser;
600
  friend auto operator<<(std::ostream &stream, const ArgumentParser &parser)
601
      -> std::ostream &;
602
603
  template <std::size_t N, std::size_t... I>
604
  explicit Argument(std::string_view prefix_chars,
605
                    std::array<std::string_view, N> &&a,
606
                    std::index_sequence<I...> /*unused*/)
607
0
      : m_accepts_optional_like_value(false),
608
0
        m_is_optional((is_optional(a[I], prefix_chars) || ...)),
609
0
        m_is_required(false), m_is_repeatable(false), m_is_used(false),
610
0
        m_is_hidden(false), m_prefix_chars(prefix_chars) {
611
0
    ((void)m_names.emplace_back(a[I]), ...);
612
0
    std::sort(
613
0
        m_names.begin(), m_names.end(), [](const auto &lhs, const auto &rhs) {
614
0
          return lhs.size() == rhs.size() ? lhs < rhs : lhs.size() < rhs.size();
615
0
        });
Unexecuted instantiation: auto gdal_argparse::Argument::Argument<1ul, 0ul>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::array<std::__1::basic_string_view<char, std::__1::char_traits<char> >, 1ul>&&, std::__1::integer_sequence<unsigned long, 0ul>)::{lambda(auto:1 const&, auto:2 const&)#1}::operator()<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<char> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::allocator<char> const&) const
Unexecuted instantiation: auto gdal_argparse::Argument::Argument<2ul, 0ul, 1ul>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::array<std::__1::basic_string_view<char, std::__1::char_traits<char> >, 2ul>&&, std::__1::integer_sequence<unsigned long, 0ul, 1ul>)::{lambda(auto:1 const&, auto:2 const&)#1}::operator()<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<char> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::allocator<char> const&) const
616
0
  }
Unexecuted instantiation: gdal_argparse::Argument::Argument<1ul, 0ul>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::array<std::__1::basic_string_view<char, std::__1::char_traits<char> >, 1ul>&&, std::__1::integer_sequence<unsigned long, 0ul>)
Unexecuted instantiation: gdal_argparse::Argument::Argument<2ul, 0ul, 1ul>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::array<std::__1::basic_string_view<char, std::__1::char_traits<char> >, 2ul>&&, std::__1::integer_sequence<unsigned long, 0ul, 1ul>)
617
618
public:
619
  template <std::size_t N>
620
  explicit Argument(std::string_view prefix_chars,
621
                    std::array<std::string_view, N> &&a)
622
0
      : Argument(prefix_chars, std::move(a), std::make_index_sequence<N>{}) {}
Unexecuted instantiation: gdal_argparse::Argument::Argument<1ul>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::array<std::__1::basic_string_view<char, std::__1::char_traits<char> >, 1ul>&&)
Unexecuted instantiation: gdal_argparse::Argument::Argument<2ul>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::array<std::__1::basic_string_view<char, std::__1::char_traits<char> >, 2ul>&&)
623
624
0
  Argument &help(std::string help_text) {
625
0
    m_help = std::move(help_text);
626
0
    return *this;
627
0
  }
628
629
0
  Argument &metavar(std::string metavar) {
630
0
    m_metavar = std::move(metavar);
631
0
    return *this;
632
0
  }
633
634
0
  template <typename T> Argument &default_value(T &&value) {
635
0
    m_num_args_range = NArgsRange{0, m_num_args_range.get_max()};
636
0
    m_default_value_repr = details::repr(value);
637
638
    if constexpr (std::is_convertible_v<T, std::string_view>) {
639
      m_default_value_str = std::string{std::string_view{value}};
640
0
    } else if constexpr (details::can_invoke_to_string<T>::value) {
641
0
      m_default_value_str = std::to_string(value);
642
0
    }
643
644
0
    m_default_value = std::forward<T>(value);
645
0
    return *this;
646
0
  }
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::Argument::default_value<bool>(bool&&)
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::Argument::default_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::Argument::default_value<double&>(double&)
647
648
0
  Argument &default_value(const char *value) {
649
0
    return default_value(std::string(value));
650
0
  }
651
652
0
  Argument &required() {
653
0
    m_is_required = true;
654
0
    return *this;
655
0
  }
656
657
0
  Argument &implicit_value(std::any value) {
658
0
    m_implicit_value = std::move(value);
659
0
    m_num_args_range = NArgsRange{0, 0};
660
0
    return *this;
661
0
  }
662
663
  // This is shorthand for:
664
  //   program.add_argument("foo")
665
  //     .default_value(false)
666
  //     .implicit_value(true)
667
0
  Argument &flag() {
668
0
    default_value(false);
669
0
    implicit_value(true);
670
0
    return *this;
671
0
  }
672
673
  template <class F, class... Args>
674
  auto action(F &&callable, Args &&... bound_args)
675
      -> std::enable_if_t<std::is_invocable_v<F, Args..., std::string const>,
676
0
                          Argument &> {
677
0
    using action_type = std::conditional_t<
678
0
        std::is_void_v<std::invoke_result_t<F, Args..., std::string const>>,
679
0
        void_action, valued_action>;
680
0
    if constexpr (sizeof...(Args) == 0) {
681
0
      m_actions.emplace_back<action_type>(std::forward<F>(callable));
682
    } else {
683
      m_actions.emplace_back<action_type>(
684
          [f = std::forward<F>(callable),
685
           tup = std::make_tuple(std::forward<Args>(bound_args)...)](
686
              std::string const &opt) mutable {
687
            return details::apply_plus_one(f, tup, opt);
688
          });
689
    }
690
0
    return *this;
691
0
  }
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_1JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_2JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_3JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoERbEUlRKT_E_JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIS3_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS3_DpOS9_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_4JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionINS_7details12parse_numberIdLNS2_12chars_formatE243EEEJEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERS0_E4typeEOS8_DpOS9_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_5JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoERNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEUlRKS8_E_JEEENS2_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SA_EERS0_E4typeEOSE_DpOSF_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_6JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoERdEUlRKT_E_JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIS3_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS3_DpOS9_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_7JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_8JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE3$_9JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdal_translate_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL29GDALTranslateOptionsGetParserP20GDALTranslateOptionsP29GDALTranslateOptionsForBinaryE4$_10JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoIiTnPNSt3__19enable_ifIXsr3std11is_integralIT_EE5valueEvE4typeELPv0EEERDaRS5_EUlRKS5_E_JEEENS4_IXsr3stdE14is_invocable_vIS5_DpT0_KNS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEERS0_E4typeEOS5_DpOSF_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoERNSt3__16vectorINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS7_IS9_EEEEEUlRKS9_E_JEEENS2_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SD_EERS0_E4typeEOSH_DpOSI_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoERNSt3__16vectorIiNS2_9allocatorIiEEEEEUlRKNS2_12basic_stringIcNS2_11char_traitsIcEENS4_IcEEEEE_JEEENS2_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SD_EERS0_E4typeEOSH_DpOSI_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoERNSt3__13setINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_4lessIS9_EENS7_IS9_EEEEEUlRKS9_E_JEEENS2_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SF_EERS0_E4typeEOSJ_DpOSK_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoERNSt3__13setIiNS2_4lessIiEENS2_9allocatorIiEEEEEUlRKNS2_12basic_stringIcNS2_11char_traitsIcEENS6_IcEEEEE_JEEENS2_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SF_EERS0_E4typeEOSJ_DpOSK_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS_14ArgumentParserC1ENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEES9_NS_17default_argumentsEbRNS3_13basic_ostreamIcS6_EEEUlRKT_E_JEEENS3_9enable_ifIXsr3stdE14is_invocable_vISE_DpT0_KS9_EERS0_E4typeEOSE_DpOSJ_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS_14ArgumentParserC1ENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEES9_NS_17default_argumentsEbRNS3_13basic_ostreamIcS6_EEEUlRKT_E0_JEEENS3_9enable_ifIXsr3stdE14is_invocable_vISE_DpT0_KS9_EERS0_E4typeEOSE_DpOSJ_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_1JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_2JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_3JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionINS_7details12parse_numberIiLi0EEEJEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEERS0_E4typeEOS7_DpOS8_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_4JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_5JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_6JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_7JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_8JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE3$_9JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_10JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_11JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_12JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_13JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_14JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_15JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_16JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_17JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_18JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_19JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_20JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_21JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_22JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_23JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_24JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_25JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_26JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_27JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_28JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_29JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_30JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_31JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalwarp_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL27GDALWarpAppOptionsGetParserP18GDALWarpAppOptionsP27GDALWarpAppOptionsForBinaryE4$_32JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParserC1ERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbE3$_0JEEENS3_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SA_EERS0_E4typeEOSE_DpOSF_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParserC1ERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbE3$_1JEEENS3_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SA_EERS0_E4typeEOSE_DpOSF_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParserC1ERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbE3$_2JEEENS3_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SA_EERS0_E4typeEOSE_DpOSF_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParserC1ERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbE3$_3JEEENS3_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SA_EERS0_E4typeEOSE_DpOSF_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParser25add_input_format_argumentEP13CPLStringListE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERS0_E4typeEOS8_DpOS9_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParser29add_creation_options_argumentER13CPLStringListE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERS0_E4typeEOS8_DpOS9_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParser34add_metadata_item_options_argumentER13CPLStringListE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERS0_E4typeEOS8_DpOS9_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParser25add_open_options_argumentEP13CPLStringListE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERS0_E4typeEOS8_DpOS9_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParser24add_output_type_argumentER12GDALDataTypeE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERS0_E4typeEOS8_DpOS9_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParser35add_layer_creation_options_argumentER13CPLStringListE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERS0_E4typeEOS8_DpOS9_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParser37add_dataset_creation_options_argumentER13CPLStringListE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERS0_E4typeEOS8_DpOS9_
Unexecuted instantiation: gdalargumentparser.cpp:_ZN13gdal_argparse8Argument6actionIZN18GDALArgumentParser23add_inverted_logic_flagERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPbSB_E3$_0JEEENS3_9enable_ifIXsr3stdE14is_invocable_vIT_DpT0_SA_EERS0_E4typeEOSF_DpOSG_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_1JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_2JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_3JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_4JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_5JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_6JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_7JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: gdalbuildvrt_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL28GDALBuildVRTOptionsGetParserP19GDALBuildVRTOptionsP28GDALBuildVRTOptionsForBinaryE3$_8JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_0JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_1JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_2JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_3JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_4JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_5JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_6JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_7JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_8JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE3$_9JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_10JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_11JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_12JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_13JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_14JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_15JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_16JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_17JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_18JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_19JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_20JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_21JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_22JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_23JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_24JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_25JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_26JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_27JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_28JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_29JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: _ZN13gdal_argparse8Argument6actionIZNS0_10store_intoIxTnPNSt3__19enable_ifIXsr3std11is_integralIT_EE5valueEvE4typeELPv0EEERDaRS5_EUlRKS5_E_JEEENS4_IXsr3stdE14is_invocable_vIS5_DpT0_KNS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEERS0_E4typeEOS5_DpOSF_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_30JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_31JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_32JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_33JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
Unexecuted instantiation: ogr2ogr_lib.cpp:_ZN13gdal_argparse8Argument6actionIZL35GDALVectorTranslateOptionsGetParserP26GDALVectorTranslateOptionsP35GDALVectorTranslateOptionsForBinaryiiE4$_34JEEENSt3__19enable_ifIXsr3stdE14is_invocable_vIT_DpT0_KNS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEERS0_E4typeEOS9_DpOSA_
692
693
0
  auto &store_into(bool &var) {
694
0
    flag();
695
0
    if (m_default_value.has_value()) {
696
0
      var = std::any_cast<bool>(m_default_value);
697
0
    }
698
0
    action([&var](const auto & /*unused*/) { var = true; });
699
0
    return *this;
700
0
  }
701
702
  template <typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
703
0
  auto &store_into(T &var) {
704
0
    if (m_default_value.has_value()) {
705
0
      try
706
0
      {
707
0
        var = std::any_cast<T>(m_default_value);
708
0
      }
709
0
      catch (...)
710
0
      {
711
0
        var = static_cast<T>(std::any_cast<int>(m_default_value));
712
0
      }
713
0
    }
714
0
    action([&var](const auto &s) {
715
0
      var = details::parse_number<T, details::radix_10>()(s);
716
0
    });
Unexecuted instantiation: _ZZN13gdal_argparse8Argument10store_intoIiTnPNSt3__19enable_ifIXsr3std11is_integralIT_EE5valueEvE4typeELPv0EEERDaRS4_ENKUlRKS4_E_clINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEDaSC_
Unexecuted instantiation: _ZZN13gdal_argparse8Argument10store_intoIxTnPNSt3__19enable_ifIXsr3std11is_integralIT_EE5valueEvE4typeELPv0EEERDaRS4_ENKUlRKS4_E_clINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEDaSC_
717
0
    return *this;
718
0
  }
Unexecuted instantiation: _ZN13gdal_argparse8Argument10store_intoIiTnPNSt3__19enable_ifIXsr3std11is_integralIT_EE5valueEvE4typeELPv0EEERDaRS4_
Unexecuted instantiation: _ZN13gdal_argparse8Argument10store_intoIxTnPNSt3__19enable_ifIXsr3std11is_integralIT_EE5valueEvE4typeELPv0EEERDaRS4_
719
720
0
  auto &store_into(double &var) {
721
0
    if (m_default_value.has_value()) {
722
0
      try
723
0
      {
724
0
        var = std::any_cast<double>(m_default_value);
725
0
      }
726
0
      catch (...)
727
0
      {
728
0
        var = std::any_cast<int>(m_default_value);
729
0
      }
730
0
    }
731
0
    action([&var](const auto &s) {
732
0
      var = details::parse_number<double, details::chars_format::general>()(s);
733
0
    });
734
0
    return *this;
735
0
  }
736
737
0
  auto &store_into(std::string &var) {
738
0
    if (m_default_value.has_value()) {
739
0
      var = std::any_cast<std::string>(m_default_value);
740
0
    }
741
0
    action([&var](const std::string &s) { var = s; });
742
0
    return *this;
743
0
  }
744
745
0
  auto &store_into(std::vector<std::string> &var) {
746
0
    if (m_default_value.has_value()) {
747
0
      var = std::any_cast<std::vector<std::string>>(m_default_value);
748
0
    }
749
0
    action([this, &var](const std::string &s) {
750
0
      if (!m_is_used) {
751
0
        var.clear();
752
0
      }
753
0
      m_is_used = true;
754
0
      var.push_back(s);
755
0
    });
756
0
    return *this;
757
0
  }
758
759
0
  auto &store_into(std::vector<int> &var) {
760
0
    if (m_default_value.has_value()) {
761
0
      var = std::any_cast<std::vector<int>>(m_default_value);
762
0
    }
763
0
    action([this, &var](const std::string &s) {
764
0
      if (!m_is_used) {
765
0
        var.clear();
766
0
      }
767
0
      m_is_used = true;
768
0
      var.push_back(details::parse_number<int, details::radix_10>()(s));
769
0
    });
770
0
    return *this;
771
0
  }
772
773
0
  auto &store_into(std::set<std::string> &var) {
774
0
    if (m_default_value.has_value()) {
775
0
      var = std::any_cast<std::set<std::string>>(m_default_value);
776
0
    }
777
0
    action([this, &var](const std::string &s) {
778
0
      if (!m_is_used) {
779
0
        var.clear();
780
0
      }
781
0
      m_is_used = true;
782
0
      var.insert(s);
783
0
    });
784
0
    return *this;
785
0
  }
786
787
0
  auto &store_into(std::set<int> &var) {
788
0
    if (m_default_value.has_value()) {
789
0
      var = std::any_cast<std::set<int>>(m_default_value);
790
0
    }
791
0
    action([this, &var](const std::string &s) {
792
0
      if (!m_is_used) {
793
0
        var.clear();
794
0
      }
795
0
      m_is_used = true;
796
0
      var.insert(details::parse_number<int, details::radix_10>()(s));
797
0
    });
798
0
    return *this;
799
0
  }
800
801
0
  auto &append() {
802
0
    m_is_repeatable = true;
803
0
    return *this;
804
0
  }
805
806
  // Cause the argument to be invisible in usage and help
807
0
  auto &hidden() {
808
0
    m_is_hidden = true;
809
0
    return *this;
810
0
  }
811
812
  template <char Shape, typename T>
813
0
  auto scan() -> std::enable_if_t<std::is_arithmetic_v<T>, Argument &> {
814
0
    static_assert(!(std::is_const_v<T> || std::is_volatile_v<T>),
815
0
                  "T should not be cv-qualified");
816
0
    auto is_one_of = [](char c, auto... x) constexpr {
817
0
      return ((c == x) || ...);
818
0
    };
Unexecuted instantiation: _ZZN13gdal_argparse8Argument4scanILc103EdEENSt3__19enable_ifIXsr3stdE15is_arithmetic_vIT0_EERS0_E4typeEvENKUlcDpT_E_clIJcEEEDacS9_
Unexecuted instantiation: _ZZN13gdal_argparse8Argument4scanILc103EdEENSt3__19enable_ifIXsr3stdE15is_arithmetic_vIT0_EERS0_E4typeEvENKUlcDpT_E_clIJccEEEDacS9_
Unexecuted instantiation: _ZZN13gdal_argparse8Argument4scanILc105EiEENSt3__19enable_ifIXsr3stdE15is_arithmetic_vIT0_EERS0_E4typeEvENKUlcDpT_E_clIJcEEEDacS9_
819
820
    if constexpr (is_one_of(Shape, 'd') && details::standard_integer<T>) {
821
      action(details::parse_number<T, details::radix_10>());
822
    } else if constexpr (is_one_of(Shape, 'i') &&
823
0
                         details::standard_integer<T>) {
824
0
      action(details::parse_number<T>());
825
    } else if constexpr (is_one_of(Shape, 'u') &&
826
                         details::standard_unsigned_integer<T>) {
827
      action(details::parse_number<T, details::radix_10>());
828
    } else if constexpr (is_one_of(Shape, 'b') &&
829
                         details::standard_unsigned_integer<T>) {
830
      action(details::parse_number<T, details::radix_2>());
831
    } else if constexpr (is_one_of(Shape, 'o') &&
832
                         details::standard_unsigned_integer<T>) {
833
      action(details::parse_number<T, details::radix_8>());
834
    } else if constexpr (is_one_of(Shape, 'x', 'X') &&
835
                         details::standard_unsigned_integer<T>) {
836
      action(details::parse_number<T, details::radix_16>());
837
    } else if constexpr (is_one_of(Shape, 'a', 'A') &&
838
                         std::is_floating_point_v<T>) {
839
      action(details::parse_number<T, details::chars_format::hex>());
840
    } else if constexpr (is_one_of(Shape, 'e', 'E') &&
841
                         std::is_floating_point_v<T>) {
842
      action(details::parse_number<T, details::chars_format::scientific>());
843
    } else if constexpr (is_one_of(Shape, 'f', 'F') &&
844
                         std::is_floating_point_v<T>) {
845
      action(details::parse_number<T, details::chars_format::fixed>());
846
    } else if constexpr (is_one_of(Shape, 'g', 'G') &&
847
0
                         std::is_floating_point_v<T>) {
848
0
      action(details::parse_number<T, details::chars_format::general>());
849
    } else {
850
      static_assert(alignof(T) == 0, "No scan specification for T");
851
    }
852
853
0
    return *this;
854
0
  }
Unexecuted instantiation: _ZN13gdal_argparse8Argument4scanILc103EdEENSt3__19enable_ifIXsr3stdE15is_arithmetic_vIT0_EERS0_E4typeEv
Unexecuted instantiation: _ZN13gdal_argparse8Argument4scanILc105EiEENSt3__19enable_ifIXsr3stdE15is_arithmetic_vIT0_EERS0_E4typeEv
855
856
0
  Argument &nargs(std::size_t num_args) {
857
0
    m_num_args_range = NArgsRange{num_args, num_args};
858
0
    return *this;
859
0
  }
860
861
0
  Argument &nargs(std::size_t num_args_min, std::size_t num_args_max) {
862
0
    m_num_args_range = NArgsRange{num_args_min, num_args_max};
863
0
    return *this;
864
0
  }
865
866
0
  Argument &nargs(nargs_pattern pattern) {
867
0
    switch (pattern) {
868
0
    case nargs_pattern::optional:
869
0
      m_num_args_range = NArgsRange{0, 1};
870
0
      break;
871
0
    case nargs_pattern::any:
872
0
      m_num_args_range =
873
0
          NArgsRange{0, (std::numeric_limits<std::size_t>::max)()};
874
0
      break;
875
0
    case nargs_pattern::at_least_one:
876
0
      m_num_args_range =
877
0
          NArgsRange{1, (std::numeric_limits<std::size_t>::max)()};
878
0
      break;
879
0
    }
880
0
    return *this;
881
0
  }
882
883
0
  Argument &remaining() {
884
0
    m_accepts_optional_like_value = true;
885
0
    return nargs(nargs_pattern::any);
886
0
  }
887
888
0
  template <typename T> void add_choice(T &&choice) {
889
0
    static_assert(details::IsChoiceTypeSupported<T>::value,
890
0
                  "Only string or integer type supported for choice");
891
0
    static_assert(std::is_convertible_v<T, std::string_view> ||
892
0
                      details::can_invoke_to_string<T>::value,
893
0
                  "Choice is not convertible to string_type");
894
0
    if (!m_choices.has_value()) {
895
0
      m_choices = std::vector<std::string>{};
896
0
    }
897
898
0
    if constexpr (std::is_convertible_v<T, std::string_view>) {
899
0
      m_choices.value().push_back(
900
0
          std::string{std::string_view{std::forward<T>(choice)}});
901
    } else if constexpr (details::can_invoke_to_string<T>::value) {
902
      m_choices.value().push_back(std::to_string(std::forward<T>(choice)));
903
    }
904
0
  }
905
906
0
  Argument &choices() {
907
0
    if (!m_choices.has_value()) {
908
0
      throw std::runtime_error("Zero choices provided");
909
0
    }
910
0
    return *this;
911
0
  }
912
913
  template <typename T, typename... U>
914
0
  Argument &choices(T &&first, U &&... rest) {
915
0
    add_choice(std::forward<T>(first));
916
0
    choices(std::forward<U>(rest)...);
917
0
    return *this;
918
0
  }
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::Argument::choices<char const (&) [2], char const (&) [2], char const (&) [2]>(char const (&) [2], char const (&) [2], char const (&) [2])
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::Argument::choices<char const (&) [2], char const (&) [2]>(char const (&) [2], char const (&) [2])
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::Argument::choices<char const (&) [2]>(char const (&) [2])
919
920
0
  void find_default_value_in_choices_or_throw() const {
921
922
0
    const auto &choices = m_choices.value();
923
924
0
    if (m_default_value.has_value()) {
925
0
      if (std::find(choices.begin(), choices.end(), m_default_value_str) ==
926
0
          choices.end()) {
927
        // provided arg not in list of allowed choices
928
        // report error
929
930
0
        std::string choices_as_csv =
931
0
            std::accumulate(choices.begin(), choices.end(), std::string(),
932
0
                            [](const std::string &a, const std::string &b) {
933
0
                              return a + (a.empty() ? "" : ", ") + b;
934
0
                            });
935
936
0
        throw std::runtime_error(
937
0
            std::string{"Invalid default value "} + m_default_value_repr +
938
0
            " - allowed options: {" + choices_as_csv + "}");
939
0
      }
940
0
    }
941
0
  }
942
943
  template <typename Iterator>
944
0
  void find_value_in_choices_or_throw(Iterator it) const {
945
946
0
    const auto &choices = m_choices.value();
947
948
0
    if (std::find(choices.begin(), choices.end(), *it) == choices.end()) {
949
      // provided arg not in list of allowed choices
950
      // report error
951
952
0
      std::string choices_as_csv =
953
0
          std::accumulate(choices.begin(), choices.end(), std::string(),
954
0
                          [](const std::string &a, const std::string &b) {
955
0
                            return a + (a.empty() ? "" : ", ") + b;
956
0
                          });
957
958
0
      throw std::runtime_error(std::string{"Invalid argument "} +
959
0
                               details::repr(*it) + " - allowed options: {" +
960
0
                               choices_as_csv + "}");
961
0
    }
962
0
  }
963
964
  /* The dry_run parameter can be set to true to avoid running the actions,
965
   * and setting m_is_used. This may be used by a pre-processing step to do
966
   * a first iteration over arguments.
967
   */
968
  template <typename Iterator>
969
  Iterator consume(Iterator start, Iterator end,
970
0
                   std::string_view used_name = {}, bool dry_run = false) {
971
0
    if (!m_is_repeatable && m_is_used) {
972
0
      throw std::runtime_error(
973
0
          std::string("Duplicate argument ").append(used_name));
974
0
    }
975
0
    m_used_name = used_name;
976
977
0
    if (m_choices.has_value()) {
978
      // Check each value in (start, end) and make sure
979
      // it is in the list of allowed choices/options
980
0
      std::size_t i = 0;
981
0
      auto max_number_of_args = m_num_args_range.get_max();
982
0
      for (auto it = start; it != end; ++it) {
983
0
        if (i == max_number_of_args) {
984
0
          break;
985
0
        }
986
0
        find_value_in_choices_or_throw(it);
987
0
        i += 1;
988
0
      }
989
0
    }
990
991
0
    const auto num_args_max = m_num_args_range.get_max();
992
0
    const auto num_args_min = m_num_args_range.get_min();
993
0
    std::size_t dist = 0;
994
0
    if (num_args_max == 0) {
995
0
      if (!dry_run) {
996
0
        m_values.emplace_back(m_implicit_value);
997
0
        for(auto &action: m_actions) {
998
0
          std::visit([&](const auto &f) { f({}); }, action);
Unexecuted instantiation: auto gdal_argparse::Argument::consume<std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*> >(std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>, std::__1::basic_string_view<char, std::__1::char_traits<char> >, bool)::{lambda(auto:1 const&)#1}::operator()<std::__1::function<std::__1::any (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> >(std::__1::function<std::__1::any (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&) const
Unexecuted instantiation: auto gdal_argparse::Argument::consume<std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*> >(std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>, std::__1::basic_string_view<char, std::__1::char_traits<char> >, bool)::{lambda(auto:1 const&)#1}::operator()<std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> >(std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&) const
999
0
        }
1000
0
        if(m_actions.empty()){
1001
0
          std::visit([&](const auto &f) { f({}); }, m_default_action);
Unexecuted instantiation: auto gdal_argparse::Argument::consume<std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*> >(std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>, std::__1::basic_string_view<char, std::__1::char_traits<char> >, bool)::{lambda(auto:1 const&)#2}::operator()<std::__1::function<std::__1::any (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> >(std::__1::function<std::__1::any (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&) const
Unexecuted instantiation: auto gdal_argparse::Argument::consume<std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*> >(std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>, std::__1::basic_string_view<char, std::__1::char_traits<char> >, bool)::{lambda(auto:1 const&)#2}::operator()<std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> >(std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)> const&) const
1002
0
        }
1003
0
        m_is_used = true;
1004
0
      }
1005
0
      return start;
1006
0
    }
1007
0
    if ((dist = static_cast<std::size_t>(std::distance(start, end))) >=
1008
0
        num_args_min) {
1009
0
      if (num_args_max < dist) {
1010
0
        end = std::next(start, num_args_max);
1011
0
      }
1012
0
      if (!m_accepts_optional_like_value) {
1013
0
        end = std::find_if(
1014
0
            start, end,
1015
0
            std::bind(is_optional, std::placeholders::_1, m_prefix_chars));
1016
0
        dist = static_cast<std::size_t>(std::distance(start, end));
1017
0
        if (dist < num_args_min) {
1018
0
          throw std::runtime_error("Too few arguments for '" +
1019
0
                                   std::string(m_used_name) + "'.");
1020
0
        }
1021
0
      }
1022
1023
0
      struct ActionApply {
1024
0
        void operator()(valued_action &f) {
1025
0
          std::transform(first, last, std::back_inserter(self.m_values), f);
1026
0
        }
1027
1028
0
        void operator()(void_action &f) {
1029
0
          std::for_each(first, last, f);
1030
0
          if (!self.m_default_value.has_value()) {
1031
0
            if (!self.m_accepts_optional_like_value) {
1032
0
              self.m_values.resize(
1033
0
                  static_cast<std::size_t>(std::distance(first, last)));
1034
0
            }
1035
0
          }
1036
0
        }
1037
1038
0
        Iterator first, last;
1039
0
        Argument &self;
1040
0
      };
1041
0
      if (!dry_run) {
1042
0
        for(auto &action: m_actions) {
1043
0
          std::visit(ActionApply{start, end, *this}, action);
1044
0
        }
1045
0
        if(m_actions.empty()){
1046
0
          std::visit(ActionApply{start, end, *this}, m_default_action);
1047
0
        }
1048
0
        m_is_used = true;
1049
0
      }
1050
0
      return end;
1051
0
    }
1052
0
    if (m_default_value.has_value()) {
1053
0
      if (!dry_run) {
1054
0
        m_is_used = true;
1055
0
      }
1056
0
      return start;
1057
0
    }
1058
0
    throw std::runtime_error("Too few arguments for '" +
1059
0
                             std::string(m_used_name) + "'.");
1060
0
  }
1061
1062
  /*
1063
   * @throws std::runtime_error if argument values are not valid
1064
   */
1065
0
  void validate() const {
1066
0
    if (m_is_optional) {
1067
      // TODO: check if an implicit value was programmed for this argument
1068
0
      if (!m_is_used && !m_default_value.has_value() && m_is_required) {
1069
0
        throw_required_arg_not_used_error();
1070
0
      }
1071
0
      if (m_is_used && m_is_required && m_values.empty()) {
1072
0
        throw_required_arg_no_value_provided_error();
1073
0
      }
1074
0
    } else {
1075
0
      if (!m_num_args_range.contains(m_values.size()) &&
1076
0
          !m_default_value.has_value()) {
1077
0
        throw_nargs_range_validation_error();
1078
0
      }
1079
0
    }
1080
1081
0
    if (m_choices.has_value()) {
1082
      // Make sure the default value (if provided)
1083
      // is in the list of choices
1084
0
      find_default_value_in_choices_or_throw();
1085
0
    }
1086
0
  }
1087
1088
0
  std::string get_names_csv(char separator = ',') const {
1089
0
    return std::accumulate(
1090
0
        m_names.begin(), m_names.end(), std::string{""},
1091
0
        [&](const std::string &result, const std::string &name) {
1092
0
          return result.empty() ? name : result + separator + name;
1093
0
        });
1094
0
  }
1095
1096
0
  std::string get_usage_full() const {
1097
0
    std::stringstream usage;
1098
1099
0
    usage << get_names_csv('/');
1100
0
    const std::string metavar = !m_metavar.empty() ? m_metavar : "VAR";
1101
0
    if (m_num_args_range.get_max() > 0) {
1102
0
      usage << " " << metavar;
1103
0
      if (m_num_args_range.get_max() > 1) {
1104
0
        usage << "...";
1105
0
      }
1106
0
    }
1107
0
    return usage.str();
1108
0
  }
1109
1110
0
  std::string get_inline_usage() const {
1111
0
    std::stringstream usage;
1112
    // Find the longest variant to show in the usage string
1113
0
    std::string longest_name = m_names.front();
1114
0
    for (const auto &s : m_names) {
1115
0
      if (s.size() > longest_name.size()) {
1116
0
        longest_name = s;
1117
0
      }
1118
0
    }
1119
0
    if (!m_is_required) {
1120
0
      usage << "[";
1121
0
    }
1122
0
    usage << longest_name;
1123
0
    const std::string metavar = !m_metavar.empty() ? m_metavar : "VAR";
1124
0
    if (m_num_args_range.get_max() > 0) {
1125
0
      usage << " " << metavar;
1126
0
      if (m_num_args_range.get_max() > 1 &&
1127
0
          m_metavar.find("> <") == std::string::npos) {
1128
0
        usage << "...";
1129
0
      }
1130
0
    }
1131
0
    if (!m_is_required) {
1132
0
      usage << "]";
1133
0
    }
1134
0
    if (m_is_repeatable) {
1135
0
      usage << "...";
1136
0
    }
1137
0
    return usage.str();
1138
0
  }
1139
1140
0
  std::size_t get_arguments_length() const {
1141
1142
0
    std::size_t names_size = std::accumulate(
1143
0
        std::begin(m_names), std::end(m_names), std::size_t(0),
1144
0
        [](const auto &sum, const auto &s) { return sum + s.size(); });
1145
1146
0
    if (is_positional(m_names.front(), m_prefix_chars)) {
1147
      // A set metavar means this replaces the names
1148
0
      if (!m_metavar.empty()) {
1149
        // Indent and metavar
1150
0
        return 2 + m_metavar.size();
1151
0
      }
1152
1153
      // Indent and space-separated
1154
0
      return 2 + names_size + (m_names.size() - 1);
1155
0
    }
1156
    // Is an option - include both names _and_ metavar
1157
    // size = text + (", " between names)
1158
0
    std::size_t size = names_size + 2 * (m_names.size() - 1);
1159
0
    if (!m_metavar.empty() && m_num_args_range == NArgsRange{1, 1}) {
1160
0
      size += m_metavar.size() + 1;
1161
0
    }
1162
0
    return size + 2; // indent
1163
0
  }
1164
1165
  friend std::ostream &operator<<(std::ostream &stream,
1166
0
                                  const Argument &argument) {
1167
0
    std::stringstream name_stream;
1168
0
    name_stream << "  "; // indent
1169
0
    if (argument.is_positional(argument.m_names.front(),
1170
0
                               argument.m_prefix_chars)) {
1171
0
      if (!argument.m_metavar.empty()) {
1172
0
        name_stream << argument.m_metavar;
1173
0
      } else {
1174
0
        name_stream << details::join(argument.m_names.begin(),
1175
0
                                     argument.m_names.end(), " ");
1176
0
      }
1177
0
    } else {
1178
0
      name_stream << details::join(argument.m_names.begin(),
1179
0
                                   argument.m_names.end(), ", ");
1180
      // If we have a metavar, and one narg - print the metavar
1181
0
      if (!argument.m_metavar.empty() &&
1182
0
          argument.m_num_args_range == NArgsRange{1, 1}) {
1183
0
        name_stream << " " << argument.m_metavar;
1184
0
      }
1185
0
      else if (!argument.m_metavar.empty() &&
1186
0
               argument.m_num_args_range.get_min() == argument.m_num_args_range.get_max() &&
1187
0
               argument.m_metavar.find("> <") != std::string::npos) {
1188
0
        name_stream << " " << argument.m_metavar;
1189
0
      }
1190
0
    }
1191
1192
    // align multiline help message
1193
0
    auto stream_width = stream.width();
1194
0
    auto name_padding = std::string(name_stream.str().size(), ' ');
1195
0
    auto pos = std::string::size_type{};
1196
0
    auto prev = std::string::size_type{};
1197
0
    auto first_line = true;
1198
0
    auto hspace = "  "; // minimal space between name and help message
1199
0
    stream << name_stream.str();
1200
0
    std::string_view help_view(argument.m_help);
1201
0
    while ((pos = argument.m_help.find('\n', prev)) != std::string::npos) {
1202
0
      auto line = help_view.substr(prev, pos - prev + 1);
1203
0
      if (first_line) {
1204
0
        stream << hspace << line;
1205
0
        first_line = false;
1206
0
      } else {
1207
0
        stream.width(stream_width);
1208
0
        stream << name_padding << hspace << line;
1209
0
      }
1210
0
      prev += pos - prev + 1;
1211
0
    }
1212
0
    if (first_line) {
1213
0
      stream << hspace << argument.m_help;
1214
0
    } else {
1215
0
      auto leftover = help_view.substr(prev, argument.m_help.size() - prev);
1216
0
      if (!leftover.empty()) {
1217
0
        stream.width(stream_width);
1218
0
        stream << name_padding << hspace << leftover;
1219
0
      }
1220
0
    }
1221
1222
    // print nargs spec
1223
0
    if (!argument.m_help.empty()) {
1224
0
      stream << " ";
1225
0
    }
1226
0
    stream << argument.m_num_args_range;
1227
1228
0
    bool add_space = false;
1229
0
    if (argument.m_default_value.has_value() &&
1230
0
        argument.m_num_args_range != NArgsRange{0, 0}) {
1231
0
      stream << "[default: " << argument.m_default_value_repr << "]";
1232
0
      add_space = true;
1233
0
    } else if (argument.m_is_required) {
1234
0
      stream << "[required]";
1235
0
      add_space = true;
1236
0
    }
1237
0
    if (argument.m_is_repeatable) {
1238
0
      if (add_space) {
1239
0
        stream << " ";
1240
0
      }
1241
0
      stream << "[may be repeated]";
1242
0
    }
1243
0
    stream << "\n";
1244
0
    return stream;
1245
0
  }
1246
1247
  template <typename T> bool operator!=(const T &rhs) const {
1248
    return !(*this == rhs);
1249
  }
1250
1251
  /*
1252
   * Compare to an argument value of known type
1253
   * @throws std::logic_error in case of incompatible types
1254
   */
1255
  template <typename T> bool operator==(const T &rhs) const {
1256
    if constexpr (!details::IsContainer<T>) {
1257
      return get<T>() == rhs;
1258
    } else {
1259
      using ValueType = typename T::value_type;
1260
      auto lhs = get<T>();
1261
      return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs),
1262
                        std::end(rhs), [](const auto &a, const auto &b) {
1263
                          return std::any_cast<const ValueType &>(a) == b;
1264
                        });
1265
    }
1266
  }
1267
1268
  /*
1269
   * positional:
1270
   *    _empty_
1271
   *    '-'
1272
   *    '-' decimal-literal
1273
   *    !'-' anything
1274
   */
1275
  static bool is_positional(std::string_view name,
1276
0
                            std::string_view prefix_chars) {
1277
0
    auto first = lookahead(name);
1278
1279
0
    if (first == eof) {
1280
0
      return true;
1281
0
    }
1282
0
    if (prefix_chars.find(static_cast<char>(first)) !=
1283
0
                          std::string_view::npos) {
1284
0
      name.remove_prefix(1);
1285
0
      if (name.empty()) {
1286
0
        return true;
1287
0
      }
1288
0
      return is_decimal_literal(name);
1289
0
    }
1290
0
    return true;
1291
0
  }
1292
1293
private:
1294
  class NArgsRange {
1295
    std::size_t m_min;
1296
    std::size_t m_max;
1297
1298
  public:
1299
    NArgsRange(std::size_t minimum, std::size_t maximum)
1300
0
        : m_min(minimum), m_max(maximum) {
1301
0
      if (minimum > maximum) {
1302
0
        throw std::logic_error("Range of number of arguments is invalid");
1303
0
      }
1304
0
    }
1305
1306
0
    bool contains(std::size_t value) const {
1307
0
      return value >= m_min && value <= m_max;
1308
0
    }
1309
1310
0
    bool is_exact() const { return m_min == m_max; }
1311
1312
0
    bool is_right_bounded() const {
1313
0
      return m_max < (std::numeric_limits<std::size_t>::max)();
1314
0
    }
1315
1316
0
    std::size_t get_min() const { return m_min; }
1317
1318
0
    std::size_t get_max() const { return m_max; }
1319
1320
    // Print help message
1321
    friend auto operator<<(std::ostream &stream, const NArgsRange &range)
1322
0
        -> std::ostream & {
1323
0
      if (range.m_min == range.m_max) {
1324
0
        if (range.m_min != 0 && range.m_min != 1) {
1325
0
          stream << "[nargs: " << range.m_min << "] ";
1326
0
        }
1327
0
      } else {
1328
0
        if (range.m_max == (std::numeric_limits<std::size_t>::max)()) {
1329
0
          stream << "[nargs: " << range.m_min << " or more] ";
1330
0
        } else {
1331
0
          stream << "[nargs=" << range.m_min << ".." << range.m_max << "] ";
1332
0
        }
1333
0
      }
1334
0
      return stream;
1335
0
    }
1336
1337
0
    bool operator==(const NArgsRange &rhs) const {
1338
0
      return rhs.m_min == m_min && rhs.m_max == m_max;
1339
0
    }
1340
1341
0
    bool operator!=(const NArgsRange &rhs) const { return !(*this == rhs); }
1342
  };
1343
1344
0
  void throw_nargs_range_validation_error() const {
1345
0
    std::stringstream stream;
1346
0
    if (!m_used_name.empty()) {
1347
0
      stream << m_used_name << ": ";
1348
0
    } else {
1349
0
      stream << m_names.front() << ": ";
1350
0
    }
1351
0
    if (m_num_args_range.is_exact()) {
1352
0
      stream << m_num_args_range.get_min();
1353
0
    } else if (m_num_args_range.is_right_bounded()) {
1354
0
      stream << m_num_args_range.get_min() << " to "
1355
0
             << m_num_args_range.get_max();
1356
0
    } else {
1357
0
      stream << m_num_args_range.get_min() << " or more";
1358
0
    }
1359
0
    stream << " argument(s) expected. " << m_values.size() << " provided.";
1360
0
    throw std::runtime_error(stream.str());
1361
0
  }
1362
1363
0
  void throw_required_arg_not_used_error() const {
1364
0
    std::stringstream stream;
1365
0
    stream << m_names.front() << ": required.";
1366
0
    throw std::runtime_error(stream.str());
1367
0
  }
1368
1369
0
  void throw_required_arg_no_value_provided_error() const {
1370
0
    std::stringstream stream;
1371
0
    stream << m_used_name << ": no value provided.";
1372
0
    throw std::runtime_error(stream.str());
1373
0
  }
1374
1375
  static constexpr int eof = std::char_traits<char>::eof();
1376
1377
0
  static auto lookahead(std::string_view s) -> int {
1378
0
    if (s.empty()) {
1379
0
      return eof;
1380
0
    }
1381
0
    return static_cast<int>(static_cast<unsigned char>(s[0]));
1382
0
  }
1383
1384
  /*
1385
   * decimal-literal:
1386
   *    '0'
1387
   *    nonzero-digit digit-sequence_opt
1388
   *    integer-part fractional-part
1389
   *    fractional-part
1390
   *    integer-part '.' exponent-part_opt
1391
   *    integer-part exponent-part
1392
   *
1393
   * integer-part:
1394
   *    digit-sequence
1395
   *
1396
   * fractional-part:
1397
   *    '.' post-decimal-point
1398
   *
1399
   * post-decimal-point:
1400
   *    digit-sequence exponent-part_opt
1401
   *
1402
   * exponent-part:
1403
   *    'e' post-e
1404
   *    'E' post-e
1405
   *
1406
   * post-e:
1407
   *    sign_opt digit-sequence
1408
   *
1409
   * sign: one of
1410
   *    '+' '-'
1411
   */
1412
0
  static bool is_decimal_literal(std::string_view s) {
1413
0
    if (s == "inf") {
1414
0
      return true;
1415
0
    }
1416
1417
0
    auto is_digit = [](auto c) constexpr {
1418
0
      switch (c) {
1419
0
      case '0':
1420
0
      case '1':
1421
0
      case '2':
1422
0
      case '3':
1423
0
      case '4':
1424
0
      case '5':
1425
0
      case '6':
1426
0
      case '7':
1427
0
      case '8':
1428
0
      case '9':
1429
0
        return true;
1430
0
      default:
1431
0
        return false;
1432
0
      }
1433
0
    };
Unexecuted instantiation: auto gdal_argparse::Argument::is_decimal_literal(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(auto:1)#1}::operator()<char>(char) const
Unexecuted instantiation: auto gdal_argparse::Argument::is_decimal_literal(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(auto:1)#1}::operator()<int>(int) const
1434
1435
    // precondition: we have consumed or will consume at least one digit
1436
0
    auto consume_digits = [=](std::string_view sd) {
1437
      // NOLINTNEXTLINE(readability-qualified-auto)
1438
0
      auto it = std::find_if_not(std::begin(sd), std::end(sd), is_digit);
1439
0
      return sd.substr(static_cast<std::size_t>(it - std::begin(sd)));
1440
0
    };
1441
1442
0
    switch (lookahead(s)) {
1443
0
    case '0': {
1444
0
      s.remove_prefix(1);
1445
0
      if (s.empty()) {
1446
0
        return true;
1447
0
      }
1448
0
      goto integer_part;
1449
0
    }
1450
0
    case '1':
1451
0
    case '2':
1452
0
    case '3':
1453
0
    case '4':
1454
0
    case '5':
1455
0
    case '6':
1456
0
    case '7':
1457
0
    case '8':
1458
0
    case '9': {
1459
0
      s = consume_digits(s);
1460
0
      if (s.empty()) {
1461
0
        return true;
1462
0
      }
1463
0
      goto integer_part_consumed;
1464
0
    }
1465
0
    case '.': {
1466
0
      s.remove_prefix(1);
1467
0
      goto post_decimal_point;
1468
0
    }
1469
0
    default:
1470
0
      return false;
1471
0
    }
1472
1473
0
  integer_part:
1474
0
    s = consume_digits(s);
1475
0
  integer_part_consumed:
1476
0
    switch (lookahead(s)) {
1477
0
    case '.': {
1478
0
      s.remove_prefix(1);
1479
0
      if (is_digit(lookahead(s))) {
1480
0
        goto post_decimal_point;
1481
0
      } else {
1482
0
        goto exponent_part_opt;
1483
0
      }
1484
0
    }
1485
0
    case 'e':
1486
0
    case 'E': {
1487
0
      s.remove_prefix(1);
1488
0
      goto post_e;
1489
0
    }
1490
0
    default:
1491
0
      return false;
1492
0
    }
1493
1494
0
  post_decimal_point:
1495
0
    if (is_digit(lookahead(s))) {
1496
0
      s = consume_digits(s);
1497
0
      goto exponent_part_opt;
1498
0
    }
1499
0
    return false;
1500
1501
0
  exponent_part_opt:
1502
0
    switch (lookahead(s)) {
1503
0
    case eof:
1504
0
      return true;
1505
0
    case 'e':
1506
0
    case 'E': {
1507
0
      s.remove_prefix(1);
1508
0
      goto post_e;
1509
0
    }
1510
0
    default:
1511
0
      return false;
1512
0
    }
1513
1514
0
  post_e:
1515
0
    switch (lookahead(s)) {
1516
0
    case '-':
1517
0
    case '+':
1518
0
      s.remove_prefix(1);
1519
0
    }
1520
0
    if (is_digit(lookahead(s))) {
1521
0
      s = consume_digits(s);
1522
0
      return s.empty();
1523
0
    }
1524
0
    return false;
1525
0
  }
1526
1527
  static bool is_optional(std::string_view name,
1528
0
                          std::string_view prefix_chars) {
1529
0
    return !is_positional(name, prefix_chars);
1530
0
  }
1531
1532
  /*
1533
   * Get argument value given a type
1534
   * @throws std::logic_error in case of incompatible types
1535
   */
1536
  template <typename T> T get() const {
1537
    if (!m_values.empty()) {
1538
      if constexpr (details::IsContainer<T>) {
1539
        return any_cast_container<T>(m_values);
1540
      } else {
1541
        return std::any_cast<T>(m_values.front());
1542
      }
1543
    }
1544
    if (m_default_value.has_value()) {
1545
      return std::any_cast<T>(m_default_value);
1546
    }
1547
    if constexpr (details::IsContainer<T>) {
1548
      if (!m_accepts_optional_like_value) {
1549
        return any_cast_container<T>(m_values);
1550
      }
1551
    }
1552
1553
    throw std::logic_error("No value provided for '" + m_names.back() + "'.");
1554
  }
1555
1556
  /*
1557
   * Get argument value given a type.
1558
   * @pre The object has no default value.
1559
   * @returns The stored value if any, std::nullopt otherwise.
1560
   */
1561
0
  template <typename T> auto present() const -> std::optional<T> {
1562
0
    if (m_default_value.has_value()) {
1563
0
      throw std::logic_error("Argument with default value always presents");
1564
0
    }
1565
0
    if (m_values.empty()) {
1566
0
      return std::nullopt;
1567
0
    }
1568
0
    if constexpr (details::IsContainer<T>) {
1569
0
      return any_cast_container<T>(m_values);
1570
0
    }
1571
0
    return std::any_cast<T>(m_values.front());
1572
0
  }
Unexecuted instantiation: std::__1::optional<std::__1::vector<double, std::__1::allocator<double> > > gdal_argparse::Argument::present<std::__1::vector<double, std::__1::allocator<double> > >() const
Unexecuted instantiation: std::__1::optional<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > gdal_argparse::Argument::present<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >() const
Unexecuted instantiation: std::__1::optional<std::__1::vector<int, std::__1::allocator<int> > > gdal_argparse::Argument::present<std::__1::vector<int, std::__1::allocator<int> > >() const
1573
1574
  template <typename T>
1575
0
  static auto any_cast_container(const std::vector<std::any> &operand) -> T {
1576
0
    using ValueType = typename T::value_type;
1577
1578
0
    T result;
1579
0
    std::transform(
1580
0
        std::begin(operand), std::end(operand), std::back_inserter(result),
1581
0
        [](const auto &value) { return std::any_cast<ValueType>(value); });
Unexecuted instantiation: auto gdal_argparse::Argument::any_cast_container<std::__1::vector<double, std::__1::allocator<double> > >(std::__1::vector<std::__1::any, std::__1::allocator<std::__1::any> > const&)::{lambda(auto:1 const&)#1}::operator()<std::__1::any>(std::__1::any const&) const
Unexecuted instantiation: auto gdal_argparse::Argument::any_cast_container<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(std::__1::vector<std::__1::any, std::__1::allocator<std::__1::any> > const&)::{lambda(auto:1 const&)#1}::operator()<std::__1::any>(std::__1::any const&) const
Unexecuted instantiation: auto gdal_argparse::Argument::any_cast_container<std::__1::vector<int, std::__1::allocator<int> > >(std::__1::vector<std::__1::any, std::__1::allocator<std::__1::any> > const&)::{lambda(auto:1 const&)#1}::operator()<std::__1::any>(std::__1::any const&) const
1582
0
    return result;
1583
0
  }
Unexecuted instantiation: std::__1::vector<double, std::__1::allocator<double> > gdal_argparse::Argument::any_cast_container<std::__1::vector<double, std::__1::allocator<double> > >(std::__1::vector<std::__1::any, std::__1::allocator<std::__1::any> > const&)
Unexecuted instantiation: std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > gdal_argparse::Argument::any_cast_container<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(std::__1::vector<std::__1::any, std::__1::allocator<std::__1::any> > const&)
Unexecuted instantiation: std::__1::vector<int, std::__1::allocator<int> > gdal_argparse::Argument::any_cast_container<std::__1::vector<int, std::__1::allocator<int> > >(std::__1::vector<std::__1::any, std::__1::allocator<std::__1::any> > const&)
1584
1585
0
  void set_usage_newline_counter(int i) { m_usage_newline_counter = i; }
1586
1587
0
  void set_group_idx(std::size_t i) { m_group_idx = i; }
1588
1589
  std::vector<std::string> m_names;
1590
  std::string_view m_used_name;
1591
  std::string m_help;
1592
  std::string m_metavar;
1593
  std::any m_default_value;
1594
  std::string m_default_value_repr;
1595
  std::optional<std::string>
1596
      m_default_value_str; // used for checking default_value against choices
1597
  std::any m_implicit_value;
1598
  std::optional<std::vector<std::string>> m_choices{std::nullopt};
1599
  using valued_action = std::function<std::any(const std::string &)>;
1600
  using void_action = std::function<void(const std::string &)>;
1601
  std::vector<std::variant<valued_action, void_action>> m_actions;
1602
  std::variant<valued_action, void_action> m_default_action{
1603
    std::in_place_type<valued_action>,
1604
0
    [](const std::string &value) { return value; }};
1605
  std::vector<std::any> m_values;
1606
  NArgsRange m_num_args_range{1, 1};
1607
  // Bit field of bool values. Set default value in ctor.
1608
  bool m_accepts_optional_like_value : 1;
1609
  bool m_is_optional : 1;
1610
  bool m_is_required : 1;
1611
  bool m_is_repeatable : 1;
1612
  bool m_is_used : 1;
1613
  bool m_is_hidden : 1;            // if set, does not appear in usage or help
1614
  std::string_view m_prefix_chars; // ArgumentParser has the prefix_chars
1615
  int m_usage_newline_counter = 0;
1616
  std::size_t m_group_idx = 0;
1617
};
1618
1619
class ArgumentParser {
1620
public:
1621
  explicit ArgumentParser(std::string program_name = {},
1622
                          std::string version = "1.0",
1623
                          default_arguments add_args = default_arguments::all,
1624
                          bool exit_on_default_arguments = true,
1625
                          std::ostream &os = std::cout)
1626
0
      : m_program_name(std::move(program_name)), m_version(std::move(version)),
1627
0
        m_exit_on_default_arguments(exit_on_default_arguments),
1628
0
        m_parser_path(m_program_name) {
1629
0
    if ((add_args & default_arguments::help) == default_arguments::help) {
1630
0
      add_argument("-h", "--help")
1631
0
          .action([&](const auto & /*unused*/) {
1632
0
            os << help().str();
1633
0
            if (m_exit_on_default_arguments) {
1634
0
              std::exit(0);
1635
0
            }
1636
0
          })
1637
0
          .default_value(false)
1638
0
          .help("shows help message and exits")
1639
0
          .implicit_value(true)
1640
0
          .nargs(0);
1641
0
    }
1642
0
    if ((add_args & default_arguments::version) == default_arguments::version) {
1643
0
      add_argument("-v", "--version")
1644
0
          .action([&](const auto & /*unused*/) {
1645
0
            os << m_version << std::endl;
1646
0
            if (m_exit_on_default_arguments) {
1647
0
              std::exit(0);
1648
0
            }
1649
0
          })
1650
0
          .default_value(false)
1651
0
          .help("prints version information and exits")
1652
0
          .implicit_value(true)
1653
0
          .nargs(0);
1654
0
    }
1655
0
  }
1656
1657
0
  ~ArgumentParser() = default;
1658
1659
  // ArgumentParser is meant to be used in a single function.
1660
  // Setup everything and parse arguments in one place.
1661
  //
1662
  // ArgumentParser internally uses std::string_views,
1663
  // references, iterators, etc.
1664
  // Many of these elements become invalidated after a copy or move.
1665
  ArgumentParser(const ArgumentParser &other) = delete;
1666
  ArgumentParser &operator=(const ArgumentParser &other) = delete;
1667
  ArgumentParser(ArgumentParser &&) noexcept = delete;
1668
  ArgumentParser &operator=(ArgumentParser &&) = delete;
1669
1670
0
  explicit operator bool() const {
1671
0
    auto arg_used = std::any_of(m_argument_map.cbegin(), m_argument_map.cend(),
1672
0
                                [](auto &it) { return it.second->m_is_used; });
1673
0
    auto subparser_used =
1674
0
        std::any_of(m_subparser_used.cbegin(), m_subparser_used.cend(),
1675
0
                    [](auto &it) { return it.second; });
1676
0
1677
0
    return m_is_parsed && (arg_used || subparser_used);
1678
0
  }
1679
1680
  // Parameter packing
1681
  // Call add_argument with variadic number of string arguments
1682
0
  template <typename... Targs> Argument &add_argument(Targs... f_args) {
1683
0
    using array_of_sv = std::array<std::string_view, sizeof...(Targs)>;
1684
0
    auto argument =
1685
0
        m_optional_arguments.emplace(std::cend(m_optional_arguments),
1686
0
                                     m_prefix_chars, array_of_sv{f_args...});
1687
1688
0
    if (!argument->m_is_optional) {
1689
0
      m_positional_arguments.splice(std::cend(m_positional_arguments),
1690
0
                                    m_optional_arguments, argument);
1691
0
    }
1692
0
    argument->set_usage_newline_counter(m_usage_newline_counter);
1693
0
    argument->set_group_idx(m_group_names.size());
1694
1695
0
    index_argument(argument);
1696
0
    return *argument;
1697
0
  }
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::ArgumentParser::add_argument<char const*>(char const*)
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::ArgumentParser::add_argument<char const*, char const*>(char const*, char const*)
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::ArgumentParser::add_argument<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
1698
1699
  class MutuallyExclusiveGroup {
1700
    friend class ArgumentParser;
1701
1702
  public:
1703
    MutuallyExclusiveGroup() = delete;
1704
1705
    explicit MutuallyExclusiveGroup(ArgumentParser &parent,
1706
                                    bool required = false)
1707
0
        : m_parent(parent), m_required(required), m_elements({}) {}
1708
1709
    MutuallyExclusiveGroup(const MutuallyExclusiveGroup &other) = delete;
1710
    MutuallyExclusiveGroup &
1711
    operator=(const MutuallyExclusiveGroup &other) = delete;
1712
1713
    MutuallyExclusiveGroup(MutuallyExclusiveGroup &&other) noexcept
1714
0
        : m_parent(other.m_parent), m_required(other.m_required),
1715
0
          m_elements(std::move(other.m_elements)) {
1716
0
      other.m_elements.clear();
1717
0
    }
1718
1719
0
    template <typename... Targs> Argument &add_argument(Targs... f_args) {
1720
0
      auto &argument = m_parent.add_argument(std::forward<Targs>(f_args)...);
1721
0
      m_elements.push_back(&argument);
1722
0
      argument.set_usage_newline_counter(m_parent.m_usage_newline_counter);
1723
0
      argument.set_group_idx(m_parent.m_group_names.size());
1724
0
      return argument;
1725
0
    }
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::ArgumentParser::MutuallyExclusiveGroup::add_argument<char const*>(char const*)
Unexecuted instantiation: gdal_argparse::Argument& gdal_argparse::ArgumentParser::MutuallyExclusiveGroup::add_argument<char const*, char const*>(char const*, char const*)
1726
1727
  private:
1728
    ArgumentParser &m_parent;
1729
    bool m_required{false};
1730
    std::vector<Argument *> m_elements{};
1731
  };
1732
1733
0
  MutuallyExclusiveGroup &add_mutually_exclusive_group(bool required = false) {
1734
0
    m_mutually_exclusive_groups.emplace_back(*this, required);
1735
0
    return m_mutually_exclusive_groups.back();
1736
0
  }
1737
1738
  // Parameter packed add_parents method
1739
  // Accepts a variadic number of ArgumentParser objects
1740
  template <typename... Targs>
1741
  ArgumentParser &add_parents(const Targs &... f_args) {
1742
    for (const ArgumentParser &parent_parser : {std::ref(f_args)...}) {
1743
      for (const auto &argument : parent_parser.m_positional_arguments) {
1744
        auto it = m_positional_arguments.insert(
1745
            std::cend(m_positional_arguments), argument);
1746
        index_argument(it);
1747
      }
1748
      for (const auto &argument : parent_parser.m_optional_arguments) {
1749
        auto it = m_optional_arguments.insert(std::cend(m_optional_arguments),
1750
                                              argument);
1751
        index_argument(it);
1752
      }
1753
    }
1754
    return *this;
1755
  }
1756
1757
  // Ask for the next optional arguments to be displayed on a separate
1758
  // line in usage() output. Only effective if set_usage_max_line_width() is
1759
  // also used.
1760
0
  ArgumentParser &add_usage_newline() {
1761
0
    ++m_usage_newline_counter;
1762
0
    return *this;
1763
0
  }
1764
1765
  // Ask for the next optional arguments to be displayed in a separate section
1766
  // in usage() and help (<< *this) output.
1767
  // For usage(), this is only effective if set_usage_max_line_width() is
1768
  // also used.
1769
0
  ArgumentParser &add_group(std::string group_name) {
1770
0
    m_group_names.emplace_back(std::move(group_name));
1771
0
    return *this;
1772
0
  }
1773
1774
0
  ArgumentParser &add_description(std::string description) {
1775
0
    m_description = std::move(description);
1776
0
    return *this;
1777
0
  }
1778
1779
0
  ArgumentParser &add_epilog(std::string epilog) {
1780
0
    m_epilog = std::move(epilog);
1781
0
    return *this;
1782
0
  }
1783
1784
  // Add a un-documented/hidden alias for an argument.
1785
  // Ideally we'd want this to be a method of Argument, but Argument
1786
  // does not own its owing ArgumentParser.
1787
0
  ArgumentParser &add_hidden_alias_for(Argument &arg, std::string_view alias) {
1788
0
    for (auto it = m_optional_arguments.begin();
1789
0
         it != m_optional_arguments.end(); ++it) {
1790
0
      if (&(*it) == &arg) {
1791
0
        m_argument_map.insert_or_assign(std::string(alias), it);
1792
0
        return *this;
1793
0
      }
1794
0
    }
1795
0
    throw std::logic_error(
1796
0
        "Argument is not an optional argument of this parser");
1797
0
  }
1798
1799
  /* Getter for arguments and subparsers.
1800
   * @throws std::logic_error in case of an invalid argument or subparser name
1801
   */
1802
  template <typename T = Argument> T &at(std::string_view name) {
1803
    if constexpr (std::is_same_v<T, Argument>) {
1804
      return (*this)[name];
1805
    } else {
1806
      std::string str_name(name);
1807
      auto subparser_it = m_subparser_map.find(str_name);
1808
      if (subparser_it != m_subparser_map.end()) {
1809
        return subparser_it->second->get();
1810
      }
1811
      throw std::logic_error("No such subparser: " + str_name);
1812
    }
1813
  }
1814
1815
0
  ArgumentParser &set_prefix_chars(std::string prefix_chars) {
1816
0
    m_prefix_chars = std::move(prefix_chars);
1817
0
    return *this;
1818
0
  }
1819
1820
0
  ArgumentParser &set_assign_chars(std::string assign_chars) {
1821
0
    m_assign_chars = std::move(assign_chars);
1822
0
    return *this;
1823
0
  }
1824
1825
  /* Call parse_args_internal - which does all the work
1826
   * Then, validate the parsed arguments
1827
   * This variant is used mainly for testing
1828
   * @throws std::runtime_error in case of any invalid argument
1829
   */
1830
0
  void parse_args(const std::vector<std::string> &arguments) {
1831
0
    parse_args_internal(arguments);
1832
    // Check if all arguments are parsed
1833
0
    for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) {
1834
0
      argument->validate();
1835
0
    }
1836
1837
    // Check each mutually exclusive group and make sure
1838
    // there are no constraint violations
1839
0
    for (const auto &group : m_mutually_exclusive_groups) {
1840
0
      auto mutex_argument_used{false};
1841
0
      Argument *mutex_argument_it{nullptr};
1842
0
      for (Argument *arg : group.m_elements) {
1843
0
        if (!mutex_argument_used && arg->m_is_used) {
1844
0
          mutex_argument_used = true;
1845
0
          mutex_argument_it = arg;
1846
0
        } else if (mutex_argument_used && arg->m_is_used) {
1847
          // Violation
1848
0
          throw std::runtime_error("Argument '" + arg->get_usage_full() +
1849
0
                                   "' not allowed with '" +
1850
0
                                   mutex_argument_it->get_usage_full() + "'");
1851
0
        }
1852
0
      }
1853
1854
0
      if (!mutex_argument_used && group.m_required) {
1855
        // at least one argument from the group is
1856
        // required
1857
0
        std::string argument_names{};
1858
0
        std::size_t i = 0;
1859
0
        std::size_t size = group.m_elements.size();
1860
0
        for (Argument *arg : group.m_elements) {
1861
0
          if (i + 1 == size) {
1862
            // last
1863
0
            argument_names += "'" + arg->get_usage_full() + "' ";
1864
0
          } else {
1865
0
            argument_names += "'" + arg->get_usage_full() + "' or ";
1866
0
          }
1867
0
          i += 1;
1868
0
        }
1869
0
        throw std::runtime_error("One of the arguments " + argument_names +
1870
0
                                 "is required");
1871
0
      }
1872
0
    }
1873
0
  }
1874
1875
  /* Call parse_known_args_internal - which does all the work
1876
   * Then, validate the parsed arguments
1877
   * This variant is used mainly for testing
1878
   * @throws std::runtime_error in case of any invalid argument
1879
   */
1880
  std::vector<std::string>
1881
0
  parse_known_args(const std::vector<std::string> &arguments) {
1882
0
    auto unknown_arguments = parse_known_args_internal(arguments);
1883
0
    // Check if all arguments are parsed
1884
0
    for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) {
1885
0
      argument->validate();
1886
0
    }
1887
0
    return unknown_arguments;
1888
0
  }
1889
1890
  /* Main entry point for parsing command-line arguments using this
1891
   * ArgumentParser
1892
   * @throws std::runtime_error in case of any invalid argument
1893
   */
1894
  // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
1895
0
  void parse_args(int argc, const char *const argv[]) {
1896
0
    parse_args({argv, argv + argc});
1897
0
  }
1898
1899
  /* Main entry point for parsing command-line arguments using this
1900
   * ArgumentParser
1901
   * @throws std::runtime_error in case of any invalid argument
1902
   */
1903
  // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
1904
0
  auto parse_known_args(int argc, const char *const argv[]) {
1905
0
    return parse_known_args({argv, argv + argc});
1906
0
  }
1907
1908
  /* Getter for options with default values.
1909
   * @throws std::logic_error if parse_args() has not been previously called
1910
   * @throws std::logic_error if there is no such option
1911
   * @throws std::logic_error if the option has no value
1912
   * @throws std::bad_any_cast if the option is not of type T
1913
   */
1914
  template <typename T = std::string> T get(std::string_view arg_name) const {
1915
    if (!m_is_parsed) {
1916
      throw std::logic_error("Nothing parsed, no arguments are available.");
1917
    }
1918
    return (*this)[arg_name].get<T>();
1919
  }
1920
1921
  /* Getter for options without default values.
1922
   * @pre The option has no default value.
1923
   * @throws std::logic_error if there is no such option
1924
   * @throws std::bad_any_cast if the option is not of type T
1925
   */
1926
  template <typename T = std::string>
1927
0
  auto present(std::string_view arg_name) const -> std::optional<T> {
1928
0
    return (*this)[arg_name].present<T>();
1929
0
  }
Unexecuted instantiation: std::__1::optional<std::__1::vector<double, std::__1::allocator<double> > > gdal_argparse::ArgumentParser::present<std::__1::vector<double, std::__1::allocator<double> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >) const
Unexecuted instantiation: std::__1::optional<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > gdal_argparse::ArgumentParser::present<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >) const
Unexecuted instantiation: std::__1::optional<std::__1::vector<int, std::__1::allocator<int> > > gdal_argparse::ArgumentParser::present<std::__1::vector<int, std::__1::allocator<int> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >) const
1930
1931
  /* Getter that returns true for user-supplied options. Returns false if not
1932
   * user-supplied, even with a default value.
1933
   */
1934
0
  auto is_used(std::string_view arg_name) const {
1935
0
    return (*this)[arg_name].m_is_used;
1936
0
  }
1937
1938
  /* Getter that returns true if a subcommand is used.
1939
   */
1940
0
  auto is_subcommand_used(std::string_view subcommand_name) const {
1941
0
    return m_subparser_used.at(std::string(subcommand_name));
1942
0
  }
1943
1944
  /* Getter that returns true if a subcommand is used.
1945
   */
1946
0
  auto is_subcommand_used(const ArgumentParser &subparser) const {
1947
0
    return is_subcommand_used(subparser.m_program_name);
1948
0
  }
1949
1950
  /* Indexing operator. Return a reference to an Argument object
1951
   * Used in conjunction with Argument.operator== e.g., parser["foo"] == true
1952
   * @throws std::logic_error in case of an invalid argument name
1953
   */
1954
0
  Argument &operator[](std::string_view arg_name) const {
1955
0
    std::string name(arg_name);
1956
0
    auto it = m_argument_map.find(name);
1957
0
    if (it != m_argument_map.end()) {
1958
0
      return *(it->second);
1959
0
    }
1960
0
    if (!is_valid_prefix_char(arg_name.front())) {
1961
0
      const auto legal_prefix_char = get_any_valid_prefix_char();
1962
0
      const auto prefix = std::string(1, legal_prefix_char);
1963
1964
      // "-" + arg_name
1965
0
      name = prefix + name;
1966
0
      it = m_argument_map.find(name);
1967
0
      if (it != m_argument_map.end()) {
1968
0
        return *(it->second);
1969
0
      }
1970
      // "--" + arg_name
1971
0
      name = prefix + name;
1972
0
      it = m_argument_map.find(name);
1973
0
      if (it != m_argument_map.end()) {
1974
0
        return *(it->second);
1975
0
      }
1976
0
    }
1977
0
    throw std::logic_error("No such argument: " + std::string(arg_name));
1978
0
  }
1979
1980
  // Print help message
1981
  friend auto operator<<(std::ostream &stream, const ArgumentParser &parser)
1982
0
      -> std::ostream & {
1983
0
    stream.setf(std::ios_base::left);
1984
1985
0
    auto longest_arg_length = parser.get_length_of_longest_argument();
1986
1987
0
    stream << parser.usage() << "\n\n";
1988
1989
0
    if (!parser.m_description.empty()) {
1990
0
      stream << parser.m_description << "\n\n";
1991
0
    }
1992
1993
0
    const bool has_visible_positional_args = std::find_if(
1994
0
      parser.m_positional_arguments.begin(),
1995
0
      parser.m_positional_arguments.end(),
1996
0
      [](const auto &argument) {
1997
0
      return !argument.m_is_hidden; }) !=
1998
0
      parser.m_positional_arguments.end();
1999
0
    if (has_visible_positional_args) {
2000
0
      stream << "Positional arguments:\n";
2001
0
    }
2002
2003
0
    for (const auto &argument : parser.m_positional_arguments) {
2004
0
      if (!argument.m_is_hidden) {
2005
0
        stream.width(static_cast<std::streamsize>(longest_arg_length));
2006
0
        stream << argument;
2007
0
      }
2008
0
    }
2009
2010
0
    if (!parser.m_optional_arguments.empty()) {
2011
0
      stream << (!has_visible_positional_args ? "" : "\n")
2012
0
             << "Optional arguments:\n";
2013
0
    }
2014
2015
0
    for (const auto &argument : parser.m_optional_arguments) {
2016
0
      if (argument.m_group_idx == 0 && !argument.m_is_hidden) {
2017
0
        stream.width(static_cast<std::streamsize>(longest_arg_length));
2018
0
        stream << argument;
2019
0
      }
2020
0
    }
2021
2022
0
    for (size_t i_group = 0; i_group < parser.m_group_names.size(); ++i_group) {
2023
0
      stream << "\n" << parser.m_group_names[i_group] << " (detailed usage):\n";
2024
0
      for (const auto &argument : parser.m_optional_arguments) {
2025
0
        if (argument.m_group_idx == i_group + 1 && !argument.m_is_hidden) {
2026
0
          stream.width(static_cast<std::streamsize>(longest_arg_length));
2027
0
          stream << argument;
2028
0
        }
2029
0
      }
2030
0
    }
2031
2032
0
    bool has_visible_subcommands = std::any_of(
2033
0
        parser.m_subparser_map.begin(), parser.m_subparser_map.end(),
2034
0
        [](auto &p) { return !p.second->get().m_suppress; });
2035
2036
0
    if (has_visible_subcommands) {
2037
0
      stream << (parser.m_positional_arguments.empty()
2038
0
                     ? (parser.m_optional_arguments.empty() ? "" : "\n")
2039
0
                     : "\n")
2040
0
             << "Subcommands:\n";
2041
0
      for (const auto &[command, subparser] : parser.m_subparser_map) {
2042
0
        if (subparser->get().m_suppress) {
2043
0
          continue;
2044
0
        }
2045
2046
0
        stream << std::setw(2) << " ";
2047
0
        if (longest_arg_length >= 2) {
2048
0
          stream << std::setw(static_cast<int>(longest_arg_length - 2))
2049
0
                 << command;
2050
0
        }
2051
0
        stream << " " << subparser->get().m_description << "\n";
2052
0
      }
2053
0
    }
2054
2055
0
    if (!parser.m_epilog.empty()) {
2056
0
      stream << '\n';
2057
0
      stream << parser.m_epilog << "\n\n";
2058
0
    }
2059
2060
0
    return stream;
2061
0
  }
2062
2063
  // Format help message
2064
0
  auto help() const -> std::stringstream {
2065
0
    std::stringstream out;
2066
0
    out << *this;
2067
0
    return out;
2068
0
  }
2069
2070
  // Sets the maximum width for a line of the Usage message
2071
0
  ArgumentParser &set_usage_max_line_width(size_t w) {
2072
0
    this->m_usage_max_line_width = w;
2073
0
    return *this;
2074
0
  }
2075
2076
  // Asks to display arguments of mutually exclusive group on separate lines in
2077
  // the Usage message
2078
0
  ArgumentParser &set_usage_break_on_mutex() {
2079
0
    this->m_usage_break_on_mutex = true;
2080
0
    return *this;
2081
0
  }
2082
2083
  // Format usage part of help only
2084
0
  auto usage() const -> std::string {
2085
0
    std::stringstream stream;
2086
2087
0
    std::string curline("Usage: ");
2088
0
    curline += this->m_parser_path;
2089
0
    const bool multiline_usage =
2090
0
        this->m_usage_max_line_width < std::numeric_limits<std::size_t>::max();
2091
0
    const size_t indent_size = curline.size();
2092
2093
0
    const auto deal_with_options_of_group = [&](std::size_t group_idx) {
2094
0
      bool found_options = false;
2095
      // Add any options inline here
2096
0
      const MutuallyExclusiveGroup *cur_mutex = nullptr;
2097
0
      int usage_newline_counter = -1;
2098
0
      for (const auto &argument : this->m_optional_arguments) {
2099
0
        if (argument.m_is_hidden) {
2100
0
          continue;
2101
0
        }
2102
0
        if (multiline_usage) {
2103
0
          if (argument.m_group_idx != group_idx) {
2104
0
            continue;
2105
0
          }
2106
0
          if (usage_newline_counter != argument.m_usage_newline_counter) {
2107
0
            if (usage_newline_counter >= 0) {
2108
0
              if (curline.size() > indent_size) {
2109
0
                stream << curline << std::endl;
2110
0
                curline = std::string(indent_size, ' ');
2111
0
              }
2112
0
            }
2113
0
            usage_newline_counter = argument.m_usage_newline_counter;
2114
0
          }
2115
0
        }
2116
0
        found_options = true;
2117
0
        const std::string arg_inline_usage = argument.get_inline_usage();
2118
0
        const MutuallyExclusiveGroup *arg_mutex =
2119
0
            get_belonging_mutex(&argument);
2120
0
        if ((cur_mutex != nullptr) && (arg_mutex == nullptr)) {
2121
0
          curline += ']';
2122
0
          if (this->m_usage_break_on_mutex) {
2123
0
            stream << curline << std::endl;
2124
0
            curline = std::string(indent_size, ' ');
2125
0
          }
2126
0
        } else if ((cur_mutex == nullptr) && (arg_mutex != nullptr)) {
2127
0
          if ((this->m_usage_break_on_mutex && curline.size() > indent_size) ||
2128
0
              curline.size() + 3 + arg_inline_usage.size() >
2129
0
                  this->m_usage_max_line_width) {
2130
0
            stream << curline << std::endl;
2131
0
            curline = std::string(indent_size, ' ');
2132
0
          }
2133
0
          curline += " [";
2134
0
        } else if ((cur_mutex != nullptr) && (arg_mutex != nullptr)) {
2135
0
          if (cur_mutex != arg_mutex) {
2136
0
            curline += ']';
2137
0
            if (this->m_usage_break_on_mutex ||
2138
0
                curline.size() + 3 + arg_inline_usage.size() >
2139
0
                    this->m_usage_max_line_width) {
2140
0
              stream << curline << std::endl;
2141
0
              curline = std::string(indent_size, ' ');
2142
0
            }
2143
0
            curline += " [";
2144
0
          } else {
2145
0
            curline += '|';
2146
0
          }
2147
0
        }
2148
0
        cur_mutex = arg_mutex;
2149
0
        if (curline.size() != indent_size &&
2150
0
            curline.size() + 1 + arg_inline_usage.size() >
2151
0
            this->m_usage_max_line_width) {
2152
0
          stream << curline << std::endl;
2153
0
          curline = std::string(indent_size, ' ');
2154
0
          curline += " ";
2155
0
        } else if (cur_mutex == nullptr) {
2156
0
          curline += " ";
2157
0
        }
2158
0
        curline += arg_inline_usage;
2159
0
      }
2160
0
      if (cur_mutex != nullptr) {
2161
0
        curline += ']';
2162
0
      }
2163
0
      return found_options;
2164
0
    };
2165
2166
0
    const bool found_options = deal_with_options_of_group(0);
2167
2168
0
    if (found_options && multiline_usage &&
2169
0
        !this->m_positional_arguments.empty()) {
2170
0
      stream << curline << std::endl;
2171
0
      curline = std::string(indent_size, ' ');
2172
0
    }
2173
    // Put positional arguments after the optionals
2174
0
    for (const auto &argument : this->m_positional_arguments) {
2175
0
      if (argument.m_is_hidden) {
2176
0
        continue;
2177
0
      }
2178
0
      const std::string pos_arg = !argument.m_metavar.empty()
2179
0
                                      ? argument.m_metavar
2180
0
                                      : argument.m_names.front();
2181
0
      if (curline.size() + 1 + pos_arg.size() > this->m_usage_max_line_width) {
2182
0
        stream << curline << std::endl;
2183
0
        curline = std::string(indent_size, ' ');
2184
0
      }
2185
0
      curline += " ";
2186
0
      if (argument.m_num_args_range.get_min() == 0 &&
2187
0
          !argument.m_num_args_range.is_right_bounded()) {
2188
0
        curline += "[";
2189
0
        curline += pos_arg;
2190
0
        curline += "]...";
2191
0
      } else if (argument.m_num_args_range.get_min() == 1 &&
2192
0
                 !argument.m_num_args_range.is_right_bounded()) {
2193
0
        curline += pos_arg;
2194
0
        curline += "...";
2195
0
      } else {
2196
0
        curline += pos_arg;
2197
0
      }
2198
0
    }
2199
2200
0
    if (multiline_usage) {
2201
      // Display options of other groups
2202
0
      for (std::size_t i = 0; i < m_group_names.size(); ++i) {
2203
0
        stream << curline << std::endl << std::endl;
2204
0
        stream << m_group_names[i] << ":" << std::endl;
2205
0
        curline = std::string(indent_size, ' ');
2206
0
        deal_with_options_of_group(i + 1);
2207
0
      }
2208
0
    }
2209
2210
0
    stream << curline;
2211
2212
    // Put subcommands after positional arguments
2213
0
    if (!m_subparser_map.empty()) {
2214
0
      stream << " {";
2215
0
      std::size_t i{0};
2216
0
      for (const auto &[command, subparser] : m_subparser_map) {
2217
0
        if (subparser->get().m_suppress) {
2218
0
          continue;
2219
0
        }
2220
2221
0
        if (i == 0) {
2222
0
          stream << command;
2223
0
        } else {
2224
0
          stream << "," << command;
2225
0
        }
2226
0
        ++i;
2227
0
      }
2228
0
      stream << "}";
2229
0
    }
2230
2231
0
    return stream.str();
2232
0
  }
2233
2234
  // Printing the one and only help message
2235
  // I've stuck with a simple message format, nothing fancy.
2236
  [[deprecated("Use cout << program; instead.  See also help().")]] std::string
2237
0
  print_help() const {
2238
0
    auto out = help();
2239
0
    std::cout << out.rdbuf();
2240
0
    return out.str();
2241
0
  }
2242
2243
0
  void add_subparser(ArgumentParser &parser) {
2244
0
    parser.m_parser_path = m_program_name + " " + parser.m_program_name;
2245
0
    auto it = m_subparsers.emplace(std::cend(m_subparsers), parser);
2246
0
    m_subparser_map.insert_or_assign(parser.m_program_name, it);
2247
0
    m_subparser_used.insert_or_assign(parser.m_program_name, false);
2248
0
  }
2249
2250
0
  void set_suppress(bool suppress) { m_suppress = suppress; }
2251
2252
protected:
2253
0
  const MutuallyExclusiveGroup *get_belonging_mutex(const Argument *arg) const {
2254
0
    for (const auto &mutex : m_mutually_exclusive_groups) {
2255
0
      if (std::find(mutex.m_elements.begin(), mutex.m_elements.end(), arg) !=
2256
0
          mutex.m_elements.end()) {
2257
0
        return &mutex;
2258
0
      }
2259
0
    }
2260
0
    return nullptr;
2261
0
  }
2262
2263
0
  bool is_valid_prefix_char(char c) const {
2264
0
    return m_prefix_chars.find(c) != std::string::npos;
2265
0
  }
2266
2267
0
  char get_any_valid_prefix_char() const { return m_prefix_chars[0]; }
2268
2269
  /*
2270
   * Pre-process this argument list. Anything starting with "--", that
2271
   * contains an =, where the prefix before the = has an entry in the
2272
   * options table, should be split.
2273
   */
2274
  std::vector<std::string>
2275
0
  preprocess_arguments(const std::vector<std::string> &raw_arguments) const {
2276
0
    std::vector<std::string> arguments{};
2277
0
    for (const auto &arg : raw_arguments) {
2278
2279
0
      const auto argument_starts_with_prefix_chars =
2280
0
          [this](const std::string &a) -> bool {
2281
0
        if (!a.empty()) {
2282
2283
0
          const auto legal_prefix = [this](char c) -> bool {
2284
0
            return m_prefix_chars.find(c) != std::string::npos;
2285
0
          };
2286
2287
          // Windows-style
2288
          // if '/' is a legal prefix char
2289
          // then allow single '/' followed by argument name, followed by an
2290
          // assign char, e.g., ':' e.g., 'test.exe /A:Foo'
2291
0
          const auto windows_style = legal_prefix('/');
2292
2293
0
          if (windows_style) {
2294
0
            if (legal_prefix(a[0])) {
2295
0
              return true;
2296
0
            }
2297
0
          } else {
2298
            // Slash '/' is not a legal prefix char
2299
            // For all other characters, only support long arguments
2300
            // i.e., the argument must start with 2 prefix chars, e.g,
2301
            // '--foo' e,g, './test --foo=Bar -DARG=yes'
2302
0
            if (a.size() > 1) {
2303
0
              return (legal_prefix(a[0]) && legal_prefix(a[1]));
2304
0
            }
2305
0
          }
2306
0
        }
2307
0
        return false;
2308
0
      };
2309
2310
      // Check that:
2311
      // - We don't have an argument named exactly this
2312
      // - The argument starts with a prefix char, e.g., "--"
2313
      // - The argument contains an assign char, e.g., "="
2314
0
      auto assign_char_pos = arg.find_first_of(m_assign_chars);
2315
2316
0
      if (m_argument_map.find(arg) == m_argument_map.end() &&
2317
0
          argument_starts_with_prefix_chars(arg) &&
2318
0
          assign_char_pos != std::string::npos) {
2319
        // Get the name of the potential option, and check it exists
2320
0
        std::string opt_name = arg.substr(0, assign_char_pos);
2321
0
        if (m_argument_map.find(opt_name) != m_argument_map.end()) {
2322
          // This is the name of an option! Split it into two parts
2323
0
          arguments.push_back(std::move(opt_name));
2324
0
          arguments.push_back(arg.substr(assign_char_pos + 1));
2325
0
          continue;
2326
0
        }
2327
0
      }
2328
      // If we've fallen through to here, then it's a standard argument
2329
0
      arguments.push_back(arg);
2330
0
    }
2331
0
    return arguments;
2332
0
  }
2333
2334
  /*
2335
   * @throws std::runtime_error in case of any invalid argument
2336
   */
2337
0
  void parse_args_internal(const std::vector<std::string> &raw_arguments) {
2338
0
    auto arguments = preprocess_arguments(raw_arguments);
2339
0
    if (m_program_name.empty() && !arguments.empty()) {
2340
0
      m_program_name = arguments.front();
2341
0
    }
2342
0
    auto end = std::end(arguments);
2343
0
    auto positional_argument_it = std::begin(m_positional_arguments);
2344
0
    for (auto it = std::next(std::begin(arguments)); it != end;) {
2345
0
      const auto &current_argument = *it;
2346
0
      if (Argument::is_positional(current_argument, m_prefix_chars)) {
2347
0
        if (positional_argument_it == std::end(m_positional_arguments)) {
2348
2349
          // Check sub-parsers
2350
0
          auto subparser_it = m_subparser_map.find(current_argument);
2351
0
          if (subparser_it != m_subparser_map.end()) {
2352
2353
            // build list of remaining args
2354
0
            const auto unprocessed_arguments =
2355
0
                std::vector<std::string>(it, end);
2356
2357
            // invoke subparser
2358
0
            m_is_parsed = true;
2359
0
            m_subparser_used[current_argument] = true;
2360
0
            return subparser_it->second->get().parse_args(
2361
0
                unprocessed_arguments);
2362
0
          }
2363
2364
0
          if (m_positional_arguments.empty()) {
2365
2366
            // Ask the user if they argument they provided was a typo
2367
            // for some sub-parser,
2368
            // e.g., user provided `git totes` instead of `git notes`
2369
0
            if (!m_subparser_map.empty()) {
2370
0
              throw std::runtime_error(
2371
0
                  "Failed to parse '" + current_argument + "', did you mean '" +
2372
0
                  std::string{details::get_most_similar_string(
2373
0
                      m_subparser_map, current_argument)} +
2374
0
                  "'");
2375
0
            }
2376
2377
            // Ask the user if they meant to use a specific optional argument
2378
0
            if (!m_optional_arguments.empty()) {
2379
0
              for (const auto &opt : m_optional_arguments) {
2380
0
                if (!opt.m_implicit_value.has_value()) {
2381
                  // not a flag, requires a value
2382
0
                  if (!opt.m_is_used) {
2383
0
                    throw std::runtime_error(
2384
0
                        "Zero positional arguments expected, did you mean " +
2385
0
                        opt.get_usage_full());
2386
0
                  }
2387
0
                }
2388
0
              }
2389
2390
0
              throw std::runtime_error("Zero positional arguments expected");
2391
0
            } else {
2392
0
              throw std::runtime_error("Zero positional arguments expected");
2393
0
            }
2394
0
          } else {
2395
0
            throw std::runtime_error("Maximum number of positional arguments "
2396
0
                                     "exceeded, failed to parse '" +
2397
0
                                     current_argument + "'");
2398
0
          }
2399
0
        }
2400
0
        auto argument = positional_argument_it++;
2401
2402
        // Deal with the situation of <positional_arg1>... <positional_arg2>
2403
0
        if (argument->m_num_args_range.get_min() == 1 &&
2404
0
            argument->m_num_args_range.get_max() == (std::numeric_limits<std::size_t>::max)() &&
2405
0
            positional_argument_it != std::end(m_positional_arguments) &&
2406
0
            std::next(positional_argument_it) == std::end(m_positional_arguments) &&
2407
0
            positional_argument_it->m_num_args_range.get_min() == 1 &&
2408
0
            positional_argument_it->m_num_args_range.get_max() == 1 ) {
2409
0
          if (std::next(it) != end) {
2410
0
            positional_argument_it->consume(std::prev(end), end);
2411
0
            end = std::prev(end);
2412
0
          } else {
2413
0
            throw std::runtime_error("Missing " + positional_argument_it->m_names.front());
2414
0
          }
2415
0
        }
2416
2417
0
        it = argument->consume(it, end);
2418
0
        continue;
2419
0
      }
2420
2421
0
      auto arg_map_it = m_argument_map.find(current_argument);
2422
0
      if (arg_map_it != m_argument_map.end()) {
2423
0
        auto argument = arg_map_it->second;
2424
0
        it = argument->consume(std::next(it), end, arg_map_it->first);
2425
0
      } else if (const auto &compound_arg = current_argument;
2426
0
                 compound_arg.size() > 1 &&
2427
0
                 is_valid_prefix_char(compound_arg[0]) &&
2428
0
                 !is_valid_prefix_char(compound_arg[1])) {
2429
0
        ++it;
2430
0
        for (std::size_t j = 1; j < compound_arg.size(); j++) {
2431
0
          auto hypothetical_arg = std::string{'-', compound_arg[j]};
2432
0
          auto arg_map_it2 = m_argument_map.find(hypothetical_arg);
2433
0
          if (arg_map_it2 != m_argument_map.end()) {
2434
0
            auto argument = arg_map_it2->second;
2435
0
            it = argument->consume(it, end, arg_map_it2->first);
2436
0
          } else {
2437
0
            throw std::runtime_error("Unknown argument: " + current_argument);
2438
0
          }
2439
0
        }
2440
0
      } else {
2441
0
        throw std::runtime_error("Unknown argument: " + current_argument);
2442
0
      }
2443
0
    }
2444
0
    m_is_parsed = true;
2445
0
  }
2446
2447
  /*
2448
   * Like parse_args_internal but collects unused args into a vector<string>
2449
   */
2450
  std::vector<std::string>
2451
0
  parse_known_args_internal(const std::vector<std::string> &raw_arguments) {
2452
0
    auto arguments = preprocess_arguments(raw_arguments);
2453
0
2454
0
    std::vector<std::string> unknown_arguments{};
2455
0
2456
0
    if (m_program_name.empty() && !arguments.empty()) {
2457
0
      m_program_name = arguments.front();
2458
0
    }
2459
0
    auto end = std::end(arguments);
2460
0
    auto positional_argument_it = std::begin(m_positional_arguments);
2461
0
    for (auto it = std::next(std::begin(arguments)); it != end;) {
2462
0
      const auto &current_argument = *it;
2463
0
      if (Argument::is_positional(current_argument, m_prefix_chars)) {
2464
0
        if (positional_argument_it == std::end(m_positional_arguments)) {
2465
0
2466
0
          // Check sub-parsers
2467
0
          auto subparser_it = m_subparser_map.find(current_argument);
2468
0
          if (subparser_it != m_subparser_map.end()) {
2469
0
2470
0
            // build list of remaining args
2471
0
            const auto unprocessed_arguments =
2472
0
                std::vector<std::string>(it, end);
2473
0
2474
0
            // invoke subparser
2475
0
            m_is_parsed = true;
2476
0
            m_subparser_used[current_argument] = true;
2477
0
            return subparser_it->second->get().parse_known_args_internal(
2478
0
                unprocessed_arguments);
2479
0
          }
2480
0
2481
0
          // save current argument as unknown and go to next argument
2482
0
          unknown_arguments.push_back(current_argument);
2483
0
          ++it;
2484
0
        } else {
2485
0
          // current argument is the value of a positional argument
2486
0
          // consume it
2487
0
          auto argument = positional_argument_it++;
2488
0
          it = argument->consume(it, end);
2489
0
        }
2490
0
        continue;
2491
0
      }
2492
0
2493
0
      auto arg_map_it = m_argument_map.find(current_argument);
2494
0
      if (arg_map_it != m_argument_map.end()) {
2495
0
        auto argument = arg_map_it->second;
2496
0
        it = argument->consume(std::next(it), end, arg_map_it->first);
2497
0
      } else if (const auto &compound_arg = current_argument;
2498
0
                 compound_arg.size() > 1 &&
2499
0
                 is_valid_prefix_char(compound_arg[0]) &&
2500
0
                 !is_valid_prefix_char(compound_arg[1])) {
2501
0
        ++it;
2502
0
        for (std::size_t j = 1; j < compound_arg.size(); j++) {
2503
0
          auto hypothetical_arg = std::string{'-', compound_arg[j]};
2504
0
          auto arg_map_it2 = m_argument_map.find(hypothetical_arg);
2505
0
          if (arg_map_it2 != m_argument_map.end()) {
2506
0
            auto argument = arg_map_it2->second;
2507
0
            it = argument->consume(it, end, arg_map_it2->first);
2508
0
          } else {
2509
0
            unknown_arguments.push_back(current_argument);
2510
0
            break;
2511
0
          }
2512
0
        }
2513
0
      } else {
2514
0
        // current argument is an optional-like argument that is unknown
2515
0
        // save it and move to next argument
2516
0
        unknown_arguments.push_back(current_argument);
2517
0
        ++it;
2518
0
      }
2519
0
    }
2520
0
    m_is_parsed = true;
2521
0
    return unknown_arguments;
2522
0
  }
2523
2524
  // Used by print_help.
2525
0
  std::size_t get_length_of_longest_argument() const {
2526
0
    if (m_argument_map.empty()) {
2527
0
      return 0;
2528
0
    }
2529
0
    std::size_t max_size = 0;
2530
0
    for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) {
2531
0
      max_size =
2532
0
          std::max<std::size_t>(max_size, argument->get_arguments_length());
2533
0
    }
2534
0
    for ([[maybe_unused]] const auto &[command, unused] : m_subparser_map) {
2535
0
      max_size = std::max<std::size_t>(max_size, command.size());
2536
0
    }
2537
0
    return max_size;
2538
0
  }
2539
2540
  using argument_it = std::list<Argument>::iterator;
2541
  using mutex_group_it = std::vector<MutuallyExclusiveGroup>::iterator;
2542
  using argument_parser_it =
2543
      std::list<std::reference_wrapper<ArgumentParser>>::iterator;
2544
2545
0
  void index_argument(argument_it it) {
2546
0
    for (const auto &name : std::as_const(it->m_names)) {
2547
0
      m_argument_map.insert_or_assign(name, it);
2548
0
    }
2549
0
  }
2550
2551
  std::string m_program_name;
2552
  std::string m_version;
2553
  std::string m_description;
2554
  std::string m_epilog;
2555
  bool m_exit_on_default_arguments = true;
2556
  std::string m_prefix_chars{"-"};
2557
  std::string m_assign_chars{"="};
2558
  bool m_is_parsed = false;
2559
  std::list<Argument> m_positional_arguments;
2560
  std::list<Argument> m_optional_arguments;
2561
  std::map<std::string, argument_it> m_argument_map;
2562
  std::string m_parser_path;
2563
  std::list<std::reference_wrapper<ArgumentParser>> m_subparsers;
2564
  std::map<std::string, argument_parser_it> m_subparser_map;
2565
  std::map<std::string, bool> m_subparser_used;
2566
  std::vector<MutuallyExclusiveGroup> m_mutually_exclusive_groups;
2567
  bool m_suppress = false;
2568
  std::size_t m_usage_max_line_width = std::numeric_limits<std::size_t>::max();
2569
  bool m_usage_break_on_mutex = false;
2570
  int m_usage_newline_counter = 0;
2571
  std::vector<std::string> m_group_names;
2572
};
2573
2574
} // namespace argparse