libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
writer_integer.hpp
1#pragma once
2
7template <std::unsigned_integral UInt, uint8_t Base>
8consteval size_t Writer::UnsignedDigitCapacity()
9{
10 static_assert(Base == 2 || Base == 8 || Base == 10 || Base == 16,
11 "LibXR::Print::Writer only supports base 2, 8, 10, and 16");
12
13 UInt value = std::numeric_limits<UInt>::max();
14 size_t digits = 1;
15 while (value >= static_cast<UInt>(Base))
16 {
17 value /= static_cast<UInt>(Base);
18 ++digits;
19 }
20 return digits;
21}
22
33template <uint8_t Base, bool UpperCase, size_t N, std::unsigned_integral UInt>
34size_t Writer::AppendUnsigned(char (&out)[N], UInt value)
35{
36 constexpr char lower_digits[] = "0123456789abcdef";
37 constexpr char upper_digits[] = "0123456789ABCDEF";
38 static_assert(N >= UnsignedDigitCapacity<UInt, Base>(),
39 "LibXR::Print::Writer digit buffer is too small for the selected integer type");
40
41 const char* digits = UpperCase ? upper_digits : lower_digits;
42 char reverse[UnsignedDigitCapacity<UInt, Base>()];
43 size_t count = 0;
44
45 if (value == 0)
46 {
47 out[0] = '0';
48 return 1;
49 }
50
51 while (value != 0)
52 {
53 reverse[count++] = digits[static_cast<size_t>(value % static_cast<UInt>(Base))];
54 value /= static_cast<UInt>(Base);
55 }
56
57 for (size_t i = 0; i < count; ++i)
58 {
59 out[i] = reverse[count - i - 1];
60 }
61
62 return count;
63}
64
71template <size_t N>
72inline size_t Writer::AppendSmallUnsigned(char (&out)[N], uint8_t value)
73{
74 return AppendUnsigned<10>(out, value);
75}
76
83constexpr size_t Writer::FieldPadding(uint8_t width, size_t payload_size)
84{
85 return (width > payload_size) ? static_cast<size_t>(width) - payload_size : 0;
86}
87
94constexpr size_t Writer::IntegerPrecisionZeros(const Spec& spec, size_t digit_count)
95{
96 return (spec.HasPrecision() && spec.precision > digit_count)
97 ? static_cast<size_t>(spec.precision) - digit_count
98 : 0;
99}
100
109template <std::unsigned_integral UInt>
110constexpr std::string_view Writer::IntegerPrefix(FormatType type, const Spec& spec,
111 UInt value)
112{
113 if (!spec.Alternate() || value == 0)
114 {
115 return {};
116 }
117 if (type == FormatType::HexLower32 || type == FormatType::HexLower64)
118 {
119 return "0x";
120 }
121 if (type == FormatType::HexUpper32 || type == FormatType::HexUpper64)
122 {
123 return "0X";
124 }
125 if (type == FormatType::Binary32 || type == FormatType::Binary64)
126 {
127 return spec.UpperCase() ? "0B" : "0b";
128 }
129 return {};
130}
131
141template <std::unsigned_integral UInt>
142size_t Writer::ApplyAlternateOctal(char* digits, size_t digit_count, const Spec& spec,
143 UInt value)
144{
145 if (!spec.Alternate())
146 {
147 return (value == 0 && spec.precision == 0) ? 0 : digit_count;
148 }
149
150 if (value == 0 && spec.precision == 0)
151 {
152 return 1;
153 }
154
155 if (value == 0)
156 {
157 return digit_count;
158 }
159
160 if (spec.HasPrecision() && spec.precision > digit_count)
161 {
162 return digit_count;
163 }
164
165 digits[digit_count++] = '0';
166 for (size_t i = digit_count - 1; i > 0; --i)
167 {
168 digits[i] = digits[i - 1];
169 }
170 digits[0] = '0';
171 return digit_count;
172}