mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Moved nesting decrement logic to class NestingLimit
This commit is contained in:
		| @@ -5,13 +5,25 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Namespace.hpp> | ||||
| #include <ArduinoJson/Polyfills/assert.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| struct NestingLimit { | ||||
|   NestingLimit() : value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {} | ||||
|   explicit NestingLimit(uint8_t n) : value(n) {} | ||||
| class NestingLimit { | ||||
|  public: | ||||
|   NestingLimit() : _value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {} | ||||
|   explicit NestingLimit(uint8_t n) : _value(n) {} | ||||
|  | ||||
|   uint8_t value; | ||||
|   NestingLimit decrement() const { | ||||
|     ARDUINOJSON_ASSERT(_value > 0); | ||||
|     return NestingLimit(static_cast<uint8_t>(_value - 1)); | ||||
|   } | ||||
|  | ||||
|   bool reached() const { | ||||
|     return _value == 0; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   uint8_t _value; | ||||
| }; | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -15,9 +15,9 @@ namespace ARDUINOJSON_NAMESPACE { | ||||
| template <template <typename, typename> class TDeserializer, typename TReader, | ||||
|           typename TWriter> | ||||
| TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool, | ||||
|                                                  TReader reader, TWriter writer, | ||||
|                                                  uint8_t nestingLimit) { | ||||
|   return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit); | ||||
|                                                  TReader reader, | ||||
|                                                  TWriter writer) { | ||||
|   return TDeserializer<TReader, TWriter>(pool, reader, writer); | ||||
| } | ||||
|  | ||||
| // deserialize(JsonDocument&, const std::string&, NestingLimit, Filter); | ||||
| @@ -34,8 +34,8 @@ deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit, | ||||
|   doc.clear(); | ||||
|   return makeDeserializer<TDeserializer>( | ||||
|              doc.memoryPool(), reader, | ||||
|              makeStringStorage(doc.memoryPool(), input), nestingLimit.value) | ||||
|       .parse(doc.data(), filter); | ||||
|              makeStringStorage(doc.memoryPool(), input)) | ||||
|       .parse(doc.data(), filter, nestingLimit); | ||||
| } | ||||
| // | ||||
| // deserialize(JsonDocument&, char*, size_t, NestingLimit, Filter); | ||||
| @@ -50,8 +50,8 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input, | ||||
|   doc.clear(); | ||||
|   return makeDeserializer<TDeserializer>( | ||||
|              doc.memoryPool(), reader, | ||||
|              makeStringStorage(doc.memoryPool(), input), nestingLimit.value) | ||||
|       .parse(doc.data(), filter); | ||||
|              makeStringStorage(doc.memoryPool(), input)) | ||||
|       .parse(doc.data(), filter, nestingLimit); | ||||
| } | ||||
| // | ||||
| // deserialize(JsonDocument&, std::istream&, NestingLimit, Filter); | ||||
| @@ -64,8 +64,8 @@ DeserializationError deserialize(JsonDocument &doc, TStream &input, | ||||
|   doc.clear(); | ||||
|   return makeDeserializer<TDeserializer>( | ||||
|              doc.memoryPool(), reader, | ||||
|              makeStringStorage(doc.memoryPool(), input), nestingLimit.value) | ||||
|       .parse(doc.data(), filter); | ||||
|              makeStringStorage(doc.memoryPool(), input)) | ||||
|       .parse(doc.data(), filter, nestingLimit); | ||||
| } | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -23,15 +23,13 @@ class JsonDeserializer { | ||||
|  | ||||
|  public: | ||||
|   JsonDeserializer(MemoryPool &pool, TReader reader, | ||||
|                    TStringStorage stringStorage, uint8_t nestingLimit) | ||||
|       : _pool(&pool), | ||||
|         _stringStorage(stringStorage), | ||||
|         _nestingLimit(nestingLimit), | ||||
|         _latch(reader) {} | ||||
|                    TStringStorage stringStorage) | ||||
|       : _pool(&pool), _stringStorage(stringStorage), _latch(reader) {} | ||||
|  | ||||
|   template <typename TFilter> | ||||
|   DeserializationError parse(VariantData &variant, TFilter filter) { | ||||
|     DeserializationError err = parseVariant(variant, filter); | ||||
|   DeserializationError parse(VariantData &variant, TFilter filter, | ||||
|                              NestingLimit nestingLimit) { | ||||
|     DeserializationError 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 | ||||
| @@ -59,22 +57,23 @@ class JsonDeserializer { | ||||
|   } | ||||
|  | ||||
|   template <typename TFilter> | ||||
|   DeserializationError parseVariant(VariantData &variant, TFilter filter) { | ||||
|   DeserializationError parseVariant(VariantData &variant, TFilter filter, | ||||
|                                     NestingLimit nestingLimit) { | ||||
|     DeserializationError err = skipSpacesAndComments(); | ||||
|     if (err) return err; | ||||
|  | ||||
|     switch (current()) { | ||||
|       case '[': | ||||
|         if (filter.allowArray()) | ||||
|           return parseArray(variant.toArray(), filter); | ||||
|           return parseArray(variant.toArray(), filter, nestingLimit); | ||||
|         else | ||||
|           return skipArray(); | ||||
|           return skipArray(nestingLimit); | ||||
|  | ||||
|       case '{': | ||||
|         if (filter.allowObject()) | ||||
|           return parseObject(variant.toObject(), filter); | ||||
|           return parseObject(variant.toObject(), filter, nestingLimit); | ||||
|         else | ||||
|           return skipObject(); | ||||
|           return skipObject(nestingLimit); | ||||
|  | ||||
|       case '\"': | ||||
|       case '\'': | ||||
| @@ -91,16 +90,16 @@ class JsonDeserializer { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   DeserializationError skipVariant() { | ||||
|   DeserializationError skipVariant(NestingLimit nestingLimit) { | ||||
|     DeserializationError err = skipSpacesAndComments(); | ||||
|     if (err) return err; | ||||
|  | ||||
|     switch (current()) { | ||||
|       case '[': | ||||
|         return skipArray(); | ||||
|         return skipArray(nestingLimit); | ||||
|  | ||||
|       case '{': | ||||
|         return skipObject(); | ||||
|         return skipObject(nestingLimit); | ||||
|  | ||||
|       case '\"': | ||||
|       case '\'': | ||||
| @@ -112,8 +111,9 @@ class JsonDeserializer { | ||||
|   } | ||||
|  | ||||
|   template <typename TFilter> | ||||
|   DeserializationError parseArray(CollectionData &array, TFilter filter) { | ||||
|     if (_nestingLimit == 0) return DeserializationError::TooDeep; | ||||
|   DeserializationError parseArray(CollectionData &array, TFilter filter, | ||||
|                                   NestingLimit nestingLimit) { | ||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; | ||||
|  | ||||
|     // Check opening braket | ||||
|     if (!eat('[')) return DeserializationError::InvalidInput; | ||||
| @@ -135,14 +135,10 @@ class JsonDeserializer { | ||||
|         if (!value) return DeserializationError::NoMemory; | ||||
|  | ||||
|         // 1 - Parse value | ||||
|         _nestingLimit--; | ||||
|         err = parseVariant(*value, memberFilter); | ||||
|         _nestingLimit++; | ||||
|         err = parseVariant(*value, memberFilter, nestingLimit.decrement()); | ||||
|         if (err) return err; | ||||
|       } else { | ||||
|         _nestingLimit--; | ||||
|         err = skipVariant(); | ||||
|         _nestingLimit++; | ||||
|         err = skipVariant(nestingLimit.decrement()); | ||||
|         if (err) return err; | ||||
|       } | ||||
|  | ||||
| @@ -156,8 +152,8 @@ class JsonDeserializer { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   DeserializationError skipArray() { | ||||
|     if (_nestingLimit == 0) return DeserializationError::TooDeep; | ||||
|   DeserializationError skipArray(NestingLimit nestingLimit) { | ||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; | ||||
|  | ||||
|     // Check opening braket | ||||
|     if (!eat('[')) return DeserializationError::InvalidInput; | ||||
| @@ -165,9 +161,7 @@ class JsonDeserializer { | ||||
|     // Read each value | ||||
|     for (;;) { | ||||
|       // 1 - Skip value | ||||
|       _nestingLimit--; | ||||
|       DeserializationError err = skipVariant(); | ||||
|       _nestingLimit++; | ||||
|       DeserializationError err = skipVariant(nestingLimit.decrement()); | ||||
|       if (err) return err; | ||||
|  | ||||
|       // 2 - Skip spaces | ||||
| @@ -181,8 +175,9 @@ class JsonDeserializer { | ||||
|   } | ||||
|  | ||||
|   template <typename TFilter> | ||||
|   DeserializationError parseObject(CollectionData &object, TFilter filter) { | ||||
|     if (_nestingLimit == 0) return DeserializationError::TooDeep; | ||||
|   DeserializationError parseObject(CollectionData &object, TFilter filter, | ||||
|                                    NestingLimit nestingLimit) { | ||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; | ||||
|  | ||||
|     // Check opening brace | ||||
|     if (!eat('{')) return DeserializationError::InvalidInput; | ||||
| @@ -221,15 +216,11 @@ class JsonDeserializer { | ||||
|         } | ||||
|  | ||||
|         // Parse value | ||||
|         _nestingLimit--; | ||||
|         err = parseVariant(*variant, memberFilter); | ||||
|         _nestingLimit++; | ||||
|         err = parseVariant(*variant, memberFilter, nestingLimit.decrement()); | ||||
|         if (err) return err; | ||||
|       } else { | ||||
|         _stringStorage.reclaim(key); | ||||
|         _nestingLimit--; | ||||
|         err = skipVariant(); | ||||
|         _nestingLimit++; | ||||
|         err = skipVariant(nestingLimit.decrement()); | ||||
|         if (err) return err; | ||||
|       } | ||||
|  | ||||
| @@ -247,8 +238,8 @@ class JsonDeserializer { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   DeserializationError skipObject() { | ||||
|     if (_nestingLimit == 0) return DeserializationError::TooDeep; | ||||
|   DeserializationError skipObject(NestingLimit nestingLimit) { | ||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; | ||||
|  | ||||
|     // Check opening brace | ||||
|     if (!eat('{')) return DeserializationError::InvalidInput; | ||||
| @@ -263,7 +254,7 @@ class JsonDeserializer { | ||||
|     // Read each key value pair | ||||
|     for (;;) { | ||||
|       // Skip key | ||||
|       err = skipVariant(); | ||||
|       err = skipVariant(nestingLimit.decrement()); | ||||
|       if (err) return err; | ||||
|  | ||||
|       // Skip spaces | ||||
| @@ -272,9 +263,7 @@ class JsonDeserializer { | ||||
|       if (!eat(':')) return DeserializationError::InvalidInput; | ||||
|  | ||||
|       // Skip value | ||||
|       _nestingLimit--; | ||||
|       err = skipVariant(); | ||||
|       _nestingLimit++; | ||||
|       err = skipVariant(nestingLimit.decrement()); | ||||
|       if (err) return err; | ||||
|  | ||||
|       // Skip spaces | ||||
| @@ -538,7 +527,6 @@ class JsonDeserializer { | ||||
|  | ||||
|   MemoryPool *_pool; | ||||
|   TStringStorage _stringStorage; | ||||
|   uint8_t _nestingLimit; | ||||
|   Latch<TReader> _latch; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -20,15 +20,16 @@ class MsgPackDeserializer { | ||||
|  | ||||
|  public: | ||||
|   MsgPackDeserializer(MemoryPool &pool, TReader reader, | ||||
|                       TStringStorage stringStorage, uint8_t nestingLimit) | ||||
|       : _pool(&pool), | ||||
|         _reader(reader), | ||||
|         _stringStorage(stringStorage), | ||||
|         _nestingLimit(nestingLimit) {} | ||||
|                       TStringStorage stringStorage) | ||||
|       : _pool(&pool), _reader(reader), _stringStorage(stringStorage) {} | ||||
|  | ||||
|   // TODO: add support for filter | ||||
|   DeserializationError parse(VariantData &variant, | ||||
|                              AllowAllFilter = AllowAllFilter()) { | ||||
|   DeserializationError parse(VariantData &variant, AllowAllFilter, | ||||
|                              NestingLimit nestingLimit) { | ||||
|     return parse(variant, nestingLimit); | ||||
|   } | ||||
|  | ||||
|   DeserializationError parse(VariantData &variant, NestingLimit nestingLimit) { | ||||
|     uint8_t code; | ||||
|     if (!readByte(code)) return DeserializationError::IncompleteInput; | ||||
|  | ||||
| @@ -48,11 +49,11 @@ class MsgPackDeserializer { | ||||
|     } | ||||
|  | ||||
|     if ((code & 0xf0) == 0x90) { | ||||
|       return readArray(variant.toArray(), code & 0x0F); | ||||
|       return readArray(variant.toArray(), code & 0x0F, nestingLimit); | ||||
|     } | ||||
|  | ||||
|     if ((code & 0xf0) == 0x80) { | ||||
|       return readObject(variant.toObject(), code & 0x0F); | ||||
|       return readObject(variant.toObject(), code & 0x0F, nestingLimit); | ||||
|     } | ||||
|  | ||||
|     switch (code) { | ||||
| @@ -116,16 +117,16 @@ class MsgPackDeserializer { | ||||
|         return readString<uint32_t>(variant); | ||||
|  | ||||
|       case 0xdc: | ||||
|         return readArray<uint16_t>(variant.toArray()); | ||||
|         return readArray<uint16_t>(variant.toArray(), nestingLimit); | ||||
|  | ||||
|       case 0xdd: | ||||
|         return readArray<uint32_t>(variant.toArray()); | ||||
|         return readArray<uint32_t>(variant.toArray(), nestingLimit); | ||||
|  | ||||
|       case 0xde: | ||||
|         return readObject<uint16_t>(variant.toObject()); | ||||
|         return readObject<uint16_t>(variant.toObject(), nestingLimit); | ||||
|  | ||||
|       case 0xdf: | ||||
|         return readObject<uint32_t>(variant.toObject()); | ||||
|         return readObject<uint32_t>(variant.toObject(), nestingLimit); | ||||
|  | ||||
|       default: | ||||
|         return DeserializationError::NotSupported; | ||||
| @@ -242,36 +243,40 @@ class MsgPackDeserializer { | ||||
|   } | ||||
|  | ||||
|   template <typename TSize> | ||||
|   DeserializationError readArray(CollectionData &array) { | ||||
|   DeserializationError readArray(CollectionData &array, | ||||
|                                  NestingLimit nestingLimit) { | ||||
|     TSize size; | ||||
|     if (!readInteger(size)) return DeserializationError::IncompleteInput; | ||||
|     return readArray(array, size); | ||||
|     return readArray(array, size, nestingLimit); | ||||
|   } | ||||
|  | ||||
|   DeserializationError readArray(CollectionData &array, size_t n) { | ||||
|     if (_nestingLimit == 0) return DeserializationError::TooDeep; | ||||
|     --_nestingLimit; | ||||
|   DeserializationError readArray(CollectionData &array, size_t n, | ||||
|                                  NestingLimit nestingLimit) { | ||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; | ||||
|  | ||||
|     for (; n; --n) { | ||||
|       VariantData *value = array.add(_pool); | ||||
|       if (!value) return DeserializationError::NoMemory; | ||||
|  | ||||
|       DeserializationError err = parse(*value); | ||||
|       DeserializationError err = parse(*value, nestingLimit.decrement()); | ||||
|       if (err) return err; | ||||
|     } | ||||
|     ++_nestingLimit; | ||||
|  | ||||
|     return DeserializationError::Ok; | ||||
|   } | ||||
|  | ||||
|   template <typename TSize> | ||||
|   DeserializationError readObject(CollectionData &object) { | ||||
|   DeserializationError readObject(CollectionData &object, | ||||
|                                   NestingLimit nestingLimit) { | ||||
|     TSize size; | ||||
|     if (!readInteger(size)) return DeserializationError::IncompleteInput; | ||||
|     return readObject(object, size); | ||||
|     return readObject(object, size, nestingLimit); | ||||
|   } | ||||
|  | ||||
|   DeserializationError readObject(CollectionData &object, size_t n) { | ||||
|     if (_nestingLimit == 0) return DeserializationError::TooDeep; | ||||
|     --_nestingLimit; | ||||
|   DeserializationError readObject(CollectionData &object, size_t n, | ||||
|                                   NestingLimit nestingLimit) { | ||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; | ||||
|  | ||||
|     for (; n; --n) { | ||||
|       VariantSlot *slot = object.addSlot(_pool); | ||||
|       if (!slot) return DeserializationError::NoMemory; | ||||
| @@ -281,10 +286,10 @@ class MsgPackDeserializer { | ||||
|       if (err) return err; | ||||
|       slot->setOwnedKey(make_not_null(key)); | ||||
|  | ||||
|       err = parse(*slot->data()); | ||||
|       err = parse(*slot->data(), nestingLimit.decrement()); | ||||
|       if (err) return err; | ||||
|     } | ||||
|     ++_nestingLimit; | ||||
|  | ||||
|     return DeserializationError::Ok; | ||||
|   } | ||||
|  | ||||
| @@ -312,7 +317,6 @@ class MsgPackDeserializer { | ||||
|   MemoryPool *_pool; | ||||
|   TReader _reader; | ||||
|   TStringStorage _stringStorage; | ||||
|   uint8_t _nestingLimit; | ||||
| }; | ||||
|  | ||||
| template <typename TInput> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user