argv_input.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2023 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_INPUT_ARGV_INPUT_HPP_INCLUDED
5 #define LEXY_INPUT_ARGV_INPUT_HPP_INCLUDED
6 
9 #include <lexy/dsl/base.hpp>
10 #include <lexy/dsl/token.hpp>
11 #include <lexy/input/base.hpp>
12 #include <lexy/lexeme.hpp>
13 
14 namespace lexy
15 {
16 class argv_iterator;
17 
19 class argv_sentinel : public _detail::sentinel_base<argv_sentinel, argv_iterator>
20 {};
21 
23 class argv_iterator : public _detail::bidirectional_iterator_base<argv_iterator, const char>
24 {
25 public:
26  constexpr argv_iterator() noexcept : _arg(nullptr), _c(nullptr) {}
27 
28  constexpr const char& deref() const noexcept
29  {
30  return *_c;
31  }
32 
33  constexpr void increment() noexcept
34  {
35  LEXY_PRECONDITION(*this != argv_sentinel{});
36  if (*_c == '\0')
37  {
38  // Go to next argument.
39  // We will have one, otherwise the precondition above would have fired.
40  ++_arg;
41  // Update c to the beginning of next argument.
42  _c = *_arg;
43  }
44  else
45  ++_c;
46  }
47  constexpr void decrement() noexcept
48  {
49  // Check whether we point to the first character of the argument.
50  if (_c == *_arg)
51  {
52  // Go to end of previous argument.
53  --_arg;
54  _c = *_arg;
55  while (*_c != '\0')
56  ++_c;
57  }
58  else
59  --_c;
60  }
61 
62  constexpr bool equal(argv_iterator rhs) const noexcept
63  {
64  return _arg == rhs._arg && _c == rhs._c;
65  }
66  constexpr bool is_end() const noexcept
67  {
68  // We're at the end if we're at the last character of the last argument,
69  // or have an empty argv range.
70  return _c == nullptr || (*_c == '\0' && _arg[1] == nullptr);
71  }
72 
73 #ifndef _MSC_VER
74 private:
75  // MSVC is a bad compiler and should feel bad.
76  // Or at least fix their friend declarations.
77 #endif
78  constexpr explicit argv_iterator(char** argument, char* c) noexcept : _arg(argument), _c(c) {}
79 
80 private:
81  char** _arg;
82  char* _c;
83 
84  friend constexpr argv_iterator argv_begin(int argc, char* argv[]) noexcept;
85  friend constexpr argv_iterator argv_end(int argc, char* argv[]) noexcept;
86 };
87 
89 constexpr argv_iterator argv_begin(int argc, char* argv[]) noexcept
90 {
91  if (argc <= 1)
92  // Create an iterator where *arg_ == nullptr, *c_ == nullptr.
93  return argv_iterator(&argv[argc], nullptr);
94  else
95  return argv_iterator(&argv[1], &argv[1][0]);
96 }
97 
99 constexpr argv_iterator argv_end(int argc, char* argv[]) noexcept
100 {
101  if (argc <= 1)
102  // Create an iterator where *arg_ == nullptr, *c_ == nullptr.
103  return argv_iterator(&argv[argc], nullptr);
104  else
105  {
106  // Construct an iterator pointing to the nullptr arg.
107  // Then decrement it to get the null terminator of the last argument,
108  // which is the actual end.
109  argv_iterator one_past_end(&argv[argc], nullptr);
110  --one_past_end;
111  return one_past_end;
112  }
113 }
114 } // namespace lexy
115 
116 namespace lexy
117 {
118 template <typename Encoding = default_encoding>
120 {
121 public:
122  using encoding = Encoding;
123  using char_type = typename encoding::char_type;
124  static_assert(
125  std::is_same_v<char_type, char> || Encoding::template is_secondary_char_type<char>(),
126  "invalid encoding for argv");
127 
128  //=== constructors ===//
129  constexpr argv_input() = default;
130 
133  {}
134 
136  constexpr argv_input(int argc, char* argv[]) noexcept
137  : _begin(argv_begin(argc, argv)), _end(argv_end(argc, argv))
138  {}
139 
140  //=== reader ===//
141  constexpr auto reader() const& noexcept
142  {
143  return _range_reader<encoding>(_begin, _end);
144  }
145 
146 private:
148 };
149 
150 argv_input(int argc, char* argv[])->argv_input<>;
151 } // namespace lexy
152 
153 namespace lexy
154 {
155 template <typename Encoding = default_encoding>
157 
158 template <typename Tag, typename Encoding = default_encoding>
160 
161 template <typename Encoding = default_encoding>
163 } // namespace lexy
164 
165 namespace lexyd
166 {
167 struct _argvsep : token_base<_argvsep>
168 {
169  template <typename Reader>
170  struct tp
171  {
172  typename Reader::iterator end;
173 
174  constexpr explicit tp(const Reader& reader) : end(reader.position()) {}
175 
176  constexpr auto try_parse([[maybe_unused]] Reader reader)
177  {
178  using encoding = typename Reader::encoding;
179  if constexpr (std::is_same_v<Reader, lexy::input_reader<lexy::argv_input<encoding>>>)
180  {
181  if (reader.peek() != lexy::_detail::transcode_int<encoding>('\0'))
182  return false;
183 
184  reader.bump();
185  end = reader.position();
186  return true;
187  }
188  else
189  {
190  return std::false_type{};
191  }
192  }
193 
194  template <typename Context>
195  constexpr void report_error(Context& context, const Reader& reader)
196  {
197  auto err = lexy::error<Reader, lexy::expected_char_class>(reader.position(),
198  "argv-separator");
199  context.on(_ev::error{}, err);
200  }
201  };
202 };
203 
205 constexpr auto argv_separator = _argvsep{};
206 } // namespace lexyd
207 
208 namespace lexy
209 {
210 template <>
211 inline constexpr auto token_kind_of<lexy::dsl::_argvsep> = lexy::literal_token_kind;
212 } // namespace lexy
213 
214 #endif // LEXY_INPUT_ARGV_INPUT_HPP_INCLUDED
215 
lexy::argv_iterator::equal
constexpr bool equal(argv_iterator rhs) const noexcept
Definition: argv_input.hpp:62
lexyd::position
constexpr auto position
Produces an iterator to the current reader position without parsing anything.
Definition: position.hpp:79
lexy::argv_input::reader
constexpr auto reader() const &noexcept
Definition: argv_input.hpp:141
token.hpp
lexy::argv_iterator::argv_begin
constexpr friend argv_iterator argv_begin(int argc, char *argv[]) noexcept
Returns an iterator to the beginning of the command-line arguments.
Definition: argv_input.hpp:89
magic_enum::char_type
string_view::value_type char_type
Definition: magic_enum.hpp:145
iterator.hpp
lexy::argv_iterator::_arg
char ** _arg
Definition: argv_input.hpp:81
lexy::argv_end
constexpr argv_iterator argv_end(int argc, char *argv[]) noexcept
Returns an iterator one past the end of the command-line arguments.
Definition: argv_input.hpp:99
lexy::argv_iterator::is_end
constexpr bool is_end() const noexcept
Definition: argv_input.hpp:66
lexy::argv_input::char_type
typename encoding::char_type char_type
Definition: argv_input.hpp:123
lexyd::_argvsep::tp::end
Reader::iterator end
Definition: argv_input.hpp:172
lexyd::_argvsep::tp::report_error
constexpr void report_error(Context &context, const Reader &reader)
Definition: argv_input.hpp:195
lexy::argv_input::argv_input
constexpr argv_input()=default
lexy::error_context
Contains information about the context of an error, production is type-erased.
Definition: error.hpp:198
lexy
Definition: any_ref.hpp:12
lexy::argv_iterator::_c
char * _c
Definition: argv_input.hpp:82
LEXY_PRECONDITION
#define LEXY_PRECONDITION(Expr)
Definition: assert.hpp:36
lexy::argv_iterator::argv_iterator
constexpr argv_iterator() noexcept
Definition: argv_input.hpp:26
lexy::literal_token_kind
@ literal_token_kind
Definition: grammar.hpp:81
cx::end
constexpr auto end(const C &c) -> decltype(c.end())
Definition: wildcards.hpp:686
lexyd::_argvsep
Definition: argv_input.hpp:167
lexyd::_argvsep::tp::try_parse
constexpr auto try_parse([[maybe_unused]] Reader reader)
Definition: argv_input.hpp:176
lexy::argv_iterator::argv_iterator
constexpr argv_iterator(char **argument, char *c) noexcept
Definition: argv_input.hpp:78
lexy::error
Generic failure.
Definition: error.hpp:14
lexy::argv_input::_end
argv_iterator _end
Definition: argv_input.hpp:147
lexy::argv_input::argv_input
constexpr argv_input(int argc, char *argv[]) noexcept
Iterate over the command-line arguments.
Definition: argv_input.hpp:136
lexy::parse_events::error
Definition: dsl/base.hpp:55
lexeme.hpp
lexyd::token_base
Definition: dsl/token.hpp:42
lexy::argv_iterator::argv_end
constexpr friend argv_iterator argv_end(int argc, char *argv[]) noexcept
Returns an iterator one past the end of the command-line arguments.
Definition: argv_input.hpp:99
lexy::argv_input::encoding
Encoding encoding
Definition: argv_input.hpp:122
assert.hpp
lexy::argv_sentinel
A sentinel for the command-line arguments.
Definition: argv_input.hpp:19
cx::begin
constexpr auto begin(const C &c) -> decltype(c.begin())
Definition: wildcards.hpp:661
lexy::argv_begin
constexpr argv_iterator argv_begin(int argc, char *argv[]) noexcept
Returns an iterator to the beginning of the command-line arguments.
Definition: argv_input.hpp:89
lexy::argv_input
argv_input(int argc, char *argv[]) -> argv_input<>
base.hpp
lexy::argv_input
Definition: argv_input.hpp:119
lexy::argv_iterator::decrement
constexpr void decrement() noexcept
Definition: argv_input.hpp:47
lexy::lexeme
Definition: lexeme.hpp:16
lexy::argv_input::_begin
argv_iterator _begin
Definition: argv_input.hpp:147
lexy::_detail::bidirectional_iterator_base
Definition: iterator.hpp:202
lexyd::_argvsep::tp
Definition: argv_input.hpp:170
lexy::argv_iterator::increment
constexpr void increment() noexcept
Definition: argv_input.hpp:33
base.hpp
lexy::_detail::sentinel_base
Definition: iterator.hpp:222
lexyd
Definition: trace.hpp:22
lexyd::_argvsep::tp::tp
constexpr tp(const Reader &reader)
Definition: argv_input.hpp:174
lexy::input_reader
decltype(LEXY_DECLVAL(Input).reader()) input_reader
Definition: input/base.hpp:92
lexyd::argv_separator
constexpr auto argv_separator
Matches the separator between arguments of an argv_input.
Definition: argv_input.hpp:205
lexy::argv_input::argv_input
constexpr argv_input(argv_iterator begin, argv_iterator end) noexcept
Iterate over the range of command-line arguments.
Definition: argv_input.hpp:132
lexy::argv_iterator::deref
constexpr const char & deref() const noexcept
Definition: argv_input.hpp:28
lexy::argv_iterator
An iterator over the command-line arguments.
Definition: argv_input.hpp:23


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:07