81 {
82 #if !FASTLED_ENABLE_JSON
84 #else
85
86 FLArduinoJson::JsonDocument doc;
87
88 FLArduinoJson::DeserializationError error = FLArduinoJson::deserializeJson(doc, txt.
c_str());
89
90 if (error) {
91 FL_WARN(
"JSON parsing failed: " << error.c_str());
93 }
94
95
96 struct Converter {
97 static fl::shared_ptr<JsonValue> convert(const FLArduinoJson::JsonVariantConst& src) {
98 if (src.isNull()) {
100 } else if (src.is<bool>()) {
102 } else if (src.is<int64_t>()) {
103
105 } else if (src.is<int32_t>()) {
106
108 } else if (src.is<uint32_t>()) {
109
111 } else if (src.is<double>()) {
112
114 } else if (src.is<float>()) {
115
117 } else if (src.is<const char*>()) {
119 } else if (src.is<FLArduinoJson::JsonArrayConst>()) {
120 FLArduinoJson::JsonArrayConst arr = src.as<FLArduinoJson::JsonArrayConst>();
121
122
123 if (arr.size() == 0) {
125 }
126
127
128 enum ArrayType {
129 ALL_UINT8,
130 ALL_INT16,
131 ALL_FLOATS,
132 GENERIC_ARRAY
133 };
134
135
136 struct ArrayTypeInfo {
137 bool isUint8 = true;
138 bool isInt16 = true;
139 bool isFloat = true;
140
141 void disableAll() {
142 isUint8 = false;
143 isInt16 = false;
144 isFloat = false;
145 }
146
147 void checkNumericValue(double val) {
148
149 bool isInteger = val ==
floor(val);
150 if (!isInteger || val < 0 || val >
UINT8_MAX) {
151 isUint8 = false;
152 }
153 if (!isInteger || val < INT16_MIN || val >
INT16_MAX) {
154 isInt16 = false;
155 }
156 if (!canBeRepresentedAsFloat(val)) {
157 isFloat = false;
158 }
159 }
160
161 void checkIntegerValue(int64_t val) {
162
164 isUint8 = false;
165 }
166 if (val < INT16_MIN || val >
INT16_MAX) {
167 isInt16 = false;
168 }
169 if (val < -16777216 || val > 16777216) {
170 isFloat = false;
171 }
172 }
173
174 ArrayType getBestType() const {
175 if (isUint8) return ALL_UINT8;
176 if (isInt16) return ALL_INT16;
177 if (isFloat) return ALL_FLOATS;
178 return GENERIC_ARRAY;
179 }
180 };
181
182 ArrayTypeInfo typeInfo;
183
184 #if FASTLED_DEBUG_LEVEL >= 2
185 FASTLED_WARN(
"Array conversion: processing " << arr.size() <<
" items");
186 #endif
187
188 for (const auto& item : arr) {
189
190 if (!item.is<int32_t>() && !item.is<int64_t>() && !item.is<double>()) {
191 typeInfo.disableAll();
192 #if FASTLED_DEBUG_LEVEL >= 2
193 FASTLED_WARN(
"Non-numeric value found, no optimization possible");
194 #endif
195 break;
196 }
197
198
199 if (item.is<double>()) {
200 double val = item.as<double>();
201 typeInfo.checkNumericValue(val);
202 } else {
203 int64_t val = item.is<int32_t>() ? item.as<int32_t>() : item.as<int64_t>();
204 typeInfo.checkIntegerValue(val);
205 }
206 }
207
208
209 ArrayType arrayType = arr.size() > 0 ? typeInfo.getBestType() : GENERIC_ARRAY;
210
211
212 switch (arrayType) {
213 case ALL_UINT8: {
214
216 for (const auto& item : arr) {
217 if (item.is<double>()) {
218 byteData.
push_back(
static_cast<uint8_t
>(item.as<
double>()));
219 } else {
220 int64_t val = item.is<int32_t>() ? item.as<int32_t>() : item.as<int64_t>();
221 byteData.
push_back(
static_cast<uint8_t
>(val));
222 }
223 }
225 }
226 case ALL_INT16: {
227
229 for (const auto& item : arr) {
230 if (item.is<double>()) {
231 intData.
push_back(
static_cast<int16_t
>(item.as<
double>()));
232 } else {
233 int64_t val = item.is<int32_t>() ? item.as<int32_t>() : item.as<int64_t>();
234 intData.
push_back(
static_cast<int16_t
>(val));
235 }
236 }
238 }
239 case ALL_FLOATS: {
240
242 for (const auto& item : arr) {
243 if (item.is<double>()) {
244 floatData.
push_back(
static_cast<float>(item.as<
double>()));
245 } else {
246 int64_t val = item.is<int32_t>() ? item.as<int32_t>() : item.as<int64_t>();
247 floatData.
push_back(
static_cast<float>(val));
248 }
249 }
251 }
252 case GENERIC_ARRAY:
253 default: {
254
256 for (const auto& item : arr) {
257 regularArr.push_back(convert(item));
258 }
260 }
261 }
262 } else if (src.is<FLArduinoJson::JsonObjectConst>()) {
264 for (const auto& kv : src.as<FLArduinoJson::JsonObjectConst>()) {
265 obj[fl::string(kv.key().c_str())] = convert(kv.value());
266 }
268 }
270 }
271 };
272
273 return Converter::convert(doc.as<FLArduinoJson::JsonVariantConst>());
274 #endif
275}
void push_back(const T &value)
const char * c_str() const
constexpr remove_reference< T >::type && move(T &&t) noexcept
shared_ptr< T > make_shared(Args &&... args)
fl::HashMap< fl::string, fl::shared_ptr< JsonValue > > JsonObject
fl::vector< fl::shared_ptr< JsonValue > > JsonArray
HeapVector< T, Allocator > vector