mod_servlet
C++Servlets
 All Classes Files Functions Variables Typedefs Macros Pages
io.h
Go to the documentation of this file.
1 /*
2 Copyright (c) 2016 Alexei Novakov
3 https://github.com/novalexei
4 
5 Distributed under the Boost Software License, Version 1.0.
6 http://boost.org/LICENSE_1_0.txt
7 */
8 #ifndef SERVLET_IO_H
9 #define SERVLET_IO_H
10 
11 #include <type_traits>
12 #include <iostream>
13 #include <vector>
14 
15 #include <experimental/type_traits>
16 
30 namespace servlet {
31 
35 template<std::size_t BufSize>
36 struct buffering
37 {
41  static constexpr std::size_t buf_size = BufSize;
42 };
43 
64 
91 struct sink {};
114 struct source {};
143 struct buffer_provider {};
144 
145 template<typename Sink, typename Buffering, typename CharT, typename Traits, typename Category = void>
146 class basic_outbuf;
147 
148 template<typename Sink, typename Buffering, typename CharT, typename Traits, typename Category>
149 class basic_outbuf : public std::basic_streambuf<CharT, Traits>
150 {
151 public:
152  typedef CharT char_type;
153  typedef Traits traits_type;
154  typedef typename Traits::int_type int_type;
155  typedef typename Traits::pos_type pos_type;
156  typedef typename Traits::off_type off_type;
157 
158  typedef std::basic_ostream<char_type, traits_type> _super_type;
159 
160  template<class... Args>
161  basic_outbuf(Args &&... args) : _sink{std::forward<Args>(args)...}, _buffer{new CharT[Buffering::buf_size]}
162  {
163  this->setp(_buffer, _buffer + Buffering::buf_size - 1);
164  }
165 
166  basic_outbuf(const basic_outbuf& other) = delete;
167  basic_outbuf(basic_outbuf&& ) = delete;
168 
169  ~basic_outbuf() noexcept override { sync(); delete[] _buffer; }
170 
171  basic_outbuf& operator=(const basic_outbuf& ) = delete;
172  basic_outbuf& operator=(basic_outbuf&& ) = delete;
173 
174  Sink& operator*() { return _sink; }
175  Sink* operator->() { return &_sink; }
176 
177  const Sink& operator*() const { return _sink; }
178  const Sink* operator->() const { return &_sink; }
179 
180  void reset() { this->setp(_buffer, _buffer + Buffering::buf_size - 1); }
181 
182 protected:
183  int_type overflow(int_type ch) override
184  {
185  _buffer[Buffering::buf_size-1] = static_cast<char>(ch);
186  this->setp(_buffer, _buffer + Buffering::buf_size - 1);
187  return _sink.write(_buffer, Buffering::buf_size) < Buffering::buf_size ? traits_type::eof() : ch;
188  }
189 
190  int sync() override
191  {
192  std::size_t size = this->pptr() - _buffer;
193  if (size > 0)
194  {
195  if (_sink.write(_buffer, static_cast<std::streamsize>(size)) < size) return -1;
196  }
197  _sink.flush();
198  this->setp(_buffer, _buffer + Buffering::buf_size - 1);
199  return 0;
200  }
201 
202 private:
203  Sink _sink;
204  CharT *_buffer;
205 };
206 
207 template<typename Sink, typename CharT, typename Traits>
208 class basic_outbuf<Sink, non_buffered, CharT, Traits,
209  typename std::enable_if_t<std::is_same<typename Sink::category, buffer_provider>::value>> :
210  public std::basic_streambuf<CharT, Traits>
211 {
212 public:
213  typedef CharT char_type;
214  typedef Traits traits_type;
215  typedef typename Traits::int_type int_type;
216  typedef typename Traits::pos_type pos_type;
217  typedef typename Traits::off_type off_type;
218 
219  typedef std::basic_ostream<char_type, traits_type> _super_type;
220 
221  template<class... Args>
222  basic_outbuf(Args &&... args) : _sink{std::forward<Args>(args)...} {}
223 
224  basic_outbuf(const basic_outbuf& other) = delete;
225  basic_outbuf(basic_outbuf&& ) = delete;
226 
227  ~basic_outbuf() noexcept override { sync(); }
228 
229  basic_outbuf& operator=(const basic_outbuf& ) = delete;
230  basic_outbuf& operator=(basic_outbuf&& ) = delete;
231 
232  Sink& operator*() { return _sink; }
233  Sink* operator->() { return &_sink; }
234 
235  const Sink& operator*() const { return _sink; }
236  const Sink* operator->() const { return &_sink; }
237 
238  void reset() { this->setp(this->pbase(), this->epptr()); }
239 
240 protected:
241  int_type overflow(int_type ch) override
242  {
243  *this->pptr() = static_cast<char>(ch);
244  std::pair<CharT*, std::size_t> buffer = _sink.get_buffer();
245  if (!buffer.first || buffer.second <= 0) return traits_type::eof();
246  this->setp(buffer.first, buffer.first + buffer.second - 1);
247  return ch;
248  }
249 
250  int sync() override
251  {
252  _sink.flush(this->pptr() - this->pbase());
253  return 0;
254  }
255 
256 private:
257  Sink _sink;
258 };
259 
260 template<typename Sink, typename CharT, typename Traits, typename Category>
261 class basic_outbuf<Sink, non_buffered, CharT, Traits, Category> : public std::basic_streambuf<CharT, Traits>
262 {
263 public:
264  typedef CharT char_type;
265  typedef Traits traits_type;
266  typedef typename Traits::int_type int_type;
267  typedef typename Traits::pos_type pos_type;
268  typedef typename Traits::off_type off_type;
269 
270  template <class... Args>
271  basic_outbuf(Args&&... args) : _sink{std::forward<Args>(args)...} {}
272 
273  basic_outbuf(const basic_outbuf& ) = default;
274  basic_outbuf(basic_outbuf&& ) = default;
275 
276  basic_outbuf& operator=(const basic_outbuf& ) = default;
277  basic_outbuf& operator=(basic_outbuf&& ) = default;
278 
279  void reset() { }
280 
281  Sink& operator*() { return _sink; }
282  Sink* operator->() { return &_sink; }
283 
284  const Sink& operator*() const { return _sink; }
285  const Sink* operator->() const { return &_sink; }
286 
287 protected:
288  int_type overflow(int_type ch) override
289  {
290  char_type tmp_ch = static_cast<char_type>(ch);
291  return _sink.write(&tmp_ch, 1) == 1 ? ch : traits_type::eof();
292  }
293 
294  int sync() override { _sink.flush(); return 0; }
295 
296  std::streamsize xsputn(const char_type* s, std::streamsize n) override { return _sink.write(s, n); }
297 
298 private:
299  Sink _sink;
300 };
301 
302 
321 template<typename Sink, typename Buffering, typename CharT, typename Traits = std::char_traits<CharT>>
322 class basic_outstream : public std::basic_ostream<CharT, Traits>
323 {
324  typedef basic_outbuf<Sink, Buffering, CharT, Traits> _outbuf_type;
325  typedef std::basic_ostream<CharT, Traits> _ostream_type;
326 public:
330  typedef CharT char_type;
334  typedef Traits traits_type;
338  typedef typename traits_type::int_type int_type;
342  typedef typename traits_type::pos_type pos_type;
346  typedef typename traits_type::off_type off_type;
347 
357  template <class... Args>
358  explicit basic_outstream(Args&&... args) : _ostream_type{}
359  {
360  this->rdbuf(new _outbuf_type{std::forward<Args>(args)...});
361  }
367  basic_outstream(basic_outstream&& other) : _ostream_type{}
368  {
369  this->rdbuf(other.rdbuf());
370  other.rdbuf(nullptr);
371  }
379  {
380  this->rdbuf(other.rdbuf());
381  other.rdbuf(nullptr);
382  return *this;
383  }
384 
388  ~basic_outstream() noexcept override { delete this->rdbuf(); }
389 
395  Sink& operator*() { return buf()->operator*(); }
401  Sink* operator->() { return buf()->operator->(); }
402 
408  const Sink& operator*() const { return buf()->operator*(); }
414  const Sink* operator->() const { return buf()->operator->(); }
415 
416 // void reset_buffer() { return buf()->reset(); }
417 
418 private:
419  inline _outbuf_type *buf() { return static_cast<_outbuf_type*>(this->rdbuf()); }
420  inline const _outbuf_type *buf() const { return static_cast<const _outbuf_type*>(this->rdbuf()); }
421 };
422 
423 template<typename Source, typename Buffering, typename CharT, typename Traits, typename Enable = void>
424 class basic_inbuf;
425 
426 template<typename Source, typename Buffering, typename CharT, typename Traits, typename Enable>
427 class basic_inbuf : public std::basic_streambuf<CharT, Traits>
428 {
429 public:
430  typedef CharT char_type;
431  typedef Traits traits_type;
432  typedef typename Traits::int_type int_type;
433  typedef typename Traits::pos_type pos_type;
434  typedef typename Traits::off_type off_type;
435 
436  template <class... Args>
437  basic_inbuf(Args&&... args) : _source{std::forward<Args>(args)...}, _buffer{new char_type[Buffering::buf_size]} {}
438 
439  ~basic_inbuf() noexcept override { delete[] _buffer; }
440 
441  basic_inbuf(const basic_inbuf& ) = delete;
442  basic_inbuf(basic_inbuf&& other) = delete;
443 
444  basic_inbuf& operator=(const basic_inbuf& ) = delete;
445  basic_inbuf& operator=(basic_inbuf&& ) = delete;
446 
447  Source& operator*() { return _source; }
448  Source* operator->() { return &_source; }
449 
450  const Source& operator*() const { return _source; }
451  const Source* operator->() const { return &_source; }
452 
453  void reset() { }
454 
455 protected:
456  int_type underflow() override
457  {
458  std::streamsize new_size = _source.read(_buffer, Buffering::buf_size);
459  if (new_size == 0) return traits_type::eof();
460  this->setg(_buffer, _buffer, _buffer + new_size);
461  return traits_type::to_int_type(*_buffer);
462  }
463 
464  int_type pbackfail(int_type ch) override
465  {
466  if (this->egptr() <= this->eback()) return traits_type::eof();
467  this->gbump(-1);
468  return ch;
469  }
470 
471 private:
472  Source _source;
473  CharT *_buffer;
474 };
475 
476 template<typename Source, typename CharT, typename Traits>
477 class basic_inbuf<Source, non_buffered, CharT, Traits,
478  typename std::enable_if_t<std::is_same<typename Source::category, buffer_provider>::value>> :
479  public std::basic_streambuf<CharT, Traits>
480 {
481 public:
482  typedef CharT char_type;
483  typedef Traits traits_type;
484  typedef typename Traits::int_type int_type;
485  typedef typename Traits::pos_type pos_type;
486  typedef typename Traits::off_type off_type;
487 
488  template <class... Args>
489  basic_inbuf(Args&&... args) : _source{std::forward<Args>(args)...} {}
490 
491  ~basic_inbuf() noexcept = default;
492 
493  basic_inbuf(const basic_inbuf& ) = delete;
494  basic_inbuf(basic_inbuf&& other) = delete;
495 
496  basic_inbuf& operator=(const basic_inbuf& ) = delete;
497  basic_inbuf& operator=(basic_inbuf&& ) = delete;
498 
499  Source& operator*() { return _source; }
500  Source* operator->() { return &_source; }
501 
502  const Source& operator*() const { return _source; }
503  const Source* operator->() const { return &_source; }
504 
505  void reset() { this->setg(this->eback(), this->eback(), this->egptr()); }
506 
507 protected:
508  int_type underflow() override
509  {
510  std::pair<CharT*, std::size_t> buffer = _source.get_buffer();
511  if (!buffer.first || buffer.second <= 0) return traits_type::eof();
512  this->setg(buffer.first, buffer.first, buffer.first + buffer.second);
513  return traits_type::to_int_type(*this->eback());
514  }
515 
516  int_type pbackfail(int_type ch) override
517  {
518  if (this->egptr() <= this->eback()) return traits_type::eof();
519  this->gbump(-1);
520  return ch;
521  }
522 
523 private:
524  Source _source;
525 };
526 
545 template<typename Source, typename Buffering, typename CharT, typename Traits = std::char_traits<CharT>>
546 class basic_instream : public std::basic_istream<CharT, Traits>
547 {
548  typedef basic_inbuf<Source, Buffering, CharT, Traits> _inbuf_type;
549  typedef std::basic_istream<CharT, Traits> _istream_type;
550 public:
554  typedef CharT char_type;
558  typedef Traits traits_type;
562  typedef typename traits_type::int_type int_type;
566  typedef typename traits_type::pos_type pos_type;
570  typedef typename traits_type::off_type off_type;
571 
581  template <typename... Args>
582  explicit basic_instream(Args&&... args) : _istream_type{}
583  {
584  this->rdbuf(new _inbuf_type{std::forward<Args>(args)...});
585  }
589  basic_instream(const basic_instream& ) = delete;
595  basic_instream(basic_instream&& other) : _istream_type{}
596  {
597  this->rdbuf(other.rdbuf());
598  other.rdbuf(nullptr);
599  }
600 
608  {
609  this->rdbuf(other.rdbuf());
610  other.rdbuf(nullptr);
611  return *this;
612  }
613 
617  ~basic_instream() noexcept override { delete this->rdbuf(); }
618 
624  Source& operator*() { return buf()->operator*(); }
630  Source* operator->() { return buf()->operator->(); }
631 
637  const Source& operator*() const { return buf()->operator*(); }
643  const Source* operator->() const { return buf()->operator->(); }
644 
645 // void reset_buffer() { return buf()->reset(); }
646 private:
647  inline _inbuf_type* buf() { return static_cast<_inbuf_type*>(this->rdbuf()); }
648  inline const _inbuf_type* buf() const { return static_cast<const _inbuf_type*>(this->rdbuf()); }
649 };
650 
654 template <typename Sink, typename Buffering = non_buffered>
655 using outstream = basic_outstream<Sink, Buffering, char>;
659 template <typename Source, typename Buffering = non_buffered>
660 using instream = basic_instream<Source, Buffering, char>;
661 
662 } // end of servlet namespace
663 
664 #endif // SERVLET_IO_H
traits_type::int_type int_type
traits_type::int_type
Definition: io.h:338
Source & operator*()
Provides access to the reference to the Source instance associated with this stream.
Definition: io.h:624
Implementation of output stream object.
Definition: io.h:322
Sink * operator->()
Provides access to the pointer to the Sink instance associated with this stream.
Definition: io.h:401
Traits traits_type
Type of character traits class to be used by this stream.
Definition: io.h:558
static constexpr std::size_t buf_size
Size of buffer as constant expression.
Definition: io.h:41
traits_type::pos_type pos_type
traits_type::pos_type
Definition: io.h:566
~basic_outstream() noexceptoverride
Destructor.
Definition: io.h:388
traits_type::off_type off_type
traits_type::off_type
Definition: io.h:570
traits_type::int_type int_type
traits_type::int_type
Definition: io.h:562
basic_outstream(basic_outstream &&other)
Move constructor.
Definition: io.h:367
Source tag.
Definition: io.h:143
const Sink & operator*() const
Provides access to the constant reference to the Sink instance associated with this stream...
Definition: io.h:408
Source tag.
Definition: io.h:114
basic_instream(basic_instream &&other)
Move constructor.
Definition: io.h:595
const Source * operator->() const
Provides access to the constant pointer to the Source instance associated with this stream...
Definition: io.h:643
const Source & operator*() const
Provides access to the constant reference to the Source instance associated with this stream...
Definition: io.h:637
Traits traits_type
Type of character traits class to be used by this stream.
Definition: io.h:334
~basic_instream() noexceptoverride
Destructor.
Definition: io.h:617
Implementation of input stream object.
Definition: io.h:546
Template class holder of the buffer size.
Definition: io.h:36
CharT char_type
Cacracter type to be used by this stream.
Definition: io.h:330
basic_outstream & operator=(basic_outstream &&other)
Move assignment operator.
Definition: io.h:378
Sink & operator*()
Provides access to the reference to the Sink instance associated with this stream.
Definition: io.h:395
traits_type::off_type off_type
traits_type::off_type
Definition: io.h:346
traits_type::pos_type pos_type
traits_type::pos_type
Definition: io.h:342
Sink tag.
Definition: io.h:91
basic_instream & operator=(basic_instream &&other)
Move assignment operator.
Definition: io.h:607
CharT char_type
Cacracter type to be used by this stream.
Definition: io.h:554
basic_outstream(Args &&...args)
Main constructor.
Definition: io.h:358
basic_instream(Args &&...args)
Main constructor.
Definition: io.h:582
const Sink * operator->() const
Provides access to the constant pointer to the Sink instance associated with this stream...
Definition: io.h:414
Source * operator->()
Provides access to the pointer to the Source instance associated with this stream.
Definition: io.h:630