56 const u32 biased_exp = (bits >> 23) & 0xFFu;
57 const u32 mantissa = bits & 0x7FFFFFu;
58 return biased_exp == 0xFFu || biased_exp > 151u ||
59 (biased_exp == 151u && mantissa != 0u);
142 size_t start_pos =
mPos;
145 bool has_int =
false;
146 bool has_float =
false;
147 bool has_float_beyond_precision =
false;
148 bool has_string =
false;
149 bool has_bool =
false;
150 bool has_null =
false;
174 if (c ==
'[' || c ==
'{') {
194 else if (c ==
'-' || (c >=
'0' && c <=
'9')) {
195 size_t num_start =
mPos;
196 bool is_float =
false;
198 if (c ==
'-')
mPos++;
216#if FL_PLATFORM_HAS_LARGE_MEMORY
223 has_float_beyond_precision =
true;
230 has_float_beyond_precision =
true;
237 if (val < int_min) int_min = val;
238 if (val > int_max) int_max = val;
242 else if (c ==
't' &&
mPos + 3 <
mLen &&
248 else if (c ==
'f' &&
mPos + 4 <
mLen &&
255 else if (c ==
'n' &&
mPos + 3 <
mLen &&
279 int type_count = (has_int ? 1 : 0) + (has_float ? 1 : 0) +
280 (has_string ? 1 : 0) + (has_bool ? 1 : 0) + (has_null ? 1 : 0);
285 if (type_count == 1 || (type_count == 2 && has_int && has_float)) {
286 if (has_float || (has_int && has_float)) {
288 if (has_float_beyond_precision) {
295 if (int_min >= 0 && int_max <= 255) {
298 if (int_min >= -32768 && int_max <= 32767) {
332#if FL_PLATFORM_HAS_LARGE_MEMORY
333 size_t saved_pos =
mPos;
376 size_t start =
mPos + 1;
404 if (c ==
'-' || (c >=
'0' && c <=
'9')) {
408 if (c ==
'-')
mPos++;
633 for (
size_t i = 0; i <
span.
size(); i++) {
634 if (
span[i] ==
'\\') {
645 for (
size_t k = 0; k < 4; ++k) {
648 if (h >=
'0' && h <=
'9') digit = h -
'0';
649 else if (h >=
'a' && h <=
'f') digit = h -
'a' + 10;
650 else if (h >=
'A' && h <=
'F') digit = h -
'A' + 10;
659 out +=
static_cast<char>(cp);
660 }
else if (cp < 0x800) {
661 out +=
static_cast<char>(0xC0 | (cp >> 6));
662 out +=
static_cast<char>(0x80 | (cp & 0x3F));
663 }
else if (cp < 0x10000) {
664 out +=
static_cast<char>(0xE0 | (cp >> 12));
665 out +=
static_cast<char>(0x80 | ((cp >> 6) & 0x3F));
666 out +=
static_cast<char>(0x80 | (cp & 0x3F));
668 out +=
static_cast<char>(0xF0 | (cp >> 18));
669 out +=
static_cast<char>(0x80 | ((cp >> 12) & 0x3F));
670 out +=
static_cast<char>(0x80 | ((cp >> 6) & 0x3F));
671 out +=
static_cast<char>(0x80 | (cp & 0x3F));
680 for (
size_t i = 0; i <
span.
size(); i++) {
682 char next =
span[i + 1];
684 case '"':
result +=
'"'; i++;
break;
685 case '\\':
result +=
'\\'; i++;
break;
686 case '/':
result +=
'/'; i++;
break;
687 case 'b':
result +=
'\b'; i++;
break;
688 case 'f':
result +=
'\f'; i++;
break;
689 case 'n':
result +=
'\n'; i++;
break;
690 case 'r':
result +=
'\r'; i++;
break;
691 case 't':
result +=
'\t'; i++;
break;
700 if (cp >= 0xD800 && cp <= 0xDBFF && i + 11 <
span.
size() &&
701 span[i + 6] ==
'\\' &&
span[i + 7] ==
'u') {
703 if (lo >= 0xDC00 && lo <= 0xDFFF) {
704 cp = 0x10000 + ((cp - 0xD800) << 10) + (lo - 0xDC00);
709 if (cp >= 0xD800 && cp <= 0xDFFF) {
732 bool all_numeric =
true;
735 bool has_float =
false;
736 bool has_float_beyond_precision =
false;
738 for (
const auto& elem : arr) {
744 if (elem->is_int()) {
745 auto val = elem->as_int();
748 min_val = (v < min_val) ? v : min_val;
749 max_val = (v > max_val) ? v : max_val;
754 }
else if (elem->is_float()) {
756 auto val = elem->as_float();
765 has_float_beyond_precision =
true;
778 if (has_float_beyond_precision) {
785 if (min_val >= 0 && max_val <= 255) {
789 if (min_val >= -32768 && max_val <= 32767) {
795 if (min_val >= -16777216 && max_val <= 16777216) {
804 if (!arr)
return array_val;
812 for (
const auto& elem : *arr) {
813 auto val = elem->as_int();
822 for (
const auto& elem : *arr) {
823 auto val = elem->as_int();
824 if (val) vec.
push_back(
static_cast<i16
>(*val));
832 for (
const auto& elem : *arr) {
833 if (elem->is_float()) {
834 auto val = elem->as_float();
836 }
else if (elem->is_int()) {
837 auto val = elem->as_int();
845 vec.
push_back(
static_cast<float>(
static_cast<fl::i32
>(*val)));
880 while (p <
end && (*p ==
' ' || *p ==
'\t' || *p ==
'\n' || *p ==
'\r')) p++;
884 const char* num_start = p;
886 while (p < end && *p >=
'0' && *p <=
'9') p++;
889 out_vec.push_back(
static_cast<T
>(val));
892 while (p <
end && (*p ==
' ' || *p ==
'\t' || *p ==
'\n' || *p ==
'\r')) p++;
895 if (p <
end && *p ==
',') p++;
909 while (p <
end && (*p ==
' ' || *p ==
'\t' || *p ==
'\n' || *p ==
'\r')) p++;
913 const char* num_start = p;
914 bool is_float =
false;
917 while (p < end && *p >=
'0' && *p <=
'9') p++;
919 if (p <
end && *p ==
'.') {
922 while (p < end && *p >=
'0' && *p <=
'9') p++;
925 if (p <
end && (*p ==
'e' || *p ==
'E')) {
928 if (p <
end && (*p ==
'+' || *p ==
'-')) p++;
929 while (p < end && *p >=
'0' && *p <=
'9') p++;
934#if FL_PLATFORM_HAS_LARGE_MEMORY
945 val =
static_cast<T
>(0);
948 val =
static_cast<T
>(
fl::parseInt(num_start, p - num_start));
950 out_vec.push_back(val);
953 while (p <
end && (*p ==
' ' || *p ==
'\t' || *p ==
'\n' || *p ==
'\r')) p++;
956 if (p <
end && *p ==
',') p++;
1004#if FL_PLATFORM_HAS_LARGE_MEMORY
1040 auto obj_val =
mStack.back().value;
1072 mStack.back().pending_key.empty()) {
1096 bool is_float =
false;
1097 for (
size_t i = 0; i <
value.size(); i++) {
1105#if FL_PLATFORM_HAS_LARGE_MEMORY
1115 i64 i64_val =
static_cast<i64>(i);
1128 i64 i64_val =
static_cast<i64>(i);
1170 JsonTokenizer tokenizer;
1173 JsonValidator validator;
1174 if (!tokenizer.parse(txt, validator) || !validator.is_valid()) {
1179 JsonBuilder builder;
1180 if (!tokenizer.parse(txt, builder)) {
1184 return builder.get_result();
1193 JsonTokenizer tokenizer;
1194 JsonValidator validator;
1195 return tokenizer.parse(txt, validator) && validator.is_valid();
1246template <
typename Sink>
1251 while (*str) {
out.push_back(*str++); }
1255 for (
size_t i = 0; i < str.size(); ++i) {
1256 out.push_back(str[i]);
1262 for (
size_t i = 0; i < str.size(); ++i) {
1265 case '"':
append(
"\\\"");
break;
1266 case '\\':
append(
"\\\\");
break;
1267 case '\n':
append(
"\\n");
break;
1268 case '\r':
append(
"\\r");
break;
1269 case '\t':
append(
"\\t");
break;
1270 case '\b':
append(
"\\b");
break;
1271 case '\f':
append(
"\\f");
break;
1273 if (
static_cast<unsigned char>(c) < 0x20) {
1276 static const char kHex[] =
"0123456789abcdef";
1278 out.push_back(kHex[(c >> 4) & 0xF]);
1279 out.push_back(kHex[c & 0xF]);
1295 value->data.visit(*
this);
1310#if FL_PLATFORM_HAS_LARGE_MEMORY
1335 for (
const auto& item : arr) {
1336 if (!first)
out.push_back(
',');
1350 for (
const auto& kv : obj) {
1351 if (!first)
out.push_back(
',');
1363 for (
const auto& item :
audio) {
1364 if (!first)
out.push_back(
',');
1367 num_str.
append(
static_cast<int>(item));
1376 for (
const auto& item : bytes) {
1377 if (!first)
out.push_back(
',');
1380 num_str.
append(
static_cast<int>(item));
1389 for (
const auto& item : floats) {
1390 if (!first)
out.push_back(
',');
1392#if FL_PLATFORM_HAS_LARGE_MEMORY
1423 JsonStringSink sink{
result};
1438 JsonChunkSink sink(fn, ctx);
1453 size_t len =
strlen(jsonStr);
1454 for (
size_t i = 0; i < len; ++i) {
1455 char c = jsonStr[i];
1456 if (c !=
' ' && c !=
'\t' && c !=
'\n' && c !=
'\r') {
JsonBuilder() FL_NO_EXCEPT
fl::StringInterner mInterner
bool parse_float_array(const fl::span< const char > &span, fl::vector< T > &out_vec) FL_NO_EXCEPT
void push_value(const fl::shared_ptr< json_value > &val) FL_NO_EXCEPT
bool parse_int_array(const fl::span< const char > &span, fl::vector< T > &out_vec) FL_NO_EXCEPT
fl::shared_ptr< json_value > get_result() FL_NO_EXCEPT
fl::shared_ptr< json_value > mRoot
ParseState on_token(JsonToken token, const fl::span< const char > &value) FL_NO_EXCEPT override
fl::vector_inlined< StackFrame, 8 > mStack
bool parse(fl::string_view input, JsonVisitor &visitor) FL_NO_EXCEPT
JsonTokenizer(bool enable_lookahead=true) FL_NO_EXCEPT
bool parse(const fl::string &input, JsonVisitor &visitor) FL_NO_EXCEPT
void skip_whitespace() FL_NO_EXCEPT
JsonToken next_token(fl::span< const char > &out_value) FL_NO_EXCEPT
JsonToken scan_array_lookahead(fl::span< const char > &out_span) FL_NO_EXCEPT
JsonValidator() FL_NO_EXCEPT
fl::vector_inlined< char, 32 > mBracketStack
ParseState on_token(JsonToken token, const fl::span< const char > &value) FL_NO_EXCEPT override
bool is_valid() const FL_NO_EXCEPT
virtual ~JsonVisitor() FL_NO_EXCEPT=default
virtual ParseState on_token(JsonToken token, const fl::span< const char > &value) FL_NO_EXCEPT=0
void clear(bool freeMemory=false) FL_NO_EXCEPT
bool empty() const FL_NO_EXCEPT
void set_value(const fl::shared_ptr< json_value > &value) FL_NO_EXCEPT
void(*)(void *ctx, const char *data, fl::size len) WriteFn
fl::shared_ptr< json_value > mValue
void write_to(WriteFn fn, void *ctx) const FL_NO_EXCEPT
fl::string to_string_native() const FL_NO_EXCEPT
static fl::string normalize_json_string(const char *jsonStr) FL_NO_EXCEPT
const T * data() const FL_NO_EXCEPT
constexpr fl::size size() const FL_NO_EXCEPT
string & append(const bitset_fixed< N > &bs) FL_NO_EXCEPT
void reserve(fl::size n) FL_NO_EXCEPT
void push_back(const T &value) FL_NO_EXCEPT
FastLED's Elegant JSON Library: fl::json
Centralized logging categories for FastLED hardware interfaces and subsystems.
constexpr T * end(T(&array)[N]) FL_NO_EXCEPT
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
ArrayType classify_array(const json_array &arr) FL_NO_EXCEPT
bool has_escape_sequences(const fl::span< const char > &span) FL_NO_EXCEPT
long read_hex4(const fl::span< const char > &span, size_t pos) FL_NO_EXCEPT
fl::shared_ptr< json_value > optimize_array(fl::shared_ptr< json_value > array_val) FL_NO_EXCEPT
void append_utf8(fl::string &out, unsigned long cp) FL_NO_EXCEPT
fl::string unescape_string(const fl::span< const char > &span) FL_NO_EXCEPT
constexpr int MAX_JSON_DEPTH
constexpr remove_reference< T >::type && move(T &&t) FL_NO_EXCEPT
decltype(nullptr) nullptr_t
json_value & get_null_json_value() FL_NO_EXCEPT
u8 u8 fract8 blur_amount FL_NO_EXCEPT
constexpr int type_rank< T >::value
u32 ieee754_parse_decimal(const char *s, fl::size len, fl::size *consumed) FL_NO_EXCEPT
Parse a decimal floating-point number into IEEE 754 single-precision bits.
json_object & get_empty_json_obj() FL_NO_EXCEPT
int parseInt(const char *str, fl::size len) FL_NO_EXCEPT
Parse an integer from a character buffer.
static bool float_bits_magnitude_exceeds_2_24(u32 bits) FL_NO_EXCEPT
fl::vector< fl::shared_ptr< json_value > > json_array
expected< T, E > result
Alias for expected (Rust-style naming)
To bit_cast(const From &from) FL_NO_EXCEPT
fl::flat_map< fl::string, fl::shared_ptr< json_value >, fl::StringFastLess > json_object
fl::string ieee754_format_decimal(u32 bits, int precision) FL_NO_EXCEPT
Format IEEE 754 single-precision bits as decimal text.
VectorN< T, INLINED_SIZE > vector_inlined
fl::string serializeValue(const json_value &value) FL_NO_EXCEPT
FASTLED_FORCE_INLINE size_t strlen(const char *s) FL_NO_EXCEPT
Base definition for an LED controller.
void accept(const fl::vector< u8 > &bytes) FL_NO_EXCEPT
void append_str(const fl::string &str) FL_NO_EXCEPT
void accept(const bool &b) FL_NO_EXCEPT
void accept(const fl::nullptr_t &) FL_NO_EXCEPT
void append_escaped(const fl::string &str) FL_NO_EXCEPT
void accept(const i64 &i) FL_NO_EXCEPT
void accept(const fl::vector< float > &floats) FL_NO_EXCEPT
void accept(const fl::string &s) FL_NO_EXCEPT
void serialize_value(const json_value *value) FL_NO_EXCEPT
void accept(const json_array &arr) FL_NO_EXCEPT
void accept(const float &f) FL_NO_EXCEPT
void accept(const json_object &obj) FL_NO_EXCEPT
void append(const char *str) FL_NO_EXCEPT
void accept(const fl::vector< i16 > &audio) FL_NO_EXCEPT
enum fl::anonymous_namespace{json.cpp.hpp}::JsonBuilder::StackFrame::Type type
fl::shared_ptr< json_value > value
JsonChunkSink(json::WriteFn f, void *c) FL_NO_EXCEPT
void flush() FL_NO_EXCEPT
static constexpr fl::size kSize
void push_back(char c) FL_NO_EXCEPT
void push_back(char) FL_NO_EXCEPT
void push_back(char c) FL_NO_EXCEPT
static bool parse2_validate_only(const fl::string &txt) FL_NO_EXCEPT
static fl::shared_ptr< json_value > parse2(const fl::string &txt) FL_NO_EXCEPT
fl::string to_string() const FL_NO_EXCEPT
static constexpr T min() FL_NO_EXCEPT
static constexpr T max() FL_NO_EXCEPT