FastLED 3.9.15
Loading...
Searching...
No Matches

◆ parse()

fl::shared_ptr< JsonValue > fl::JsonValue::parse ( const fl::string & txt)
static

Definition at line 81 of file json.cpp.

81 {
82 #if !FASTLED_ENABLE_JSON
83 return fl::make_shared<JsonValue>(fl::string(txt));
84 #else
85 // Determine the size of the JsonDocument needed.
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());
92 return fl::make_shared<JsonValue>(nullptr); // Return null on error
93 }
94
95 // Helper function to convert FLArduinoJson::JsonVariantConst to fl::Json::JsonValue
96 struct Converter {
97 static fl::shared_ptr<JsonValue> convert(const FLArduinoJson::JsonVariantConst& src) {
98 if (src.isNull()) {
99 return fl::make_shared<JsonValue>(nullptr);
100 } else if (src.is<bool>()) {
101 return fl::make_shared<JsonValue>(src.as<bool>());
102 } else if (src.is<int64_t>()) {
103 // Handle 64-bit integers
104 return fl::make_shared<JsonValue>(src.as<int64_t>());
105 } else if (src.is<int32_t>()) {
106 // Handle 32-bit integers explicitly for platform compatibility
107 return fl::make_shared<JsonValue>(static_cast<int64_t>(src.as<int32_t>()));
108 } else if (src.is<uint32_t>()) {
109 // Handle unsigned 32-bit integers
110 return fl::make_shared<JsonValue>(static_cast<int64_t>(src.as<uint32_t>()));
111 } else if (src.is<double>()) {
112 // Handle double precision floats - convert to float
113 return fl::make_shared<JsonValue>(static_cast<float>(src.as<double>()));
114 } else if (src.is<float>()) {
115 // Handle single precision floats explicitly
116 return fl::make_shared<JsonValue>(src.as<float>());
117 } else if (src.is<const char*>()) {
118 return fl::make_shared<JsonValue>(fl::string(src.as<const char*>()));
119 } else if (src.is<FLArduinoJson::JsonArrayConst>()) {
120 FLArduinoJson::JsonArrayConst arr = src.as<FLArduinoJson::JsonArrayConst>();
121
122 // Empty arrays should remain regular arrays
123 if (arr.size() == 0) {
124 return fl::make_shared<JsonValue>(JsonArray{});
125 }
126
127 // Enum to represent array optimization types
128 enum ArrayType {
129 ALL_UINT8,
130 ALL_INT16,
131 ALL_FLOATS,
132 GENERIC_ARRAY
133 };
134
135 // Helper struct to track array type info
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 // Check integer ranges in one pass
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 // Check all ranges in one pass
163 if (val < 0 || val > UINT8_MAX) {
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 // Check if all items are numeric
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 // Update type flags based on item type
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 // Determine the optimal array type based on the flags
209 ArrayType arrayType = arr.size() > 0 ? typeInfo.getBestType() : GENERIC_ARRAY;
210
211 // Apply the most appropriate optimization based on determined type
212 switch (arrayType) {
213 case ALL_UINT8: {
214 // All values fit in uint8_t - most compact representation
215 fl::vector<uint8_t> byteData;
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 }
224 return fl::make_shared<JsonValue>(fl::move(byteData));
225 }
226 case ALL_INT16: {
227 // All values fit in int16_t - good compression
228 fl::vector<int16_t> intData;
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 }
237 return fl::make_shared<JsonValue>(fl::move(intData));
238 }
239 case ALL_FLOATS: {
240 // All values can be exactly represented as floats - use float vector
241 fl::vector<float> floatData;
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 }
250 return fl::make_shared<JsonValue>(fl::move(floatData));
251 }
252 case GENERIC_ARRAY:
253 default: {
254 // No optimization possible - use regular array
255 JsonArray regularArr;
256 for (const auto& item : arr) {
257 regularArr.push_back(convert(item));
258 }
259 return fl::make_shared<JsonValue>(fl::move(regularArr));
260 }
261 }
262 } else if (src.is<FLArduinoJson::JsonObjectConst>()) {
263 JsonObject obj;
264 for (const auto& kv : src.as<FLArduinoJson::JsonObjectConst>()) {
265 obj[fl::string(kv.key().c_str())] = convert(kv.value());
266 }
268 }
269 return fl::make_shared<JsonValue>(nullptr); // Should not happen
270 }
271 };
272
273 return Converter::convert(doc.as<FLArduinoJson::JsonVariantConst>());
274 #endif
275}
void push_back(const T &value)
Definition vector.h:552
const char * c_str() const
Definition str.h:326
#define INT16_MAX
Definition json.cpp:18
#define UINT8_MAX
Definition json.cpp:22
constexpr remove_reference< T >::type && move(T &&t) noexcept
Definition move.h:27
shared_ptr< T > make_shared(Args &&... args)
Definition shared_ptr.h:348
fl::HashMap< fl::string, fl::shared_ptr< JsonValue > > JsonObject
Definition json.h:171
fl::vector< fl::shared_ptr< JsonValue > > JsonArray
Definition json.h:170
T floor(T value)
Definition math.h:32
HeapVector< T, Allocator > vector
Definition vector.h:1214
#define FASTLED_WARN
Definition warn.h:7
#define FL_WARN
Definition warn.h:12

References fl::StrN< SIZE >::c_str(), FASTLED_WARN, FL_WARN, fl::floor(), INT16_MAX, fl::make_shared(), fl::move(), fl::HeapVector< T, Allocator >::push_back(), and UINT8_MAX.

Referenced by fl::Json::parse().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: