1 /* 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors 3 * 4 * Squid software is distributed under GPLv2+ license and includes 5 * contributions from numerous individuals and organizations. 6 * Please see the COPYING and CONTRIBUTORS files for details. 7 */ 8 9 #ifndef SQUID_SRC_BASE_PACKABLESTREAM_H 10 #define SQUID_SRC_BASE_PACKABLESTREAM_H 11 12 #include "base/Packable.h" 13 14 #include <ostream> 15 16 /** 17 * Provides a streambuf interface for writing to Packable objects. 18 * Typical use is via a PackableStream rather than direct manipulation 19 */ 20 class PackableStreamBuf : public std::streambuf 21 { 22 public: PackableStreamBuf(Packable & p)23 explicit PackableStreamBuf(Packable &p) : buf_(p) { buf_.buffer(); } 24 virtual ~PackableStreamBuf() = default; 25 26 protected: 27 /** flush the current buffer and the character that is overflowing 28 * to the Packable. 29 */ 30 virtual int_type overflow(int_type aChar = traits_type::eof()) override { 31 std::streamsize pending(pptr() - pbase()); 32 33 if (pending && sync()) 34 return traits_type::eof(); 35 36 if (aChar != traits_type::eof()) { 37 const char C = static_cast<char>(aChar); 38 lowAppend(&C, 1); 39 } 40 41 pbump(-pending); // Reset pptr(). 42 return aChar; 43 } 44 45 /** push the buffer to the Packable */ sync()46 virtual int sync() override { 47 std::streamsize pending(pptr() - pbase()); 48 lowAppend(pbase(), pending); 49 buf_.flush(); 50 return 0; 51 } 52 53 /** write multiple characters to the Packable 54 * - this is an optimisation method. 55 */ xsputn(const char * chars,std::streamsize number)56 virtual std::streamsize xsputn(const char * chars, std::streamsize number) override { 57 lowAppend(chars, number); 58 return number; 59 } 60 61 private: lowAppend(const char * s,const std::streamsize n)62 void lowAppend(const char *s, const std::streamsize n) {buf_.append(s,n);} 63 64 Packable &buf_; 65 }; 66 67 class PackableStream : public std::ostream 68 { 69 public: 70 /* create a stream for writing text etc into theBuffer */ 71 // See http://www.codecomments.com/archive292-2005-2-396222.html PackableStream(Packable & p)72 explicit PackableStream(Packable &p) : std::ostream(0), theBuffer(p) { 73 rdbuf(&theBuffer); // set the buffer to now-initialized theBuffer 74 clear(); //clear badbit set by calling init(0) 75 } 76 77 private: 78 PackableStreamBuf theBuffer; 79 }; 80 81 #endif /* SQUID_SRC_BASE_PACKABLESTREAM_H */ 82 83