scnlib  0.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
istream.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_ISTREAM_H
19 #define SCN_DETAIL_ISTREAM_H
20 
21 #include "reader.h"
22 
23 #include <istream>
24 
25 namespace scn {
27 
28  namespace detail {
29  template <typename WrappedRange>
31  : public std::basic_streambuf<typename WrappedRange::char_type> {
32  using base = std::basic_streambuf<typename WrappedRange::char_type>;
33 
34  public:
35  using range_type = WrappedRange;
37  using traits_type = typename base::traits_type;
38  using int_type = typename base::int_type;
39 
40  explicit range_streambuf(range_type& r) : m_range(std::addressof(r))
41  {
42  }
43 
44  private:
45  int_type underflow() override
46  {
47  // already read
48  if (!traits_type::eq_int_type(m_ch, traits_type::eof())) {
49  return m_ch;
50  }
51 
52  auto ret = read_char(*m_range);
53  if (!ret) {
54  // error
55  // m_ch is already eof
56  return traits_type::eof();
57  }
58  m_ch = traits_type::to_int_type(ret.value());
59  return m_ch;
60  }
61  int_type uflow() override
62  {
63  auto ret = underflow();
64  if (ret != traits_type::eof()) {
65  m_ch = traits_type::eof();
66  }
67  return ret;
68  }
69  std::streamsize showmanyc() override
70  {
71  return traits_type::eq_int_type(m_ch, traits_type::eof()) ? 0
72  : 1;
73  }
74  int_type pbackfail(int_type) override
75  {
76  auto e = putback_n(*m_range, 1);
77  if (!e) {
78  return traits_type::eof();
79  }
80  return traits_type::to_int_type(0);
81  }
82 
83  range_type* m_range;
84  int_type m_ch{traits_type::eof()};
85  };
86 
87  // Trick stolen from {fmt}
88  template <typename CharT>
89  struct test_std_stream : std::basic_istream<CharT> {
90  private:
91  struct null;
92  // Hide all operator>> from std::basic_istream<CharT>
93  void operator>>(null);
94  };
95 
96  // Check for user-defined operator>>
97  template <typename CharT, typename T, typename = void>
98  struct is_std_streamable : std::false_type {
99  };
100 
101  template <typename CharT, typename T>
103  CharT,
104  T,
105  void_t<decltype(std::declval<test_std_stream<CharT>&>() >>
106  std::declval<T&>())>> : std::true_type {
107  };
108  } // namespace detail
109 
110  template <typename CharT, typename T>
111  struct scanner<CharT,
112  T,
113  typename std::enable_if<
114  detail::is_std_streamable<CharT, T>::value>::type>
115  : public empty_parser {
116  template <typename Context>
117  error scan(T& val, Context& ctx)
118  {
120  ctx.range());
121  std::basic_istream<CharT> stream(std::addressof(streambuf));
122 
123  if (!(stream >> val)) {
125  "Bad stream after reading");
126  }
127  return {};
128  }
129  };
130 
132 } // namespace scn
133 
134 #endif // SCN_DETAIL_ISTREAM_H
typename make_void< Ts...>::type void_t
Definition: util.h:42
#define SCN_END_NAMESPACE
Definition: config.h:401
expected< detail::ranges::range_value_t< WrappedRange > > read_char(WrappedRange &r)
Reads a single character from the range.
Definition: reader.h:53
typename base::traits_type traits_type
Definition: istream.h:37
WrappedRange range_type
Definition: istream.h:35
Error class.
Definition: result.h:32
#define SCN_BEGIN_NAMESPACE
Definition: config.h:400
range_streambuf(range_type &r)
Definition: istream.h:40
The source range emitted an error that cannot be recovered from.
Definition: result.h:58
typename base::int_type int_type
Definition: istream.h:38
typename WrappedRange::char_type char_type
Definition: istream.h:36
error putback_n(WrappedRange &r, detail::ranges::range_difference_t< WrappedRange > n)
Puts back n characters into r as if by repeatedly calling r.advance(-1) .
Definition: reader.h:486