microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
metadata_map.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2// SPDX-License-Identifier: BSD-2-Clause
3
4#pragma once
5
9#include "../markdown.hpp"
10#include "../microfmt.hpp"
11#include "../reloco.hpp"
12#include <reloco/type_id.hpp>
13
14namespace microfmt {
15
19using property_print_fn_t = void (*)(const void *val_ptr, const sink &out) noexcept;
20
24struct MICROFMT_API_CLASS RELOCO_POINTER property_entry {
25 microfmt::string_view key{};
26 value_ptr<const void> val_ptr{};
27 property_print_fn_t print_fn{nullptr};
28
32 void format_value(const sink &out) const noexcept {
33 if (print_fn != nullptr && val_ptr) {
34 print_fn(val_ptr.get(), out);
35 } else {
36 out.write("null");
37 }
38 }
39};
40
48using metadata_next_fn_t = bool (*)(void *ctx, property_entry &out) noexcept;
49
56class MICROFMT_API_CLASS RELOCO_POINTER metadata_map {
57public:
64 constexpr metadata_map(void *ctx RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS,
65 metadata_next_fn_t next_fn) noexcept
66 : m_ctx(ctx), m_next_fn(next_fn) {}
67
73 [[nodiscard]] constexpr bool get_next(property_entry &out) const noexcept {
74 if (m_next_fn != nullptr && m_ctx) {
75 return m_next_fn(m_ctx.get(), out);
76 }
77 return false;
78 }
79
80private:
81 value_ptr<void> m_ctx{};
82 metadata_next_fn_t m_next_fn{nullptr};
83};
84
85} // namespace microfmt
86
87// ============================================================================
88// Formatter Specialization for metadata_map (Zero-Overhead while Loop)
89// ============================================================================
90
91namespace microfmt {
92
93template <> struct formatter<microfmt::metadata_map> {
94 constexpr void parse(format_parse_context &) noexcept {}
95
96 void format(const microfmt::metadata_map &map, const sink &out) const noexcept {
97 out.put('{');
98 property_entry entry;
99 std::size_t idx = 0;
100
101 // Direct generator loop minimizing local stack variables and branch overhead
102 while (map.get_next(entry)) {
103 if (idx > 0) {
104 out.write(", ");
105 }
106 microfmt::format_to(out, "\"{}\": ", entry.key);
107 entry.format_value(out);
108 ++idx;
109 }
110 out.put('}');
111 }
112};
113
114} // namespace microfmt
115
116namespace microfmt::md {
117
126inline void write_metadata_table(writer &w, metadata_map map, span<char> scratch_buf,
127 string_view title = "Metadata Properties") noexcept {
128 // NOLINTNEXTLINE(reloco-no-c-array): fixed-size buffer/table for span APIs
129 static constexpr column cols[2] = {{"Property", 12, align::left}, {"Value", 16, align::left}};
130
131 w.h3(title);
132
133 table_writer<2> tw(w, cols);
134
135 // Initialize the caller-provided span_sink scratchpad
136 span_sink scratch(scratch_buf);
137
138 property_entry entry;
139 while (map.get_next(entry)) {
140 scratch.reset(); // Clear workspace for the next row
141 entry.format_value(scratch.as_sink()); // Format into scratch buffer
142
143 tw.row(entry.key, scratch.view());
144 }
145}
146
147} // namespace microfmt::md
148
149// See <reloco/type_id.hpp> for the full RELOCO_TYPE_ID_NAME rationale;
150// defined here, alongside property_entry's own definition.
Definition markdown.hpp:431
table_writer & row(const Cells &...cells) &noexcept
Definition markdown.hpp:437
Definition markdown.hpp:43
writer & h3(microfmt::string_view title) &noexcept
Definition markdown.hpp:99
Type-erased, non-owning metadata map view driven by a sequential next callback.
Definition metadata_map.hpp:56
constexpr metadata_map(void *ctx RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS, metadata_next_fn_t next_fn) noexcept
Constructs a metadata_map view over an iteration context and a next function.
Definition metadata_map.hpp:64
constexpr bool get_next(property_entry &out) const noexcept
Fetches the next property entry, advancing the internal generator state.
Definition metadata_map.hpp:73
Output sink that writes formatted characters into a fixed-size contiguous memory buffer.
Definition microfmt.hpp:60
RELOCO_REINITIALIZES constexpr void reset() noexcept
Resets the write offset back to the beginning of the buffer.
Definition microfmt.hpp:135
sink as_sink() noexcept RELOCO_LIFETIMEBOUND
Creates a type-erased sink adapter pointing to this instance.
Definition microfmt.hpp:93
constexpr microfmt::string_view view() const noexcept RELOCO_LIFETIMEBOUND
Returns a string view over the characters written so far.
Definition microfmt.hpp:112
#define MICROFMT_API_CLASS
Definition compat.hpp:181
RELOCO_TYPE_ID_NAME(microfmt::property_entry, "microfmt::property_entry")
Definition metadata_map.hpp:116
void write_metadata_table(writer &w, metadata_map map, span< char > scratch_buf, string_view title="Metadata Properties") noexcept
Streams any type-erased metadata_map view into a Markdown table.
Definition metadata_map.hpp:126
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_CONSTEXPR20 void format_to(const sink &out, microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1766
RELOCO_CONSTEXPR20 buffer_sink< N > format(microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1786
void(*)(const void *val_ptr, const sink &out) noexcept property_print_fn_t
Function pointer signature for type-erased property value formatting.
Definition metadata_map.hpp:19
bool(*)(void *ctx, property_entry &out) noexcept metadata_next_fn_t
Function pointer signature for fetching the next property entry.
Definition metadata_map.hpp:48
Definition markdown.hpp:26
Type-erased property entry synthesized during generation.
Definition metadata_map.hpp:24
void format_value(const sink &out) const noexcept
Formats the underlying property value using its type-erased thunk.
Definition metadata_map.hpp:32
microfmt::string_view key
Definition metadata_map.hpp:25