Option++  2.0
C++ library for reading command-line options
result_iterator.hpp
Go to the documentation of this file.
1 /* Option++ -- read command-line program options
2  * Copyright (C) 2017-2020 Greg Kikola.
3  *
4  * This file is part of Option++.
5  *
6  * Option++ is free software: you can redistribute it and/or modify
7  * it under the terms of the Boost Software License version 1.0.
8  *
9  * Option++ is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * Boost Software License for more details.
13  *
14  * You should have received a copy of the Boost Software License
15  * along with Option++. If not, see
16  * <https://www.boost.org/LICENSE_1_0.txt>.
17  */
18 /* Written by Greg Kikola <[email protected]>. */
19 
25 #ifndef OPTIONPP_RESULT_ITERATOR_HPP
26 #define OPTIONPP_RESULT_ITERATOR_HPP
27 
29 
30 namespace optionpp {
31 
35  template <typename T, typename Ptr, typename Ref, bool IsOption>
36  class result_iterator : public std::iterator<std::bidirectional_iterator_tag,
37  T, std::ptrdiff_t,
38  Ptr, Ref> {
39  public:
43  result_iterator() noexcept : m_result{nullptr}, m_index{} {}
48  result_iterator(T& result)
49  : m_result{&result}, m_index{0} {
50  if (!result.empty() && result[0].is_option != IsOption)
51  ++(*this);
52  }
53 
60  Ref operator*() const;
61 
68  Ptr operator->() const { return &**this; }
69 
76 
83  ++(*this);
84  return copy;
85  }
86 
95 
104  --(*this);
105  return copy;
106  }
107 
114  bool operator==(const result_iterator<T, Ptr, Ref, IsOption>& other) const;
115 
122  inline bool operator!=(const result_iterator<T, Ptr, Ref, IsOption>& other) const {
123  return !(*this == other);
124  }
125 
126  private:
127  T* m_result; //< `parser_result` being iterated over.
128  typename T::size_type m_index; //< Current entry index.
129  };
130 
136  template <typename T,
137  typename Ptr, typename Ref, bool IsOption>
138  inline result_iterator<T, Ptr, Ref, IsOption>
139  begin(result_iterator<T, Ptr, Ref, IsOption> it) noexcept { return it; }
140 
145  template <typename T,
146  typename Ptr, typename Ref, bool IsOption>
147  inline result_iterator<T, Ptr, Ref, IsOption>
150  }
151 
155  using option_iterator = result_iterator<parser_result,
156  parsed_entry*,
157  parsed_entry&,
158  true>;
159 
165  const parsed_entry*,
166  const parsed_entry&,
167  true>;
168 
173  parsed_entry*,
174  parsed_entry&,
175  false>;
176 
182  const parsed_entry*,
183  const parsed_entry&,
184  false>;
185 
186 } // End namespace
187 
188 
189 /* Implementation */
190 
191 template <typename T,
192  typename Ptr, typename Ref, bool IsOption>
194  if (!m_result)
195  throw bad_dereference{"tried to dereference a nullptr",
196  "optionpp::non_option_iterator::operator*"};
197  if (m_index == m_result->size())
198  throw bad_dereference{"tried to dereference past-the-end iterator",
199  "optionpp::non_option_iterator::operator*"};
200  return (*m_result)[m_index];
201 }
202 
203 template <typename T,
204  typename Ptr, typename Ref, bool IsOption>
207  if (m_result) {
208  do {
209  ++m_index;
210  } while (m_index < m_result->size()
211  && (*m_result)[m_index].is_option != IsOption);
212  }
213  return *this;
214 }
215 
216 template <typename T,
217  typename Ptr, typename Ref, bool IsOption>
220  if (m_result) {
221  do {
222  if (m_index == 0)
223  throw out_of_range{"out of bounds parser_result access",
224  "optionpp::non_option_iterator::operator--"};
225  --m_index;
226  } while ((*m_result)[m_index].is_option != IsOption);
227  }
228  return *this;
229 }
230 
231 template <typename T,
232  typename Ptr, typename Ref, bool IsOption>
235  bool left_default = !m_result;
236  bool right_default = !other.m_result;
237  bool left_at_end = left_default || m_result->size() == m_index;
238  bool right_at_end = right_default
239  || other.m_result->size() == other.m_index;
240 
241  // If neither iterator was default-constructed, compare contents
242  if (!left_default && !right_default)
243  return m_index == other.m_index && m_result == other.m_result;
244  // If both are `end()` iterators, they're equal
245  else if (left_at_end && right_at_end)
246  return true;
247  else // Otherwise, not equal
248  return false;
249 }
250 
251 #endif
optionpp::out_of_range
Exception indicating out of range access.
Definition: error.hpp:59
optionpp::parsed_entry
Holds data parsed from the command line.
Definition: parser_result.hpp:45
optionpp::begin
result_iterator< T, Ptr, Ref, IsOption > begin(result_iterator< T, Ptr, Ref, IsOption > it) noexcept
begin function for range for loop support.
Definition: result_iterator.hpp:139
optionpp::result_iterator::operator==
bool operator==(const result_iterator< T, Ptr, Ref, IsOption > &other) const
result_iterator comparison operator.
Definition: result_iterator.hpp:234
optionpp::result_iterator::result_iterator
result_iterator(T &result)
Constructor.
Definition: result_iterator.hpp:48
optionpp::result_iterator
Iterator over parser_result arguments.
Definition: result_iterator.hpp:36
optionpp::result_iterator::result_iterator
result_iterator() noexcept
Default constructor.
Definition: result_iterator.hpp:43
optionpp::result_iterator::operator++
result_iterator operator++(int)
Postfix increment operator.
Definition: result_iterator.hpp:81
optionpp::result_iterator::operator!=
bool operator!=(const result_iterator< T, Ptr, Ref, IsOption > &other) const
result_iterator comparison operator.
Definition: result_iterator.hpp:122
optionpp::option_iterator
result_iterator< parser_result, parsed_entry *, parsed_entry &, true > option_iterator
Iterator over option entries in a parser_result.
Definition: result_iterator.hpp:158
optionpp::result_iterator::operator->
Ptr operator->() const
Member access operator.
Definition: result_iterator.hpp:68
optionpp::result_iterator::operator--
result_iterator operator--(int)
Postfix decrement operator.
Definition: result_iterator.hpp:102
optionpp::bad_dereference
Exception indicating an invalid iterator was dereferenced.
Definition: error.hpp:73
optionpp::result_iterator::operator++
result_iterator & operator++()
Prefix increment operator.
Definition: result_iterator.hpp:205
optionpp
Library namespace.
Definition: error.hpp:31
optionpp::parser_result
Holds data that was parsed from the program command line.
Definition: parser_result.hpp:152
parser_result.hpp
Header file for parser_result class.
optionpp::end
result_iterator< T, Ptr, Ref, IsOption > end(const result_iterator< T, Ptr, Ref, IsOption > &) noexcept
end function for range for loop support.
Definition: result_iterator.hpp:148
optionpp::result_iterator::operator*
Ref operator*() const
Dereference operator.
Definition: result_iterator.hpp:193
optionpp::result_iterator::operator--
result_iterator & operator--()
Prefix decrement operator.
Definition: result_iterator.hpp:218