FastLED 3.10.6
Loading...
Searching...
No Matches
json_dispatch.cpp.hpp
Go to the documentation of this file.
1// IWYU pragma: private, include "fl/remote/rpc/json_dispatch.h"
2//
3// json_dispatch: implementation of the non-template JSON-to-primitive
4// conversion cores. See `json_dispatch.h` for design rationale
5// (FastLED #3247 / #3244 Tier 2E Phase 2).
6
8#include "fl/stl/json/types.h"
9#include "fl/stl/string.h"
10#include "fl/stl/cstdlib.h" // fl::strtol
11#include "fl/system/sketch_macros.h" // FL_PLATFORM_HAS_LARGE_MEMORY
12
13namespace fl {
14namespace detail {
15
18 fl::i64* out_value) FL_NO_EXCEPT {
20 if (auto* p = val.data.template ptr<i64>()) {
21 *out_value = *p;
22 return result;
23 }
24 if (auto* p = val.data.template ptr<bool>()) {
25 *out_value = *p ? 1 : 0;
26 result.addWarning(fl::string("bool converted to int ") + fl::to_string(*out_value));
27 return result;
28 }
29 if (auto* p = val.data.template ptr<float>()) {
30#if FL_PLATFORM_HAS_LARGE_MEMORY
31 *out_value = static_cast<i64>(*p);
32 if (*p != static_cast<float>(*out_value)) {
33 result.addWarning(fl::string("float ") + fl::to_string(*p, 6) +
34 " truncated to int " + fl::to_string(*out_value));
35 }
36#else
37 (void)p;
38 *out_value = 0;
39 result.setError("float -> int not supported on Low-memory");
40#endif
41 return result;
42 }
43 if (auto* p = val.data.template ptr<fl::string>()) {
44 char* end = nullptr;
45 long parsed = fl::strtol(p->c_str(), &end, 10);
46 if (end != p->c_str() && *end == '\0') {
47 *out_value = static_cast<i64>(parsed);
48 result.addWarning(fl::string("string '") + *p + "' parsed to int " + fl::to_string(*out_value));
49 } else {
50 result.setError(fl::string("cannot parse string '") + *p + "' as integer");
51 }
52 return result;
53 }
54 if (val.data.template ptr<fl::nullptr_t>()) {
55 result.setError("cannot convert null to integer");
56 return result;
57 }
58 // Any remaining alternative (json_object, json_array, vector<i16>,
59 // vector<u8>, vector<float>) -- all are "container" types that don't
60 // convert cleanly to an integer.
61 result.setError("cannot convert array or object to integer");
62 *out_value = 0;
63 return result;
64}
65
68 bool* out_value) FL_NO_EXCEPT {
70 if (auto* p = val.data.template ptr<bool>()) {
71 *out_value = *p;
72 return result;
73 }
74 if (auto* p = val.data.template ptr<i64>()) {
75 *out_value = (*p != 0);
76 result.addWarning(fl::string("int ") + fl::to_string(*p) +
77 " converted to bool " + (*out_value ? "true" : "false"));
78 return result;
79 }
80 if (auto* p = val.data.template ptr<float>()) {
81#if FL_PLATFORM_HAS_LARGE_MEMORY
82 *out_value = (*p != 0.0f);
83 result.addWarning(fl::string("float ") + fl::to_string(*p, 6) +
84 " converted to bool " + (*out_value ? "true" : "false"));
85#else
86 (void)p;
87 *out_value = false;
88 result.setError("float -> bool not supported on Low-memory");
89#endif
90 return result;
91 }
92 if (auto* p = val.data.template ptr<fl::string>()) {
93 if (*p == "true" || *p == "1" || *p == "yes") {
94 *out_value = true;
95 result.addWarning(fl::string("string '") + *p + "' parsed as bool true");
96 } else if (*p == "false" || *p == "0" || *p == "no") {
97 *out_value = false;
98 result.addWarning(fl::string("string '") + *p + "' parsed as bool false");
99 } else {
100 result.setError(fl::string("cannot parse string '") + *p + "' as bool");
101 *out_value = false;
102 }
103 return result;
104 }
105 if (val.data.template ptr<fl::nullptr_t>()) {
106 result.setError("cannot convert null to bool");
107 *out_value = false;
108 return result;
109 }
110 result.setError("cannot convert array or object to bool");
111 *out_value = false;
112 return result;
113}
114
117 float* out_value) FL_NO_EXCEPT {
119 if (auto* p = val.data.template ptr<float>()) {
120 *out_value = *p;
121 return result;
122 }
123 if (auto* p = val.data.template ptr<i64>()) {
124#if FL_PLATFORM_HAS_LARGE_MEMORY
125 *out_value = static_cast<float>(*p);
126 if (sizeof(float) < 8 && (*p > 16777216 || *p < -16777216)) {
127 result.addWarning(fl::string("large int ") + fl::to_string(*p) +
128 " may lose precision as float");
129 }
130#else
131 // Avoid __aeabi_l2f via i32 route (same trick as #3076).
132 if (*p > 2147483647LL) {
133 *out_value = static_cast<float>(2147483647);
134 } else if (*p < -2147483648LL) {
135 *out_value = static_cast<float>(-2147483648);
136 } else {
137 *out_value = static_cast<float>(static_cast<fl::i32>(*p));
138 }
139#endif
140 return result;
141 }
142 if (auto* p = val.data.template ptr<bool>()) {
143 *out_value = *p ? 1.0f : 0.0f;
144 result.addWarning(fl::string("bool converted to float ") +
145 (*p ? "1.0" : "0.0"));
146 return result;
147 }
148 if (auto* p = val.data.template ptr<fl::string>()) {
149#if FL_PLATFORM_HAS_LARGE_MEMORY
150 char* end = nullptr;
151 double parsed = fl::strtod(p->c_str(), &end);
152 if (end != p->c_str() && *end == '\0') {
153 *out_value = static_cast<float>(parsed);
154 result.addWarning(fl::string("string '") + *p + "' parsed to float");
155 } else {
156 result.setError(fl::string("cannot parse string '") + *p + "' as float");
157 *out_value = 0.0f;
158 }
159#else
160 (void)p;
161 *out_value = 0.0f;
162 result.setError("string -> float not supported on Low-memory");
163#endif
164 return result;
165 }
166 if (val.data.template ptr<fl::nullptr_t>()) {
167 result.setError("cannot convert null to float");
168 *out_value = 0.0f;
169 return result;
170 }
171 result.setError("cannot convert array or object to float");
172 *out_value = 0.0f;
173 return result;
174}
175
178 fl::string* out_value) FL_NO_EXCEPT {
180 if (auto* p = val.data.template ptr<fl::string>()) {
181 *out_value = *p;
182 return result;
183 }
184 if (auto* p = val.data.template ptr<i64>()) {
185 *out_value = fl::to_string(*p);
186 result.addWarning(fl::string("int ") + *out_value + " converted to string");
187 return result;
188 }
189 if (auto* p = val.data.template ptr<float>()) {
190#if FL_PLATFORM_HAS_LARGE_MEMORY
191 *out_value = fl::to_string(*p, 6);
192 result.addWarning(fl::string("float ") + *out_value + " converted to string");
193#else
194 (void)p;
195 *out_value = "0";
196 result.setError("float -> string not supported on Low-memory");
197#endif
198 return result;
199 }
200 if (auto* p = val.data.template ptr<bool>()) {
201 *out_value = *p ? "true" : "false";
202 result.addWarning(fl::string("bool converted to string '") + *out_value + "'");
203 return result;
204 }
205 if (val.data.template ptr<fl::nullptr_t>()) {
206 *out_value = "null";
207 result.addWarning("null converted to string 'null'");
208 return result;
209 }
210 result.setError("cannot convert array or object to string");
211 out_value->clear();
212 return result;
213}
214
215} // namespace detail
216} // namespace fl
#define FL_NO_INLINE
FL_NO_INLINE TypeConversionResult json_convert_to_i64_core(const json_value &val, fl::i64 *out_value) FL_NO_EXCEPT
FL_NO_INLINE TypeConversionResult json_convert_to_float_core(const json_value &val, float *out_value) FL_NO_EXCEPT
FL_NO_INLINE TypeConversionResult json_convert_to_bool_core(const json_value &val, bool *out_value) FL_NO_EXCEPT
FL_NO_INLINE TypeConversionResult json_convert_to_string_core(const json_value &val, fl::string *out_value) FL_NO_EXCEPT
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_info.h:57
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
constexpr T * end(T(&array)[N]) FL_NO_EXCEPT
string to_string(T value) FL_NO_EXCEPT
Definition string.h:459
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
fl::i64 i64
Definition stdint.h:221