4#include <reloco/default_allocator.hpp>
8RELOCO_BEGIN_UNSAFE_BUFFER_USAGE
37 if (m_data != m_inline_ptr) {
38 m_alloc.deallocate(m_data, m_capacity);
45 [[nodiscard]]
sink as_sink() &
noexcept RELOCO_LIFETIMEBOUND {
47 this, [](
void *ctx, microfmt::string_view sv)
noexcept {
static_cast<memory_buffer_base *
>(ctx)->append(sv); }};
50 [[nodiscard]]
constexpr microfmt::string_view
view() const & noexcept RELOCO_LIFETIMEBOUND {
51 return microfmt::string_view(m_data, m_size);
55 [[nodiscard]]
constexpr pointer data() &
noexcept RELOCO_LIFETIMEBOUND {
return m_data; }
56 [[nodiscard]]
constexpr const_pointer data() const & noexcept RELOCO_LIFETIMEBOUND {
return m_data; }
58 [[nodiscard]]
constexpr iterator begin() &
noexcept RELOCO_LIFETIMEBOUND {
return m_data; }
59 [[nodiscard]]
constexpr const_iterator begin() const & noexcept RELOCO_LIFETIMEBOUND {
return m_data; }
62 [[nodiscard]]
constexpr iterator end() &
noexcept RELOCO_LIFETIMEBOUND {
return m_data + m_size; }
63 [[nodiscard]]
constexpr const_iterator end() const & noexcept RELOCO_LIFETIMEBOUND {
return m_data + m_size; }
64 [[nodiscard]]
constexpr const_iterator cend() const & noexcept RELOCO_LIFETIMEBOUND {
return m_data + m_size; }
66 [[nodiscard]]
constexpr size_type size() const noexcept {
return m_size; }
68 [[nodiscard]]
constexpr bool empty() const noexcept {
return m_size == 0; }
71 RELOCO_ASSERT(pos < size(),
"Index out of bounds");
75 RELOCO_ASSERT(pos < size(),
"Index out of bounds");
80 RELOCO_ASSERT(!empty(),
"Container is empty");
84 RELOCO_ASSERT(!empty(),
"Container is empty");
87 [[nodiscard]]
constexpr reference back() &
noexcept RELOCO_LIFETIMEBOUND {
88 RELOCO_ASSERT(!empty(),
"Container is empty");
89 return m_data[m_size - 1];
92 RELOCO_ASSERT(!empty(),
"Container is empty");
93 return m_data[m_size - 1];
96 RELOCO_REINITIALIZES
void clear() &
noexcept { m_size = 0; }
102 if (m_size >= m_capacity) {
103 if (!grow(m_size + 1))
106 m_data[m_size++] = c;
113 constexpr memory_buffer_base(reloco::allocator_ref alloc,
char *inline_buf, std::size_t inline_cap) noexcept
114 : m_alloc(alloc), m_data(inline_buf), m_inline_ptr(inline_buf), m_size(0), m_capacity(inline_cap) {}
120 : m_alloc(other.m_alloc), m_data(other.m_data == other.m_inline_ptr ? new_inline_ptr : other.m_data),
121 m_inline_ptr(new_inline_ptr), m_size(other.m_size), m_capacity(other.m_capacity) {
124 if (other.m_data == other.m_inline_ptr) {
125 std::copy_n(other.m_inline_ptr, other.m_size, new_inline_ptr);
129 other.m_data = other.m_inline_ptr;
131 other.m_capacity = inline_cap;
142 if (m_data != m_inline_ptr) {
143 m_alloc.deallocate(m_data, m_capacity);
146 m_alloc = other.m_alloc;
147 m_size = other.m_size;
148 m_capacity = other.m_capacity;
150 if (other.m_data == other.m_inline_ptr) {
152 m_data = m_inline_ptr;
153 std::copy_n(other.m_inline_ptr, other.m_size, m_inline_ptr);
156 m_data = other.m_data;
160 other.m_data = other.m_inline_ptr;
162 other.m_capacity = inline_cap;
166 reloco::allocator_ref m_alloc;
170 std::size_t m_capacity;
172 void append(microfmt::string_view sv)
noexcept {
176 if (m_size + sv.size() > m_capacity) {
177 if (!grow(m_size + sv.size())) {
179 const std::size_t avail = m_capacity - m_size;
181 std::copy_n(sv.data(), avail, m_data + m_size);
188 std::copy_n(sv.data(), sv.size(), m_data + m_size);
192 [[nodiscard]]
bool grow(std::size_t required_capacity)
noexcept {
193 std::size_t new_capacity = m_capacity + (m_capacity / 2);
194 if (new_capacity < required_capacity) {
195 new_capacity = required_capacity;
198 if (m_data == m_inline_ptr) {
200 const auto new_mem = m_alloc.allocate(new_capacity,
alignof(
char));
204 char *new_data =
static_cast<char *
>(new_mem->ptr);
205 std::copy_n(m_inline_ptr, m_size, new_data);
208 m_capacity = new_capacity;
211 if (
const auto actual_capacity = m_alloc.expand_in_place(m_data, m_capacity, new_capacity);
212 actual_capacity && actual_capacity.value() >= new_capacity) {
213 m_capacity = actual_capacity.value();
216 const auto new_mem = m_alloc.reallocate(m_data, m_capacity, new_capacity,
alignof(
char));
220 m_data =
static_cast<char *
>(new_mem->ptr);
221 m_capacity = new_capacity;
230RELOCO_END_UNSAFE_BUFFER_USAGE
253 this->
move_assign(std::move(other), InlineCapacity);
258 alignas(
void *)
char m_inline[InlineCapacity];
263template <>
struct reloco::is_trivially_relocatable<
microfmt::detail::memory_buffer_base> : std::false_type {};
264template <std::
size_t N>
struct reloco::is_trivially_relocatable<
microfmt::memory_buffer<N>> : std::false_type {};
Non-templated base class for dynamically growing buffers.
Definition memory_buffer.hpp:19
constexpr reference back() &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:87
memory_buffer_base & operator=(const memory_buffer_base &)=delete
constexpr reference front() &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:79
void push_back(char c) &noexcept
Fast-path single character append (enables std::back_inserter compatibility).
Definition memory_buffer.hpp:101
const_pointer const_iterator
Definition memory_buffer.hpp:29
constexpr const_iterator end() const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:63
~memory_buffer_base() noexcept
Definition memory_buffer.hpp:36
constexpr pointer data() &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:55
memory_buffer_base(const memory_buffer_base &)=delete
constexpr const_iterator cend() const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:64
constexpr memory_buffer_base(reloco::allocator_ref alloc, char *inline_buf, std::size_t inline_cap) noexcept
Initializes the buffer state using the derived class's stack storage.
Definition memory_buffer.hpp:113
constexpr const_reference front() const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:83
std::ptrdiff_t difference_type
Definition memory_buffer.hpp:23
std::size_t size_type
Definition memory_buffer.hpp:22
RELOCO_REINITIALIZES void clear() &noexcept
Definition memory_buffer.hpp:96
RELOCO_BLOCK_RVALUE_ACCESS(memory_buffer_base)
constexpr const_pointer data() const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:56
constexpr reference operator[](size_type pos) &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:70
constexpr const_iterator cbegin() const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:60
sink as_sink() &noexcept RELOCO_LIFETIMEBOUND
Creates a type-erased sink adapter pointing to this instance.
Definition memory_buffer.hpp:45
constexpr iterator begin() &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:58
const value_type & const_reference
Definition memory_buffer.hpp:25
constexpr bool empty() const noexcept
Definition memory_buffer.hpp:68
const value_type * const_pointer
Definition memory_buffer.hpp:27
constexpr iterator end() &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:62
void move_assign(memory_buffer_base &&other, std::size_t inline_cap) noexcept
Safely move-assigns the buffer, handling heap/stack transitions.
Definition memory_buffer.hpp:137
constexpr const_reference back() const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:91
constexpr memory_buffer_base(memory_buffer_base &&other, char *new_inline_ptr, std::size_t inline_cap) noexcept
Move-constructs from another buffer base, resolving inline pointers.
Definition memory_buffer.hpp:119
pointer iterator
Definition memory_buffer.hpp:28
char value_type
Definition memory_buffer.hpp:21
constexpr const_reference operator[](size_type pos) const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:74
constexpr size_type size() const noexcept
Definition memory_buffer.hpp:66
value_type & reference
Definition memory_buffer.hpp:24
constexpr size_type capacity() const noexcept
Definition memory_buffer.hpp:67
constexpr const_iterator begin() const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:59
value_type * pointer
Definition memory_buffer.hpp:26
constexpr microfmt::string_view view() const &noexcept RELOCO_LIFETIMEBOUND
Definition memory_buffer.hpp:50
A dynamically growing buffer with inline stack storage.
Definition memory_buffer.hpp:240
constexpr memory_buffer(reloco::allocator_ref alloc) noexcept
Definition memory_buffer.hpp:242
constexpr memory_buffer() noexcept
Definition memory_buffer.hpp:245
constexpr memory_buffer(memory_buffer &&other) noexcept
Definition memory_buffer.hpp:248
memory_buffer & operator=(memory_buffer &&other) noexcept
Definition memory_buffer.hpp:252
#define MICROFMT_API_CLASS
Definition compat.hpp:181
Core formatting primitives, sinks, and customization point.
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
Definition debug_float.hpp:36