scnlib  0.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
range.h
Go to the documentation of this file.
1 // Copyright 2017-2019 Elias Kosunen
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // This file is a part of scnlib:
16 // https://github.com/eliaskosunen/scnlib
17 
18 #ifndef SCN_DETAIL_RANGE_H
19 #define SCN_DETAIL_RANGE_H
20 
21 #include "ranges.h"
22 #include "result.h"
23 
24 namespace scn {
26 
27  namespace detail {
28  template <typename Iterator, typename = void>
30  template <typename Iterator>
32  Iterator,
33  typename std::enable_if<std::is_integral<
34  ranges::iter_value_t<Iterator>>::value>::type> {
36  };
37  template <typename Iterator>
39  Iterator,
40  void_t<typename std::enable_if<!std::is_integral<
41  ranges::iter_value_t<Iterator>>::value>::type,
42  typename ranges::iter_value_t<Iterator>::success_type>> {
44  };
45 
46  template <typename Range, typename = void>
48  : std::is_integral<ranges::range_value_t<const Range>> {
49  };
50  template <typename Range, typename = void>
52  };
53  template <typename Range, typename = void>
54  struct provides_buffer_access_impl : std::false_type {
55  };
56 
57  template <typename Range, typename It>
58  void write_return(const Range&, It)
59  {
60  }
61  template <typename Range, typename It>
62  void write_return(Range&& r, It begin)
63  {
65  ranges::end(std::forward<Range>(r))};
66  }
67 
68  template <typename Range>
69  struct is_caching_range_impl : std::false_type {
70  };
71  template <typename Range>
72  struct is_caching_range : is_caching_range_impl<remove_cvref_t<Range>> {
73  };
74 
75  template <typename Range>
76  class range_wrapper {
77  public:
78  using range_type = Range;
84 
85  template <typename R,
86  typename std::enable_if<
87  std::is_same<remove_cvref_t<R>,
88  return_type>::value>::type* = nullptr>
90  : m_range(std::forward<R>(r)), m_begin(ranges::begin(m_range))
91  {
92  }
93 
95  {
96  return {m_begin, ranges::end(m_range)};
97  }
99  {
100  write_return(m_range, m_begin);
101  return range();
102  }
103 
104  iterator begin() const noexcept
105  {
106  return m_begin;
107  }
108  sentinel end() const
109  noexcept(noexcept(ranges::end(std::declval<const Range&>())))
110  {
111  return ranges::end(m_range);
112  }
113 
115  {
116  m_read += n;
118  ranges::advance(m_begin, n);
119  }
120  return m_begin;
121  }
122  template <typename R = Range,
123  typename std::enable_if<
125  void advance_to(iterator it) noexcept
126  {
127  const auto diff = ranges::distance(m_begin, it);
128  m_read += diff;
129  m_begin = it;
130  }
131 
133  noexcept(noexcept(ranges::begin(std::declval<const Range&>())))
134  {
135  return ranges::begin(m_range);
136  }
137  range_type range_underlying() const noexcept
138  {
139  return m_range;
140  }
141 
142  template <typename R = Range,
143  typename std::enable_if<
145  auto data() const
146  noexcept(noexcept(*std::declval<ranges::iterator_t<const R>>()))
147  -> decltype(std::addressof(
148  *std::declval<ranges::iterator_t<const R>>()))
149  {
150  return std::addressof(*m_begin);
151  }
152  template <typename R = Range,
153  typename std::enable_if<
155  auto size() const noexcept(noexcept(
156  ranges::distance(std::declval<ranges::iterator_t<const R>>(),
157  std::declval<ranges::sentinel_t<const R>>())))
158  -> decltype(ranges::distance(
159  std::declval<ranges::iterator_t<const R>>(),
160  std::declval<ranges::sentinel_t<const R>>()))
161  {
162  return ranges::distance(m_begin, end());
163  }
164 
166  {
167  for (; m_read != 0; --m_read) {
168  --m_begin;
169  if (m_begin == end()) {
171  "Putback failed");
172  }
173  }
174  return {};
175  }
177  {
178  m_read = 0;
179  }
180 
181  // iterator value type is a character
182  static constexpr bool is_direct = is_direct_impl<Range>::value;
183  // can call .data() and memcpy
184  static constexpr bool is_contiguous =
186  // provides mechanism to get a pointer to memcpy from
187  static constexpr bool provides_buffer_access =
189 
190  private:
191  range_type m_range;
192  iterator m_begin;
193  difference_type m_read{0};
194  };
195 
196  namespace _wrap {
197  struct fn {
198  private:
199  template <typename Range>
201  priority_tag<4>) noexcept
202  {
203  return r;
204  }
205 
206  template <typename Range>
207  static auto impl(Range&& r, priority_tag<3>) noexcept(
208  noexcept(std::forward<Range>(r)))
209  -> decltype(wrap(std::forward<Range>(r)))
210  {
211  return wrap(std::forward<Range>(r));
212  }
213 
214  template <typename Range>
215  static auto impl(Range& r,
216  priority_tag<2>) noexcept(noexcept(r.wrap()))
217  -> decltype(r.wrap())
218  {
219  return r.wrap();
220  }
221 
222  template <typename CharT, std::size_t N>
223  static auto impl(CharT (&str)[N], priority_tag<1>) noexcept
224  -> range_wrapper<
226  {
227  return {
229  str, str + N - 1)};
230  }
231 
232  template <typename Range>
233  static auto impl(Range&& r, priority_tag<0>) noexcept
235  {
236  static_assert(ranges::view<remove_cvref_t<Range>>::value,
237  "Cannot scan from a non-view!");
238 
239  return {std::forward<Range>(r)};
240  }
241 
242  public:
243  template <typename Range>
244  auto operator()(Range&& r) const
245  noexcept(noexcept(fn::impl(std::forward<Range>(r),
246  priority_tag<4>{})))
247  -> decltype(fn::impl(std::forward<Range>(r),
248  priority_tag<4>{}))
249  {
250  return fn::impl(std::forward<Range>(r), priority_tag<4>{});
251  }
252  };
253  } // namespace _wrap
254  namespace {
255  static constexpr auto& wrap = static_const<_wrap::fn>::value;
256  }
257 
258  template <typename Range>
260  using type = decltype(wrap(std::declval<Range>()));
261  };
262  template <typename Range>
264  } // namespace detail
265 
266  namespace detail {
267  template <typename CharT>
269  {
270  return {ch};
271  }
272  template <typename CharT>
274  {
275  return e;
276  }
277  } // namespace detail
278 
279  namespace _make_view {
280  struct fn {
281  private:
282  template <typename CharT, std::size_t N>
284  CharT (&str)[N],
285  detail::priority_tag<4>) noexcept
286  {
287  return {str, str + N - 1}; // damn you, null terminator!
288  }
289 
290  template <typename CharT>
291  static basic_string_view<CharT> impl(
292  const std::basic_string<CharT>& str,
293  detail::priority_tag<3>) noexcept
294  {
295  return {str.data(), str.size()};
296  }
297 
298  template <typename Range>
299  static auto impl(Range& r, detail::priority_tag<2>) noexcept(
300  noexcept(make_view(r))) -> decltype(make_view(r))
301  {
302  return make_view(r);
303  }
304  template <typename Range>
305  static auto impl(Range& r, detail::priority_tag<1>) noexcept(
306  noexcept(r.make_view())) -> decltype(r.make_view())
307  {
308  return r.make_view();
309  }
310 
311  template <typename Range>
312  static Range impl(Range v, detail::priority_tag<0>) noexcept
313  {
315  "Unknown value given to make_view");
316  return v;
317  }
318 
319  public:
320  template <typename Range>
321  auto operator()(Range&& r) const
322  noexcept(noexcept(fn::impl(std::forward<Range>(r),
323  detail::priority_tag<4>{})))
324  -> decltype(fn::impl(std::forward<Range>(r),
326  {
327  return fn::impl(std::forward<Range>(r),
329  }
330  };
331  } // namespace _make_view
332  namespace {
333  static constexpr auto& make_view =
334  detail::static_const<_make_view::fn>::value;
335  }
336 
338 } // namespace scn
339 
340 #endif // SCN_DETAIL_RANGE_H
typename make_void< Ts...>::type void_t
Definition: util.h:42
expected< CharT > wrap_deref(CharT ch)
Definition: range.h:268
constexpr bool is_integral(type t) noexcept
Definition: args.h:96
iterator begin_underlying() const noexcept(noexcept(ranges::begin(std::declval< const Range & >())))
Definition: range.h:132
constexpr const_pointer data() const noexcept
Definition: string_view.h:155
#define SCN_END_NAMESPACE
Definition: config.h:401
range_type range_underlying() const noexcept
Definition: range.h:137
iterator begin() const noexcept
Definition: range.h:104
auto operator()(Range &&r) const noexcept(noexcept(fn::impl(std::forward< Range >(r), priority_tag< 4 >{}))) -> decltype(fn::impl(std::forward< Range >(r), priority_tag< 4 >
Definition: range.h:244
typename remove_cvref< T >::type remove_cvref_t
Definition: util.h:54
typename std::enable_if< range< R >::value, decltype(::scn::detail::ranges::end(std::declval< R & >()))>::type sentinel_t
Definition: ranges.h:496
remove_cvref_t< range_type > range() const
Definition: range.h:94
sentinel end() const noexcept(noexcept(ranges::end(std::declval< const Range & >())))
Definition: range.h:108
auto operator()(Range &&r) const noexcept(noexcept(fn::impl(std::forward< Range >(r), detail::priority_tag< 4 >{}))) -> decltype(fn::impl(std::forward< Range >(r), detail::priority_tag< 4 >
Definition: range.h:321
iterator advance(difference_type n=1) noexcept
Definition: range.h:114
ranges::iterator_t< const Range > iterator
Definition: range.h:79
error reset_to_rollback_point()
Definition: range.h:165
decltype(wrap(std::declval< Range >())) type
Definition: range.h:260
typename readable_traits< T >::value_type iter_value_t
Definition: ranges.h:227
typename std::enable_if< range< R >::value, decltype(::scn::detail::ranges::begin(std::declval< R & >()))>::type iterator_t
Definition: ranges.h:491
remove_cvref_t< range_type > get_return()
Definition: range.h:98
expected-like type.
Definition: result.h:180
typename range_wrapper_for< Range >::type range_wrapper_for_t
Definition: range.h:263
static constexpr bool is_direct
Definition: range.h:182
void advance_to(iterator it) noexcept
Definition: range.h:125
ranges::sentinel_t< const Range > sentinel
Definition: range.h:80
static constexpr bool is_contiguous
Definition: range.h:184
typename std::enable_if< range< R >::value, iter_difference_t< iterator_t< R >>>::type range_difference_t
Definition: ranges.h:500
auto data() const noexcept(noexcept(*std::declval< ranges::iterator_t< const R >>())) -> decltype(std::addressof(*std::declval< ranges::iterator_t< const R >>()))
Definition: range.h:145
Error class.
Definition: result.h:32
#define SCN_BEGIN_NAMESPACE
Definition: config.h:400
remove_cvref_t< range_type > return_type
Definition: range.h:82
void write_return(const Range &, It)
Definition: range.h:58
typename extract_char_type< iterator >::type char_type
Definition: range.h:81
The source range emitted an error that cannot be recovered from.
Definition: result.h:58
void end(T &&)=delete
ranges::range_difference_t< Range > difference_type
Definition: range.h:83
void begin(T &&)=delete
A view over a (sub)string.
Definition: string_view.h:60
static constexpr bool provides_buffer_access
Definition: range.h:187
auto size() const noexcept(noexcept(ranges::distance(std::declval< ranges::iterator_t< const R >>(), std::declval< ranges::sentinel_t< const R >>()))) -> decltype(ranges::distance(std::declval< ranges::iterator_t< const R >>(), std::declval< ranges::sentinel_t< const R >>()))
Definition: range.h:155