libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
printf_frontend_parse_util.hpp
1#pragma once
2
7struct IndexingState
8{
10 false;
11 bool uses_sequential = false;
14 size_t next_index = 0;
15};
16
24[[nodiscard]] constexpr bool IsDigit(char ch) { return ch >= '0' && ch <= '9'; }
25
33[[nodiscard]] constexpr bool HasEmbeddedNul(std::string_view source)
34{
35 for (char ch : source)
36 {
37 if (ch == '\0')
38 {
39 return true;
40 }
41 }
42 return false;
43}
44
62[[nodiscard]] consteval Error ParseArgumentIndex(std::string_view source, size_t& pos,
63 IndexingState& indexing,
64 Conversion& conversion)
65{
66 if (pos >= source.size() || !IsDigit(source[pos]))
67 {
68 return Error::None;
69 }
70
71 size_t probe = pos;
72 size_t index = 0;
73 while (probe < source.size() && IsDigit(source[probe]))
74 {
75 auto digit = static_cast<size_t>(source[probe] - '0');
76 if (index > (std::numeric_limits<size_t>::max() - digit) / 10)
77 {
78 return Error::NumberOverflow;
79 }
80
81 index = index * 10 + digit;
82 ++probe;
83 }
84
85 if (probe >= source.size() || source[probe] != '$')
86 {
87 return Error::None;
88 }
89
90 if (!Config::enable_explicit_argument_indexing)
91 {
92 return Error::PositionalArgumentDisabled;
93 }
94
95 if (index == 0)
96 {
97 return Error::InvalidArgumentIndex;
98 }
99 if (indexing.uses_sequential)
100 {
101 return Error::MixedIndexing;
102 }
103
104 indexing.uses_positional = true;
105 conversion.positional = true;
106 conversion.arg_index = index - 1;
107 pos = probe + 1;
108 return Error::None;
109}
110
122[[nodiscard]] consteval Error ParseByte(std::string_view source, size_t& pos,
123 uint8_t limit, uint8_t& value)
124{
125 value = 0;
126 if (pos >= source.size() || !IsDigit(source[pos]))
127 {
128 return Error::None;
129 }
130
131 while (pos < source.size() && IsDigit(source[pos]))
132 {
133 auto digit = static_cast<uint8_t>(source[pos] - '0');
134 if (value > static_cast<uint8_t>((limit - digit) / 10))
135 {
136 return Error::NumberOverflow;
137 }
138
139 value = static_cast<uint8_t>(value * 10 + digit);
140 ++pos;
141 }
142
143 return Error::None;
144}
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
arg_index 是否来自 n$ 语法 / whether arg_index came from n$ syntax
size_t arg_index
当前字段消耗的源参数索引 / source argument index consumed by this field
brace 字段自动索引与手动索引的源级状态 / Source-level indexing mode for automatic versus manual brace fields
bool uses_positional
至少有一个转换使用了 n$ 语法 / at least one conversion used n$ syntax
size_t next_index
下一个顺序参数索引 / next sequential argument index