mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Reduced stack usage when compiled with -Og (issue #1210)
This saves 112 bytes on ESP8266
This commit is contained in:
		| @@ -22,19 +22,22 @@ class JsonDeserializer { | |||||||
|  public: |  public: | ||||||
|   JsonDeserializer(MemoryPool &pool, TReader reader, |   JsonDeserializer(MemoryPool &pool, TReader reader, | ||||||
|                    TStringStorage stringStorage) |                    TStringStorage stringStorage) | ||||||
|       : _stringStorage(stringStorage), _latch(reader), _pool(&pool) {} |       : _stringStorage(stringStorage), | ||||||
|  |         _latch(reader), | ||||||
|  |         _pool(&pool), | ||||||
|  |         _error(DeserializationError::Ok) {} | ||||||
|  |  | ||||||
|   template <typename TFilter> |   template <typename TFilter> | ||||||
|   DeserializationError parse(VariantData &variant, TFilter filter, |   DeserializationError parse(VariantData &variant, TFilter filter, | ||||||
|                              NestingLimit nestingLimit) { |                              NestingLimit nestingLimit) { | ||||||
|     DeserializationError err = parseVariant(variant, filter, nestingLimit); |     parseVariant(variant, filter, nestingLimit); | ||||||
|  |  | ||||||
|     if (!err && _latch.last() != 0 && !variant.isEnclosed()) { |     if (!_error && _latch.last() != 0 && !variant.isEnclosed()) { | ||||||
|       // We don't detect trailing characters earlier, so we need to check now |       // We don't detect trailing characters earlier, so we need to check now | ||||||
|       err = DeserializationError::InvalidInput; |       _error = DeserializationError::InvalidInput; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return err; |     return _error; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
| @@ -56,11 +59,10 @@ class JsonDeserializer { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TFilter> |   template <typename TFilter> | ||||||
|   DeserializationError parseVariant(VariantData &variant, TFilter filter, |   bool parseVariant(VariantData &variant, TFilter filter, | ||||||
|                                     NestingLimit nestingLimit) { |                     NestingLimit nestingLimit) { | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     if (!skipSpacesAndComments()) | ||||||
|     if (err) |       return false; | ||||||
|       return err; |  | ||||||
|  |  | ||||||
|     switch (current()) { |     switch (current()) { | ||||||
|       case '[': |       case '[': | ||||||
| @@ -90,10 +92,9 @@ class JsonDeserializer { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError skipVariant(NestingLimit nestingLimit) { |   bool skipVariant(NestingLimit nestingLimit) { | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     if (!skipSpacesAndComments()) | ||||||
|     if (err) |       return false; | ||||||
|       return err; |  | ||||||
|  |  | ||||||
|     switch (current()) { |     switch (current()) { | ||||||
|       case '[': |       case '[': | ||||||
| @@ -112,23 +113,24 @@ class JsonDeserializer { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TFilter> |   template <typename TFilter> | ||||||
|   DeserializationError parseArray(CollectionData &array, TFilter filter, |   bool parseArray(CollectionData &array, TFilter filter, | ||||||
|                                   NestingLimit nestingLimit) { |                   NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) |     if (nestingLimit.reached()) { | ||||||
|       return DeserializationError::TooDeep; |       _error = DeserializationError::TooDeep; | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Skip opening braket |     // Skip opening braket | ||||||
|     ARDUINOJSON_ASSERT(current() == '['); |     ARDUINOJSON_ASSERT(current() == '['); | ||||||
|     move(); |     move(); | ||||||
|  |  | ||||||
|     // Skip spaces |     // Skip spaces | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     if (!skipSpacesAndComments()) | ||||||
|     if (err) |       return false; | ||||||
|       return err; |  | ||||||
|  |  | ||||||
|     // Empty array? |     // Empty array? | ||||||
|     if (eat(']')) |     if (eat(']')) | ||||||
|       return DeserializationError::Ok; |       return true; | ||||||
|  |  | ||||||
|     TFilter memberFilter = filter[0UL]; |     TFilter memberFilter = filter[0UL]; | ||||||
|  |  | ||||||
| @@ -137,35 +139,38 @@ class JsonDeserializer { | |||||||
|       if (memberFilter.allow()) { |       if (memberFilter.allow()) { | ||||||
|         // Allocate slot in array |         // Allocate slot in array | ||||||
|         VariantData *value = array.addElement(_pool); |         VariantData *value = array.addElement(_pool); | ||||||
|         if (!value) |         if (!value) { | ||||||
|           return DeserializationError::NoMemory; |           _error = DeserializationError::NoMemory; | ||||||
|  |           return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // 1 - Parse value |         // 1 - Parse value | ||||||
|         err = parseVariant(*value, memberFilter, nestingLimit.decrement()); |         if (!parseVariant(*value, memberFilter, nestingLimit.decrement())) | ||||||
|         if (err) |           return false; | ||||||
|           return err; |  | ||||||
|       } else { |       } else { | ||||||
|         err = skipVariant(nestingLimit.decrement()); |         if (!skipVariant(nestingLimit.decrement())) | ||||||
|         if (err) |           return false; | ||||||
|           return err; |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // 2 - Skip spaces |       // 2 - Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       if (!skipSpacesAndComments()) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // 3 - More values? |       // 3 - More values? | ||||||
|       if (eat(']')) |       if (eat(']')) | ||||||
|         return DeserializationError::Ok; |         return true; | ||||||
|       if (!eat(',')) |       if (!eat(',')) { | ||||||
|         return DeserializationError::InvalidInput; |         _error = DeserializationError::InvalidInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError skipArray(NestingLimit nestingLimit) { |   bool skipArray(NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) |     if (nestingLimit.reached()) { | ||||||
|       return DeserializationError::TooDeep; |       _error = DeserializationError::TooDeep; | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Skip opening braket |     // Skip opening braket | ||||||
|     ARDUINOJSON_ASSERT(current() == '['); |     ARDUINOJSON_ASSERT(current() == '['); | ||||||
| @@ -174,55 +179,60 @@ class JsonDeserializer { | |||||||
|     // Read each value |     // Read each value | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       // 1 - Skip value |       // 1 - Skip value | ||||||
|       DeserializationError err = skipVariant(nestingLimit.decrement()); |       if (!skipVariant(nestingLimit.decrement())) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // 2 - Skip spaces |       // 2 - Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       if (!skipSpacesAndComments()) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // 3 - More values? |       // 3 - More values? | ||||||
|       if (eat(']')) |       if (eat(']')) | ||||||
|         return DeserializationError::Ok; |         return true; | ||||||
|       if (!eat(',')) |       if (!eat(',')) { | ||||||
|         return DeserializationError::InvalidInput; |         _error = DeserializationError::InvalidInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TFilter> |   template <typename TFilter> | ||||||
|   DeserializationError parseObject(CollectionData &object, TFilter filter, |   bool parseObject(CollectionData &object, TFilter filter, | ||||||
|                                    NestingLimit nestingLimit) { |                    NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) |     if (nestingLimit.reached()) { | ||||||
|       return DeserializationError::TooDeep; |       _error = DeserializationError::TooDeep; | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Skip opening brace |     // Skip opening brace | ||||||
|     ARDUINOJSON_ASSERT(current() == '{'); |     ARDUINOJSON_ASSERT(current() == '{'); | ||||||
|     move(); |     move(); | ||||||
|  |  | ||||||
|     // Skip spaces |     // Skip spaces | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     if (!skipSpacesAndComments()) | ||||||
|     if (err) |       return false; | ||||||
|       return err; |  | ||||||
|  |  | ||||||
|     // Empty object? |     // Empty object? | ||||||
|     if (eat('}')) |     if (eat('}')) { | ||||||
|       return DeserializationError::Ok; |       _error = DeserializationError::Ok; | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Read each key value pair |     // Read each key value pair | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       // Parse key |       // Parse key | ||||||
|       err = parseKey(); |       if (!parseKey()) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       if (!skipSpacesAndComments()) | ||||||
|       if (err) |         return false; | ||||||
|         return err;  // Colon |  | ||||||
|       if (!eat(':')) |       // Colon | ||||||
|         return DeserializationError::InvalidInput; |       if (!eat(':')) { | ||||||
|  |         _error = DeserializationError::InvalidInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |  | ||||||
|       const char *key = _stringStorage.c_str(); |       const char *key = _stringStorage.c_str(); | ||||||
|  |  | ||||||
| @@ -237,8 +247,10 @@ class JsonDeserializer { | |||||||
|  |  | ||||||
|           // Allocate slot in object |           // Allocate slot in object | ||||||
|           VariantSlot *slot = object.addSlot(_pool); |           VariantSlot *slot = object.addSlot(_pool); | ||||||
|           if (!slot) |           if (!slot) { | ||||||
|             return DeserializationError::NoMemory; |             _error = DeserializationError::NoMemory; | ||||||
|  |             return false; | ||||||
|  |           } | ||||||
|  |  | ||||||
|           slot->setKey(key, typename TStringStorage::storage_policy()); |           slot->setKey(key, typename TStringStorage::storage_policy()); | ||||||
|  |  | ||||||
| @@ -246,85 +258,84 @@ class JsonDeserializer { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Parse value |         // Parse value | ||||||
|         err = parseVariant(*variant, memberFilter, nestingLimit.decrement()); |         if (!parseVariant(*variant, memberFilter, nestingLimit.decrement())) | ||||||
|         if (err) |           return false; | ||||||
|           return err; |  | ||||||
|       } else { |       } else { | ||||||
|         err = skipVariant(nestingLimit.decrement()); |         if (!skipVariant(nestingLimit.decrement())) | ||||||
|         if (err) |           return false; | ||||||
|           return err; |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       if (!skipSpacesAndComments()) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // More keys/values? |       // More keys/values? | ||||||
|       if (eat('}')) |       if (eat('}')) | ||||||
|         return DeserializationError::Ok; |         return true; | ||||||
|       if (!eat(',')) |       if (!eat(',')) { | ||||||
|         return DeserializationError::InvalidInput; |         _error = DeserializationError::InvalidInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       if (!skipSpacesAndComments()) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError skipObject(NestingLimit nestingLimit) { |   bool skipObject(NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) |     if (nestingLimit.reached()) { | ||||||
|       return DeserializationError::TooDeep; |       _error = DeserializationError::TooDeep; | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Skip opening brace |     // Skip opening brace | ||||||
|     ARDUINOJSON_ASSERT(current() == '{'); |     ARDUINOJSON_ASSERT(current() == '{'); | ||||||
|     move(); |     move(); | ||||||
|  |  | ||||||
|     // Skip spaces |     // Skip spaces | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     if (!skipSpacesAndComments()) | ||||||
|     if (err) |       return false; | ||||||
|       return err; |  | ||||||
|  |  | ||||||
|     // Empty object? |     // Empty object? | ||||||
|     if (eat('}')) |     if (eat('}')) | ||||||
|       return DeserializationError::Ok; |       return true; | ||||||
|  |  | ||||||
|     // Read each key value pair |     // Read each key value pair | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       // Skip key |       // Skip key | ||||||
|       err = skipVariant(nestingLimit.decrement()); |       if (!skipVariant(nestingLimit.decrement())) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       if (!skipSpacesAndComments()) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // Colon |       // Colon | ||||||
|       if (!eat(':')) |       if (!eat(':')) { | ||||||
|         return DeserializationError::InvalidInput; |         _error = DeserializationError::InvalidInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |  | ||||||
|       // Skip value |       // Skip value | ||||||
|       err = skipVariant(nestingLimit.decrement()); |       if (!skipVariant(nestingLimit.decrement())) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       if (!skipSpacesAndComments()) | ||||||
|       if (err) |         return false; | ||||||
|         return err; |  | ||||||
|  |  | ||||||
|       // More keys/values? |       // More keys/values? | ||||||
|       if (eat('}')) |       if (eat('}')) | ||||||
|         return DeserializationError::Ok; |         return true; | ||||||
|       if (!eat(',')) |       if (!eat(',')) { | ||||||
|         return DeserializationError::InvalidInput; |         _error = DeserializationError::InvalidInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError parseKey() { |   bool parseKey() { | ||||||
|     _stringStorage.startString(_pool); |     _stringStorage.startString(_pool); | ||||||
|     if (isQuote(current())) { |     if (isQuote(current())) { | ||||||
|       return parseQuotedString(); |       return parseQuotedString(); | ||||||
| @@ -333,18 +344,17 @@ class JsonDeserializer { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError parseStringValue(VariantData &variant) { |   bool parseStringValue(VariantData &variant) { | ||||||
|     _stringStorage.startString(_pool); |     _stringStorage.startString(_pool); | ||||||
|     DeserializationError err = parseQuotedString(); |     if (!parseQuotedString()) | ||||||
|     if (err) |       return false; | ||||||
|       return err; |  | ||||||
|     const char *value = _stringStorage.save(_pool); |     const char *value = _stringStorage.save(_pool); | ||||||
|     variant.setString(make_not_null(value), |     variant.setString(make_not_null(value), | ||||||
|                       typename TStringStorage::storage_policy()); |                       typename TStringStorage::storage_policy()); | ||||||
|     return DeserializationError::Ok; |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError parseQuotedString() { |   bool parseQuotedString() { | ||||||
| #if ARDUINOJSON_DECODE_UNICODE | #if ARDUINOJSON_DECODE_UNICODE | ||||||
|     Utf16::Codepoint codepoint; |     Utf16::Codepoint codepoint; | ||||||
| #endif | #endif | ||||||
| @@ -357,31 +367,40 @@ class JsonDeserializer { | |||||||
|       if (c == stopChar) |       if (c == stopChar) | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       if (c == '\0') |       if (c == '\0') { | ||||||
|         return DeserializationError::IncompleteInput; |         _error = DeserializationError::IncompleteInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |  | ||||||
|       if (c == '\\') { |       if (c == '\\') { | ||||||
|         c = current(); |         c = current(); | ||||||
|         if (c == '\0') |  | ||||||
|           return DeserializationError::IncompleteInput; |         if (c == '\0') { | ||||||
|  |           _error = DeserializationError::IncompleteInput; | ||||||
|  |           return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (c == 'u') { |         if (c == 'u') { | ||||||
| #if ARDUINOJSON_DECODE_UNICODE | #if ARDUINOJSON_DECODE_UNICODE | ||||||
|           move(); |           move(); | ||||||
|           uint16_t codeunit; |           uint16_t codeunit; | ||||||
|           DeserializationError err = parseHex4(codeunit); |           if (!parseHex4(codeunit)) | ||||||
|           if (err) |             return false; | ||||||
|             return err; |  | ||||||
|           if (codepoint.append(codeunit)) |           if (codepoint.append(codeunit)) | ||||||
|             Utf8::encodeCodepoint(codepoint.value(), _stringStorage); |             Utf8::encodeCodepoint(codepoint.value(), _stringStorage); | ||||||
|           continue; |           continue; | ||||||
| #else | #else | ||||||
|           return DeserializationError::NotSupported; |           _error = DeserializationError::NotSupported; | ||||||
|  |           return false; | ||||||
| #endif | #endif | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // replace char |         // replace char | ||||||
|         c = EscapeSequence::unescapeChar(c); |         c = EscapeSequence::unescapeChar(c); | ||||||
|         if (c == '\0') |         if (c == '\0') { | ||||||
|           return DeserializationError::InvalidInput; |           _error = DeserializationError::InvalidInput; | ||||||
|  |           return false; | ||||||
|  |         } | ||||||
|         move(); |         move(); | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -390,13 +409,15 @@ class JsonDeserializer { | |||||||
|  |  | ||||||
|     _stringStorage.append('\0'); |     _stringStorage.append('\0'); | ||||||
|  |  | ||||||
|     if (!_stringStorage.isValid()) |     if (!_stringStorage.isValid()) { | ||||||
|       return DeserializationError::NoMemory; |       _error = DeserializationError::NoMemory; | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return DeserializationError::Ok; |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError parseNonQuotedString() { |   bool parseNonQuotedString() { | ||||||
|     char c = current(); |     char c = current(); | ||||||
|     ARDUINOJSON_ASSERT(c); |     ARDUINOJSON_ASSERT(c); | ||||||
|  |  | ||||||
| @@ -407,18 +428,21 @@ class JsonDeserializer { | |||||||
|         c = current(); |         c = current(); | ||||||
|       } while (canBeInNonQuotedString(c)); |       } while (canBeInNonQuotedString(c)); | ||||||
|     } else { |     } else { | ||||||
|       return DeserializationError::InvalidInput; |       _error = DeserializationError::InvalidInput; | ||||||
|  |       return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     _stringStorage.append('\0'); |     _stringStorage.append('\0'); | ||||||
|  |  | ||||||
|     if (!_stringStorage.isValid()) |     if (!_stringStorage.isValid()) { | ||||||
|       return DeserializationError::NoMemory; |       _error = DeserializationError::NoMemory; | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return DeserializationError::Ok; |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError skipString() { |   bool skipString() { | ||||||
|     const char stopChar = current(); |     const char stopChar = current(); | ||||||
|  |  | ||||||
|     move(); |     move(); | ||||||
| @@ -427,18 +451,20 @@ class JsonDeserializer { | |||||||
|       move(); |       move(); | ||||||
|       if (c == stopChar) |       if (c == stopChar) | ||||||
|         break; |         break; | ||||||
|       if (c == '\0') |       if (c == '\0') { | ||||||
|         return DeserializationError::IncompleteInput; |         _error = DeserializationError::IncompleteInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|       if (c == '\\') { |       if (c == '\\') { | ||||||
|         if (current() != '\0') |         if (current() != '\0') | ||||||
|           move(); |           move(); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return DeserializationError::Ok; |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError parseNumericValue(VariantData &result) { |   bool parseNumericValue(VariantData &result) { | ||||||
|     uint8_t n = 0; |     uint8_t n = 0; | ||||||
|  |  | ||||||
|     char c = current(); |     char c = current(); | ||||||
| @@ -452,18 +478,27 @@ class JsonDeserializer { | |||||||
|     c = _buffer[0]; |     c = _buffer[0]; | ||||||
|     if (c == 't') {  // true |     if (c == 't') {  // true | ||||||
|       result.setBoolean(true); |       result.setBoolean(true); | ||||||
|       return n == 4 ? DeserializationError::Ok |       if (n != 4) { | ||||||
|                     : DeserializationError::IncompleteInput; |         _error = DeserializationError::IncompleteInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |       return true; | ||||||
|     } |     } | ||||||
|     if (c == 'f') {  // false |     if (c == 'f') {  // false | ||||||
|       result.setBoolean(false); |       result.setBoolean(false); | ||||||
|       return n == 5 ? DeserializationError::Ok |       if (n != 5) { | ||||||
|                     : DeserializationError::IncompleteInput; |         _error = DeserializationError::IncompleteInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |       return true; | ||||||
|     } |     } | ||||||
|     if (c == 'n') {  // null |     if (c == 'n') {  // null | ||||||
|       // the variant is already null |       // the variant is already null | ||||||
|       return n == 4 ? DeserializationError::Ok |       if (n != 4) { | ||||||
|                     : DeserializationError::IncompleteInput; |         _error = DeserializationError::IncompleteInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |       return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ParsedNumber<Float, UInt> num; |     ParsedNumber<Float, UInt> num; | ||||||
| @@ -472,42 +507,48 @@ class JsonDeserializer { | |||||||
|     switch (num.type()) { |     switch (num.type()) { | ||||||
|       case VALUE_IS_NEGATIVE_INTEGER: |       case VALUE_IS_NEGATIVE_INTEGER: | ||||||
|         result.setNegativeInteger(num.uintValue); |         result.setNegativeInteger(num.uintValue); | ||||||
|         return DeserializationError::Ok; |         return true; | ||||||
|  |  | ||||||
|       case VALUE_IS_POSITIVE_INTEGER: |       case VALUE_IS_POSITIVE_INTEGER: | ||||||
|         result.setPositiveInteger(num.uintValue); |         result.setPositiveInteger(num.uintValue); | ||||||
|         return DeserializationError::Ok; |         return true; | ||||||
|  |  | ||||||
|       case VALUE_IS_FLOAT: |       case VALUE_IS_FLOAT: | ||||||
|         result.setFloat(num.floatValue); |         result.setFloat(num.floatValue); | ||||||
|         return DeserializationError::Ok; |         return true; | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return DeserializationError::InvalidInput; |       default: | ||||||
|  |         _error = DeserializationError::InvalidInput; | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError skipNumericValue() { |   bool skipNumericValue() { | ||||||
|     char c = current(); |     char c = current(); | ||||||
|     while (canBeInNonQuotedString(c)) { |     while (canBeInNonQuotedString(c)) { | ||||||
|       move(); |       move(); | ||||||
|       c = current(); |       c = current(); | ||||||
|     } |     } | ||||||
|     return DeserializationError::Ok; |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError parseHex4(uint16_t &result) { |   bool parseHex4(uint16_t &result) { | ||||||
|     result = 0; |     result = 0; | ||||||
|     for (uint8_t i = 0; i < 4; ++i) { |     for (uint8_t i = 0; i < 4; ++i) { | ||||||
|       char digit = current(); |       char digit = current(); | ||||||
|       if (!digit) |       if (!digit) { | ||||||
|         return DeserializationError::IncompleteInput; |         _error = DeserializationError::IncompleteInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|       uint8_t value = decodeHex(digit); |       uint8_t value = decodeHex(digit); | ||||||
|       if (value > 0x0F) |       if (value > 0x0F) { | ||||||
|         return DeserializationError::InvalidInput; |         _error = DeserializationError::InvalidInput; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|       result = uint16_t((result << 4) | value); |       result = uint16_t((result << 4) | value); | ||||||
|       move(); |       move(); | ||||||
|     } |     } | ||||||
|     return DeserializationError::Ok; |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static inline bool isBetween(char c, char min, char max) { |   static inline bool isBetween(char c, char min, char max) { | ||||||
| @@ -530,12 +571,13 @@ class JsonDeserializer { | |||||||
|     return uint8_t(c - 'A' + 10); |     return uint8_t(c - 'A' + 10); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError skipSpacesAndComments() { |   bool skipSpacesAndComments() { | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       switch (current()) { |       switch (current()) { | ||||||
|         // end of string |         // end of string | ||||||
|         case '\0': |         case '\0': | ||||||
|           return DeserializationError::IncompleteInput; |           _error = DeserializationError::IncompleteInput; | ||||||
|  |           return false; | ||||||
|  |  | ||||||
|         // spaces |         // spaces | ||||||
|         case ' ': |         case ' ': | ||||||
| @@ -556,8 +598,10 @@ class JsonDeserializer { | |||||||
|               bool wasStar = false; |               bool wasStar = false; | ||||||
|               for (;;) { |               for (;;) { | ||||||
|                 char c = current(); |                 char c = current(); | ||||||
|                 if (c == '\0') |                 if (c == '\0') { | ||||||
|                   return DeserializationError::IncompleteInput; |                   _error = DeserializationError::IncompleteInput; | ||||||
|  |                   return false; | ||||||
|  |                 } | ||||||
|                 if (c == '/' && wasStar) { |                 if (c == '/' && wasStar) { | ||||||
|                   move(); |                   move(); | ||||||
|                   break; |                   break; | ||||||
| @@ -574,8 +618,10 @@ class JsonDeserializer { | |||||||
|               for (;;) { |               for (;;) { | ||||||
|                 move(); |                 move(); | ||||||
|                 char c = current(); |                 char c = current(); | ||||||
|                 if (c == '\0') |                 if (c == '\0') { | ||||||
|                   return DeserializationError::IncompleteInput; |                   _error = DeserializationError::IncompleteInput; | ||||||
|  |                   return false; | ||||||
|  |                 } | ||||||
|                 if (c == '\n') |                 if (c == '\n') | ||||||
|                   break; |                   break; | ||||||
|               } |               } | ||||||
| @@ -583,13 +629,14 @@ class JsonDeserializer { | |||||||
|  |  | ||||||
|             // not a comment, just a '/' |             // not a comment, just a '/' | ||||||
|             default: |             default: | ||||||
|               return DeserializationError::InvalidInput; |               _error = DeserializationError::InvalidInput; | ||||||
|  |               return false; | ||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|         default: |         default: | ||||||
|           return DeserializationError::Ok; |           return true; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -600,6 +647,7 @@ class JsonDeserializer { | |||||||
|   char _buffer[64];  // using a member instead of a local variable because it |   char _buffer[64];  // using a member instead of a local variable because it | ||||||
|                      // ended in the recursive path after compiler inlined the |                      // ended in the recursive path after compiler inlined the | ||||||
|                      // code |                      // code | ||||||
|  |   DeserializationError _error; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // deserializeJson(JsonDocument&, const std::string&, ...) | // deserializeJson(JsonDocument&, const std::string&, ...) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user