libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
writer_float_general.hpp
1#pragma once
2
21template <typename Float>
22bool Writer::FormatScientificText(Float value, uint8_t precision, bool alternate,
23 bool upper_case, char* out, size_t& out_size)
24{
25 auto rounded = RoundScientificDigits(value, precision);
26 Float rounded_digits = rounded.digits;
27 Float digit_scale = rounded.scale;
28
29 out_size = 0;
30 if (!AppendBufferChar(
31 out, float_buffer_capacity, out_size,
32 static_cast<char>('0' + ExtractDigit(rounded_digits, digit_scale))))
33 {
34 return false;
35 }
36
37 if (precision != 0 || alternate)
38 {
39 if (!AppendBufferChar(out, float_buffer_capacity, out_size, '.'))
40 {
41 return false;
42 }
43 }
44
45 digit_scale /= 10;
46 for (uint8_t i = 0; i < precision; ++i)
47 {
48 if (!AppendBufferChar(
49 out, float_buffer_capacity, out_size,
50 static_cast<char>('0' + ExtractDigit(rounded_digits, digit_scale))))
51 {
52 return false;
53 }
54 digit_scale /= 10;
55 }
56
57 return AppendExponentText(out, out_size, rounded.exponent, upper_case);
58}
59
72template <typename Float>
73bool Writer::FormatFloatText(FormatType type, const Spec& spec, Float value, char* out,
74 size_t& out_size)
75{
76 out_size = 0;
77
78 if (std::isnan(value))
79 {
80 return AppendBufferText(out, float_buffer_capacity, out_size,
81 spec.UpperCase() ? "NAN" : "nan");
82 }
83 if (std::isinf(value))
84 {
85 return AppendBufferText(out, float_buffer_capacity, out_size,
86 spec.UpperCase() ? "INF" : "inf");
87 }
88
89 uint8_t precision = spec.HasPrecision() ? spec.precision : DefaultFloatPrecision();
90 switch (type)
91 {
92 case FormatType::FloatFixed:
93 case FormatType::DoubleFixed:
94 case FormatType::LongDoubleFixed:
95 if (ExceedsFixedIntegerDigits(value, precision))
96 {
97 return false;
98 }
99 return FormatFixedText(value, precision, spec.Alternate(), out, out_size);
100 case FormatType::FloatScientific:
101 case FormatType::DoubleScientific:
102 case FormatType::LongDoubleScientific:
103 return FormatScientificText(value, precision, spec.Alternate(), spec.UpperCase(),
104 out, out_size);
105 case FormatType::FloatGeneral:
106 case FormatType::DoubleGeneral:
107 case FormatType::LongDoubleGeneral:
108 {
109 uint8_t significant = precision == 0 ? 1 : precision;
110 // TODO(perf): RoundScientificDigits is called here only to read .exponent,
111 // and then called again inside FormatScientificText. A future refactor can
112 // add an overload that accepts a pre-computed ScientificDigits to avoid
113 // the redundant calculation.
114 int exponent =
115 RoundScientificDigits(value, static_cast<uint8_t>(significant - 1)).exponent;
116 if (exponent < -4 || exponent >= significant)
117 {
118 if (!FormatScientificText(value, static_cast<uint8_t>(significant - 1),
119 spec.Alternate(), spec.UpperCase(), out, out_size))
120 {
121 return false;
122 }
123 }
124 else
125 {
126 int fractional_precision = static_cast<int>(significant) - (exponent + 1);
127 if (fractional_precision < 0)
128 {
129 fractional_precision = 0;
130 }
131 if (ExceedsFixedIntegerDigits(value, static_cast<uint8_t>(fractional_precision)))
132 {
133 return false;
134 }
135 if (!FormatFixedText(value, static_cast<uint8_t>(fractional_precision),
136 spec.Alternate(), out, out_size))
137 {
138 return false;
139 }
140 }
141
142 if (!spec.Alternate())
143 {
144 out_size = TrimGeneralText(out, out_size);
145 }
146 return true;
147 }
148 default:
149 return false;
150 }
151}