FastLED 3.9.15
Loading...
Searching...
No Matches
json_visitors.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/remote/rpc/type_conversion_result.h" // IWYU pragma: keep
4#include "fl/stl/stdint.h" // IWYU pragma: keep
5#include "fl/stl/string.h" // IWYU pragma: keep
6#include "fl/stl/cstdlib.h" // IWYU pragma: keep
7#include "fl/stl/noexcept.h"
8namespace fl {
9namespace detail {
10
11// =============================================================================
12// JsonToIntegerVisitor - Visitor for converting JSON to integer types
13// =============================================================================
14template <typename T>
18
20
21 template<typename U>
22 void accept(const U& value) {
23 (*this)(value);
24 }
25
26 // Exact match: i64
27 void operator()(const i64& raw) {
28 mValue = static_cast<T>(raw);
29 // Check for overflow/truncation
30 if (static_cast<i64>(mValue) != raw) {
31 mResult.addWarning("integer overflow/truncation: " + fl::to_string(raw) +
32 " converted to " + fl::to_string(static_cast<i64>(mValue)));
33 }
34 }
35
36 // Boolean to integer
37 void operator()(const bool& b) {
38 mValue = b ? T(1) : T(0);
39 mResult.addWarning("bool converted to int " + fl::to_string(static_cast<i64>(mValue)));
40 }
41
42 // Float to integer
43 void operator()(const float& raw) {
44 mValue = static_cast<T>(raw);
45 // Keep the precision check in single precision. The natural
46 // formulation `(double)raw != (double)mValue` drags libgcc's
47 // soft-double helpers (`__aeabi_dcmpeq`, `__ledf2`, `__gedf2`,
48 // `__aeabi_d2f`, ...) into the link on no-FPU targets — ~760 B
49 // we can't afford on LPC845 (FastLED #3002).
50 if (raw != static_cast<float>(mValue)) {
51 mResult.addWarning("float " + fl::to_string(raw, 6) +
52 " truncated to int " + fl::to_string(static_cast<i64>(mValue)));
53 }
54 }
55
56 // String to integer
57 void operator()(const fl::string& str) {
58 char* end = nullptr;
59 long parsed = fl::strtol(str.c_str(), &end, 10);
60 if (end != str.c_str() && *end == '\0') {
61 mValue = static_cast<T>(parsed);
62 mResult.addWarning("string '" + str + "' parsed to int " + fl::to_string(static_cast<i64>(mValue)));
63 } else {
64 mResult.setError("cannot parse string '" + str + "' as integer");
65 }
66 }
67
68 // Null
70 mResult.setError("cannot convert null to integer");
71 }
72
73 // Object (json_object)
74 void operator()(const json_object&) {
75 mResult.setError("cannot convert object to integer");
76 }
77
78 // Array (json_array)
79 void operator()(const json_array&) {
80 mResult.setError("cannot convert array to integer");
81 }
82
83 // Specialized arrays
85 mResult.setError("cannot convert array to integer");
86 }
87
89 mResult.setError("cannot convert array to integer");
90 }
91
93 mResult.setError("cannot convert array to integer");
94 }
95};
96
97// =============================================================================
98// JsonToBoolVisitor - Visitor for converting JSON to bool
99// =============================================================================
101 bool mValue;
103
105
106 template<typename U>
107 void accept(const U& value) {
108 (*this)(value);
109 }
110
111 // Exact match: bool
112 void operator()(const bool& b) {
113 mValue = b;
114 }
115
116 // Integer to bool
117 void operator()(const i64& raw) {
118 mValue = raw != 0;
119 mResult.addWarning("int " + fl::to_string(raw) + " converted to bool " + (mValue ? "true" : "false"));
120 }
121
122 // Float to bool
123 void operator()(const float& raw) {
124 mValue = raw != 0.0f;
125 // No double promotion (see JsonToIntVisitor — same #3002 reason).
126 mResult.addWarning("float " + fl::to_string(raw, 6) + " converted to bool " + (mValue ? "true" : "false"));
127 }
128
129 // String to bool
130 void operator()(const fl::string& str) {
131 if (str == "true" || str == "1" || str == "yes") {
132 mValue = true;
133 mResult.addWarning("string '" + str + "' parsed as bool true");
134 } else if (str == "false" || str == "0" || str == "no") {
135 mValue = false;
136 mResult.addWarning("string '" + str + "' parsed as bool false");
137 } else {
138 mResult.setError("cannot parse string '" + str + "' as bool");
139 }
140 }
141
142 // Null
144 mResult.setError("cannot convert null to bool");
145 }
146
147 // Object
148 void operator()(const json_object&) {
149 mResult.setError("cannot convert object to bool");
150 }
151
152 // Array
153 void operator()(const json_array&) {
154 mResult.setError("cannot convert array to bool");
155 }
156
157 // Specialized arrays
159 mResult.setError("cannot convert array to bool");
160 }
161
163 mResult.setError("cannot convert array to bool");
164 }
165
167 mResult.setError("cannot convert array to bool");
168 }
169};
170
171// =============================================================================
172// JsonToFloatVisitor - Visitor for converting JSON to float/double
173// =============================================================================
174template <typename T>
178
180
181 template<typename U>
182 void accept(const U& value) {
183 (*this)(value);
184 }
185
186 // Float to float/double
187 void operator()(const float& raw) {
188 mValue = static_cast<T>(raw);
189 }
190
191 // Integer to float
192 void operator()(const i64& raw) {
193 mValue = static_cast<T>(raw);
194 // Large integers may lose precision when converted to float
195 if (sizeof(T) < 8 && (raw > 16777216 || raw < -16777216)) {
196 mResult.addWarning("large int " + fl::to_string(raw) + " may lose precision as float");
197 }
198 }
199
200 // Bool to float
201 void operator()(const bool& b) {
202 mValue = b ? T(1) : T(0);
203 // Format through float to avoid pulling in double helpers on no-FPU
204 // targets (FastLED #3002). For T = double the round-trip costs one
205 // extra `.0f` digit of formatting precision, which is acceptable.
206 mResult.addWarning("bool converted to float " + fl::to_string(static_cast<float>(mValue), 6));
207 }
208
209 // String to float
210 void operator()(const fl::string& str) {
211 char* end = nullptr;
212 double parsed = fl::strtod(str.c_str(), &end);
213 if (end != str.c_str() && *end == '\0') {
214 mValue = static_cast<T>(parsed);
215 // Warning string uses float precision (see #3002).
216 mResult.addWarning("string '" + str + "' parsed to float " + fl::to_string(static_cast<float>(mValue), 6));
217 } else {
218 mResult.setError("cannot parse string '" + str + "' as float");
219 }
220 }
221
222 // Null
224 mResult.setError("cannot convert null to float");
225 }
226
227 // Object
228 void operator()(const json_object&) {
229 mResult.setError("cannot convert object to float");
230 }
231
232 // Array
233 void operator()(const json_array&) {
234 mResult.setError("cannot convert array to float");
235 }
236
237 // Specialized arrays
239 mResult.setError("cannot convert array to float");
240 }
241
243 mResult.setError("cannot convert array to float");
244 }
245
247 mResult.setError("cannot convert array to float");
248 }
249};
250
251// =============================================================================
252// JsonToStringVisitor - Visitor for converting JSON to string
253// =============================================================================
257
259
260 template<typename U>
261 void accept(const U& value) {
262 (*this)(value);
263 }
264
265 // Exact match: string
266 void operator()(const fl::string& str) {
267 mValue = str;
268 }
269
270 // Integer to string
271 void operator()(const i64& raw) {
272 mValue = fl::to_string(raw);
273 mResult.addWarning("int " + mValue + " converted to string");
274 }
275
276 // Float to string
277 void operator()(const float& raw) {
278 // Format in float (see JsonToIntVisitor — same #3002 reason).
279 mValue = fl::to_string(raw, 6);
280 mResult.addWarning("float " + mValue + " converted to string");
281 }
282
283 // Bool to string
284 void operator()(const bool& b) {
285 mValue = b ? "true" : "false";
286 mResult.addWarning("bool converted to string '" + mValue + "'");
287 }
288
289 // Null to string
291 mValue = "null";
292 mResult.addWarning("null converted to string 'null'");
293 }
294
295 // Object
296 void operator()(const json_object&) {
297 mResult.setError("cannot convert object to string");
298 }
299
300 // Array
301 void operator()(const json_array&) {
302 mResult.setError("cannot convert array to string");
303 }
304
305 // Specialized arrays
307 mResult.setError("cannot convert array to string");
308 }
309
311 mResult.setError("cannot convert array to string");
312 }
313
315 mResult.setError("cannot convert array to string");
316 }
317};
318
319} // namespace detail
320} // namespace fl
const char * c_str() const FL_NOEXCEPT
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_traits.h:48
decltype(nullptr) nullptr_t
Definition s16x16x4.h:13
string to_string(T value) FL_NOEXCEPT
Definition string.h:450
constexpr int type_rank< T >::value
constexpr T * end(T(&array)[N]) FL_NOEXCEPT
fl::i64 i64
Definition s16x16x4.h:222
fl::vector< fl::shared_ptr< json_value > > json_array
Definition types.h:33
fl::flat_map< fl::string, fl::shared_ptr< json_value >, fl::StringFastLess > json_object
Definition types.h:34
double strtod(const char *str, char **endptr)
long strtol(const char *str, char **endptr, int base)
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT
void operator()(const json_array &)
void operator()(const bool &b)
void operator()(const fl::nullptr_t &)
void operator()(const fl::string &str)
void operator()(const json_object &)
void operator()(const fl::vector< float > &)
TypeConversionResult mResult
void operator()(const fl::vector< i16 > &)
void accept(const U &value)
void operator()(const i64 &raw)
void operator()(const float &raw)
void operator()(const fl::vector< u8 > &)
void operator()(const json_array &)
void operator()(const fl::vector< u8 > &)
void operator()(const fl::vector< i16 > &)
void operator()(const fl::string &str)
void operator()(const i64 &raw)
void operator()(const fl::nullptr_t &)
TypeConversionResult mResult
void accept(const U &value)
void operator()(const bool &b)
void operator()(const float &raw)
void operator()(const fl::vector< float > &)
void operator()(const json_object &)
void operator()(const json_object &)
void operator()(const i64 &raw)
void operator()(const fl::vector< i16 > &)
void operator()(const float &raw)
void operator()(const fl::nullptr_t &)
void operator()(const fl::vector< u8 > &)
void operator()(const fl::vector< float > &)
void operator()(const json_array &)
void operator()(const fl::string &str)
void operator()(const fl::vector< u8 > &)
void operator()(const fl::vector< float > &)
void operator()(const i64 &raw)
void operator()(const fl::vector< i16 > &)
void operator()(const json_array &)
void operator()(const fl::nullptr_t &)
void operator()(const float &raw)
void operator()(const json_object &)
void operator()(const fl::string &str)