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