libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
printf_frontend_parse_util.hpp
1#pragma once
2
6struct IndexingState
7{
8 bool uses_positional = false;
9 bool uses_sequential = false;
10 size_t next_index = 0;
11};
12
18[[nodiscard]] constexpr bool IsDigit(char ch)
19{
20 return ch >= '0' && ch <= '9';
21}
22
28[[nodiscard]] constexpr bool HasEmbeddedNul(std::string_view source)
29{
30 for (char ch : source)
31 {
32 if (ch == '\0')
33 {
34 return true;
35 }
36 }
37 return false;
38}
39
53[[nodiscard]] consteval Error ParseArgumentIndex(std::string_view source, size_t& pos,
54 IndexingState& indexing,
55 Conversion& conversion)
56{
57 if (pos >= source.size() || !IsDigit(source[pos]))
58 {
59 return Error::None;
60 }
61
62 size_t probe = pos;
63 size_t index = 0;
64 while (probe < source.size() && IsDigit(source[probe]))
65 {
66 auto digit = static_cast<size_t>(source[probe] - '0');
67 if (index > (std::numeric_limits<size_t>::max() - digit) / 10)
68 {
69 return Error::NumberOverflow;
70 }
71
72 index = index * 10 + digit;
73 ++probe;
74 }
75
76 if (probe >= source.size() || source[probe] != '$')
77 {
78 return Error::None;
79 }
80
81 if (!Config::enable_explicit_argument_indexing)
82 {
83 return Error::PositionalArgumentDisabled;
84 }
85
86 if (index == 0)
87 {
88 return Error::InvalidArgumentIndex;
89 }
90 if (indexing.uses_sequential)
91 {
92 return Error::MixedIndexing;
93 }
94
95 indexing.uses_positional = true;
96 conversion.positional = true;
97 conversion.arg_index = index - 1;
98 pos = probe + 1;
99 return Error::None;
100}
101
110[[nodiscard]] consteval Error ParseByte(std::string_view source, size_t& pos,
111 uint8_t limit, uint8_t& value)
112{
113 value = 0;
114 if (pos >= source.size() || !IsDigit(source[pos]))
115 {
116 return Error::None;
117 }
118
119 while (pos < source.size() && IsDigit(source[pos]))
120 {
121 auto digit = static_cast<uint8_t>(source[pos] - '0');
122 if (value > static_cast<uint8_t>((limit - digit) / 10))
123 {
124 return Error::NumberOverflow;
125 }
126
127 value = static_cast<uint8_t>(value * 10 + digit);
128 ++pos;
129 }
130
131 return Error::None;
132}
Error
brace 风格 format 前端的编译期失败类别。 / Compile-time failure categories for the brace-style format frontend.
consteval Error ParseByte(std::string_view source, size_t &pos, uint8_t limit, uint8_t &value)
解析一个目标为字节宽度的十进制整数字段片段,并检查是否溢出 / Parse one decimal byte-sized integer fragment with overflow checking
consteval Error ParseArgumentIndex(std::string_view source, size_t &pos, IndexingState &indexing, Conversion &conversion)
解析可选的前导 n$ 位置参数选择器 / Parse the optional leading n$ positional argument selector
单个 printf 转换在降为共享格式前的解析结果 / One parsed printf conversion before lowering into the shared format
bool positional
whether arg_index came from n$ syntax / arg_index 是否来自 n$ 语法
size_t arg_index
source argument index consumed by this field / 当前字段消耗的源参数索引
brace 字段自动索引与手动索引的源级状态 / Source-level indexing mode for automatic versus manual brace fields
bool uses_sequential
at least one conversion used implicit sequential order / 至少有一个转换使用了隐式顺序参数
bool uses_positional
at least one conversion used n$ syntax / 至少有一个转换使用了 n$ 语法
size_t next_index
next sequential argument index / 下一个顺序参数索引