BufferedStreamBuf.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //
  2. // BufferedStreamBuf.h
  3. //
  4. // Library: Foundation
  5. // Package: Streams
  6. // Module: StreamBuf
  7. //
  8. // Definition of template BasicBufferedStreamBuf and class BufferedStreamBuf.
  9. //
  10. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef Foundation_BufferedStreamBuf_INCLUDED
  16. #define Foundation_BufferedStreamBuf_INCLUDED
  17. #include "Poco/Foundation.h"
  18. #include "Poco/BufferAllocator.h"
  19. #include "Poco/StreamUtil.h"
  20. #include <streambuf>
  21. #include <iosfwd>
  22. #include <ios>
  23. namespace Poco {
  24. template <typename ch, typename tr, typename ba = BufferAllocator<ch> >
  25. class BasicBufferedStreamBuf: public std::basic_streambuf<ch, tr>
  26. /// This is an implementation of a buffered streambuf
  27. /// that greatly simplifies the implementation of
  28. /// custom streambufs of various kinds.
  29. /// Derived classes only have to override the methods
  30. /// readFromDevice() or writeToDevice().
  31. ///
  32. /// This streambuf only supports unidirectional streams.
  33. /// In other words, the BasicBufferedStreamBuf can be
  34. /// used for the implementation of an istream or an
  35. /// ostream, but not for an iostream.
  36. {
  37. protected:
  38. typedef std::basic_streambuf<ch, tr> Base;
  39. typedef std::basic_ios<ch, tr> IOS;
  40. typedef ch char_type;
  41. typedef tr char_traits;
  42. typedef ba Allocator;
  43. typedef typename Base::int_type int_type;
  44. typedef typename Base::pos_type pos_type;
  45. typedef typename Base::off_type off_type;
  46. typedef typename IOS::openmode openmode;
  47. public:
  48. BasicBufferedStreamBuf(std::streamsize bufferSize, openmode mode):
  49. _bufsize(bufferSize),
  50. _pBuffer(Allocator::allocate(_bufsize)),
  51. _mode(mode)
  52. {
  53. this->setg(_pBuffer + 4, _pBuffer + 4, _pBuffer + 4);
  54. this->setp(_pBuffer, _pBuffer + _bufsize);
  55. }
  56. ~BasicBufferedStreamBuf()
  57. {
  58. Allocator::deallocate(_pBuffer, _bufsize);
  59. }
  60. virtual int_type overflow(int_type c)
  61. {
  62. if (!(_mode & IOS::out)) return char_traits::eof();
  63. if (flushBuffer() == std::streamsize(-1)) return char_traits::eof();
  64. if (c != char_traits::eof())
  65. {
  66. *this->pptr() = char_traits::to_char_type(c);
  67. this->pbump(1);
  68. }
  69. return c;
  70. }
  71. virtual int_type underflow()
  72. {
  73. if (!(_mode & IOS::in)) return char_traits::eof();
  74. if (this->gptr() && (this->gptr() < this->egptr()))
  75. return char_traits::to_int_type(*this->gptr());
  76. int putback = int(this->gptr() - this->eback());
  77. if (putback > 4) putback = 4;
  78. char_traits::move(_pBuffer + (4 - putback), this->gptr() - putback, putback);
  79. int n = readFromDevice(_pBuffer + 4, _bufsize - 4);
  80. if (n <= 0) return char_traits::eof();
  81. this->setg(_pBuffer + (4 - putback), _pBuffer + 4, _pBuffer + 4 + n);
  82. // return next character
  83. return char_traits::to_int_type(*this->gptr());
  84. }
  85. virtual int sync()
  86. {
  87. if (this->pptr() && this->pptr() > this->pbase())
  88. {
  89. if (flushBuffer() == -1) return -1;
  90. }
  91. return 0;
  92. }
  93. protected:
  94. void setMode(openmode mode)
  95. {
  96. _mode = mode;
  97. }
  98. openmode getMode() const
  99. {
  100. return _mode;
  101. }
  102. private:
  103. virtual int readFromDevice(char_type* /*buffer*/, std::streamsize /*length*/)
  104. {
  105. return 0;
  106. }
  107. virtual int writeToDevice(const char_type* /*buffer*/, std::streamsize /*length*/)
  108. {
  109. return 0;
  110. }
  111. int flushBuffer()
  112. {
  113. int n = int(this->pptr() - this->pbase());
  114. if (writeToDevice(this->pbase(), n) == n)
  115. {
  116. this->pbump(-n);
  117. return n;
  118. }
  119. return -1;
  120. }
  121. std::streamsize _bufsize;
  122. char_type* _pBuffer;
  123. openmode _mode;
  124. BasicBufferedStreamBuf(const BasicBufferedStreamBuf&);
  125. BasicBufferedStreamBuf& operator = (const BasicBufferedStreamBuf&);
  126. };
  127. //
  128. // We provide an instantiation for char.
  129. //
  130. // Visual C++ needs a workaround - explicitly importing the template
  131. // instantiation - to avoid duplicate symbols due to multiple
  132. // instantiations in different libraries.
  133. //
  134. #if defined(_MSC_VER) && defined(POCO_DLL) && !defined(Foundation_EXPORTS)
  135. template class Foundation_API BasicBufferedStreamBuf<char, std::char_traits<char> >;
  136. #endif
  137. typedef BasicBufferedStreamBuf<char, std::char_traits<char> > BufferedStreamBuf;
  138. } // namespace Poco
  139. #endif // Foundation_BufferedStreamBuf_INCLUDED