libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
writer_integer.hpp
1#pragma once
2
8template <std::unsigned_integral UInt, uint8_t Base>
9consteval size_t Writer::UnsignedDigitCapacity()
10{
11 static_assert(Base == 2 || Base == 8 || Base == 10 || Base == 16,
12 "LibXR::Print::Writer only supports base 2, 8, 10, and 16");
13
14 UInt value = std::numeric_limits<UInt>::max();
15 size_t digits = 1;
16 while (value >= static_cast<UInt>(Base))
17 {
18 value /= static_cast<UInt>(Base);
19 ++digits;
20 }
21 return digits;
22}
23
36template <uint8_t Base, bool UpperCase, size_t N, std::unsigned_integral UInt>
37size_t Writer::AppendUnsigned(char (&out)[N], UInt value)
38{
39 constexpr char lower_digits[] = "0123456789abcdef";
40 constexpr char upper_digits[] = "0123456789ABCDEF";
41 static_assert(
42 N >= UnsignedDigitCapacity<UInt, Base>(),
43 "LibXR::Print::Writer digit buffer is too small for the selected integer type");
44
45 const char* digits = UpperCase ? upper_digits : lower_digits;
46 char reverse[UnsignedDigitCapacity<UInt, Base>()];
47 size_t count = 0;
48
49 if (value == 0)
50 {
51 out[0] = '0';
52 return 1;
53 }
54
55 while (value != 0)
56 {
57 reverse[count++] = digits[static_cast<size_t>(value % static_cast<UInt>(Base))];
58 value /= static_cast<UInt>(Base);
59 }
60
61 for (size_t i = 0; i < count; ++i)
62 {
63 out[i] = reverse[count - i - 1];
64 }
65
66 return count;
67}
68
75template <size_t N>
76inline size_t Writer::AppendSmallUnsigned(char (&out)[N], uint8_t value)
77{
78 return AppendUnsigned<10>(out, value);
79}
80
88constexpr size_t Writer::FieldPadding(uint8_t width, size_t payload_size)
89{
90 return (width > payload_size) ? static_cast<size_t>(width) - payload_size : 0;
91}
92
100constexpr size_t Writer::IntegerPrecisionZeros(const Spec& spec, size_t digit_count)
101{
102 return (spec.HasPrecision() && spec.precision > digit_count)
103 ? static_cast<size_t>(spec.precision) - digit_count
104 : 0;
105}
106
116template <std::unsigned_integral UInt>
117constexpr std::string_view Writer::IntegerPrefix(FormatType type, const Spec& spec,
118 UInt value)
119{
120 if (!spec.Alternate() || value == 0)
121 {
122 return {};
123 }
124 if (type == FormatType::HexLower32 || type == FormatType::HexLower64)
125 {
126 return "0x";
127 }
128 if (type == FormatType::HexUpper32 || type == FormatType::HexUpper64)
129 {
130 return "0X";
131 }
132 if (type == FormatType::Binary32 || type == FormatType::Binary64)
133 {
134 return spec.UpperCase() ? "0B" : "0b";
135 }
136 return {};
137}
138
149template <std::unsigned_integral UInt>
150size_t Writer::ApplyAlternateOctal(char* digits, size_t digit_count, const Spec& spec,
151 UInt value)
152{
153 if (!spec.Alternate())
154 {
155 return (value == 0 && spec.precision == 0) ? 0 : digit_count;
156 }
157
158 if (value == 0 && spec.precision == 0)
159 {
160 return 1;
161 }
162
163 if (value == 0)
164 {
165 return digit_count;
166 }
167
168 if (spec.HasPrecision() && spec.precision > digit_count)
169 {
170 return digit_count;
171 }
172
173 for (size_t i = digit_count; i > 0; --i)
174 {
175 digits[i] = digits[i - 1];
176 }
177 digits[0] = '0';
178 digit_count++;
179 return digit_count;
180}