libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
writer_argument.hpp
1#pragma once
2
18template <size_t N>
19constexpr size_t Writer::BoundedTextLength(const char (&text)[N]) noexcept
20{
21 static_assert(N > 0,
22 "LibXR::Print::Writer::BoundedTextLength: char array must be non-empty");
23 size_t size = 0;
24 while (size < N && text[size] != '\0')
25 {
26 ++size;
27 }
28 ASSERT(size < N);
29 // Safety: if no NUL was found (size == N) and ASSERT is stripped in release
30 // builds, return N-1 instead of N to prevent the caller from constructing a
31 // string_view that reads past the array boundary.
32 return size < N ? size : N - 1;
33}
34
44template <typename T>
45constexpr std::string_view Writer::ToStringView(const T& text)
46{
47 using Traits = Detail::FormatArgument::TypeTraits<T>;
48
49 if constexpr (std::is_same_v<typename Traits::Decayed, std::string_view>)
50 {
51 return text;
52 }
53 else if constexpr (std::is_same_v<typename Traits::Decayed, std::string>)
54 {
55 return std::string_view(text.data(), text.size());
56 }
57 else if constexpr (std::is_same_v<typename Traits::Decayed, const char*> ||
58 std::is_same_v<typename Traits::Decayed, char*>)
59 {
60 if (text == nullptr)
61 {
62 return "(null)";
63 }
64 return std::string_view(text, std::strlen(text));
65 }
66 else if constexpr (Traits::is_char_array)
67 {
68 return std::string_view(text, BoundedTextLength(text));
69 }
70 else
71 {
72 return {};
73 }
74}
75
86template <FormatPackKind pack, typename T>
87constexpr auto Writer::PackValue(T&& value)
88{
89 using Traits = Detail::FormatArgument::TypeTraits<T>;
90 using Normalized = typename Traits::Normalized;
91
92 if constexpr (pack == FormatPackKind::I32)
93 {
94 if constexpr (Traits::is_signed_integer)
95 {
96 return static_cast<int32_t>(static_cast<Normalized>(value));
97 }
98 }
99 else if constexpr (pack == FormatPackKind::I64)
100 {
101 if constexpr (Traits::is_signed_integer)
102 {
103 return static_cast<int64_t>(static_cast<Normalized>(value));
104 }
105 }
106 else if constexpr (pack == FormatPackKind::U32)
107 {
108 if constexpr (std::is_same_v<Normalized, bool>)
109 {
110 return static_cast<uint32_t>(value ? 1U : 0U);
111 }
112 else if constexpr (std::is_integral_v<Normalized>)
113 {
114 return static_cast<uint32_t>(
115 static_cast<std::make_unsigned_t<Normalized>>(static_cast<Normalized>(value)));
116 }
117 }
118 else if constexpr (pack == FormatPackKind::U64)
119 {
120 if constexpr (std::is_same_v<Normalized, bool>)
121 {
122 return static_cast<uint64_t>(value ? 1U : 0U);
123 }
124 else if constexpr (std::is_integral_v<Normalized>)
125 {
126 return static_cast<uint64_t>(
127 static_cast<std::make_unsigned_t<Normalized>>(static_cast<Normalized>(value)));
128 }
129 }
130 else if constexpr (pack == FormatPackKind::Pointer)
131 {
132 if constexpr (Traits::is_pointer_like)
133 {
134 if constexpr (std::is_same_v<typename Traits::Decayed, std::nullptr_t>)
135 {
136 return static_cast<uintptr_t>(0);
137 }
138 else
139 {
140 return (value == nullptr) ? static_cast<uintptr_t>(0)
141 : reinterpret_cast<uintptr_t>(value);
142 }
143 }
144 }
145 else if constexpr (pack == FormatPackKind::Character)
146 {
147 if constexpr (Traits::is_character_like)
148 {
149 return static_cast<char>(static_cast<Normalized>(value));
150 }
151 }
152 else if constexpr (pack == FormatPackKind::StringView)
153 {
154 if constexpr (Traits::is_string_like)
155 {
156 return ToStringView(value);
157 }
158 }
159 else if constexpr (pack == FormatPackKind::F32)
160 {
161 if constexpr (std::is_arithmetic_v<Normalized>)
162 {
163 return static_cast<float>(value);
164 }
165 }
166 else if constexpr (pack == FormatPackKind::F64)
167 {
168 if constexpr (std::is_arithmetic_v<Normalized>)
169 {
170 return static_cast<double>(value);
171 }
172 }
173 else if constexpr (pack == FormatPackKind::LongDouble)
174 {
175 if constexpr (std::is_arithmetic_v<Normalized>)
176 {
177 return static_cast<long double>(value);
178 }
179 }
180 else
181 {
182 static_assert(dependent_false_v<pack>,
183 "LibXR::Print::Writer::PackValue: unsupported packed argument kind");
184 }
185}
186
195template <typename T>
196void Writer::StoreArgument(uint8_t*& out, const T& value)
197{
198 std::memcpy(out, &value, sizeof(T));
199 out += sizeof(T);
200}
201
209template <auto ArgumentInfoList>
210consteval size_t Writer::PackedArgumentBytes()
211{
212 size_t bytes = 0;
213 for (const auto& argument : ArgumentInfoList)
214 {
215 bytes += FormatArgumentBytes(argument.pack);
216 }
217 return bytes;
218}
219
232template <auto ArgumentInfoList, auto ArgumentOrder, typename Tuple>
233void Writer::StoreArgumentsOrdered(uint8_t*& out, Tuple& tuple)
234{
235 [&]<size_t... I>(std::index_sequence<I...>)
236 {
237 (StoreArgument(
238 out, PackValue<ArgumentInfoList[I].pack>(std::get<ArgumentOrder[I]>(tuple))),
239 ...);
240 }(std::make_index_sequence<ArgumentInfoList.size()>{});
241}