libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
writer_executor_value.hpp
1#pragma once
2
15template <OutputSink Sink>
16template <std::signed_integral Int>
17char Writer::Executor<Sink>::ResolveSignChar(Int value, const Spec& spec)
18{
19 if (value < 0)
20 {
21 return '-';
22 }
23 if (spec.ForceSign())
24 {
25 return '+';
26 }
27 if (spec.SpaceSign())
28 {
29 return ' ';
30 }
31 return '\0';
32}
33
34#if LIBXR_PRINT_ENABLE_FLOAT
43template <OutputSink Sink>
44template <typename T>
45char Writer::Executor<Sink>::ResolveFloatSignChar(T value, const Spec& spec)
46{
47 if (std::isnan(value))
48 {
49 // NaN signbit is implementation-defined and platform-dependent.
50 // Derive sign from the explicit format flag only so output is stable
51 // across platforms and FPU implementations:
52 // {:f} -> "nan" {:+f} -> "+nan" {: f} -> " nan"
53 return spec.ForceSign() ? '+' : spec.SpaceSign() ? ' ' : '\0';
54 }
55 if (std::signbit(value))
56 {
57 return '-';
58 }
59 if (spec.ForceSign())
60 {
61 return '+';
62 }
63 if (spec.SpaceSign())
64 {
65 return ' ';
66 }
67 return '\0';
68}
69#endif
70
79template <OutputSink Sink>
80template <std::signed_integral Int>
81ErrorCode Writer::Executor<Sink>::WriteSigned(const Spec& spec, Int value)
82{
83 using UInt = std::make_unsigned_t<Int>;
84 char digit_buffer[UnsignedDigitCapacity<UInt, 10>()];
85 UInt bits = static_cast<UInt>(value);
86 UInt magnitude = (value < 0) ? (UInt{0} - bits) : bits;
87 size_t digit_count = AppendUnsigned<10>(digit_buffer, magnitude);
88
89 std::string_view digits(digit_buffer, digit_count);
90 if (value == 0 && spec.precision == 0)
91 {
92 digits = {};
93 }
94
95 return WriteIntegerField(ResolveSignChar(value, spec), {}, digits, spec);
96}
97
112template <OutputSink Sink>
113template <uint8_t Base, bool UpperCase, bool PrependOctalZero,
114 std::unsigned_integral UInt>
115ErrorCode Writer::Executor<Sink>::WriteUnsignedDigits(std::string_view prefix,
116 const Spec& spec, UInt value)
117{
118 char digit_buffer[UnsignedDigitCapacity<UInt, Base>() + (PrependOctalZero ? 1U : 0U)];
119 size_t digit_count = AppendUnsigned<Base, UpperCase>(digit_buffer, value);
120
121 if constexpr (PrependOctalZero)
122 {
123 digit_count = ApplyAlternateOctal(digit_buffer, digit_count, spec, value);
124 }
125 else if (value == 0 && spec.precision == 0)
126 {
127 digit_count = 0;
128 }
129
130 return WriteIntegerField('\0', prefix, std::string_view(digit_buffer, digit_count),
131 spec);
132}
133
148template <OutputSink Sink>
149template <FormatType Type, std::unsigned_integral UInt>
150ErrorCode Writer::Executor<Sink>::DispatchUnsigned(const Spec& spec, UInt value)
151{
152 auto prefix = IntegerPrefix(Type, spec, value);
153
154 if constexpr (Type == FormatType::Unsigned32 || Type == FormatType::Unsigned64)
155 {
156 return WriteUnsignedDigits<10>(prefix, spec, value);
157 }
158 if constexpr (Type == FormatType::Binary32 || Type == FormatType::Binary64)
159 {
160 return WriteUnsignedDigits<2>(prefix, spec, value);
161 }
162 if constexpr (Type == FormatType::Octal32 || Type == FormatType::Octal64)
163 {
164 return WriteUnsignedDigits<8, false, true>(prefix, spec, value);
165 }
166 if constexpr (Type == FormatType::HexLower32 || Type == FormatType::HexLower64)
167 {
168 return WriteUnsignedDigits<16>(prefix, spec, value);
169 }
170 if constexpr (Type == FormatType::HexUpper32 || Type == FormatType::HexUpper64)
171 {
172 return WriteUnsignedDigits<16, true>(prefix, spec, value);
173 }
174
175 return ErrorCode::ARG_ERR;
176}
177
185template <OutputSink Sink>
186ErrorCode Writer::Executor<Sink>::WritePointer(const Spec& spec, uintptr_t value)
187{
188 char digit_buffer[UnsignedDigitCapacity<uintptr_t, 16>()];
189 size_t digit_count = AppendUnsigned<16>(digit_buffer, value);
190 Spec actual = spec;
191
192 if (!actual.HasPrecision() || actual.precision == 0)
193 {
194 actual.precision = 1;
195 }
196
197 return WriteIntegerField('\0', "0x", std::string_view(digit_buffer, digit_count),
198 actual);
199}
200
207template <OutputSink Sink>
208ErrorCode Writer::Executor<Sink>::WriteCharacter(const Spec& spec, char ch)
209{
210 return WriteTextField(std::string_view(&ch, 1), spec);
211}
212
220template <OutputSink Sink>
221ErrorCode Writer::Executor<Sink>::WriteString(const Spec& spec, std::string_view text)
222{
223 auto view = text;
224 if (spec.HasPrecision() && spec.precision < view.size())
225 {
226 view = view.substr(0, spec.precision);
227 }
228
229 return WriteTextField(view, spec);
230}
231
241#if LIBXR_PRINT_ENABLE_FLOAT
242template <OutputSink Sink>
243template <typename T>
244ErrorCode Writer::Executor<Sink>::WriteFloat(FormatType type, const Spec& spec, T value)
245{
246 if (!UsesFloatTextBackend(type))
247 {
248 return ErrorCode::ARG_ERR;
249 }
250
251 Spec actual = spec;
252 if (!std::isfinite(value))
253 {
254 actual.flags &= static_cast<uint8_t>(~static_cast<uint8_t>(FormatFlag::ZeroPad));
255 }
256
257 char sign_char = ResolveFloatSignChar(value, actual);
258 T magnitude = std::signbit(value) ? -static_cast<T>(value) : static_cast<T>(value);
259 uint8_t precision = actual.HasPrecision() ? actual.precision : DefaultFloatPrecision();
260 if (type == FormatType::FloatFixed || type == FormatType::DoubleFixed ||
261 type == FormatType::LongDoubleFixed)
262 {
263 if (ExceedsFixedIntegerDigits(magnitude, precision))
264 {
265 return ErrorCode::OUT_OF_RANGE;
266 }
267 }
268 else if (type == FormatType::FloatGeneral || type == FormatType::DoubleGeneral ||
269 type == FormatType::LongDoubleGeneral)
270 {
271 uint8_t significant = precision == 0 ? 1 : precision;
272 int exponent =
273 RoundScientificDigits(magnitude, static_cast<uint8_t>(significant - 1)).exponent;
274 if (!(exponent < -4 || exponent >= significant))
275 {
276 int fractional_precision = static_cast<int>(significant) - (exponent + 1);
277 if (fractional_precision < 0)
278 {
279 fractional_precision = 0;
280 }
281 if (ExceedsFixedIntegerDigits(magnitude,
282 static_cast<uint8_t>(fractional_precision)))
283 {
284 return ErrorCode::OUT_OF_RANGE;
285 }
286 }
287 }
288 char output_buffer[float_buffer_capacity];
289 size_t output_size = 0;
290 if (!FormatFloatText(type, actual, magnitude, output_buffer, output_size))
291 {
292 return ErrorCode::NO_BUFF;
293 }
294
295 return WriteFloatField(sign_char, std::string_view(output_buffer, output_size), actual);
296}
297#endif
298
305template <OutputSink Sink>
306ErrorCode Writer::Executor<Sink>::WriteU32Dec(uint32_t value)
307{
308 char digit_buffer[UnsignedDigitCapacity<uint32_t, 10>()];
309 size_t digit_count = AppendUnsigned<10>(digit_buffer, value);
310 return WriteRaw(std::string_view(digit_buffer, digit_count));
311}
312
319template <OutputSink Sink>
321{
322 using UInt = std::make_unsigned_t<int32_t>;
323 char digit_buffer[UnsignedDigitCapacity<UInt, 10>()];
324 UInt bits = static_cast<UInt>(value);
325 UInt magnitude = (value < 0) ? (UInt{0} - bits) : bits;
326 size_t digit_count = AppendUnsigned<10>(digit_buffer, magnitude);
327
328 if (value < 0)
329 {
330 if (auto ec = WriteRaw("-"); ec != ErrorCode::OK)
331 {
332 return ec;
333 }
334 }
335
336 return WriteRaw(std::string_view(digit_buffer, digit_count));
337}
338
347template <OutputSink Sink>
348template <uint8_t Base, bool UpperCase>
350{
351 char digit_buffer[UnsignedDigitCapacity<uint32_t, Base>()];
352 size_t digit_count = AppendUnsigned<Base, UpperCase>(digit_buffer, value);
353 return WriteRaw(std::string_view(digit_buffer, digit_count));
354}
355
363template <OutputSink Sink>
364ErrorCode Writer::Executor<Sink>::WriteU32ZeroPadWidth(uint8_t width, uint32_t value)
365{
366 char digit_buffer[UnsignedDigitCapacity<uint32_t, 10>()];
367 size_t digit_count = AppendUnsigned<10>(digit_buffer, value);
368 size_t zeros = FieldPadding(width, digit_count);
369 if (auto ec = WritePadding('0', zeros); ec != ErrorCode::OK)
370 {
371 return ec;
372 }
373 return WriteRaw(std::string_view(digit_buffer, digit_count));
374}
375
381template <OutputSink Sink>
382ErrorCode Writer::Executor<Sink>::WriteStringRaw(std::string_view text)
383{
384 return WriteRaw(text);
385}
386
392template <OutputSink Sink>
394{
395 return WriteRaw(std::string_view(&ch, 1));
396}
按输出端共享重后端、按调用点 profile 裁剪操作码分发的字节码执行器 / Per-sink bytecode executor with shared heavy backends and per...
ErrorCode WriteI32Dec(int32_t value)
单个原始 int32_t 十进制字段的快路径。 / Fast path for one raw int32_t decimal field.
ErrorCode WriteUnsignedDigits(std::string_view prefix, const Spec &spec, UInt value)
按编译期进制/大小写/八进制备用格式参数复用无符号数字载荷写出逻辑 / Reuse the unsigned-digit payload writer with compile-time radix,...
static char ResolveSignChar(Int value, const Spec &spec)
执行器的具体运行期数值写出函数 / Concrete runtime value writers for the executor
ErrorCode WriteStringRaw(std::string_view text)
单个原始字符串参数的快路径。 / Fast path for one raw string argument.
ErrorCode WriteU32Base(uint32_t value)
单个原始 uint32_t 非十进制字段的快路径。 / Fast path for one raw uint32_t non-decimal field.
ErrorCode WritePointer(const Spec &spec, uintptr_t value)
按规范指针字段策略写出一个指针值 / Write one pointer value using the canonical pointer field policy
ErrorCode WriteString(const Spec &spec, std::string_view text)
写出一个字符串字段值,并在需要时应用精度截断 / Write one string field value, including precision truncation when present
ErrorCode DispatchUnsigned(const Spec &spec, UInt value)
通过共享整数字段路径写出一个无符号整数语义值 / Write one unsigned integer semantic value through the shared integer-field p...
ErrorCode WriteU32Dec(uint32_t value)
单个原始 uint32_t 十进制字段的快路径。 / Fast path for one raw uint32_t decimal field.
ErrorCode WriteCharacterRaw(char ch)
单个原始字符参数的快路径。 / Fast path for one raw character argument.
ErrorCode WriteCharacter(const Spec &spec, char ch)
写出一个字符字段值 / Write one character field value
ErrorCode WriteSigned(const Spec &spec, Int value)
通过共享整数字段路径写出一个有符号整数值 / Write one signed integer value through the shared integer-field path
ErrorCode WriteU32ZeroPadWidth(uint8_t width, uint32_t value)
单个零填充 uint32_t 十进制字段的快路径。 / Fast path for one zero-padded uint32_t decimal field.