Toolbox snapshot
The Reactive C++ Toolbox
Loading...
Searching...
No Matches
Stream.hpp
Go to the documentation of this file.
1// The Reactive C++ Toolbox.
2// Copyright (C) 2013-2019 Swirly Cloud Limited
3// Copyright (C) 2022 Reactive Markets Limited
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#ifndef TOOLBOX_UTIL_STREAM_HPP
18#define TOOLBOX_UTIL_STREAM_HPP
19
22
23#include <experimental/iterator>
24
25namespace toolbox {
26inline namespace util {
27namespace detail {
28
29struct ResetState {};
30TOOLBOX_API std::ostream& operator<<(std::ostream& os, ResetState) noexcept;
31
32} // namespace detail
33
35constexpr detail::ResetState reset_state{};
36
37TOOLBOX_API void reset(std::ostream& os) noexcept;
38
40template <std::size_t MaxN>
41class StreamBuf final : public std::streambuf {
42 public:
44 explicit StreamBuf(std::nullptr_t) noexcept {}
46 : storage_{make_storage<MaxN>}
47 {
48 char* begin = static_cast<char*>(storage_.get());
49 setp(begin, begin + MaxN);
50 }
51 ~StreamBuf() override = default;
52
53 // Copy.
54 StreamBuf(const StreamBuf&) = delete;
55 StreamBuf& operator=(const StreamBuf&) = delete;
56
57 // Move.
58 StreamBuf(StreamBuf&&) = delete;
60
61 const char* data() const noexcept { return pbase(); }
62 bool empty() const noexcept { return pbase() == pptr(); }
63 std::size_t size() const noexcept { return pptr() - pbase(); }
64
67 {
69 storage_.swap(storage);
70 setp(nullptr, nullptr);
71 return storage;
72 }
74 void set_storage(StoragePtr<MaxN> storage) noexcept { swap_storage(storage); }
77 {
78 if (storage_) {
79 char* begin = static_cast<char*>(storage_.get());
80 setp(begin, begin + MaxN);
81 }
82 }
83
84 private:
86 void swap_storage(StoragePtr<MaxN>& storage) noexcept
87 {
88 storage_.swap(storage);
89 if (storage_) {
90 auto* const begin = static_cast<char*>(storage_.get());
91 setp(begin, begin + MaxN);
92 } else {
93 setp(nullptr, nullptr);
94 }
95 }
96 StoragePtr<MaxN> storage_;
97};
98
100template <std::size_t MaxN>
101class OStream final : public std::ostream {
102 public:
104 explicit OStream(std::nullptr_t) noexcept
105 : std::ostream{nullptr}
106 , buf_{nullptr}
107 {
108 rdbuf(&buf_);
109 }
111 : std::ostream{nullptr}
112 {
113 rdbuf(&buf_);
114 }
115 ~OStream() override = default;
116
117 // Copy.
118 OStream(const OStream&) = delete;
119 OStream& operator=(const OStream&) = delete;
120
121 // Move.
122 OStream(OStream&&) = delete;
124
126 const char* data() const noexcept { return buf_.data(); }
127 bool empty() const noexcept { return buf_.empty(); }
128 std::size_t size() const noexcept { return buf_.size(); }
129
131 StoragePtr<MaxN> release_storage() noexcept { return buf_.release_storage(); }
134 {
135 buf_.set_storage(std::move(storage));
136 clear();
137 }
140 {
141 buf_.reset();
142 clear();
143 }
144
145 private:
146 StreamBuf<MaxN> buf_;
147};
148
149template <std::size_t MaxN>
150class StaticStreamBuf final : public std::streambuf {
151 public:
153 ~StaticStreamBuf() override = default;
154
155 // Copy.
158
159 // Move.
162
163 const char* data() const noexcept { return pbase(); }
164 bool empty() const noexcept { return pbase() == pptr(); }
165 std::size_t size() const noexcept { return pptr() - pbase(); }
166
167 std::string_view str() const noexcept { return {data(), size()}; }
169 void reset() noexcept { setp(buf_, buf_ + MaxN); };
170
171 private:
172 char buf_[MaxN];
173};
174
175template <std::size_t MaxN>
176class OStaticStream final : public std::ostream {
177 public:
179 : std::ostream{nullptr}
180 {
181 rdbuf(&buf_);
182 }
183 ~OStaticStream() override = default;
184
185 // Copy.
186 OStaticStream(const OStaticStream&) = delete;
188
189 // Move.
192
193 const char* data() const noexcept { return buf_.data(); }
194 bool empty() const noexcept { return buf_.empty(); }
195 std::size_t size() const noexcept { return buf_.size(); }
196
197 std::string_view str() const noexcept { return buf_.str(); }
200 {
201 buf_.reset();
202 clear();
203 };
204
205 private:
207};
208
209// Similar to std::ostream_iterator, but this works with any "Streamable" type.
210template <class StreamT>
211 requires Streamable<StreamT>
213 public:
214 OStreamIterator() = delete;
215
216 explicit OStreamIterator(StreamT& os, const char* delim = nullptr) noexcept
217 : os_(&os)
218 , delim_(delim)
219 {
220 }
221
222 template <class T>
223 OStreamIterator& operator=(const T& value)
224 {
225 *os_ << value;
226 if (delim_) [[unlikely]] {
227 *os_ << delim_;
228 }
229 return *this;
230 }
231
232 OStreamIterator& operator*() noexcept { return *this; }
234 OStreamIterator& operator++(int) noexcept { return *this; }
235
236 // required by std::output_iterator concept
238
239 private:
240 // Pointer (instead of reference) because this class needs to be assignable
241 // to satisfy std::output_iterator concept (references can't be assigned).
242 StreamT* os_;
243 const char* delim_{nullptr};
244};
245
246using OStreamJoiner = std::experimental::ostream_joiner<char>;
247
248template <auto DelimT, typename ArgT, typename... ArgsT>
249void join(std::ostream& os, const ArgT& arg, const ArgsT&... args)
250{
251 os << arg;
252 (..., [&os](const auto& arg) { os << DelimT << arg; }(args));
253}
254
255} // namespace util
256} // namespace toolbox
257
259template <typename ValueT>
260ostream_joiner<char>& operator<<(ostream_joiner<char>& osj, const ValueT& value)
261{
262 osj = value;
263 return osj;
264}
265} // namespace std::experimental
266
267#endif // TOOLBOX_UTIL_STREAM_HPP
#define TOOLBOX_API
Definition Config.h:39
OStaticStream & operator=(OStaticStream &&)=delete
OStaticStream(OStaticStream &&)=delete
const char * data() const noexcept
Definition Stream.hpp:193
OStaticStream & operator=(const OStaticStream &)=delete
bool empty() const noexcept
Definition Stream.hpp:194
std::size_t size() const noexcept
Definition Stream.hpp:195
~OStaticStream() override=default
void reset() noexcept
Reset the current position back to the beginning of the buffer.
Definition Stream.hpp:199
std::string_view str() const noexcept
Definition Stream.hpp:197
OStaticStream(const OStaticStream &)=delete
OStreamIterator(StreamT &os, const char *delim=nullptr) noexcept
Definition Stream.hpp:216
OStreamIterator & operator*() noexcept
Definition Stream.hpp:232
OStreamIterator & operator=(const T &value)
Definition Stream.hpp:223
OStreamIterator & operator++(int) noexcept
Definition Stream.hpp:234
OStreamIterator & operator++() noexcept
Definition Stream.hpp:233
OStream uses a dynamic storage acquired from the custom allocator.
Definition Stream.hpp:101
OStream(std::nullptr_t) noexcept
Constructor for initialising the StreamBuf with a null buffer.
Definition Stream.hpp:104
static StoragePtr< MaxN > make_storage()
Definition Stream.hpp:125
void reset() noexcept
Reset the current position back to the beginning of the buffer and clear i/o state.
Definition Stream.hpp:139
~OStream() override=default
StoragePtr< MaxN > release_storage() noexcept
Release the managed storage.
Definition Stream.hpp:131
OStream(OStream &&)=delete
OStream & operator=(OStream &&)=delete
std::size_t size() const noexcept
Definition Stream.hpp:128
void set_storage(StoragePtr< MaxN > storage) noexcept
Update the internal storage and clear i/o state.
Definition Stream.hpp:133
bool empty() const noexcept
Definition Stream.hpp:127
OStream & operator=(const OStream &)=delete
const char * data() const noexcept
Definition Stream.hpp:126
OStream(const OStream &)=delete
StaticStreamBuf(StaticStreamBuf &&)=delete
bool empty() const noexcept
Definition Stream.hpp:164
StaticStreamBuf(const StaticStreamBuf &)=delete
std::string_view str() const noexcept
Definition Stream.hpp:167
const char * data() const noexcept
Definition Stream.hpp:163
StaticStreamBuf & operator=(const StaticStreamBuf &)=delete
void reset() noexcept
Reset the current position back to the beginning of the buffer.
Definition Stream.hpp:169
~StaticStreamBuf() override=default
std::size_t size() const noexcept
Definition Stream.hpp:165
StaticStreamBuf & operator=(StaticStreamBuf &&)=delete
StreamBuf uses a dynamic storage acquired from the custom allocator.
Definition Stream.hpp:41
StreamBuf & operator=(StreamBuf &&)=delete
std::size_t size() const noexcept
Definition Stream.hpp:63
bool empty() const noexcept
Definition Stream.hpp:62
StreamBuf(const StreamBuf &)=delete
StreamBuf(std::nullptr_t) noexcept
Constructor for initialising the StreamBuf with a null buffer.
Definition Stream.hpp:44
StoragePtr< MaxN > release_storage() noexcept
Release the managed storage.
Definition Stream.hpp:66
StreamBuf(StreamBuf &&)=delete
StreamBuf & operator=(const StreamBuf &)=delete
~StreamBuf() override=default
void set_storage(StoragePtr< MaxN > storage) noexcept
Update the internal storage.
Definition Stream.hpp:74
void reset() noexcept
Reset the current position back to the beginning of the buffer.
Definition Stream.hpp:76
const char * data() const noexcept
Definition Stream.hpp:61
STL namespace.
StreamT & operator<<(StreamT &os, PutPercentiles pp)
Definition Utility.hpp:68
void clear(timeval &tv) noexcept
Definition Time.hpp:302
constexpr detail::ResetState reset_state
I/O manipulator that resets I/O state.
Definition Stream.hpp:35
TOOLBOX_API void reset(std::ostream &os) noexcept
void join(std::ostream &os, const ArgT &arg, const ArgsT &... args)
Definition Stream.hpp:249
std::experimental::ostream_joiner< char > OStreamJoiner
Definition Stream.hpp:246
StoragePtr< SizeN > make_storage()
Returns a block of dynamic storage acquired from the custom allocator.
Definition Storage.hpp:38
std::unique_ptr< void, detail::StorageDeleter< SizeN > > StoragePtr
Definition Storage.hpp:34
constexpr auto bind() noexcept
Definition Slot.hpp:92