From a6da4ad452d2f6b8d0ac683d606c7ec941789995 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 29 Jul 2022 10:53:23 +0200 Subject: [PATCH] Remove member `JsonDeserializer::_error` This reduces the code size by 72 bytes on AVR. --- src/ArduinoJson/Json/JsonDeserializer.hpp | 379 +++++++++++----------- 1 file changed, 182 insertions(+), 197 deletions(-) diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index 3d517175..569e6579 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -25,20 +25,21 @@ class JsonDeserializer { : _stringStorage(stringStorage), _foundSomething(false), _latch(reader), - _pool(&pool), - _error(DeserializationError::Ok) {} + _pool(&pool) {} template DeserializationError parse(VariantData &variant, TFilter filter, NestingLimit nestingLimit) { - parseVariant(variant, filter, nestingLimit); + DeserializationError::Code err; - if (!_error && _latch.last() != 0 && !variant.isEnclosed()) { + err = parseVariant(variant, filter, nestingLimit); + + if (!err && _latch.last() != 0 && !variant.isEnclosed()) { // We don't detect trailing characters earlier, so we need to check now return DeserializationError::InvalidInput; } - return _error; + return err; } private: @@ -58,10 +59,13 @@ class JsonDeserializer { } template - bool parseVariant(VariantData &variant, TFilter filter, - NestingLimit nestingLimit) { - if (!skipSpacesAndComments()) - return false; + DeserializationError::Code parseVariant(VariantData &variant, TFilter filter, + NestingLimit nestingLimit) { + DeserializationError::Code err; + + err = skipSpacesAndComments(); + if (err) + return err; switch (current()) { case '[': @@ -91,9 +95,12 @@ class JsonDeserializer { } } - bool skipVariant(NestingLimit nestingLimit) { - if (!skipSpacesAndComments()) - return false; + DeserializationError::Code skipVariant(NestingLimit nestingLimit) { + DeserializationError::Code err; + + err = skipSpacesAndComments(); + if (err) + return err; switch (current()) { case '[': @@ -112,24 +119,25 @@ class JsonDeserializer { } template - bool parseArray(CollectionData &array, TFilter filter, - NestingLimit nestingLimit) { - if (nestingLimit.reached()) { - _error = DeserializationError::TooDeep; - return false; - } + DeserializationError::Code parseArray(CollectionData &array, TFilter filter, + NestingLimit nestingLimit) { + DeserializationError::Code err; + + if (nestingLimit.reached()) + return DeserializationError::TooDeep; // Skip opening braket ARDUINOJSON_ASSERT(current() == '['); move(); // Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // Empty array? if (eat(']')) - return true; + return DeserializationError::Ok; TFilter memberFilter = filter[0UL]; @@ -138,38 +146,37 @@ class JsonDeserializer { if (memberFilter.allow()) { // Allocate slot in array VariantData *value = array.addElement(_pool); - if (!value) { - _error = DeserializationError::NoMemory; - return false; - } + if (!value) + return DeserializationError::NoMemory; // 1 - Parse value - if (!parseVariant(*value, memberFilter, nestingLimit.decrement())) - return false; + err = parseVariant(*value, memberFilter, nestingLimit.decrement()); + if (err) + return err; } else { - if (!skipVariant(nestingLimit.decrement())) - return false; + err = skipVariant(nestingLimit.decrement()); + if (err) + return err; } // 2 - Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // 3 - More values? if (eat(']')) - return true; - if (!eat(',')) { - _error = DeserializationError::InvalidInput; - return false; - } + return DeserializationError::Ok; + if (!eat(',')) + return DeserializationError::InvalidInput; } } - bool skipArray(NestingLimit nestingLimit) { - if (nestingLimit.reached()) { - _error = DeserializationError::TooDeep; - return false; - } + DeserializationError::Code skipArray(NestingLimit nestingLimit) { + DeserializationError::Code err; + + if (nestingLimit.reached()) + return DeserializationError::TooDeep; // Skip opening braket ARDUINOJSON_ASSERT(current() == '['); @@ -178,58 +185,59 @@ class JsonDeserializer { // Read each value for (;;) { // 1 - Skip value - if (!skipVariant(nestingLimit.decrement())) - return false; + err = skipVariant(nestingLimit.decrement()); + if (err) + return err; // 2 - Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // 3 - More values? if (eat(']')) - return true; - if (!eat(',')) { - _error = DeserializationError::InvalidInput; - return false; - } + return DeserializationError::Ok; + if (!eat(',')) + return DeserializationError::InvalidInput; } } template - bool parseObject(CollectionData &object, TFilter filter, - NestingLimit nestingLimit) { - if (nestingLimit.reached()) { - _error = DeserializationError::TooDeep; - return false; - } + DeserializationError::Code parseObject(CollectionData &object, TFilter filter, + NestingLimit nestingLimit) { + DeserializationError::Code err; + + if (nestingLimit.reached()) + return DeserializationError::TooDeep; // Skip opening brace ARDUINOJSON_ASSERT(current() == '{'); move(); // Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // Empty object? if (eat('}')) - return true; + return DeserializationError::Ok; // Read each key value pair for (;;) { // Parse key - if (!parseKey()) - return false; + err = parseKey(); + if (err) + return err; // Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // Colon - if (!eat(':')) { - _error = DeserializationError::InvalidInput; - return false; - } + if (!eat(':')) + return DeserializationError::InvalidInput; String key = _stringStorage.str(); @@ -244,10 +252,8 @@ class JsonDeserializer { // Allocate slot in object VariantSlot *slot = object.addSlot(_pool); - if (!slot) { - _error = DeserializationError::NoMemory; - return false; - } + if (!slot) + return DeserializationError::NoMemory; slot->setKey(key); @@ -255,84 +261,87 @@ class JsonDeserializer { } // Parse value - if (!parseVariant(*variant, memberFilter, nestingLimit.decrement())) - return false; + err = parseVariant(*variant, memberFilter, nestingLimit.decrement()); + if (err) + return err; } else { - if (!skipVariant(nestingLimit.decrement())) - return false; + err = skipVariant(nestingLimit.decrement()); + if (err) + return err; } // Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // More keys/values? if (eat('}')) - return true; - if (!eat(',')) { - _error = DeserializationError::InvalidInput; - return false; - } + return DeserializationError::Ok; + if (!eat(',')) + return DeserializationError::InvalidInput; // Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; } } - bool skipObject(NestingLimit nestingLimit) { - if (nestingLimit.reached()) { - _error = DeserializationError::TooDeep; - return false; - } + DeserializationError::Code skipObject(NestingLimit nestingLimit) { + DeserializationError::Code err; + + if (nestingLimit.reached()) + return DeserializationError::TooDeep; // Skip opening brace ARDUINOJSON_ASSERT(current() == '{'); move(); // Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // Empty object? if (eat('}')) - return true; + return DeserializationError::Ok; // Read each key value pair for (;;) { // Skip key - if (!skipVariant(nestingLimit.decrement())) - return false; + err = skipVariant(nestingLimit.decrement()); + if (err) + return err; // Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // Colon - if (!eat(':')) { - _error = DeserializationError::InvalidInput; - return false; - } + if (!eat(':')) + return DeserializationError::InvalidInput; // Skip value - if (!skipVariant(nestingLimit.decrement())) - return false; + err = skipVariant(nestingLimit.decrement()); + if (err) + return err; // Skip spaces - if (!skipSpacesAndComments()) - return false; + err = skipSpacesAndComments(); + if (err) + return err; // More keys/values? if (eat('}')) - return true; - if (!eat(',')) { - _error = DeserializationError::InvalidInput; - return false; - } + return DeserializationError::Ok; + if (!eat(',')) + return DeserializationError::InvalidInput; } } - bool parseKey() { + DeserializationError::Code parseKey() { _stringStorage.startString(); if (isQuote(current())) { return parseQuotedString(); @@ -341,17 +350,24 @@ class JsonDeserializer { } } - bool parseStringValue(VariantData &variant) { + DeserializationError::Code parseStringValue(VariantData &variant) { + DeserializationError::Code err; + _stringStorage.startString(); - if (!parseQuotedString()) - return false; + + err = parseQuotedString(); + if (err) + return err; + variant.setString(_stringStorage.save()); - return true; + + return DeserializationError::Ok; } - bool parseQuotedString() { + DeserializationError::Code parseQuotedString() { #if ARDUINOJSON_DECODE_UNICODE Utf16::Codepoint codepoint; + DeserializationError::Code err; #endif const char stopChar = current(); @@ -362,25 +378,22 @@ class JsonDeserializer { if (c == stopChar) break; - if (c == '\0') { - _error = DeserializationError::IncompleteInput; - return false; - } + if (c == '\0') + return DeserializationError::IncompleteInput; if (c == '\\') { c = current(); - if (c == '\0') { - _error = DeserializationError::IncompleteInput; - return false; - } + if (c == '\0') + return DeserializationError::IncompleteInput; if (c == 'u') { #if ARDUINOJSON_DECODE_UNICODE move(); uint16_t codeunit; - if (!parseHex4(codeunit)) - return false; + err = parseHex4(codeunit); + if (err) + return err; if (codepoint.append(codeunit)) Utf8::encodeCodepoint(codepoint.value(), _stringStorage); #else @@ -391,25 +404,21 @@ class JsonDeserializer { // replace char c = EscapeSequence::unescapeChar(c); - if (c == '\0') { - _error = DeserializationError::InvalidInput; - return false; - } + if (c == '\0') + return DeserializationError::InvalidInput; move(); } _stringStorage.append(c); } - if (!_stringStorage.isValid()) { - _error = DeserializationError::NoMemory; - return false; - } + if (!_stringStorage.isValid()) + return DeserializationError::NoMemory; - return true; + return DeserializationError::Ok; } - bool parseNonQuotedString() { + DeserializationError::Code parseNonQuotedString() { char c = current(); ARDUINOJSON_ASSERT(c); @@ -420,19 +429,16 @@ class JsonDeserializer { c = current(); } while (canBeInNonQuotedString(c)); } else { - _error = DeserializationError::InvalidInput; - return false; + return DeserializationError::InvalidInput; } - if (!_stringStorage.isValid()) { - _error = DeserializationError::NoMemory; - return false; - } + if (!_stringStorage.isValid()) + return DeserializationError::NoMemory; - return true; + return DeserializationError::Ok; } - bool skipString() { + DeserializationError::Code skipString() { const char stopChar = current(); move(); @@ -441,20 +447,18 @@ class JsonDeserializer { move(); if (c == stopChar) break; - if (c == '\0') { - _error = DeserializationError::IncompleteInput; - return false; - } + if (c == '\0') + return DeserializationError::IncompleteInput; if (c == '\\') { if (current() != '\0') move(); } } - return true; + return DeserializationError::Ok; } - bool parseNumericValue(VariantData &result) { + DeserializationError::Code parseNumericValue(VariantData &result) { uint8_t n = 0; char c = current(); @@ -468,63 +472,51 @@ class JsonDeserializer { c = _buffer[0]; if (c == 't') { // true result.setBoolean(true); - if (n != 4) { - _error = DeserializationError::IncompleteInput; - return false; - } - return true; + if (n != 4) + return DeserializationError::IncompleteInput; + return DeserializationError::Ok; } if (c == 'f') { // false result.setBoolean(false); - if (n != 5) { - _error = DeserializationError::IncompleteInput; - return false; - } - return true; + if (n != 5) + return DeserializationError::IncompleteInput; + return DeserializationError::Ok; } if (c == 'n') { // null // the variant is already null - if (n != 4) { - _error = DeserializationError::IncompleteInput; - return false; - } - return true; + if (n != 4) + return DeserializationError::IncompleteInput; + return DeserializationError::Ok; } - if (!parseNumber(_buffer, result)) { - _error = DeserializationError::InvalidInput; - return false; - } + if (!parseNumber(_buffer, result)) + return DeserializationError::InvalidInput; - return true; + return DeserializationError::Ok; } - bool skipNumericValue() { + DeserializationError::Code skipNumericValue() { char c = current(); while (canBeInNonQuotedString(c)) { move(); c = current(); } - return true; + return DeserializationError::Ok; } - bool parseHex4(uint16_t &result) { + DeserializationError::Code parseHex4(uint16_t &result) { result = 0; for (uint8_t i = 0; i < 4; ++i) { char digit = current(); - if (!digit) { - _error = DeserializationError::IncompleteInput; - return false; - } + if (!digit) + return DeserializationError::IncompleteInput; uint8_t value = decodeHex(digit); - if (value > 0x0F) { - _error = DeserializationError::InvalidInput; - return false; - } + if (value > 0x0F) + return DeserializationError::InvalidInput; result = uint16_t((result << 4) | value); move(); } - return true; + return DeserializationError::Ok; } static inline bool isBetween(char c, char min, char max) { @@ -547,14 +539,13 @@ class JsonDeserializer { return uint8_t(c - 'A' + 10); } - bool skipSpacesAndComments() { + DeserializationError::Code skipSpacesAndComments() { for (;;) { switch (current()) { // end of string case '\0': - _error = _foundSomething ? DeserializationError::IncompleteInput - : DeserializationError::EmptyInput; - return false; + return _foundSomething ? DeserializationError::IncompleteInput + : DeserializationError::EmptyInput; // spaces case ' ': @@ -575,10 +566,8 @@ class JsonDeserializer { bool wasStar = false; for (;;) { char c = current(); - if (c == '\0') { - _error = DeserializationError::IncompleteInput; - return false; - } + if (c == '\0') + return DeserializationError::IncompleteInput; if (c == '/' && wasStar) { move(); break; @@ -595,10 +584,8 @@ class JsonDeserializer { for (;;) { move(); char c = current(); - if (c == '\0') { - _error = DeserializationError::IncompleteInput; - return false; - } + if (c == '\0') + return DeserializationError::IncompleteInput; if (c == '\n') break; } @@ -606,15 +593,14 @@ class JsonDeserializer { // not a comment, just a '/' default: - _error = DeserializationError::InvalidInput; - return false; + return DeserializationError::InvalidInput; } break; #endif default: _foundSomething = true; - return true; + return DeserializationError::Ok; } } } @@ -626,7 +612,6 @@ class JsonDeserializer { char _buffer[64]; // using a member instead of a local variable because it // ended in the recursive path after compiler inlined the // code - DeserializationError _error; }; //