57 const u32 biased_exp = (bits >> 23) & 0xFFu;
58 const u32 mantissa = bits & 0x7FFFFFu;
59 return biased_exp == 0xFFu || biased_exp > 151u ||
60 (biased_exp == 151u && mantissa != 0u);
143 size_t start_pos =
mPos;
146 bool has_int =
false;
147 bool has_float =
false;
148 bool has_float_beyond_precision =
false;
149 bool has_string =
false;
150 bool has_bool =
false;
151 bool has_null =
false;
175 if (c ==
'[' || c ==
'{') {
195 else if (c ==
'-' || (c >=
'0' && c <=
'9')) {
196 size_t num_start =
mPos;
197 bool is_float =
false;
199 if (c ==
'-')
mPos++;
217#if FL_PLATFORM_HAS_LARGE_MEMORY
224 has_float_beyond_precision =
true;
231 has_float_beyond_precision =
true;
238 if (val < int_min) int_min = val;
239 if (val > int_max) int_max = val;
243 else if (c ==
't' &&
mPos + 3 <
mLen &&
249 else if (c ==
'f' &&
mPos + 4 <
mLen &&
256 else if (c ==
'n' &&
mPos + 3 <
mLen &&
280 int type_count = (has_int ? 1 : 0) + (has_float ? 1 : 0) +
281 (has_string ? 1 : 0) + (has_bool ? 1 : 0) + (has_null ? 1 : 0);
286 if (type_count == 1 || (type_count == 2 && has_int && has_float)) {
287 if (has_float || (has_int && has_float)) {
289 if (has_float_beyond_precision) {
296 if (int_min >= 0 && int_max <= 255) {
299 if (int_min >= -32768 && int_max <= 32767) {
333 size_t saved_pos =
mPos;
365 size_t start =
mPos + 1;
393 if (c ==
'-' || (c >=
'0' && c <=
'9')) {
397 if (c ==
'-')
mPos++;
622 for (
size_t i = 0; i <
span.
size(); i++) {
623 if (
span[i] ==
'\\') {
635 for (
size_t i = 0; i <
span.
size(); i++) {
637 char next =
span[i + 1];
639 case '"':
result +=
'"'; i++;
break;
640 case '\\':
result +=
'\\'; i++;
break;
641 case '/':
result +=
'/'; i++;
break;
642 case 'b':
result +=
'\b'; i++;
break;
643 case 'f':
result +=
'\f'; i++;
break;
644 case 'n':
result +=
'\n'; i++;
break;
645 case 'r':
result +=
'\r'; i++;
break;
646 case 't':
result +=
'\t'; i++;
break;
663 bool all_numeric =
true;
666 bool has_float =
false;
667 bool has_float_beyond_precision =
false;
669 for (
const auto& elem : arr) {
675 if (elem->is_int()) {
676 auto val = elem->as_int();
679 min_val = (v < min_val) ? v : min_val;
680 max_val = (v > max_val) ? v : max_val;
685 }
else if (elem->is_float()) {
687 auto val = elem->as_float();
696 has_float_beyond_precision =
true;
709 if (has_float_beyond_precision) {
716 if (min_val >= 0 && max_val <= 255) {
720 if (min_val >= -32768 && max_val <= 32767) {
726 if (min_val >= -16777216 && max_val <= 16777216) {
735 if (!arr)
return array_val;
743 for (
const auto& elem : *arr) {
744 auto val = elem->as_int();
753 for (
const auto& elem : *arr) {
754 auto val = elem->as_int();
755 if (val) vec.
push_back(
static_cast<i16
>(*val));
763 for (
const auto& elem : *arr) {
764 if (elem->is_float()) {
765 auto val = elem->as_float();
767 }
else if (elem->is_int()) {
768 auto val = elem->as_int();
776 vec.
push_back(
static_cast<float>(
static_cast<fl::i32
>(*val)));
811 while (p <
end && (*p ==
' ' || *p ==
'\t' || *p ==
'\n' || *p ==
'\r')) p++;
815 const char* num_start = p;
817 while (p < end && *p >=
'0' && *p <=
'9') p++;
823 while (p <
end && (*p ==
' ' || *p ==
'\t' || *p ==
'\n' || *p ==
'\r')) p++;
826 if (p <
end && *p ==
',') p++;
840 while (p <
end && (*p ==
' ' || *p ==
'\t' || *p ==
'\n' || *p ==
'\r')) p++;
844 const char* num_start = p;
845 bool is_float =
false;
848 while (p < end && *p >=
'0' && *p <=
'9') p++;
850 if (p <
end && *p ==
'.') {
853 while (p < end && *p >=
'0' && *p <=
'9') p++;
856 if (p <
end && (*p ==
'e' || *p ==
'E')) {
859 if (p <
end && (*p ==
'+' || *p ==
'-')) p++;
860 while (p < end && *p >=
'0' && *p <=
'9') p++;
865#if FL_PLATFORM_HAS_LARGE_MEMORY
876 val =
static_cast<T
>(0);
879 val =
static_cast<T
>(
fl::parseInt(num_start, p - num_start));
884 while (p <
end && (*p ==
' ' || *p ==
'\t' || *p ==
'\n' || *p ==
'\r')) p++;
887 if (p <
end && *p ==
',') p++;
962 auto obj_val =
mStack.back().value;
994 mStack.back().pending_key.empty()) {
1018 bool is_float =
false;
1019 for (
size_t i = 0; i <
value.size(); i++) {
1028#if FL_PLATFORM_HAS_LARGE_MEMORY
1043 i64 i64_val =
static_cast<i64>(i);
1085 JsonTokenizer tokenizer;
1088 JsonValidator validator;
1089 if (!tokenizer.parse(txt, validator) || !validator.is_valid()) {
1094 JsonBuilder builder;
1095 if (!tokenizer.parse(txt, builder)) {
1099 return builder.get_result();
1108 JsonTokenizer tokenizer;
1109 JsonValidator validator;
1110 return tokenizer.parse(txt, validator) && validator.is_valid();
1132 while (*str) {
out.push_back(*str++); }
1136 for (
size_t i = 0; i < str.
size(); ++i) {
1137 out.push_back(str[i]);
1143 for (
size_t i = 0; i < str.
size(); ++i) {
1146 case '"':
append(
"\\\"");
break;
1147 case '\\':
append(
"\\\\");
break;
1148 case '\n':
append(
"\\n");
break;
1149 case '\r':
append(
"\\r");
break;
1150 case '\t':
append(
"\\t");
break;
1151 case '\b':
append(
"\\b");
break;
1152 case '\f':
append(
"\\f");
break;
1153 default:
out.push_back(c);
break;
1165 value->data.visit(*
this);
1180#if FL_PLATFORM_HAS_LARGE_MEMORY
1205 for (
const auto& item : arr) {
1206 if (!first)
out.push_back(
',');
1220 for (
const auto& kv : obj) {
1221 if (!first)
out.push_back(
',');
1233 for (
const auto& item :
audio) {
1234 if (!first)
out.push_back(
',');
1237 num_str.
append(
static_cast<int>(item));
1246 for (
const auto& item : bytes) {
1247 if (!first)
out.push_back(
',');
1250 num_str.
append(
static_cast<int>(item));
1259 for (
const auto& item : floats) {
1260 if (!first)
out.push_back(
',');
1262#if FL_PLATFORM_HAS_LARGE_MEMORY
1290 if (!json_chars.
empty()) {
1291 result.assign(&json_chars[0], json_chars.
size());
1306 size_t len =
strlen(jsonStr);
1307 for (
size_t i = 0; i < len; ++i) {
1308 char c = jsonStr[i];
1309 if (c !=
' ' && c !=
'\t' && c !=
'\n' && c !=
'\r') {
fl::StringInterner mInterner
ParseState on_token(JsonToken token, const fl::span< const char > &value) override
void push_value(const fl::shared_ptr< json_value > &val)
JsonBuilder() FL_NOEXCEPT
bool parse_float_array(const fl::span< const char > &span, fl::vector< T > &out_vec)
fl::shared_ptr< json_value > mRoot
fl::shared_ptr< json_value > get_result()
fl::vector_inlined< StackFrame, 8 > mStack
bool parse_int_array(const fl::span< const char > &span, fl::vector< T > &out_vec)
JsonToken scan_array_lookahead(fl::span< const char > &out_span)
bool parse(const fl::string &input, JsonVisitor &visitor)
bool parse(fl::string_view input, JsonVisitor &visitor)
JsonTokenizer(bool enable_lookahead=true)
JsonToken next_token(fl::span< const char > &out_value)
fl::vector_inlined< char, 32 > mBracketStack
ParseState on_token(JsonToken token, const fl::span< const char > &value) override
JsonValidator() FL_NOEXCEPT
virtual ParseState on_token(JsonToken token, const fl::span< const char > &value)=0
virtual ~JsonVisitor() FL_NOEXCEPT=default
fl::size length() const FL_NOEXCEPT
bool empty() const FL_NOEXCEPT
void clear(bool freeMemory=false) FL_NOEXCEPT
const char * c_str() const FL_NOEXCEPT
fl::size size() const FL_NOEXCEPT
bool empty() const FL_NOEXCEPT
fl::shared_ptr< json_value > mValue
static fl::string normalize_json_string(const char *jsonStr) FL_NOEXCEPT
fl::string to_string_native() const FL_NOEXCEPT
void set_value(const fl::shared_ptr< json_value > &value) FL_NOEXCEPT
const T * data() const FL_NOEXCEPT
constexpr fl::size size() const FL_NOEXCEPT
constexpr fl::size size() const FL_NOEXCEPT
constexpr const char * data() const FL_NOEXCEPT
string & append(const bitset_fixed< N > &bs) FL_NOEXCEPT
bool empty() const FL_NOEXCEPT
void reserve(fl::size n) FL_NOEXCEPT
void push_back(const T &value) FL_NOEXCEPT
FastLED's Elegant JSON Library: fl::json
Centralized logging categories for FastLED hardware interfaces and subsystems.
fl::string unescape_string(const fl::span< const char > &span)
bool has_escape_sequences(const fl::span< const char > &span)
ArrayType classify_array(const json_array &arr)
constexpr int MAX_JSON_DEPTH
fl::shared_ptr< json_value > optimize_array(fl::shared_ptr< json_value > array_val)
decltype(nullptr) nullptr_t
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
fl::string ieee754_format_decimal(u32 bits, int precision) FL_NOEXCEPT
Format IEEE 754 single-precision bits as decimal text.
constexpr int type_rank< T >::value
size_t strlen(const char *s) FL_NOEXCEPT
int parseInt(const char *str, fl::size len)
Parse an integer from a character buffer.
constexpr T * end(T(&array)[N]) FL_NOEXCEPT
json_object & get_empty_json_obj()
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
fl::vector< fl::shared_ptr< json_value > > json_array
expected< T, E > result
Alias for expected (Rust-style naming)
json_value & get_null_json_value()
fl::flat_map< fl::string, fl::shared_ptr< json_value >, fl::StringFastLess > json_object
fl::string serializeValue(const json_value &value)
VectorN< T, INLINED_SIZE > vector_inlined
To bit_cast(const From &from) FL_NOEXCEPT
u32 ieee754_parse_decimal(const char *s, fl::size len, fl::size *consumed) FL_NOEXCEPT
Parse a decimal floating-point number into IEEE 754 single-precision bits.
static bool float_bits_magnitude_exceeds_2_24(u32 bits) FL_NOEXCEPT
Base definition for an LED controller.
void accept(const float &f)
void accept(const fl::string &s)
void accept(const json_object &obj)
void accept(const fl::vector< i16 > &audio)
void accept(const fl::vector< float > &floats)
void accept(const bool &b)
void accept(const fl::vector< u8 > &bytes)
void append_escaped(const fl::string &str)
void append(const char *str)
void append_str(const fl::string &str)
void accept(const json_array &arr)
void accept(const i64 &i)
void serialize_value(const json_value *value)
void accept(const fl::nullptr_t &)
enum fl::anonymous_namespace{json.cpp.hpp}::JsonBuilder::StackFrame::Type type
fl::shared_ptr< json_value > value
fl::string to_string() const FL_NOEXCEPT
static bool parse2_validate_only(const fl::string &txt) FL_NOEXCEPT
static fl::shared_ptr< json_value > parse2(const fl::string &txt) FL_NOEXCEPT
static constexpr T min() FL_NOEXCEPT
static constexpr T max() FL_NOEXCEPT