libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
format_protocol.hpp
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <limits>
6#include <string_view>
7#include <type_traits>
8
24#ifndef LIBXR_PRINT_ENABLE_INTEGER
25#define LIBXR_PRINT_ENABLE_INTEGER 1
26#endif
27
28#ifndef LIBXR_PRINT_ENABLE_TEXT
29#define LIBXR_PRINT_ENABLE_TEXT 1
30#endif
31
32#ifndef LIBXR_PRINT_ENABLE_POINTER
33#define LIBXR_PRINT_ENABLE_POINTER 0
34#endif
35
36#ifndef LIBXR_PRINT_ENABLE_FLOAT
37#define LIBXR_PRINT_ENABLE_FLOAT 1
38#endif
39
40#ifndef LIBXR_PRINT_INTEGER_ENABLE_BASE8_16
41#define LIBXR_PRINT_INTEGER_ENABLE_BASE8_16 1
42#endif
43
44#ifndef LIBXR_PRINT_INTEGER_ENABLE_64BIT
45#define LIBXR_PRINT_INTEGER_ENABLE_64BIT 0
46#endif
47
48#ifndef LIBXR_PRINT_FLOAT_ENABLE_FIXED
49#define LIBXR_PRINT_FLOAT_ENABLE_FIXED 1
50#endif
51
52#ifndef LIBXR_PRINT_FLOAT_ENABLE_DOUBLE
53#define LIBXR_PRINT_FLOAT_ENABLE_DOUBLE 0
54#endif
55
56#ifndef LIBXR_PRINT_FLOAT_ENABLE_SCIENTIFIC
57#define LIBXR_PRINT_FLOAT_ENABLE_SCIENTIFIC 0
58#endif
59
60#ifndef LIBXR_PRINT_FLOAT_ENABLE_GENERAL
61#define LIBXR_PRINT_FLOAT_ENABLE_GENERAL 0
62#endif
63
64#ifndef LIBXR_PRINT_FLOAT_ENABLE_LONG_DOUBLE
65#define LIBXR_PRINT_FLOAT_ENABLE_LONG_DOUBLE 0
66#endif
67
68#ifndef LIBXR_PRINT_FLOAT_MAX_PRECISION
69#define LIBXR_PRINT_FLOAT_MAX_PRECISION 32
70#endif
71
72#ifndef LIBXR_PRINT_FLOAT_MAX_INTEGER_DIGITS
73#define LIBXR_PRINT_FLOAT_MAX_INTEGER_DIGITS 32
74#endif
75
76#ifndef LIBXR_PRINT_ENABLE_WIDTH
77#define LIBXR_PRINT_ENABLE_WIDTH 1
78#endif
79
80#ifndef LIBXR_PRINT_ENABLE_PRECISION
81#define LIBXR_PRINT_ENABLE_PRECISION 1
82#endif
83
84#ifndef LIBXR_PRINT_ENABLE_ALTERNATE
85#define LIBXR_PRINT_ENABLE_ALTERNATE 0
86#endif
87
88#ifndef LIBXR_PRINT_ENABLE_EXPLICIT_ARGUMENT_INDEXING
89#define LIBXR_PRINT_ENABLE_EXPLICIT_ARGUMENT_INDEXING 0
90#endif
91
92namespace LibXR::Print::Config
93{
98inline constexpr bool enable_integer = LIBXR_PRINT_ENABLE_INTEGER;
102inline constexpr bool enable_text = LIBXR_PRINT_ENABLE_TEXT;
106inline constexpr bool enable_pointer = LIBXR_PRINT_ENABLE_POINTER;
110inline constexpr bool enable_float = LIBXR_PRINT_ENABLE_FLOAT;
111
116inline constexpr bool enable_integer_base8_16 =
117 enable_integer && LIBXR_PRINT_INTEGER_ENABLE_BASE8_16;
122inline constexpr bool enable_integer_64bit =
123 enable_integer && LIBXR_PRINT_INTEGER_ENABLE_64BIT;
124
129inline constexpr bool enable_float_fixed = enable_float && LIBXR_PRINT_FLOAT_ENABLE_FIXED;
136inline constexpr bool enable_float_double =
137 enable_float && LIBXR_PRINT_FLOAT_ENABLE_DOUBLE;
142inline constexpr bool enable_float_scientific =
143 enable_float && LIBXR_PRINT_FLOAT_ENABLE_SCIENTIFIC;
148inline constexpr bool enable_float_general =
149 enable_float && LIBXR_PRINT_FLOAT_ENABLE_GENERAL;
154inline constexpr bool enable_float_long_double =
155 enable_float_double && LIBXR_PRINT_FLOAT_ENABLE_LONG_DOUBLE;
156static_assert(LIBXR_PRINT_FLOAT_MAX_PRECISION <=
157 static_cast<int>(std::numeric_limits<uint8_t>::max() - 1),
158 "LibXR::Print: LIBXR_PRINT_FLOAT_MAX_PRECISION must fit in uint8_t "
159 "and stay below the unspecified-precision sentinel");
160static_assert(LIBXR_PRINT_FLOAT_MAX_INTEGER_DIGITS > 0,
161 "LibXR::Print: LIBXR_PRINT_FLOAT_MAX_INTEGER_DIGITS must be positive");
166inline constexpr uint8_t max_float_precision =
167 static_cast<uint8_t>(LIBXR_PRINT_FLOAT_MAX_PRECISION);
172inline constexpr size_t max_float_integer_digits =
173 static_cast<size_t>(LIBXR_PRINT_FLOAT_MAX_INTEGER_DIGITS);
174
178inline constexpr bool enable_width = LIBXR_PRINT_ENABLE_WIDTH;
182inline constexpr bool enable_precision = LIBXR_PRINT_ENABLE_PRECISION;
187inline constexpr bool enable_alternate = LIBXR_PRINT_ENABLE_ALTERNATE;
192inline constexpr bool enable_explicit_argument_indexing =
193 LIBXR_PRINT_ENABLE_EXPLICIT_ARGUMENT_INDEXING;
194} // namespace LibXR::Print::Config
195
196namespace LibXR::Print
197{
220enum class FormatArgumentRule : uint8_t
221{
222 None,
223 SignedAny,
224 SignedChar,
225 SignedShort,
226 SignedLong,
227 SignedLongLong,
228 SignedIntMax,
229 SignedSize,
230 SignedPtrDiff,
231 UnsignedAny,
232 UnsignedChar,
233 UnsignedShort,
234 UnsignedLong,
235 UnsignedLongLong,
236 UnsignedIntMax,
237 UnsignedSize,
238 UnsignedPtrDiff,
240 Pointer,
241 Character,
242 String,
243 Float,
244 LongDouble,
245};
246
255enum class FormatFlag : uint8_t
256{
257 LeftAlign = 1U << 0,
258 ForceSign = 1U << 1,
259 SpaceSign = 1U << 2,
260 Alternate = 1U << 3,
261 ZeroPad = 1U << 4,
262 UpperCase = 1U << 5,
263 CenterAlign = 1U << 6,
264};
265
288enum class FormatOp : uint8_t
289{
290 TextInline = 0x01,
291 TextRef = 0x02,
292 TextSpace = 0x03,
293 U32Dec = 0x10,
294 U32ZeroPadWidth = 0x11,
296 I32Dec = 0x12,
297 U32Binary = 0x13,
298 U32Octal = 0x14,
299 U32HexLower =
300 0x15,
301 U32HexUpper =
302 0x16,
303 StringRaw = 0x20,
304 CharacterRaw = 0x21,
305 GenericField = 0xF0,
307 End = 0xFF,
308};
309
314[[nodiscard]] constexpr size_t FormatOpPayloadBytes(FormatOp op)
315{
316 switch (op)
317 {
318 case FormatOp::TextInline:
319 return 0;
320 case FormatOp::TextRef:
321 return 2 * sizeof(uint16_t);
322 case FormatOp::U32ZeroPadWidth:
323 return 1;
324 case FormatOp::GenericField:
325 return 5;
326 case FormatOp::TextSpace:
327 case FormatOp::U32Dec:
328 case FormatOp::I32Dec:
329 case FormatOp::U32Binary:
330 case FormatOp::U32Octal:
331 case FormatOp::U32HexLower:
332 case FormatOp::U32HexUpper:
333 case FormatOp::StringRaw:
334 case FormatOp::CharacterRaw:
335 case FormatOp::End:
336 return 0;
337 }
338
339 // Unreachable for valid streams: every FormatOp value is enumerated above.
340 // A corrupt/unknown opcode falls through here and yields 0 payload bytes.
341 return 0;
342}
343
348enum class FormatType : uint8_t
349{
350 End,
352 TextInline,
353 TextRef,
354 TextSpace,
355 Signed32,
357 Signed64,
359 Unsigned32,
361 Unsigned64,
363 Binary32,
364 Binary64,
365 Octal32,
366 Octal64,
367 HexLower32,
369 HexLower64,
371 HexUpper32,
373 HexUpper64,
375 Pointer,
376 Character,
377 String,
378 FloatFixed,
379 FloatScientific,
380 FloatGeneral,
381 DoubleFixed,
382 DoubleScientific,
383 DoubleGeneral,
384 LongDoubleFixed,
385 LongDoubleScientific,
387 LongDoubleGeneral,
388};
389
397enum class FormatPackKind : uint8_t
398{
399 U32,
400 U64,
401 I32,
402 I64,
403 Pointer,
404 Character,
405 StringView,
406 F32,
407 F64,
408 LongDouble,
409};
410
421enum class FormatProfile : uint32_t
422{
423 None = 0,
424 NarrowInt = 1U << 0,
425 TextArg = 1U << 1,
426 GenericSigned32 = 1U << 2,
427 GenericSigned64 = 1U << 3,
428 GenericUnsigned32 =
429 1U << 4,
430 GenericUnsigned64 =
431 1U << 5,
432 GenericBinary32 = 1U << 6,
433 GenericBinary64 = 1U << 7,
434 GenericOctal32 = 1U << 8,
435 GenericOctal64 = 1U << 9,
436 GenericHexLower32 =
437 1U << 10,
438 GenericHexLower64 =
439 1U << 11,
440 GenericHexUpper32 =
441 1U << 12,
442 GenericHexUpper64 =
443 1U << 13,
444 GenericPointer = 1U << 14,
445 GenericCharacter = 1U << 15,
446 GenericString = 1U << 16,
447 GenericFloatFixed = 1U << 17,
448 GenericFloatScientific =
449 1U << 18,
450 GenericFloatGeneral = 1U << 19,
451 GenericDoubleFixed = 1U << 20,
452 GenericDoubleScientific =
453 1U << 21,
454 GenericDoubleGeneral = 1U << 22,
455 GenericLongDoubleFixed =
456 1U << 23,
457 GenericLongDoubleScientific =
458 1U << 24,
459 GenericLongDoubleGeneral =
460 1U << 25,
461 Generic = 0x03FFFFFCU,
463};
464
471[[nodiscard]] constexpr FormatProfile operator|(FormatProfile left, FormatProfile right)
472{
473 return static_cast<FormatProfile>(static_cast<uint32_t>(left) |
474 static_cast<uint32_t>(right));
475}
476
483constexpr FormatProfile& operator|=(FormatProfile& left, FormatProfile right)
484{
485 left = left | right;
486 return left;
487}
488
496[[nodiscard]] constexpr bool HasProfile(FormatProfile profile, FormatProfile bit)
497{
498 return (static_cast<uint32_t>(profile) & static_cast<uint32_t>(bit)) != 0;
499}
500
508[[nodiscard]] constexpr FormatProfile GenericProfileFor(FormatType type)
509{
510 auto value = static_cast<uint8_t>(type);
511 auto first = static_cast<uint8_t>(FormatType::Signed32);
512 auto last = static_cast<uint8_t>(FormatType::LongDoubleGeneral);
513 if (value < first || value > last)
514 {
515 return FormatProfile::None;
516 }
517 return static_cast<FormatProfile>(uint32_t{1} << (2U + value - first));
518}
519
520static_assert(GenericProfileFor(FormatType::Signed32) == FormatProfile::GenericSigned32);
521static_assert(GenericProfileFor(FormatType::LongDoubleGeneral) ==
522 FormatProfile::GenericLongDoubleGeneral);
523static_assert(GenericProfileFor(FormatType::TextSpace) == FormatProfile::None);
524static_assert(static_cast<uint32_t>(FormatProfile::Generic) ==
525 ((uint32_t{1} << 26U) - (uint32_t{1} << 2U)));
526
554{
555 FormatPackKind pack{};
556 FormatArgumentRule rule =
557 FormatArgumentRule::None;
558};
559static_assert(sizeof(FormatArgumentInfo) == 2,
560 "LibXR::Print::FormatArgumentInfo must stay tightly packed");
561
578{
579 FormatType type = FormatType::End;
580 FormatPackKind pack{};
581 FormatArgumentRule rule =
582 FormatArgumentRule::None;
583 uint8_t flags = 0;
584 char fill = ' ';
585 uint8_t width = 0;
586 uint8_t precision = 0xFF;
587};
588
599[[nodiscard]] constexpr size_t FormatArgumentBytes(FormatPackKind pack)
600{
601 switch (pack)
602 {
603 case FormatPackKind::I32:
604 return sizeof(int32_t);
605 case FormatPackKind::I64:
606 return sizeof(int64_t);
607 case FormatPackKind::U32:
608 return sizeof(uint32_t);
609 case FormatPackKind::U64:
610 return sizeof(uint64_t);
611 case FormatPackKind::Pointer:
612 return sizeof(uintptr_t);
613 case FormatPackKind::Character:
614 return sizeof(char);
615 case FormatPackKind::StringView:
616 return sizeof(std::string_view);
617 case FormatPackKind::F32:
618 return sizeof(float);
619 case FormatPackKind::F64:
620 return sizeof(double);
621 case FormatPackKind::LongDouble:
622 return sizeof(long double);
623 }
624
625 return 0;
626}
627
628} // namespace LibXR::Print
Writer 消费的编译格式运行期协议。 / Compiled-format runtime contract consumed by Writer.
FormatArgumentRule rule
compile-time argument rule / 编译期实参匹配规则
FormatPackKind pack
packed runtime storage kind / 运行期打包存储类别
一条已经决定完毕、运行期 writer 知道如何打印的值字段。 / One fully-decided value field that the runtime writer knows how to ...
uint8_t flags
FormatFlag bitset / 字段修饰位集合
FormatArgumentRule rule
compile-time argument rule / 编译期实参匹配规则
FormatType type
semantic render category / 语义写出类别
FormatPackKind pack
packed runtime storage kind / 运行期打包存储类别
char fill
field fill character / 字段填充字符
uint8_t precision
parsed precision, or unspecified / 已解析精度,或未指定
uint8_t width
parsed field width / 已解析的字段宽度