microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
grid_view.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
10#include "../microfmt.hpp"
11#include <cstddef>
12#include <cstdint>
13#include <string_view>
14#include <type_traits>
15
16namespace microfmt {
17
18// ============================================================================
19// Generic Named Register / Field Descriptor
20// ============================================================================
21
31template <typename WordType, size_t N> struct RELOCO_POINTER reg_grid_desc {
35 microfmt::string_view title;
39 uint8_t columns{4}; // Number of register entries per row
43 microfmt::string_view names[N];
44};
45
50template <typename T> struct reg_grid_type_tag {};
51
55template <typename WordType, typename... Names>
56reg_grid_desc(reg_grid_type_tag<WordType>, microfmt::string_view, uint8_t, Names...)
57 -> reg_grid_desc<WordType, sizeof...(Names)>;
58
59// ============================================================================
60// Grid View Wrapper
61// ============================================================================
62
68template <typename WordType, size_t N> struct RELOCO_POINTER reg_grid_view {
72 const WordType *values{nullptr};
76 const reg_grid_desc<WordType, N> *desc{nullptr};
77};
78
90// low-level formatting: raw character pointers and integer width conversions bounded by the buffer sizes checked here.
91RELOCO_BEGIN_UNSAFE_CODE
92template <typename StructOrArray, typename WordType, size_t N>
93[[nodiscard]] constexpr auto make_reg_grid(const StructOrArray &data, const reg_grid_desc<WordType, N> &desc) noexcept {
94 static_assert(sizeof(StructOrArray) >= N * sizeof(WordType),
95 "Source structure size is smaller than register grid definition");
96 return reg_grid_view<WordType, N>{reinterpret_cast<const WordType *>(&data), &desc};
97}
99
100// ============================================================================
101// Formatter for Generic Register Grid
102// ============================================================================
103
113template <typename WordType, size_t N> struct formatter<reg_grid_view<WordType, N>> {
117 static constexpr size_t hex_digits = sizeof(WordType) * 2;
118
122 constexpr void parse(format_parse_context &) noexcept {}
123
129 void format(const reg_grid_view<WordType, N> &gv, const sink &out) const noexcept {
130 if (!gv.desc || !gv.values)
131 return;
132 const auto &d = *gv.desc;
133
134 if (!d.title.empty()) {
135 out.write("=== ");
136 out.write(d.title);
137 out.write(" ===\n");
138 }
139
140 const uint8_t cols = (d.columns > 0) ? d.columns : 4;
141
142 for (size_t i = 0; i < N; ++i) {
143 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE
144
145 microfmt::string_view name = d.names[i];
146
147 RELOCO_END_UNSAFE_BUFFER_USAGE
148
149 out.write(name);
150
151 // Pad name column to 5 characters for clean alignment
152 if (name.size() < 5) {
153 for (size_t p = name.size(); p < 5; ++p)
154 out.put(' ');
155 }
156 out.write("= 0x");
157
158 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE
159
160 detail::format_unsigned<detail::radix::hex>(out, static_cast<uint64_t>(gv.values[i]), true, hex_digits);
161
162 RELOCO_END_UNSAFE_BUFFER_USAGE
163
164 // Newline or column separator
165 if ((i + 1) % cols == 0 || (i + 1) == N) {
166 out.put('\n');
167 } else {
168 out.write(" ");
169 }
170 }
171 }
172};
173
174} // namespace microfmt
Definition microfmt.hpp:881
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_BEGIN_UNSAFE_CODE constexpr auto make_reg_grid(const StructOrArray &data, const reg_grid_desc< WordType, N > &desc) noexcept
Builds a reg_grid_view over an array/struct of register data.
Definition grid_view.hpp:93
RELOCO_END_UNSAFE_CODE
Definition remote_object.hpp:132
void format(const reg_grid_view< WordType, N > &gv, const sink &out) const noexcept
Renders the register grid to the output sink.
Definition grid_view.hpp:129
constexpr void parse(format_parse_context &) noexcept
No-op parse; grid views accept no format specifier.
Definition grid_view.hpp:122
Definition microfmt.hpp:985
Static descriptor naming N register entries within a grid.
Definition grid_view.hpp:31
microfmt::string_view title
Optional grid title rendered as === title ===.
Definition grid_view.hpp:35
Empty tag used to drive CTAD for reg_grid_desc.
Definition grid_view.hpp:50
Non-owning view pairing register values with their static descriptor.
Definition grid_view.hpp:68