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