scnlib  0.1.2
FormattedinputformodernC++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
erased_stream.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_ERASED_STREAM_H
19 #define SCN_DETAIL_ERASED_STREAM_H
20 
21 #include "stream.h"
22 
23 namespace scn {
25 
27  SCN_CLANG_IGNORE("-Wpadded")
28 
29  namespace detail {
30  template <typename CharT>
32  public:
33  using char_type = CharT;
34 
35  erased_stream_base(const erased_stream_base&) = delete;
36  erased_stream_base& operator=(const erased_stream_base&) = delete;
38  erased_stream_base& operator=(erased_stream_base&&) = default;
39  virtual ~erased_stream_base() = default;
40 
41  virtual expected<char_type> read_char() = 0;
42  virtual error putback(char_type) = 0;
43 
44  virtual error set_roll_back() = 0;
45  virtual error roll_back() = 0;
46 
47  protected:
48  erased_stream_base() = default;
49  };
50 
51  template <typename CharT>
53  public:
54  using char_type = CharT;
55 
57  erased_sized_stream_base& operator=(
58  const erased_sized_stream_base&) = delete;
61  default;
62  virtual ~erased_sized_stream_base() = default;
63 
64  virtual void read_sized(span<CharT> s) = 0;
65 
66  virtual void putback_n(size_t n) = 0;
67 
68  virtual size_t chars_to_read() const = 0;
69 
70  virtual void skip(size_t n) = 0;
71  virtual void skip_all() = 0;
72 
73  protected:
74  erased_sized_stream_base() = default;
75  };
76 
77  template <typename Stream>
79  : public erased_stream_base<typename Stream::char_type> {
81 
82  public:
83  using char_type = typename base::char_type;
84 
85  erased_stream_impl(Stream s) : m_stream(std::move(s)) {}
86 
88  {
90  return m_stream.read_char();
92  }
93  error putback(char_type ch) override
94  {
96  return m_stream.putback(ch);
98  }
99 
100  error set_roll_back() override
101  {
102  return m_stream.set_roll_back();
103  }
104  error roll_back() override
105  {
107  return m_stream.roll_back();
109  }
110 
111  Stream& get()
112  {
113  return m_stream;
114  }
115  const Stream& get() const
116  {
117  return m_stream;
118  }
119 
120  private:
121  Stream m_stream;
122  };
123 
124  template <typename Stream>
126  : public erased_sized_stream_base<typename Stream::char_type> {
128 
129  public:
130  using char_type = typename base::char_type;
131 
132  erased_sized_stream_impl(Stream& s) : m_stream(std::addressof(s)) {}
133 
134  void read_sized(span<char_type> s) override
135  {
136  m_stream->read_sized(s);
137  }
138 
139  void putback_n(size_t n) override
140  {
141  m_stream->putback_n(n);
142  }
143 
144  size_t chars_to_read() const override
145  {
146  return m_stream->chars_to_read();
147  }
148 
149  void skip(size_t n) override
150  {
151  m_stream->skip(n);
152  }
153  void skip_all() override
154  {
155  m_stream->skip_all();
156  }
157 
158  Stream& get()
159  {
160  return *m_stream;
161  }
162  const Stream& get() const
163  {
164  return *m_stream;
165  }
166 
167  private:
168  Stream* m_stream;
169  };
170  } // namespace detail
171 
172  template <typename CharT>
173  class erased_stream : public stream_base {
174  public:
175  using char_type = CharT;
176  template <typename Stream>
177  erased_stream(Stream s)
178  : m_stream(detail::make_unique<detail::erased_stream_impl<Stream>>(
179  std::move(s)))
180  {
181  }
182 
184  {
185  return m_stream->read_char();
186  }
188  {
189  return m_stream->putback(ch);
190  }
191 
193  {
194  return m_stream->set_roll_back();
195  }
197  {
198  return m_stream->roll_back();
199  }
200 
202  {
203  return *m_stream;
204  }
206  {
207  return *m_stream;
208  }
209 
210  template <typename Stream>
212  {
213  return static_cast<detail::erased_stream_impl<Stream>&>(*m_stream);
214  }
215  template <typename Stream>
217  {
218  return static_cast<const detail::erased_stream_impl<Stream>&>(
219  *m_stream);
220  }
221 
222  private:
224  };
225 
226  template <typename CharT>
227  class erased_sized_stream : public erased_stream<CharT> {
228  using base = erased_stream<CharT>;
229 
230  public:
231  using char_type = CharT;
232  using is_sized_stream = std::true_type;
233 
234  template <typename Stream>
236  : base(std::move(s)),
237  m_stream(
238  detail::make_unique<detail::erased_sized_stream_impl<Stream>>(
239  base::template get_as<Stream>().get()))
240  {
241  }
242 
244  {
245  m_stream->read_sized(s);
246  }
247 
248  void putback_n(size_t n)
249  {
250  m_stream->putback_n(n);
251  }
252 
253  size_t chars_to_read() const
254  {
255  return m_stream->chars_to_read();
256  }
257 
258  void skip(size_t n)
259  {
260  m_stream->skip(n);
261  }
262  void skip_all()
263  {
264  m_stream->skip_all();
265  }
266 
268  {
269  return *m_stream;
270  }
272  {
273  return *m_stream;
274  }
275 
276  private:
278  };
279 
281 
282  template <typename Stream,
283  typename std::enable_if<!is_sized_stream<
284  typename std::remove_reference<Stream>::type>::value>::type* =
285  nullptr>
287  {
289  std::forward<Stream>(s));
290  }
291  template <typename Stream,
292  typename std::enable_if<is_sized_stream<
293  typename std::remove_reference<Stream>::type>::value>::type* =
294  nullptr>
296  {
298  std::forward<Stream>(s));
299  }
300 
301  template <typename CharT>
302  erased_stream<CharT> erase_stream(erased_stream<CharT> s) = delete;
303  template <typename CharT>
304  erased_sized_stream<CharT> erase_stream(erased_sized_stream<CharT> s) =
305  delete;
306 
307  template <typename... Args>
308  auto make_erased_stream(Args&&... a)
309  -> decltype(erase_stream(make_stream(std::forward<Args>(a)...)))
310  {
311  auto stream = make_stream(std::forward<Args>(a)...);
312  return erase_stream(std::move(stream));
313  }
314 
316 } // namespace scn
317 
318 #endif // SCN_DETAIL_ERASED_STREAM_H
SCN_CLANG_POP basic_std_istream_stream< CharT > make_stream(std::basic_istream< CharT > &is) noexcept
Definition: istream.h:76
virtual size_t chars_to_read() const =0
size_t chars_to_read() const
expected< char_type > read_char()
detail::erased_sized_stream_base< CharT > & get_sized()
detail::erased_stream_impl< Stream > & get_as()
SCN_CLANG_PUSH unique_ptr< T > make_unique(Args &&...a)
Definition: util.h:264
#define SCN_END_NAMESPACE
Definition: config.h:376
virtual error set_roll_back()=0
SCN_CLANG_POP erased_stream< typename Stream::char_type > erase_stream(Stream &&s)
virtual error putback(char_type)=0
virtual void skip(size_t n)=0
detail::erased_stream_base< CharT > & get()
virtual void read_sized(span< CharT > s)=0
#define SCN_CLANG_IGNORE(x)
Definition: config.h:128
auto make_erased_stream(Args &&...a) -> decltype(erase_stream(make_stream(std::forward< Args >(a)...)))
erased_stream(Stream s)
expected-like type.
Definition: result.h:186
virtual expected< char_type > read_char()=0
size_t chars_to_read() const override
#define SCN_CLANG_POP
Definition: config.h:127
#define SCN_CLANG_POP_IGNORE_UNDEFINED_TEMPLATE
Definition: config.h:130
void putback_n(size_t n)
error putback(char_type ch)
void putback_n(size_t n) override
void read_sized(span< char_type > s) override
Error class.
Definition: result.h:32
#define SCN_BEGIN_NAMESPACE
Definition: config.h:375
const detail::erased_sized_stream_base< CharT > & get_sized() const
const detail::erased_stream_impl< Stream > & get_as() const
typename base::char_type char_type
std::true_type is_sized_stream
void read_sized(span< char_type > s)
#define SCN_CLANG_PUSH_IGNORE_UNDEFINED_TEMPLATE
Definition: config.h:129
expected< char_type > read_char() override
Definition: erased_stream.h:87
typename base::char_type char_type
Definition: erased_stream.h:83
virtual void putback_n(size_t n)=0
#define SCN_CLANG_PUSH
Definition: config.h:126
error putback(char_type ch) override
Definition: erased_stream.h:93