microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
remote_forward_list.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 "remote_container.hpp"
12#include "remote_object.hpp"
13
14namespace microfmt {
15
24template <typename Tag> struct remote_forward_list_traits;
25
26namespace detail {
27
28template <typename Tag> struct remote_forward_list_dispatch {
30 using context_type = typename traits_type::context_type;
31
32 static bool format(value_ref<const context_type> context, uintptr_t container_addr, const container_options &opts,
33 address_space_ref space, span<std::byte> scratch, const sink &out) noexcept {
34 out.write(opts.open_bracket);
35
36 uintptr_t current_node = 0;
37 if (!traits_type::get_head_node(context, container_addr, space, scratch, current_node)) {
38 out.write(opts.close_bracket);
39 return true;
40 }
41
42 size_t print_count = 0;
43 while (current_node != 0) {
44 if (print_count >= opts.max_print) {
45 if (print_count > 0)
46 out.write(opts.entry_separator);
47 out.write("...");
48 break;
49 }
50 if (print_count > 0)
51 out.write(opts.entry_separator);
52
53 if (!traits_type::format_node_element(context, space, scratch, current_node, out)) {
54 out.write("<fault>");
55 break;
56 }
57
58 uintptr_t next_node = 0;
59 if (!traits_type::get_next_node(context, space, scratch, current_node, next_node)) {
60 out.write("<fault>");
61 break;
62 }
63 current_node = next_node;
64 ++print_count;
65 }
66
67 out.write(opts.close_bracket);
68 return true;
69 }
70};
71
72template <typename T, typename RemotePtr> struct forward_list_layout_tag {};
73
74} // namespace detail
75
76template <typename Tag>
78
82template <typename Tag>
83[[nodiscard]] constexpr remote_forward_list<Tag>
84make_remote_forward_list(uintptr_t container_addr,
85 typename remote_forward_list_traits<Tag>::context_type context) noexcept {
86 return remote_forward_list<Tag>(container_addr, std::move(context));
87}
88
89template <typename T, typename RemotePtr>
90struct remote_forward_list_traits<detail::forward_list_layout_tag<T, RemotePtr>> {
91 using pointer_query = decltype(make_remote_offset_query<uintptr_t, RemotePtr>(0));
92
93 struct context_type {
96 ptrdiff_t data_offset;
97 };
98
99 static bool get_head_node(value_ref<const context_type> context, uintptr_t container_addr, address_space_ref space,
100 span<std::byte>, uintptr_t &out_node_addr) noexcept {
101 return context->head(space, container_addr, out_node_addr);
102 }
103
104 static bool get_next_node(value_ref<const context_type> context, address_space_ref space, span<std::byte>,
105 uintptr_t node_addr, uintptr_t &out_next_addr) noexcept {
106 return context->next(space, node_addr, out_next_addr);
107 }
108
109 static bool format_node_element(value_ref<const context_type> context, address_space_ref space,
110 span<std::byte> scratch, uintptr_t node_addr, const sink &out) noexcept {
111 const uintptr_t elem_addr = detail::add_address_offset(node_addr, context->data_offset);
113 remote_object_view obj_view(elem_addr, space, type_tag<T>{}, scratch);
114 formatter<remote_object_view>().format(obj_view, out);
115 } else {
116 scratch_allocator allocator(scratch);
117 T *value = allocator.allocate<T>();
118 if (!value || !space.read_bytes(elem_addr, value, sizeof(T)))
119 return false;
120 formatter<T>().format(*value, out);
121 }
122 return true;
123 }
124};
125
129template <typename T, typename RemotePtr = uintptr_t>
130[[nodiscard]] constexpr auto make_remote_forward_list(uintptr_t container_addr, ptrdiff_t head_offset,
131 ptrdiff_t next_offset, ptrdiff_t data_offset) noexcept {
133 using traits = remote_forward_list_traits<tag>;
134 typename traits::context_type context{make_remote_offset_query<uintptr_t, RemotePtr>(head_offset),
135 make_remote_offset_query<uintptr_t, RemotePtr>(next_offset), data_offset};
136 return remote_forward_list<tag>(container_addr, std::move(context));
137}
138
139} // namespace microfmt
Type-erased, two-word handle to a remote address space.
Definition address_space.hpp:204
Owning typed container bound to a compile-time traits dispatcher.
Definition remote_container.hpp:102
Definition remote_object.hpp:231
Zero-allocation bump allocator for scratch buffers.
Definition scratch_allocator.hpp:27
RELOCO_BEGIN_UNSAFE_CODE constexpr uintptr_t add_address_offset(uintptr_t address, ptrdiff_t offset) noexcept
Definition address_space.hpp:52
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
constexpr remote_forward_list< Tag > make_remote_forward_list(uintptr_t container_addr, typename remote_forward_list_traits< Tag >::context_type context) noexcept
Creates a typed remote forward list with caller-defined traits.
Definition remote_forward_list.hpp:84
Type-erased views and contexts for formatting remote containers.
Reusable callback and typed-offset accessors for remote layouts.
Remote object dumping, layout macros, and string pointer wrappers with 32-bit compatibility support.
Configuration options for formatting container views.
Definition remote_container.hpp:25
Definition remote_forward_list.hpp:72
Definition remote_forward_list.hpp:28
static bool format(value_ref< const context_type > context, uintptr_t container_addr, const container_options &opts, address_space_ref space, span< std::byte > scratch, const sink &out) noexcept
Definition remote_forward_list.hpp:32
typename traits_type::context_type context_type
Definition remote_forward_list.hpp:30
Definition microfmt.hpp:985
decltype(make_remote_offset_query< uintptr_t, RemotePtr >(0)) pointer_query
Definition remote_forward_list.hpp:91
static bool get_head_node(value_ref< const context_type > context, uintptr_t container_addr, address_space_ref space, span< std::byte >, uintptr_t &out_node_addr) noexcept
Definition remote_forward_list.hpp:99
static bool format_node_element(value_ref< const context_type > context, address_space_ref space, span< std::byte > scratch, uintptr_t node_addr, const sink &out) noexcept
Definition remote_forward_list.hpp:109
static bool get_next_node(value_ref< const context_type > context, address_space_ref space, span< std::byte >, uintptr_t node_addr, uintptr_t &out_next_addr) noexcept
Definition remote_forward_list.hpp:104
Static customization point for a remote forward-list implementation.
Definition remote_forward_list.hpp:24
Traits customization point for remote object metadata.
Definition remote_object.hpp:217
Definition remote_object.hpp:229