microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
asio_sink.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2//
3// SPDX-License-Identifier: BSD-2-Clause
4
5#pragma once
6
7// std-interop-file: opt-in Boost.Asio/std::ostream sink adapters, not pulled in by the default umbrella.
8
11#include "../microfmt.hpp"
12#include "../reloco.hpp"
13#include <boost/asio/buffer.hpp>
14#include <boost/asio/streambuf.hpp>
15#include <cstddef>
16#include <cstring>
17#include <ostream>
18
19namespace microfmt {
20
31public:
40 boost::asio::mutable_buffer buf RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS) noexcept
41 : data_(static_cast<char *>(buf.data())), capacity_(buf.size()) {}
42
46 asio_mutable_buffer_sink &operator=(asio_mutable_buffer_sink &&) noexcept = default;
47
51 [[nodiscard]] sink as_sink() noexcept RELOCO_LIFETIMEBOUND { return sink{this, &write_impl}; }
52
56 [[nodiscard]] size_t size() const noexcept { return size_; }
57
66 [[nodiscard]] boost::asio::const_buffer written_buffer() const noexcept RELOCO_LIFETIMEBOUND {
67 return boost::asio::const_buffer(data_, size_);
68 }
69
70private:
71 static void write_impl(void *ctx, microfmt::string_view str) noexcept {
72 auto *self = static_cast<asio_mutable_buffer_sink *>(ctx);
73
74 if (self->size_ >= self->capacity_)
75 return;
76
77 size_t to_copy = str.size();
78 if (self->size_ + to_copy > self->capacity_) {
79 to_copy = self->capacity_ - self->size_;
80 }
81
82 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
83 std::memcpy(self->data_ + self->size_, str.data(), to_copy);
84 RELOCO_END_UNSAFE_BUFFER_USAGE;
85
86 self->size_ += to_copy;
87 }
88
89 char *data_;
90 size_t capacity_;
91 size_t size_{0};
92};
93
99public:
107 explicit asio_streambuf_sink(boost::asio::streambuf &buf RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS,
108 size_t max_chars = 1024) noexcept
109 : streambuf_(&buf), max_chars_(max_chars) {}
110
114 [[nodiscard]] sink as_sink() noexcept RELOCO_LIFETIMEBOUND { return sink{this, &write_impl}; }
115
116private:
117 static void write_impl(void *ctx, microfmt::string_view str) noexcept {
118 auto *self = static_cast<asio_streambuf_sink *>(ctx);
119
120 if (self->written_ >= self->max_chars_)
121 return;
122
123 size_t len = str.size();
124 if (self->written_ + len > self->max_chars_) {
125 len = self->max_chars_ - self->written_;
126 }
127
128 // Append via std::ostream so Boost.Asio grows the streambuf as needed.
129 std::ostream os(self->streambuf_);
130 os.write(str.data(), static_cast<std::streamsize>(len));
131 self->written_ += len;
132 }
133
134 boost::asio::streambuf *streambuf_;
135 size_t max_chars_;
136 size_t written_{0};
137};
138
139} // namespace microfmt
A sink adapter that writes formatted output directly into a boost::asio::mutable_buffer.
Definition asio_sink.hpp:30
asio_mutable_buffer_sink & operator=(const asio_mutable_buffer_sink &)=delete
asio_mutable_buffer_sink(asio_mutable_buffer_sink &&) noexcept=default
size_t size() const noexcept
Returns the total number of bytes written to the buffer so far.
Definition asio_sink.hpp:56
asio_mutable_buffer_sink(boost::asio::mutable_buffer buf RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS) noexcept
Constructs a sink over a Boost.Asio mutable buffer.
Definition asio_sink.hpp:39
boost::asio::const_buffer written_buffer() const noexcept RELOCO_LIFETIMEBOUND
Returns the written prefix of the wrapped buffer as a boost::asio::const_buffer, suitable for boost::...
Definition asio_sink.hpp:66
asio_mutable_buffer_sink(const asio_mutable_buffer_sink &)=delete
A sink adapter that writes formatted output into a boost::asio::streambuf dynamic buffer.
Definition asio_sink.hpp:98
asio_streambuf_sink(boost::asio::streambuf &buf RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS, size_t max_chars=1024) noexcept
Constructs a sink over an externally owned Boost.Asio streambuf.
Definition asio_sink.hpp:107
sink as_sink() noexcept RELOCO_LIFETIMEBOUND
Creates a type-erased sink adapter pointing to this instance.
Definition asio_sink.hpp:114
#define MICROFMT_API_CLASS
Definition compat.hpp:181
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46