libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
printf_frontend_parse_util.hpp
1#pragma once
2
7struct IndexingState
8{
10 false;
11 bool uses_sequential = false;
13 size_t next_index = 0;
14};
15
23[[nodiscard]] constexpr bool IsDigit(char ch) { return ch >= '0' && ch <= '9'; }
24
32[[nodiscard]] constexpr bool HasEmbeddedNul(std::string_view source)
33{
34 for (char ch : source)
35 {
36 if (ch == '\0')
37 {
38 return true;
39 }
40 }
41 return false;
42}
43
61[[nodiscard]] consteval Error ParseArgumentIndex(std::string_view source, size_t& pos,
62 IndexingState& indexing,
63 Conversion& conversion)
64{
65 if (pos >= source.size() || !IsDigit(source[pos]))
66 {
67 return Error::None;
68 }
69
70 size_t probe = pos;
71 size_t index = 0;
72 while (probe < source.size() && IsDigit(source[probe]))
73 {
74 auto digit = static_cast<size_t>(source[probe] - '0');
75 if (index > (std::numeric_limits<size_t>::max() - digit) / 10)
76 {
77 return Error::NumberOverflow;
78 }
79
80 index = index * 10 + digit;
81 ++probe;
82 }
83
84 if (probe >= source.size() || source[probe] != '$')
85 {
86 return Error::None;
87 }
88
89 if (!Config::enable_explicit_argument_indexing)
90 {
91 return Error::PositionalArgumentDisabled;
92 }
93
94 if (index == 0)
95 {
96 return Error::InvalidArgumentIndex;
97 }
98 if (indexing.uses_sequential)
99 {
100 return Error::MixedIndexing;
101 }
102
103 indexing.uses_positional = true;
104 conversion.positional = true;
105 conversion.arg_index = index - 1;
106 pos = probe + 1;
107 return Error::None;
108}
109
121[[nodiscard]] consteval Error ParseByte(std::string_view source, size_t& pos,
122 uint8_t limit, uint8_t& value)
123{
124 value = 0;
125 if (pos >= source.size() || !IsDigit(source[pos]))
126 {
127 return Error::None;
128 }
129
130 while (pos < source.size() && IsDigit(source[pos]))
131 {
132 auto digit = static_cast<uint8_t>(source[pos] - '0');
133 if (value > static_cast<uint8_t>((limit - digit) / 10))
134 {
135 return Error::NumberOverflow;
136 }
137
138 value = static_cast<uint8_t>(value * 10 + digit);
139 ++pos;
140 }
141
142 return Error::None;
143}
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_positional
at least one conversion used n$ syntax / 至少有一个转换使用了 n$ 语法
size_t next_index
next sequential argument index / 下一个顺序参数索引