]>
Commit | Line | Data |
---|---|---|
7e10ac87 | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
7e10ac87 AJ |
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 | ||
f212d110 AR |
16 | // TODO: Move to src/base/AppendingStreamBuf.h |
17 | /// write-only std::streambuf that append()s all writes to a given Buffer | |
18 | template <class Buffer> | |
19 | class AppendingStreamBuf : public std::streambuf | |
7e10ac87 AJ |
20 | { |
21 | public: | |
f212d110 | 22 | explicit AppendingStreamBuf(Buffer &p): buf_(p) { postInit(); } |
337b9aa4 | 23 | ~AppendingStreamBuf() override = default; |
7e10ac87 AJ |
24 | |
25 | protected: | |
f212d110 AR |
26 | /* std::streambuf API */ |
27 | ||
337b9aa4 | 28 | int_type overflow(int_type aChar = traits_type::eof()) override { |
7e10ac87 AJ |
29 | std::streamsize pending(pptr() - pbase()); |
30 | ||
31 | if (pending && sync()) | |
32 | return traits_type::eof(); | |
33 | ||
34 | if (aChar != traits_type::eof()) { | |
35 | const char C = static_cast<char>(aChar); | |
36 | lowAppend(&C, 1); | |
37 | } | |
38 | ||
39 | pbump(-pending); // Reset pptr(). | |
40 | return aChar; | |
41 | } | |
42 | ||
337b9aa4 | 43 | int sync() override { |
7e10ac87 AJ |
44 | std::streamsize pending(pptr() - pbase()); |
45 | lowAppend(pbase(), pending); | |
f212d110 | 46 | postSync(); |
7e10ac87 AJ |
47 | return 0; |
48 | } | |
49 | ||
337b9aa4 | 50 | std::streamsize xsputn(const char * chars, std::streamsize number) override { |
7e10ac87 AJ |
51 | lowAppend(chars, number); |
52 | return number; | |
53 | } | |
54 | ||
55 | private: | |
f212d110 AR |
56 | /// for specializations that must customize the last construction step |
57 | void postInit() {} | |
58 | ||
59 | /// for specializations that must customize the last sync() step | |
60 | void postSync() {} | |
61 | ||
7e10ac87 AJ |
62 | void lowAppend(const char *s, const std::streamsize n) {buf_.append(s,n);} |
63 | ||
f212d110 | 64 | Buffer &buf_; ///< the associated character sequence (a.k.a. the sink) |
7e10ac87 AJ |
65 | }; |
66 | ||
f212d110 AR |
67 | /** |
68 | * Provides a streambuf interface for writing to Packable objects. | |
69 | * Typical use is via a PackableStream rather than direct manipulation | |
70 | */ | |
71 | using PackableStreamBuf = AppendingStreamBuf<Packable>; | |
72 | template <> inline void PackableStreamBuf::postInit() { buf_.buffer(); } | |
73 | template <> inline void PackableStreamBuf::postSync() { buf_.flush(); } | |
74 | ||
7e10ac87 AJ |
75 | class PackableStream : public std::ostream |
76 | { | |
77 | public: | |
78 | /* create a stream for writing text etc into theBuffer */ | |
79 | // See http://www.codecomments.com/archive292-2005-2-396222.html | |
aee3523a | 80 | explicit PackableStream(Packable &p) : std::ostream(nullptr), theBuffer(p) { |
7e10ac87 AJ |
81 | rdbuf(&theBuffer); // set the buffer to now-initialized theBuffer |
82 | clear(); //clear badbit set by calling init(0) | |
83 | } | |
84 | ||
85 | private: | |
86 | PackableStreamBuf theBuffer; | |
87 | }; | |
88 | ||
89 | #endif /* SQUID_SRC_BASE_PACKABLESTREAM_H */ | |
90 |