mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Added a line-break after each "if" to get more accurate coverage report
This commit is contained in:
		| @@ -3,3 +3,6 @@ | |||||||
| BasedOnStyle: Google | BasedOnStyle: Google | ||||||
| Standard: Cpp03 | Standard: Cpp03 | ||||||
| AllowShortFunctionsOnASingleLine: Empty | AllowShortFunctionsOnASingleLine: Empty | ||||||
|  |  | ||||||
|  | # Always break after if to get accurate coverage | ||||||
|  | AllowShortIfStatementsOnASingleLine: false | ||||||
|   | |||||||
| @@ -21,9 +21,10 @@ inline void arrayAccept(const CollectionData *arr, Visitor &visitor) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) { | inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) { | ||||||
|   if (lhs == rhs) return true; |   if (lhs == rhs) | ||||||
|   if (!lhs || !rhs) return false; |     return true; | ||||||
|  |   if (!lhs || !rhs) | ||||||
|  |     return false; | ||||||
|   return lhs->equalsArray(*rhs); |   return lhs->equalsArray(*rhs); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -66,7 +66,8 @@ class ArrayConstRef : public ArrayRefBase<const CollectionData>, | |||||||
|   typedef ArrayConstRefIterator iterator; |   typedef ArrayConstRefIterator iterator; | ||||||
|  |  | ||||||
|   FORCE_INLINE iterator begin() const { |   FORCE_INLINE iterator begin() const { | ||||||
|     if (!_data) return iterator(); |     if (!_data) | ||||||
|  |       return iterator(); | ||||||
|     return iterator(_data->head()); |     return iterator(_data->head()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -116,7 +117,8 @@ class ArrayRef : public ArrayRefBase<CollectionData>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE iterator begin() const { |   FORCE_INLINE iterator begin() const { | ||||||
|     if (!_data) return iterator(); |     if (!_data) | ||||||
|  |       return iterator(); | ||||||
|     return iterator(_pool, _data->head()); |     return iterator(_pool, _data->head()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -126,7 +128,8 @@ class ArrayRef : public ArrayRefBase<CollectionData>, | |||||||
|  |  | ||||||
|   // Copy a ArrayRef |   // Copy a ArrayRef | ||||||
|   FORCE_INLINE bool set(ArrayConstRef src) const { |   FORCE_INLINE bool set(ArrayConstRef src) const { | ||||||
|     if (!_data || !src._data) return false; |     if (!_data || !src._data) | ||||||
|  |       return false; | ||||||
|     return _data->copyFrom(*src._data, _pool); |     return _data->copyFrom(*src._data, _pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -141,13 +144,15 @@ class ArrayRef : public ArrayRefBase<CollectionData>, | |||||||
|  |  | ||||||
|   // Removes element at specified position. |   // Removes element at specified position. | ||||||
|   FORCE_INLINE void remove(iterator it) const { |   FORCE_INLINE void remove(iterator it) const { | ||||||
|     if (!_data) return; |     if (!_data) | ||||||
|  |       return; | ||||||
|     _data->remove(it.internal()); |     _data->remove(it.internal()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Removes element at specified index. |   // Removes element at specified index. | ||||||
|   FORCE_INLINE void remove(size_t index) const { |   FORCE_INLINE void remove(size_t index) const { | ||||||
|     if (!_data) return; |     if (!_data) | ||||||
|  |       return; | ||||||
|     _data->remove(index); |     _data->remove(index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,8 @@ namespace ARDUINOJSON_NAMESPACE { | |||||||
|  |  | ||||||
| inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { | inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { | ||||||
|   VariantSlot* slot = pool->allocVariant(); |   VariantSlot* slot = pool->allocVariant(); | ||||||
|   if (!slot) return 0; |   if (!slot) | ||||||
|  |     return 0; | ||||||
|  |  | ||||||
|   if (_tail) { |   if (_tail) { | ||||||
|     _tail->setNextNotNull(slot); |     _tail->setNextNotNull(slot); | ||||||
| @@ -32,7 +33,8 @@ inline VariantData* CollectionData::add(MemoryPool* pool) { | |||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) { | inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) { | ||||||
|   VariantSlot* slot = addSlot(pool); |   VariantSlot* slot = addSlot(pool); | ||||||
|   if (!slotSetKey(slot, key, pool)) return 0; |   if (!slotSetKey(slot, key, pool)) | ||||||
|  |     return 0; | ||||||
|   return slot->data(); |   return slot->data(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -59,8 +61,10 @@ inline bool CollectionData::copyFrom(const CollectionData& src, | |||||||
|     } else { |     } else { | ||||||
|       var = add(pool); |       var = add(pool); | ||||||
|     } |     } | ||||||
|     if (!var) return false; |     if (!var) | ||||||
|     if (!var->copyFrom(*s->data(), pool)) return false; |       return false; | ||||||
|  |     if (!var->copyFrom(*s->data(), pool)) | ||||||
|  |       return false; | ||||||
|   } |   } | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| @@ -70,7 +74,8 @@ inline bool CollectionData::equalsObject(const CollectionData& other) const { | |||||||
|   for (VariantSlot* slot = _head; slot; slot = slot->next()) { |   for (VariantSlot* slot = _head; slot; slot = slot->next()) { | ||||||
|     VariantData* v1 = slot->data(); |     VariantData* v1 = slot->data(); | ||||||
|     VariantData* v2 = other.get(adaptString(slot->key())); |     VariantData* v2 = other.get(adaptString(slot->key())); | ||||||
|     if (!variantEquals(v1, v2)) return false; |     if (!variantEquals(v1, v2)) | ||||||
|  |       return false; | ||||||
|     count++; |     count++; | ||||||
|   } |   } | ||||||
|   return count == other.size(); |   return count == other.size(); | ||||||
| @@ -80,9 +85,12 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const { | |||||||
|   VariantSlot* s1 = _head; |   VariantSlot* s1 = _head; | ||||||
|   VariantSlot* s2 = other._head; |   VariantSlot* s2 = other._head; | ||||||
|   for (;;) { |   for (;;) { | ||||||
|     if (s1 == s2) return true; |     if (s1 == s2) | ||||||
|     if (!s1 || !s2) return false; |       return true; | ||||||
|     if (!variantEquals(s1->data(), s2->data())) return false; |     if (!s1 || !s2) | ||||||
|  |       return false; | ||||||
|  |     if (!variantEquals(s1->data(), s2->data())) | ||||||
|  |       return false; | ||||||
|     s1 = s1->next(); |     s1 = s1->next(); | ||||||
|     s2 = s2->next(); |     s2 = s2->next(); | ||||||
|   } |   } | ||||||
| @@ -92,7 +100,8 @@ template <typename TAdaptedString> | |||||||
| inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const { | inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const { | ||||||
|   VariantSlot* slot = _head; |   VariantSlot* slot = _head; | ||||||
|   while (slot) { |   while (slot) { | ||||||
|     if (key.equals(slot->key())) break; |     if (key.equals(slot->key())) | ||||||
|  |       break; | ||||||
|     slot = slot->next(); |     slot = slot->next(); | ||||||
|   } |   } | ||||||
|   return slot; |   return slot; | ||||||
| @@ -106,7 +115,8 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const { | |||||||
|   VariantSlot* current = _head; |   VariantSlot* current = _head; | ||||||
|   while (current) { |   while (current) { | ||||||
|     VariantSlot* next = current->next(); |     VariantSlot* next = current->next(); | ||||||
|     if (next == target) return current; |     if (next == target) | ||||||
|  |       return current; | ||||||
|     current = next; |     current = next; | ||||||
|   } |   } | ||||||
|   return 0; |   return 0; | ||||||
| @@ -124,14 +134,16 @@ inline VariantData* CollectionData::get(size_t index) const { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline void CollectionData::remove(VariantSlot* slot) { | inline void CollectionData::remove(VariantSlot* slot) { | ||||||
|   if (!slot) return; |   if (!slot) | ||||||
|  |     return; | ||||||
|   VariantSlot* prev = getPreviousSlot(slot); |   VariantSlot* prev = getPreviousSlot(slot); | ||||||
|   VariantSlot* next = slot->next(); |   VariantSlot* next = slot->next(); | ||||||
|   if (prev) |   if (prev) | ||||||
|     prev->setNext(next); |     prev->setNext(next); | ||||||
|   else |   else | ||||||
|     _head = next; |     _head = next; | ||||||
|   if (!next) _tail = prev; |   if (!next) | ||||||
|  |     _tail = prev; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void CollectionData::remove(size_t index) { | inline void CollectionData::remove(size_t index) { | ||||||
| @@ -142,7 +154,8 @@ inline size_t CollectionData::memoryUsage() const { | |||||||
|   size_t total = 0; |   size_t total = 0; | ||||||
|   for (VariantSlot* s = _head; s; s = s->next()) { |   for (VariantSlot* s = _head; s; s = s->next()) { | ||||||
|     total += sizeof(VariantSlot) + s->data()->memoryUsage(); |     total += sizeof(VariantSlot) + s->data()->memoryUsage(); | ||||||
|     if (s->ownsKey()) total += strlen(s->key()) + 1; |     if (s->ownsKey()) | ||||||
|  |       total += strlen(s->key()) + 1; | ||||||
|   } |   } | ||||||
|   return total; |   return total; | ||||||
| } | } | ||||||
| @@ -151,7 +164,8 @@ inline size_t CollectionData::nesting() const { | |||||||
|   size_t maxChildNesting = 0; |   size_t maxChildNesting = 0; | ||||||
|   for (VariantSlot* s = _head; s; s = s->next()) { |   for (VariantSlot* s = _head; s; s = s->next()) { | ||||||
|     size_t childNesting = s->data()->nesting(); |     size_t childNesting = s->data()->nesting(); | ||||||
|     if (childNesting > maxChildNesting) maxChildNesting = childNesting; |     if (childNesting > maxChildNesting) | ||||||
|  |       maxChildNesting = childNesting; | ||||||
|   } |   } | ||||||
|   return maxChildNesting + 1; |   return maxChildNesting + 1; | ||||||
| } | } | ||||||
| @@ -162,7 +176,8 @@ inline size_t CollectionData::size() const { | |||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline void movePointer(T*& p, ptrdiff_t offset) { | inline void movePointer(T*& p, ptrdiff_t offset) { | ||||||
|   if (!p) return; |   if (!p) | ||||||
|  |     return; | ||||||
|   p = reinterpret_cast<T*>( |   p = reinterpret_cast<T*>( | ||||||
|       reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset)); |       reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset)); | ||||||
|   ARDUINOJSON_ASSERT(isAligned(p)); |   ARDUINOJSON_ASSERT(isAligned(p)); | ||||||
|   | |||||||
| @@ -43,7 +43,8 @@ struct BoundedReader<const __FlashStringHelper*, void> { | |||||||
|  |  | ||||||
|   size_t readBytes(char* buffer, size_t length) { |   size_t readBytes(char* buffer, size_t length) { | ||||||
|     size_t available = static_cast<size_t>(_end - _ptr); |     size_t available = static_cast<size_t>(_end - _ptr); | ||||||
|     if (available < length) length = available; |     if (available < length) | ||||||
|  |       length = available; | ||||||
|     memcpy_P(buffer, _ptr, length); |     memcpy_P(buffer, _ptr, length); | ||||||
|     _ptr += length; |     _ptr += length; | ||||||
|     return length; |     return length; | ||||||
|   | |||||||
| @@ -77,7 +77,8 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument { | |||||||
|  |  | ||||||
|   void shrinkToFit() { |   void shrinkToFit() { | ||||||
|     ptrdiff_t bytes_reclaimed = _pool.squash(); |     ptrdiff_t bytes_reclaimed = _pool.squash(); | ||||||
|     if (bytes_reclaimed == 0) return; |     if (bytes_reclaimed == 0) | ||||||
|  |       return; | ||||||
|  |  | ||||||
|     void* old_ptr = _pool.buffer(); |     void* old_ptr = _pool.buffer(); | ||||||
|     void* new_ptr = this->reallocate(old_ptr, _pool.capacity()); |     void* new_ptr = this->reallocate(old_ptr, _pool.capacity()); | ||||||
| @@ -96,7 +97,8 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void reallocPoolIfTooSmall(size_t requiredSize) { |   void reallocPoolIfTooSmall(size_t requiredSize) { | ||||||
|     if (requiredSize <= capacity()) return; |     if (requiredSize <= capacity()) | ||||||
|  |       return; | ||||||
|     freePool(); |     freePool(); | ||||||
|     replacePool(allocPool(addPadding(requiredSize))); |     replacePool(allocPool(addPadding(requiredSize))); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -23,8 +23,10 @@ class EscapeSequence { | |||||||
|   static char unescapeChar(char c) { |   static char unescapeChar(char c) { | ||||||
|     const char *p = escapeTable(true); |     const char *p = escapeTable(true); | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       if (p[0] == '\0') return c; |       if (p[0] == '\0') | ||||||
|       if (p[0] == c) return p[1]; |         return c; | ||||||
|  |       if (p[0] == c) | ||||||
|  |         return p[1]; | ||||||
|       p += 2; |       p += 2; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -52,7 +52,8 @@ class JsonDeserializer { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool eat(char charToSkip) { |   bool eat(char charToSkip) { | ||||||
|     if (current() != charToSkip) return false; |     if (current() != charToSkip) | ||||||
|  |       return false; | ||||||
|     move(); |     move(); | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| @@ -61,7 +62,8 @@ class JsonDeserializer { | |||||||
|   DeserializationError parseVariant(VariantData &variant, TFilter filter, |   DeserializationError parseVariant(VariantData &variant, TFilter filter, | ||||||
|                                     NestingLimit nestingLimit) { |                                     NestingLimit nestingLimit) { | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     DeserializationError err = skipSpacesAndComments(); | ||||||
|     if (err) return err; |     if (err) | ||||||
|  |       return err; | ||||||
|  |  | ||||||
|     switch (current()) { |     switch (current()) { | ||||||
|       case '[': |       case '[': | ||||||
| @@ -93,7 +95,8 @@ class JsonDeserializer { | |||||||
|  |  | ||||||
|   DeserializationError skipVariant(NestingLimit nestingLimit) { |   DeserializationError skipVariant(NestingLimit nestingLimit) { | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     DeserializationError err = skipSpacesAndComments(); | ||||||
|     if (err) return err; |     if (err) | ||||||
|  |       return err; | ||||||
|  |  | ||||||
|     switch (current()) { |     switch (current()) { | ||||||
|       case '[': |       case '[': | ||||||
| @@ -114,7 +117,8 @@ class JsonDeserializer { | |||||||
|   template <typename TFilter> |   template <typename TFilter> | ||||||
|   DeserializationError parseArray(CollectionData &array, TFilter filter, |   DeserializationError parseArray(CollectionData &array, TFilter filter, | ||||||
|                                   NestingLimit nestingLimit) { |                                   NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; |     if (nestingLimit.reached()) | ||||||
|  |       return DeserializationError::TooDeep; | ||||||
|  |  | ||||||
|     // Skip opening braket |     // Skip opening braket | ||||||
|     ARDUINOJSON_ASSERT(current() == '['); |     ARDUINOJSON_ASSERT(current() == '['); | ||||||
| @@ -122,10 +126,12 @@ class JsonDeserializer { | |||||||
|  |  | ||||||
|     // Skip spaces |     // Skip spaces | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     DeserializationError err = skipSpacesAndComments(); | ||||||
|     if (err) return err; |     if (err) | ||||||
|  |       return err; | ||||||
|  |  | ||||||
|     // Empty array? |     // Empty array? | ||||||
|     if (eat(']')) return DeserializationError::Ok; |     if (eat(']')) | ||||||
|  |       return DeserializationError::Ok; | ||||||
|  |  | ||||||
|     TFilter memberFilter = filter[0UL]; |     TFilter memberFilter = filter[0UL]; | ||||||
|  |  | ||||||
| @@ -134,28 +140,35 @@ class JsonDeserializer { | |||||||
|       if (memberFilter.allow()) { |       if (memberFilter.allow()) { | ||||||
|         // Allocate slot in array |         // Allocate slot in array | ||||||
|         VariantData *value = array.add(_pool); |         VariantData *value = array.add(_pool); | ||||||
|         if (!value) return DeserializationError::NoMemory; |         if (!value) | ||||||
|  |           return DeserializationError::NoMemory; | ||||||
|  |  | ||||||
|         // 1 - Parse value |         // 1 - Parse value | ||||||
|         err = parseVariant(*value, memberFilter, nestingLimit.decrement()); |         err = parseVariant(*value, memberFilter, nestingLimit.decrement()); | ||||||
|         if (err) return err; |         if (err) | ||||||
|  |           return err; | ||||||
|       } else { |       } else { | ||||||
|         err = skipVariant(nestingLimit.decrement()); |         err = skipVariant(nestingLimit.decrement()); | ||||||
|         if (err) return err; |         if (err) | ||||||
|  |           return err; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // 2 - Skip spaces |       // 2 - Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       err = skipSpacesAndComments(); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|  |  | ||||||
|       // 3 - More values? |       // 3 - More values? | ||||||
|       if (eat(']')) return DeserializationError::Ok; |       if (eat(']')) | ||||||
|       if (!eat(',')) return DeserializationError::InvalidInput; |         return DeserializationError::Ok; | ||||||
|  |       if (!eat(',')) | ||||||
|  |         return DeserializationError::InvalidInput; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError skipArray(NestingLimit nestingLimit) { |   DeserializationError skipArray(NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; |     if (nestingLimit.reached()) | ||||||
|  |       return DeserializationError::TooDeep; | ||||||
|  |  | ||||||
|     // Skip opening braket |     // Skip opening braket | ||||||
|     ARDUINOJSON_ASSERT(current() == '['); |     ARDUINOJSON_ASSERT(current() == '['); | ||||||
| @@ -165,22 +178,27 @@ class JsonDeserializer { | |||||||
|     for (;;) { |     for (;;) { | ||||||
|       // 1 - Skip value |       // 1 - Skip value | ||||||
|       DeserializationError err = skipVariant(nestingLimit.decrement()); |       DeserializationError err = skipVariant(nestingLimit.decrement()); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|  |  | ||||||
|       // 2 - Skip spaces |       // 2 - Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       err = skipSpacesAndComments(); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|  |  | ||||||
|       // 3 - More values? |       // 3 - More values? | ||||||
|       if (eat(']')) return DeserializationError::Ok; |       if (eat(']')) | ||||||
|       if (!eat(',')) return DeserializationError::InvalidInput; |         return DeserializationError::Ok; | ||||||
|  |       if (!eat(',')) | ||||||
|  |         return DeserializationError::InvalidInput; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TFilter> |   template <typename TFilter> | ||||||
|   DeserializationError parseObject(CollectionData &object, TFilter filter, |   DeserializationError parseObject(CollectionData &object, TFilter filter, | ||||||
|                                    NestingLimit nestingLimit) { |                                    NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; |     if (nestingLimit.reached()) | ||||||
|  |       return DeserializationError::TooDeep; | ||||||
|  |  | ||||||
|     // Skip opening brace |     // Skip opening brace | ||||||
|     ARDUINOJSON_ASSERT(current() == '{'); |     ARDUINOJSON_ASSERT(current() == '{'); | ||||||
| @@ -188,22 +206,27 @@ class JsonDeserializer { | |||||||
|  |  | ||||||
|     // Skip spaces |     // Skip spaces | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     DeserializationError err = skipSpacesAndComments(); | ||||||
|     if (err) return err; |     if (err) | ||||||
|  |       return err; | ||||||
|  |  | ||||||
|     // Empty object? |     // Empty object? | ||||||
|     if (eat('}')) return DeserializationError::Ok; |     if (eat('}')) | ||||||
|  |       return DeserializationError::Ok; | ||||||
|  |  | ||||||
|     // Read each key value pair |     // Read each key value pair | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       // Parse key |       // Parse key | ||||||
|       const char *key; |       const char *key; | ||||||
|       err = parseKey(key); |       err = parseKey(key); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       err = skipSpacesAndComments(); | ||||||
|       if (err) return err;  // Colon |       if (err) | ||||||
|       if (!eat(':')) return DeserializationError::InvalidInput; |         return err;  // Colon | ||||||
|  |       if (!eat(':')) | ||||||
|  |         return DeserializationError::InvalidInput; | ||||||
|  |  | ||||||
|       TFilter memberFilter = filter[key]; |       TFilter memberFilter = filter[key]; | ||||||
|  |  | ||||||
| @@ -212,7 +235,8 @@ class JsonDeserializer { | |||||||
|         if (!variant) { |         if (!variant) { | ||||||
|           // Allocate slot in object |           // Allocate slot in object | ||||||
|           VariantSlot *slot = object.addSlot(_pool); |           VariantSlot *slot = object.addSlot(_pool); | ||||||
|           if (!slot) return DeserializationError::NoMemory; |           if (!slot) | ||||||
|  |             return DeserializationError::NoMemory; | ||||||
|  |  | ||||||
|           slot->setOwnedKey(make_not_null(key)); |           slot->setOwnedKey(make_not_null(key)); | ||||||
|  |  | ||||||
| @@ -221,29 +245,36 @@ class JsonDeserializer { | |||||||
|  |  | ||||||
|         // Parse value |         // Parse value | ||||||
|         err = parseVariant(*variant, memberFilter, nestingLimit.decrement()); |         err = parseVariant(*variant, memberFilter, nestingLimit.decrement()); | ||||||
|         if (err) return err; |         if (err) | ||||||
|  |           return err; | ||||||
|       } else { |       } else { | ||||||
|         _stringStorage.reclaim(key); |         _stringStorage.reclaim(key); | ||||||
|         err = skipVariant(nestingLimit.decrement()); |         err = skipVariant(nestingLimit.decrement()); | ||||||
|         if (err) return err; |         if (err) | ||||||
|  |           return err; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       err = skipSpacesAndComments(); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|  |  | ||||||
|       // More keys/values? |       // More keys/values? | ||||||
|       if (eat('}')) return DeserializationError::Ok; |       if (eat('}')) | ||||||
|       if (!eat(',')) return DeserializationError::InvalidInput; |         return DeserializationError::Ok; | ||||||
|  |       if (!eat(',')) | ||||||
|  |         return DeserializationError::InvalidInput; | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       err = skipSpacesAndComments(); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError skipObject(NestingLimit nestingLimit) { |   DeserializationError skipObject(NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; |     if (nestingLimit.reached()) | ||||||
|  |       return DeserializationError::TooDeep; | ||||||
|  |  | ||||||
|     // Skip opening brace |     // Skip opening brace | ||||||
|     ARDUINOJSON_ASSERT(current() == '{'); |     ARDUINOJSON_ASSERT(current() == '{'); | ||||||
| @@ -251,33 +282,42 @@ class JsonDeserializer { | |||||||
|  |  | ||||||
|     // Skip spaces |     // Skip spaces | ||||||
|     DeserializationError err = skipSpacesAndComments(); |     DeserializationError err = skipSpacesAndComments(); | ||||||
|     if (err) return err; |     if (err) | ||||||
|  |       return err; | ||||||
|  |  | ||||||
|     // Empty object? |     // Empty object? | ||||||
|     if (eat('}')) return DeserializationError::Ok; |     if (eat('}')) | ||||||
|  |       return DeserializationError::Ok; | ||||||
|  |  | ||||||
|     // Read each key value pair |     // Read each key value pair | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       // Skip key |       // Skip key | ||||||
|       err = skipVariant(nestingLimit.decrement()); |       err = skipVariant(nestingLimit.decrement()); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       err = skipSpacesAndComments(); | ||||||
|       if (err) return err;  // Colon |       if (err) | ||||||
|       if (!eat(':')) return DeserializationError::InvalidInput; |         return err;  // Colon | ||||||
|  |       if (!eat(':')) | ||||||
|  |         return DeserializationError::InvalidInput; | ||||||
|  |  | ||||||
|       // Skip value |       // Skip value | ||||||
|       err = skipVariant(nestingLimit.decrement()); |       err = skipVariant(nestingLimit.decrement()); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|  |  | ||||||
|       // Skip spaces |       // Skip spaces | ||||||
|       err = skipSpacesAndComments(); |       err = skipSpacesAndComments(); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|  |  | ||||||
|       // More keys/values? |       // More keys/values? | ||||||
|       if (eat('}')) return DeserializationError::Ok; |       if (eat('}')) | ||||||
|       if (!eat(',')) return DeserializationError::InvalidInput; |         return DeserializationError::Ok; | ||||||
|  |       if (!eat(',')) | ||||||
|  |         return DeserializationError::InvalidInput; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -292,7 +332,8 @@ class JsonDeserializer { | |||||||
|   DeserializationError parseStringValue(VariantData &variant) { |   DeserializationError parseStringValue(VariantData &variant) { | ||||||
|     const char *value; |     const char *value; | ||||||
|     DeserializationError err = parseQuotedString(value); |     DeserializationError err = parseQuotedString(value); | ||||||
|     if (err) return err; |     if (err) | ||||||
|  |       return err; | ||||||
|     variant.setOwnedString(make_not_null(value)); |     variant.setOwnedString(make_not_null(value)); | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
|   } |   } | ||||||
| @@ -308,19 +349,23 @@ class JsonDeserializer { | |||||||
|     for (;;) { |     for (;;) { | ||||||
|       char c = current(); |       char c = current(); | ||||||
|       move(); |       move(); | ||||||
|       if (c == stopChar) break; |       if (c == stopChar) | ||||||
|  |         break; | ||||||
|  |  | ||||||
|       if (c == '\0') return DeserializationError::IncompleteInput; |       if (c == '\0') | ||||||
|  |         return DeserializationError::IncompleteInput; | ||||||
|  |  | ||||||
|       if (c == '\\') { |       if (c == '\\') { | ||||||
|         c = current(); |         c = current(); | ||||||
|         if (c == '\0') return DeserializationError::IncompleteInput; |         if (c == '\0') | ||||||
|  |           return DeserializationError::IncompleteInput; | ||||||
|         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); |           DeserializationError err = parseHex4(codeunit); | ||||||
|           if (err) return err; |           if (err) | ||||||
|  |             return err; | ||||||
|           if (codepoint.append(codeunit)) |           if (codepoint.append(codeunit)) | ||||||
|             Utf8::encodeCodepoint(codepoint.value(), builder); |             Utf8::encodeCodepoint(codepoint.value(), builder); | ||||||
|           continue; |           continue; | ||||||
| @@ -330,7 +375,8 @@ class JsonDeserializer { | |||||||
|         } |         } | ||||||
|         // replace char |         // replace char | ||||||
|         c = EscapeSequence::unescapeChar(c); |         c = EscapeSequence::unescapeChar(c); | ||||||
|         if (c == '\0') return DeserializationError::InvalidInput; |         if (c == '\0') | ||||||
|  |           return DeserializationError::InvalidInput; | ||||||
|         move(); |         move(); | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -338,7 +384,8 @@ class JsonDeserializer { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     result = builder.complete(); |     result = builder.complete(); | ||||||
|     if (!result) return DeserializationError::NoMemory; |     if (!result) | ||||||
|  |       return DeserializationError::NoMemory; | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -346,7 +393,8 @@ class JsonDeserializer { | |||||||
|     StringBuilder builder = _stringStorage.startString(); |     StringBuilder builder = _stringStorage.startString(); | ||||||
|  |  | ||||||
|     char c = current(); |     char c = current(); | ||||||
|     if (c == '\0') return DeserializationError::IncompleteInput; |     if (c == '\0') | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|  |  | ||||||
|     if (canBeInNonQuotedString(c)) {  // no quotes |     if (canBeInNonQuotedString(c)) {  // no quotes | ||||||
|       do { |       do { | ||||||
| @@ -359,7 +407,8 @@ class JsonDeserializer { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     result = builder.complete(); |     result = builder.complete(); | ||||||
|     if (!result) return DeserializationError::NoMemory; |     if (!result) | ||||||
|  |       return DeserializationError::NoMemory; | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -370,10 +419,13 @@ class JsonDeserializer { | |||||||
|     for (;;) { |     for (;;) { | ||||||
|       char c = current(); |       char c = current(); | ||||||
|       move(); |       move(); | ||||||
|       if (c == stopChar) break; |       if (c == stopChar) | ||||||
|       if (c == '\0') return DeserializationError::IncompleteInput; |         break; | ||||||
|  |       if (c == '\0') | ||||||
|  |         return DeserializationError::IncompleteInput; | ||||||
|       if (c == '\\') { |       if (c == '\\') { | ||||||
|         if (current() != '\0') move(); |         if (current() != '\0') | ||||||
|  |           move(); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -441,9 +493,11 @@ class JsonDeserializer { | |||||||
|     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) return DeserializationError::IncompleteInput; |       if (!digit) | ||||||
|  |         return DeserializationError::IncompleteInput; | ||||||
|       uint8_t value = decodeHex(digit); |       uint8_t value = decodeHex(digit); | ||||||
|       if (value > 0x0F) return DeserializationError::InvalidInput; |       if (value > 0x0F) | ||||||
|  |         return DeserializationError::InvalidInput; | ||||||
|       result = uint16_t((result << 4) | value); |       result = uint16_t((result << 4) | value); | ||||||
|       move(); |       move(); | ||||||
|     } |     } | ||||||
| @@ -464,7 +518,8 @@ class JsonDeserializer { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   static inline uint8_t decodeHex(char c) { |   static inline uint8_t decodeHex(char c) { | ||||||
|     if (c < 'A') return uint8_t(c - '0'); |     if (c < 'A') | ||||||
|  |       return uint8_t(c - '0'); | ||||||
|     c = char(c & ~0x20);  // uppercase |     c = char(c & ~0x20);  // uppercase | ||||||
|     return uint8_t(c - 'A' + 10); |     return uint8_t(c - 'A' + 10); | ||||||
|   } |   } | ||||||
| @@ -495,7 +550,8 @@ class JsonDeserializer { | |||||||
|               bool wasStar = false; |               bool wasStar = false; | ||||||
|               for (;;) { |               for (;;) { | ||||||
|                 char c = current(); |                 char c = current(); | ||||||
|                 if (c == '\0') return DeserializationError::IncompleteInput; |                 if (c == '\0') | ||||||
|  |                   return DeserializationError::IncompleteInput; | ||||||
|                 if (c == '/' && wasStar) { |                 if (c == '/' && wasStar) { | ||||||
|                   move(); |                   move(); | ||||||
|                   break; |                   break; | ||||||
| @@ -512,8 +568,10 @@ class JsonDeserializer { | |||||||
|               for (;;) { |               for (;;) { | ||||||
|                 move(); |                 move(); | ||||||
|                 char c = current(); |                 char c = current(); | ||||||
|                 if (c == '\0') return DeserializationError::IncompleteInput; |                 if (c == '\0') | ||||||
|                 if (c == '\n') break; |                   return DeserializationError::IncompleteInput; | ||||||
|  |                 if (c == '\n') | ||||||
|  |                   break; | ||||||
|               } |               } | ||||||
|               break; |               break; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,7 +25,8 @@ class JsonSerializer { | |||||||
|       slot->data()->accept(*this); |       slot->data()->accept(*this); | ||||||
|  |  | ||||||
|       slot = slot->next(); |       slot = slot->next(); | ||||||
|       if (slot == 0) break; |       if (slot == 0) | ||||||
|  |         break; | ||||||
|  |  | ||||||
|       write(','); |       write(','); | ||||||
|     } |     } | ||||||
| @@ -44,7 +45,8 @@ class JsonSerializer { | |||||||
|       slot->data()->accept(*this); |       slot->data()->accept(*this); | ||||||
|  |  | ||||||
|       slot = slot->next(); |       slot = slot->next(); | ||||||
|       if (slot == 0) break; |       if (slot == 0) | ||||||
|  |         break; | ||||||
|  |  | ||||||
|       write(','); |       write(','); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -37,7 +37,8 @@ class Latch { | |||||||
|     ARDUINOJSON_ASSERT(!_ended); |     ARDUINOJSON_ASSERT(!_ended); | ||||||
|     int c = _reader.read(); |     int c = _reader.read(); | ||||||
| #ifdef ARDUINOJSON_DEBUG | #ifdef ARDUINOJSON_DEBUG | ||||||
|     if (c <= 0) _ended = true; |     if (c <= 0) | ||||||
|  |       _ended = true; | ||||||
| #endif | #endif | ||||||
|     _current = static_cast<char>(c > 0 ? c : 0); |     _current = static_cast<char>(c > 0 ? c : 0); | ||||||
|     _loaded = true; |     _loaded = true; | ||||||
|   | |||||||
| @@ -20,7 +20,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> { | |||||||
|  |  | ||||||
|   void visitArray(const CollectionData &array) { |   void visitArray(const CollectionData &array) { | ||||||
|     VariantSlot *slot = array.head(); |     VariantSlot *slot = array.head(); | ||||||
|     if (!slot) return base::write("[]"); |     if (!slot) | ||||||
|  |       return base::write("[]"); | ||||||
|  |  | ||||||
|     base::write("[\r\n"); |     base::write("[\r\n"); | ||||||
|     _nesting++; |     _nesting++; | ||||||
| @@ -38,7 +39,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> { | |||||||
|  |  | ||||||
|   void visitObject(const CollectionData &object) { |   void visitObject(const CollectionData &object) { | ||||||
|     VariantSlot *slot = object.head(); |     VariantSlot *slot = object.head(); | ||||||
|     if (!slot) return base::write("{}"); |     if (!slot) | ||||||
|  |       return base::write("{}"); | ||||||
|  |  | ||||||
|     base::write("{\r\n"); |     base::write("{\r\n"); | ||||||
|     _nesting++; |     _nesting++; | ||||||
|   | |||||||
| @@ -53,7 +53,8 @@ class TextFormatter { | |||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   void writeFloat(T value) { |   void writeFloat(T value) { | ||||||
|     if (isnan(value)) return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null"); |     if (isnan(value)) | ||||||
|  |       return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null"); | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_INFINITY | #if ARDUINOJSON_ENABLE_INFINITY | ||||||
|     if (value < 0.0) { |     if (value < 0.0) { | ||||||
| @@ -61,9 +62,11 @@ class TextFormatter { | |||||||
|       value = -value; |       value = -value; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (isinf(value)) return writeRaw("Infinity"); |     if (isinf(value)) | ||||||
|  |       return writeRaw("Infinity"); | ||||||
| #else | #else | ||||||
|     if (isinf(value)) return writeRaw("null"); |     if (isinf(value)) | ||||||
|  |       return writeRaw("null"); | ||||||
|  |  | ||||||
|     if (value < 0.0) { |     if (value < 0.0) { | ||||||
|       writeRaw('-'); |       writeRaw('-'); | ||||||
| @@ -74,7 +77,8 @@ class TextFormatter { | |||||||
|     FloatParts<T> parts(value); |     FloatParts<T> parts(value); | ||||||
|  |  | ||||||
|     writePositiveInteger(parts.integral); |     writePositiveInteger(parts.integral); | ||||||
|     if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces); |     if (parts.decimalPlaces) | ||||||
|  |       writeDecimals(parts.decimal, parts.decimalPlaces); | ||||||
|  |  | ||||||
|     if (parts.exponent < 0) { |     if (parts.exponent < 0) { | ||||||
|       writeRaw("e-"); |       writeRaw("e-"); | ||||||
|   | |||||||
| @@ -52,7 +52,8 @@ class MemoryPool { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   char* allocFrozenString(size_t n) { |   char* allocFrozenString(size_t n) { | ||||||
|     if (!canAlloc(n)) return 0; |     if (!canAlloc(n)) | ||||||
|  |       return 0; | ||||||
|     char* s = _left; |     char* s = _left; | ||||||
|     _left += n; |     _left += n; | ||||||
|     checkInvariants(); |     checkInvariants(); | ||||||
| @@ -97,7 +98,8 @@ class MemoryPool { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void* allocRight(size_t bytes) { |   void* allocRight(size_t bytes) { | ||||||
|     if (!canAlloc(bytes)) return 0; |     if (!canAlloc(bytes)) | ||||||
|  |       return 0; | ||||||
|     _right -= bytes; |     _right -= bytes; | ||||||
|     return _right; |     return _right; | ||||||
|   } |   } | ||||||
| @@ -120,7 +122,8 @@ class MemoryPool { | |||||||
|   // This funcion is called before a realloc. |   // This funcion is called before a realloc. | ||||||
|   ptrdiff_t squash() { |   ptrdiff_t squash() { | ||||||
|     char* new_right = addPadding(_left); |     char* new_right = addPadding(_left); | ||||||
|     if (new_right >= _right) return 0; |     if (new_right >= _right) | ||||||
|  |       return 0; | ||||||
|  |  | ||||||
|     size_t right_size = static_cast<size_t>(_end - _right); |     size_t right_size = static_cast<size_t>(_end - _right); | ||||||
|     memmove(new_right, _right, right_size); |     memmove(new_right, _right, right_size); | ||||||
|   | |||||||
| @@ -23,7 +23,8 @@ class StringBuilder { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void append(char c) { |   void append(char c) { | ||||||
|     if (!_slot.value) return; |     if (!_slot.value) | ||||||
|  |       return; | ||||||
|  |  | ||||||
|     if (_size >= _slot.size) { |     if (_size >= _slot.size) { | ||||||
|       _slot.value = 0; |       _slot.value = 0; | ||||||
|   | |||||||
| @@ -31,7 +31,8 @@ class MsgPackDeserializer { | |||||||
|  |  | ||||||
|   DeserializationError parse(VariantData &variant, NestingLimit nestingLimit) { |   DeserializationError parse(VariantData &variant, NestingLimit nestingLimit) { | ||||||
|     uint8_t code; |     uint8_t code; | ||||||
|     if (!readByte(code)) return DeserializationError::IncompleteInput; |     if (!readByte(code)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|  |  | ||||||
|     if ((code & 0x80) == 0) { |     if ((code & 0x80) == 0) { | ||||||
|       variant.setUnsignedInteger(code); |       variant.setUnsignedInteger(code); | ||||||
| @@ -139,7 +140,8 @@ class MsgPackDeserializer { | |||||||
|  |  | ||||||
|   bool readByte(uint8_t &value) { |   bool readByte(uint8_t &value) { | ||||||
|     int c = _reader.read(); |     int c = _reader.read(); | ||||||
|     if (c < 0) return false; |     if (c < 0) | ||||||
|  |       return false; | ||||||
|     value = static_cast<uint8_t>(c); |     value = static_cast<uint8_t>(c); | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| @@ -163,7 +165,8 @@ class MsgPackDeserializer { | |||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool readInteger(T &value) { |   bool readInteger(T &value) { | ||||||
|     if (!readBytes(value)) return false; |     if (!readBytes(value)) | ||||||
|  |       return false; | ||||||
|     fixEndianess(value); |     fixEndianess(value); | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| @@ -171,7 +174,8 @@ class MsgPackDeserializer { | |||||||
|   template <typename T> |   template <typename T> | ||||||
|   DeserializationError readInteger(VariantData &variant) { |   DeserializationError readInteger(VariantData &variant) { | ||||||
|     T value; |     T value; | ||||||
|     if (!readInteger(value)) return DeserializationError::IncompleteInput; |     if (!readInteger(value)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|     variant.setInteger(value); |     variant.setInteger(value); | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
|   } |   } | ||||||
| @@ -180,7 +184,8 @@ class MsgPackDeserializer { | |||||||
|   typename enable_if<sizeof(T) == 4, DeserializationError>::type readFloat( |   typename enable_if<sizeof(T) == 4, DeserializationError>::type readFloat( | ||||||
|       VariantData &variant) { |       VariantData &variant) { | ||||||
|     T value; |     T value; | ||||||
|     if (!readBytes(value)) return DeserializationError::IncompleteInput; |     if (!readBytes(value)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|     fixEndianess(value); |     fixEndianess(value); | ||||||
|     variant.setFloat(value); |     variant.setFloat(value); | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
| @@ -190,7 +195,8 @@ class MsgPackDeserializer { | |||||||
|   typename enable_if<sizeof(T) == 8, DeserializationError>::type readDouble( |   typename enable_if<sizeof(T) == 8, DeserializationError>::type readDouble( | ||||||
|       VariantData &variant) { |       VariantData &variant) { | ||||||
|     T value; |     T value; | ||||||
|     if (!readBytes(value)) return DeserializationError::IncompleteInput; |     if (!readBytes(value)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|     fixEndianess(value); |     fixEndianess(value); | ||||||
|     variant.setFloat(value); |     variant.setFloat(value); | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
| @@ -202,7 +208,8 @@ class MsgPackDeserializer { | |||||||
|     uint8_t i[8];  // input is 8 bytes |     uint8_t i[8];  // input is 8 bytes | ||||||
|     T value;       // output is 4 bytes |     T value;       // output is 4 bytes | ||||||
|     uint8_t *o = reinterpret_cast<uint8_t *>(&value); |     uint8_t *o = reinterpret_cast<uint8_t *>(&value); | ||||||
|     if (!readBytes(i, 8)) return DeserializationError::IncompleteInput; |     if (!readBytes(i, 8)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|     doubleToFloat(i, o); |     doubleToFloat(i, o); | ||||||
|     fixEndianess(value); |     fixEndianess(value); | ||||||
|     variant.setFloat(value); |     variant.setFloat(value); | ||||||
| @@ -212,21 +219,24 @@ class MsgPackDeserializer { | |||||||
|   template <typename T> |   template <typename T> | ||||||
|   DeserializationError readString(VariantData &variant) { |   DeserializationError readString(VariantData &variant) { | ||||||
|     T size; |     T size; | ||||||
|     if (!readInteger(size)) return DeserializationError::IncompleteInput; |     if (!readInteger(size)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|     return readString(variant, size); |     return readString(variant, size); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   DeserializationError readString(const char *&str) { |   DeserializationError readString(const char *&str) { | ||||||
|     T size; |     T size; | ||||||
|     if (!readInteger(size)) return DeserializationError::IncompleteInput; |     if (!readInteger(size)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|     return readString(str, size); |     return readString(str, size); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError readString(VariantData &variant, size_t n) { |   DeserializationError readString(VariantData &variant, size_t n) { | ||||||
|     const char *s; |     const char *s; | ||||||
|     DeserializationError err = readString(s, n); |     DeserializationError err = readString(s, n); | ||||||
|     if (!err) variant.setOwnedString(make_not_null(s)); |     if (!err) | ||||||
|  |       variant.setOwnedString(make_not_null(s)); | ||||||
|     return err; |     return err; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -234,11 +244,13 @@ class MsgPackDeserializer { | |||||||
|     StringBuilder builder = _stringStorage.startString(); |     StringBuilder builder = _stringStorage.startString(); | ||||||
|     for (; n; --n) { |     for (; n; --n) { | ||||||
|       uint8_t c; |       uint8_t c; | ||||||
|       if (!readBytes(c)) return DeserializationError::IncompleteInput; |       if (!readBytes(c)) | ||||||
|  |         return DeserializationError::IncompleteInput; | ||||||
|       builder.append(static_cast<char>(c)); |       builder.append(static_cast<char>(c)); | ||||||
|     } |     } | ||||||
|     result = builder.complete(); |     result = builder.complete(); | ||||||
|     if (!result) return DeserializationError::NoMemory; |     if (!result) | ||||||
|  |       return DeserializationError::NoMemory; | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -246,20 +258,24 @@ class MsgPackDeserializer { | |||||||
|   DeserializationError readArray(CollectionData &array, |   DeserializationError readArray(CollectionData &array, | ||||||
|                                  NestingLimit nestingLimit) { |                                  NestingLimit nestingLimit) { | ||||||
|     TSize size; |     TSize size; | ||||||
|     if (!readInteger(size)) return DeserializationError::IncompleteInput; |     if (!readInteger(size)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|     return readArray(array, size, nestingLimit); |     return readArray(array, size, nestingLimit); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError readArray(CollectionData &array, size_t n, |   DeserializationError readArray(CollectionData &array, size_t n, | ||||||
|                                  NestingLimit nestingLimit) { |                                  NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; |     if (nestingLimit.reached()) | ||||||
|  |       return DeserializationError::TooDeep; | ||||||
|  |  | ||||||
|     for (; n; --n) { |     for (; n; --n) { | ||||||
|       VariantData *value = array.add(_pool); |       VariantData *value = array.add(_pool); | ||||||
|       if (!value) return DeserializationError::NoMemory; |       if (!value) | ||||||
|  |         return DeserializationError::NoMemory; | ||||||
|  |  | ||||||
|       DeserializationError err = parse(*value, nestingLimit.decrement()); |       DeserializationError err = parse(*value, nestingLimit.decrement()); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
| @@ -269,25 +285,30 @@ class MsgPackDeserializer { | |||||||
|   DeserializationError readObject(CollectionData &object, |   DeserializationError readObject(CollectionData &object, | ||||||
|                                   NestingLimit nestingLimit) { |                                   NestingLimit nestingLimit) { | ||||||
|     TSize size; |     TSize size; | ||||||
|     if (!readInteger(size)) return DeserializationError::IncompleteInput; |     if (!readInteger(size)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|     return readObject(object, size, nestingLimit); |     return readObject(object, size, nestingLimit); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   DeserializationError readObject(CollectionData &object, size_t n, |   DeserializationError readObject(CollectionData &object, size_t n, | ||||||
|                                   NestingLimit nestingLimit) { |                                   NestingLimit nestingLimit) { | ||||||
|     if (nestingLimit.reached()) return DeserializationError::TooDeep; |     if (nestingLimit.reached()) | ||||||
|  |       return DeserializationError::TooDeep; | ||||||
|  |  | ||||||
|     for (; n; --n) { |     for (; n; --n) { | ||||||
|       VariantSlot *slot = object.addSlot(_pool); |       VariantSlot *slot = object.addSlot(_pool); | ||||||
|       if (!slot) return DeserializationError::NoMemory; |       if (!slot) | ||||||
|  |         return DeserializationError::NoMemory; | ||||||
|  |  | ||||||
|       const char *key; |       const char *key; | ||||||
|       DeserializationError err = parseKey(key); |       DeserializationError err = parseKey(key); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|       slot->setOwnedKey(make_not_null(key)); |       slot->setOwnedKey(make_not_null(key)); | ||||||
|  |  | ||||||
|       err = parse(*slot->data(), nestingLimit.decrement()); |       err = parse(*slot->data(), nestingLimit.decrement()); | ||||||
|       if (err) return err; |       if (err) | ||||||
|  |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return DeserializationError::Ok; |     return DeserializationError::Ok; | ||||||
| @@ -295,9 +316,11 @@ class MsgPackDeserializer { | |||||||
|  |  | ||||||
|   DeserializationError parseKey(const char *&key) { |   DeserializationError parseKey(const char *&key) { | ||||||
|     uint8_t code; |     uint8_t code; | ||||||
|     if (!readByte(code)) return DeserializationError::IncompleteInput; |     if (!readByte(code)) | ||||||
|  |       return DeserializationError::IncompleteInput; | ||||||
|  |  | ||||||
|     if ((code & 0xe0) == 0xa0) return readString(key, code & 0x1f); |     if ((code & 0xe0) == 0xa0) | ||||||
|  |       return readString(key, code & 0x1f); | ||||||
|  |  | ||||||
|     switch (code) { |     switch (code) { | ||||||
|       case 0xd9: |       case 0xd9: | ||||||
|   | |||||||
| @@ -70,7 +70,8 @@ class MsgPackSerializer { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void visitString(const char* value) { |   void visitString(const char* value) { | ||||||
|     if (!value) return writeByte(0xC0);  // nil |     if (!value) | ||||||
|  |       return writeByte(0xC0);  // nil | ||||||
|  |  | ||||||
|     size_t n = strlen(value); |     size_t n = strlen(value); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,13 +30,15 @@ struct FloatTraits<T, 8 /*64bits*/> { | |||||||
|   static T make_float(T m, TExponent e) { |   static T make_float(T m, TExponent e) { | ||||||
|     if (e > 0) { |     if (e > 0) { | ||||||
|       for (uint8_t index = 0; e != 0; index++) { |       for (uint8_t index = 0; e != 0; index++) { | ||||||
|         if (e & 1) m *= positiveBinaryPowerOfTen(index); |         if (e & 1) | ||||||
|  |           m *= positiveBinaryPowerOfTen(index); | ||||||
|         e >>= 1; |         e >>= 1; | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       e = TExponent(-e); |       e = TExponent(-e); | ||||||
|       for (uint8_t index = 0; e != 0; index++) { |       for (uint8_t index = 0; e != 0; index++) { | ||||||
|         if (e & 1) m *= negativeBinaryPowerOfTen(index); |         if (e & 1) | ||||||
|  |           m *= negativeBinaryPowerOfTen(index); | ||||||
|         e >>= 1; |         e >>= 1; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -126,13 +128,15 @@ struct FloatTraits<T, 4 /*32bits*/> { | |||||||
|   static T make_float(T m, TExponent e) { |   static T make_float(T m, TExponent e) { | ||||||
|     if (e > 0) { |     if (e > 0) { | ||||||
|       for (uint8_t index = 0; e != 0; index++) { |       for (uint8_t index = 0; e != 0; index++) { | ||||||
|         if (e & 1) m *= positiveBinaryPowerOfTen(index); |         if (e & 1) | ||||||
|  |           m *= positiveBinaryPowerOfTen(index); | ||||||
|         e >>= 1; |         e >>= 1; | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       e = -e; |       e = -e; | ||||||
|       for (uint8_t index = 0; e != 0; index++) { |       for (uint8_t index = 0; e != 0; index++) { | ||||||
|         if (e & 1) m *= negativeBinaryPowerOfTen(index); |         if (e & 1) | ||||||
|  |           m *= negativeBinaryPowerOfTen(index); | ||||||
|         e >>= 1; |         e >>= 1; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -73,7 +73,8 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_NAN | #if ARDUINOJSON_ENABLE_NAN | ||||||
|   if (*s == 'n' || *s == 'N') return traits::nan(); |   if (*s == 'n' || *s == 'N') | ||||||
|  |     return traits::nan(); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_INFINITY | #if ARDUINOJSON_ENABLE_INFINITY | ||||||
| @@ -81,7 +82,8 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) { | |||||||
|     return is_negative ? -traits::inf() : traits::inf(); |     return is_negative ? -traits::inf() : traits::inf(); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   if (!isdigit(*s) && *s != '.') return return_type(); |   if (!isdigit(*s) && *s != '.') | ||||||
|  |     return return_type(); | ||||||
|  |  | ||||||
|   mantissa_t mantissa = 0; |   mantissa_t mantissa = 0; | ||||||
|   exponent_t exponent_offset = 0; |   exponent_t exponent_offset = 0; | ||||||
| @@ -89,14 +91,17 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) { | |||||||
|  |  | ||||||
|   while (isdigit(*s)) { |   while (isdigit(*s)) { | ||||||
|     uint8_t digit = uint8_t(*s - '0'); |     uint8_t digit = uint8_t(*s - '0'); | ||||||
|     if (mantissa > maxUint / 10) break; |     if (mantissa > maxUint / 10) | ||||||
|  |       break; | ||||||
|     mantissa *= 10; |     mantissa *= 10; | ||||||
|     if (mantissa > maxUint - digit) break; |     if (mantissa > maxUint - digit) | ||||||
|  |       break; | ||||||
|     mantissa += digit; |     mantissa += digit; | ||||||
|     s++; |     s++; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (*s == '\0') return return_type(TUInt(mantissa), is_negative); |   if (*s == '\0') | ||||||
|  |     return return_type(TUInt(mantissa), is_negative); | ||||||
|  |  | ||||||
|   // avoid mantissa overflow |   // avoid mantissa overflow | ||||||
|   while (mantissa > traits::mantissa_max) { |   while (mantissa > traits::mantissa_max) { | ||||||
| @@ -142,12 +147,14 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) { | |||||||
|       } |       } | ||||||
|       s++; |       s++; | ||||||
|     } |     } | ||||||
|     if (negative_exponent) exponent = -exponent; |     if (negative_exponent) | ||||||
|  |       exponent = -exponent; | ||||||
|   } |   } | ||||||
|   exponent += exponent_offset; |   exponent += exponent_offset; | ||||||
|  |  | ||||||
|   // we should be at the end of the string, otherwise it's an error |   // we should be at the end of the string, otherwise it's an error | ||||||
|   if (*s != '\0') return return_type(); |   if (*s != '\0') | ||||||
|  |     return return_type(); | ||||||
|  |  | ||||||
|   TFloat result = traits::make_float(static_cast<TFloat>(mantissa), exponent); |   TFloat result = traits::make_float(static_cast<TFloat>(mantissa), exponent); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,34 +17,41 @@ void objectAccept(const CollectionData *obj, Visitor &visitor) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) { | inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) { | ||||||
|   if (lhs == rhs) return true; |   if (lhs == rhs) | ||||||
|   if (!lhs || !rhs) return false; |     return true; | ||||||
|  |   if (!lhs || !rhs) | ||||||
|  |     return false; | ||||||
|   return lhs->equalsObject(*rhs); |   return lhs->equalsObject(*rhs); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { | inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { | ||||||
|   if (!obj) return 0; |   if (!obj) | ||||||
|  |     return 0; | ||||||
|   return obj->get(key); |   return obj->get(key); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| void objectRemove(CollectionData *obj, TAdaptedString key) { | void objectRemove(CollectionData *obj, TAdaptedString key) { | ||||||
|   if (!obj) return; |   if (!obj) | ||||||
|  |     return; | ||||||
|   obj->remove(key); |   obj->remove(key); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key, | inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key, | ||||||
|                                       MemoryPool *pool) { |                                       MemoryPool *pool) { | ||||||
|   if (!obj) return 0; |   if (!obj) | ||||||
|  |     return 0; | ||||||
|  |  | ||||||
|   // ignore null key |   // ignore null key | ||||||
|   if (key.isNull()) return 0; |   if (key.isNull()) | ||||||
|  |     return 0; | ||||||
|  |  | ||||||
|   // search a matching key |   // search a matching key | ||||||
|   VariantData *var = obj->get(key); |   VariantData *var = obj->get(key); | ||||||
|   if (var) return var; |   if (var) | ||||||
|  |     return var; | ||||||
|  |  | ||||||
|   return obj->add(key, pool); |   return obj->add(key, pool); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -64,7 +64,8 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>, | |||||||
|   ObjectConstRef(const CollectionData* data) : base_type(data) {} |   ObjectConstRef(const CollectionData* data) : base_type(data) {} | ||||||
|  |  | ||||||
|   FORCE_INLINE iterator begin() const { |   FORCE_INLINE iterator begin() const { | ||||||
|     if (!_data) return iterator(); |     if (!_data) | ||||||
|  |       return iterator(); | ||||||
|     return iterator(_data->head()); |     return iterator(_data->head()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -154,7 +155,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE iterator begin() const { |   FORCE_INLINE iterator begin() const { | ||||||
|     if (!_data) return iterator(); |     if (!_data) | ||||||
|  |       return iterator(); | ||||||
|     return iterator(_pool, _data->head()); |     return iterator(_pool, _data->head()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -163,12 +165,14 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void clear() const { |   void clear() const { | ||||||
|     if (!_data) return; |     if (!_data) | ||||||
|  |       return; | ||||||
|     _data->clear(); |     _data->clear(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool set(ObjectConstRef src) { |   FORCE_INLINE bool set(ObjectConstRef src) { | ||||||
|     if (!_data || !src._data) return false; |     if (!_data || !src._data) | ||||||
|  |       return false; | ||||||
|     return _data->copyFrom(*src._data, _pool); |     return _data->copyFrom(*src._data, _pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -207,7 +211,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE void remove(iterator it) const { |   FORCE_INLINE void remove(iterator it) const { | ||||||
|     if (!_data) return; |     if (!_data) | ||||||
|  |       return; | ||||||
|     _data->remove(it.internal()); |     _data->remove(it.internal()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,9 +30,12 @@ inline int strncmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) { | |||||||
|   while (n-- > 0) { |   while (n-- > 0) { | ||||||
|     char c1 = *s1++; |     char c1 = *s1++; | ||||||
|     char c2 = static_cast<char>(pgm_read_byte(s2++)); |     char c2 = static_cast<char>(pgm_read_byte(s2++)); | ||||||
|     if (c1 < c2) return -1; |     if (c1 < c2) | ||||||
|     if (c1 > c2) return 1; |       return -1; | ||||||
|     if (c1 == 0 /* and c2 as well */) return 0; |     if (c1 > c2) | ||||||
|  |       return 1; | ||||||
|  |     if (c1 == 0 /* and c2 as well */) | ||||||
|  |       return 0; | ||||||
|   } |   } | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| @@ -45,9 +48,12 @@ inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) { | |||||||
|   for (;;) { |   for (;;) { | ||||||
|     char c1 = *s1++; |     char c1 = *s1++; | ||||||
|     char c2 = static_cast<char>(pgm_read_byte(s2++)); |     char c2 = static_cast<char>(pgm_read_byte(s2++)); | ||||||
|     if (c1 < c2) return -1; |     if (c1 < c2) | ||||||
|     if (c1 > c2) return 1; |       return -1; | ||||||
|     if (c1 == 0 /* and c2 as well */) return 0; |     if (c1 > c2) | ||||||
|  |       return 1; | ||||||
|  |     if (c1 == 0 /* and c2 as well */) | ||||||
|  |       return 0; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -9,16 +9,22 @@ | |||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| inline int8_t safe_strcmp(const char* a, const char* b) { | inline int8_t safe_strcmp(const char* a, const char* b) { | ||||||
|   if (a == b) return 0; |   if (a == b) | ||||||
|   if (!a) return -1; |     return 0; | ||||||
|   if (!b) return 1; |   if (!a) | ||||||
|  |     return -1; | ||||||
|  |   if (!b) | ||||||
|  |     return 1; | ||||||
|   return static_cast<int8_t>(strcmp(a, b)); |   return static_cast<int8_t>(strcmp(a, b)); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline int8_t safe_strncmp(const char* a, const char* b, size_t n) { | inline int8_t safe_strncmp(const char* a, const char* b, size_t n) { | ||||||
|   if (a == b) return 0; |   if (a == b) | ||||||
|   if (!a) return -1; |     return 0; | ||||||
|   if (!b) return 1; |   if (!a) | ||||||
|  |     return -1; | ||||||
|  |   if (!b) | ||||||
|  |     return 1; | ||||||
|   return static_cast<int8_t>(strncmp(a, b, n)); |   return static_cast<int8_t>(strncmp(a, b, n)); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -24,7 +24,8 @@ class Writer< ::String, void> { | |||||||
|   size_t write(uint8_t c) { |   size_t write(uint8_t c) { | ||||||
|     ARDUINOJSON_ASSERT(_size < bufferCapacity); |     ARDUINOJSON_ASSERT(_size < bufferCapacity); | ||||||
|     _buffer[_size++] = static_cast<char>(c); |     _buffer[_size++] = static_cast<char>(c); | ||||||
|     if (_size + 1 >= bufferCapacity) flush(); |     if (_size + 1 >= bufferCapacity) | ||||||
|  |       flush(); | ||||||
|     return 1; |     return 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,7 +16,8 @@ class StaticStringWriter { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t write(uint8_t c) { |   size_t write(uint8_t c) { | ||||||
|     if (p >= end) return 0; |     if (p >= end) | ||||||
|  |       return 0; | ||||||
|     *p++ = static_cast<char>(c); |     *p++ = static_cast<char>(c); | ||||||
|     *p = '\0'; |     *p = '\0'; | ||||||
|     return 1; |     return 1; | ||||||
|   | |||||||
| @@ -15,10 +15,12 @@ class ArduinoStringAdapter { | |||||||
|   ArduinoStringAdapter(const ::String& str) : _str(&str) {} |   ArduinoStringAdapter(const ::String& str) : _str(&str) {} | ||||||
|  |  | ||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     if (isNull()) return NULL; |     if (isNull()) | ||||||
|  |       return NULL; | ||||||
|     size_t n = _str->length() + 1; |     size_t n = _str->length() + 1; | ||||||
|     char* dup = pool->allocFrozenString(n); |     char* dup = pool->allocFrozenString(n); | ||||||
|     if (dup) memcpy(dup, _str->c_str(), n); |     if (dup) | ||||||
|  |       memcpy(dup, _str->c_str(), n); | ||||||
|     return dup; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -33,7 +33,8 @@ class ConstRamStringAdapter { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|     if (!_str) return 0; |     if (!_str) | ||||||
|  |       return 0; | ||||||
|     return strlen(_str); |     return strlen(_str); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,9 +13,12 @@ class FlashStringAdapter { | |||||||
|   FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {} |   FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {} | ||||||
|  |  | ||||||
|   int8_t compare(const char* other) const { |   int8_t compare(const char* other) const { | ||||||
|     if (!other && !_str) return 0; |     if (!other && !_str) | ||||||
|     if (!_str) return -1; |       return 0; | ||||||
|     if (!other) return 1; |     if (!_str) | ||||||
|  |       return -1; | ||||||
|  |     if (!other) | ||||||
|  |       return 1; | ||||||
|     return int8_t(-strcmp_P(other, reinterpret_cast<const char*>(_str))); |     return int8_t(-strcmp_P(other, reinterpret_cast<const char*>(_str))); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -28,10 +31,12 @@ class FlashStringAdapter { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     if (!_str) return NULL; |     if (!_str) | ||||||
|  |       return NULL; | ||||||
|     size_t n = size() + 1;  // copy the terminator |     size_t n = size() + 1;  // copy the terminator | ||||||
|     char* dup = pool->allocFrozenString(n); |     char* dup = pool->allocFrozenString(n); | ||||||
|     if (dup) memcpy_P(dup, reinterpret_cast<const char*>(_str), n); |     if (dup) | ||||||
|  |       memcpy_P(dup, reinterpret_cast<const char*>(_str), n); | ||||||
|     return dup; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -40,7 +45,8 @@ class FlashStringAdapter { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|     if (!_str) return 0; |     if (!_str) | ||||||
|  |       return 0; | ||||||
|     return strlen_P(reinterpret_cast<const char*>(_str)); |     return strlen_P(reinterpret_cast<const char*>(_str)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,10 +13,12 @@ class RamStringAdapter : public ConstRamStringAdapter { | |||||||
|   RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {} |   RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {} | ||||||
|  |  | ||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     if (!_str) return NULL; |     if (!_str) | ||||||
|  |       return NULL; | ||||||
|     size_t n = size() + 1; |     size_t n = size() + 1; | ||||||
|     char* dup = pool->allocFrozenString(n); |     char* dup = pool->allocFrozenString(n); | ||||||
|     if (dup) memcpy(dup, _str, n); |     if (dup) | ||||||
|  |       memcpy(dup, _str, n); | ||||||
|     return dup; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,9 +14,12 @@ class SizedFlashStringAdapter { | |||||||
|       : _str(str), _size(sz) {} |       : _str(str), _size(sz) {} | ||||||
|  |  | ||||||
|   int8_t compare(const char* other) const { |   int8_t compare(const char* other) const { | ||||||
|     if (!other && !_str) return 0; |     if (!other && !_str) | ||||||
|     if (!_str) return -1; |       return 0; | ||||||
|     if (!other) return 1; |     if (!_str) | ||||||
|  |       return -1; | ||||||
|  |     if (!other) | ||||||
|  |       return 1; | ||||||
|     return int8_t( |     return int8_t( | ||||||
|         -strncmp_P(other, reinterpret_cast<const char*>(_str), _size)); |         -strncmp_P(other, reinterpret_cast<const char*>(_str), _size)); | ||||||
|   } |   } | ||||||
| @@ -30,9 +33,11 @@ class SizedFlashStringAdapter { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     if (!_str) return NULL; |     if (!_str) | ||||||
|  |       return NULL; | ||||||
|     char* dup = pool->allocFrozenString(_size); |     char* dup = pool->allocFrozenString(_size); | ||||||
|     if (dup) memcpy_P(dup, reinterpret_cast<const char*>(_str), _size); |     if (dup) | ||||||
|  |       memcpy_P(dup, reinterpret_cast<const char*>(_str), _size); | ||||||
|     return dup; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,9 +27,11 @@ class SizedRamStringAdapter { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     if (!_str) return NULL; |     if (!_str) | ||||||
|  |       return NULL; | ||||||
|     char* dup = pool->allocFrozenString(_size); |     char* dup = pool->allocFrozenString(_size); | ||||||
|     if (dup) memcpy(dup, _str, _size); |     if (dup) | ||||||
|  |       memcpy(dup, _str, _size); | ||||||
|     return dup; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,8 @@ class StlStringAdapter { | |||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     size_t n = _str->length() + 1; |     size_t n = _str->length() + 1; | ||||||
|     char* dup = pool->allocFrozenString(n); |     char* dup = pool->allocFrozenString(n); | ||||||
|     if (dup) memcpy(dup, _str->c_str(), n); |     if (dup) | ||||||
|  |       memcpy(dup, _str->c_str(), n); | ||||||
|     return dup; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -27,12 +28,14 @@ class StlStringAdapter { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   int8_t compare(const char* other) const { |   int8_t compare(const char* other) const { | ||||||
|     if (!other) return 1; |     if (!other) | ||||||
|  |       return 1; | ||||||
|     return static_cast<int8_t>(_str->compare(other)); |     return static_cast<int8_t>(_str->compare(other)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool equals(const char* expected) const { |   bool equals(const char* expected) const { | ||||||
|     if (!expected) return false; |     if (!expected) | ||||||
|  |       return false; | ||||||
|     return *_str == expected; |     return *_str == expected; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,9 +27,12 @@ class String { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   friend bool operator==(String lhs, String rhs) { |   friend bool operator==(String lhs, String rhs) { | ||||||
|     if (lhs._data == rhs._data) return true; |     if (lhs._data == rhs._data) | ||||||
|     if (!lhs._data) return false; |       return true; | ||||||
|     if (!rhs._data) return false; |     if (!lhs._data) | ||||||
|  |       return false; | ||||||
|  |     if (!rhs._data) | ||||||
|  |       return false; | ||||||
|     return strcmp(lhs._data, rhs._data) == 0; |     return strcmp(lhs._data, rhs._data) == 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,12 +11,14 @@ namespace ARDUINOJSON_NAMESPACE { | |||||||
|  |  | ||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) { | inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) { | ||||||
|   if (!var) return false; |   if (!var) | ||||||
|  |     return false; | ||||||
|   if (key.isStatic()) { |   if (key.isStatic()) { | ||||||
|     var->setLinkedKey(make_not_null(key.data())); |     var->setLinkedKey(make_not_null(key.data())); | ||||||
|   } else { |   } else { | ||||||
|     const char* dup = key.save(pool); |     const char* dup = key.save(pool); | ||||||
|     if (!dup) return false; |     if (!dup) | ||||||
|  |       return false; | ||||||
|     var->setOwnedKey(make_not_null(dup)); |     var->setOwnedKey(make_not_null(dup)); | ||||||
|   } |   } | ||||||
|   return true; |   return true; | ||||||
|   | |||||||
| @@ -32,7 +32,8 @@ template <typename T> | |||||||
| inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs( | inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs( | ||||||
|     const VariantData* _data) { |     const VariantData* _data) { | ||||||
|   const char* cstr = _data != 0 ? _data->asString() : 0; |   const char* cstr = _data != 0 ? _data->asString() : 0; | ||||||
|   if (cstr) return T(cstr); |   if (cstr) | ||||||
|  |     return T(cstr); | ||||||
|   T s; |   T s; | ||||||
|   serializeJson(VariantConstRef(_data), s); |   serializeJson(VariantConstRef(_data), s); | ||||||
|   return s; |   return s; | ||||||
|   | |||||||
| @@ -185,12 +185,14 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void remove(size_t index) { |   void remove(size_t index) { | ||||||
|     if (isArray()) _content.asCollection.remove(index); |     if (isArray()) | ||||||
|  |       _content.asCollection.remove(index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
|   void remove(TAdaptedString key) { |   void remove(TAdaptedString key) { | ||||||
|     if (isObject()) _content.asCollection.remove(key); |     if (isObject()) | ||||||
|  |       _content.asCollection.remove(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void setBoolean(bool value) { |   void setBoolean(bool value) { | ||||||
| @@ -329,8 +331,10 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   VariantData *addElement(MemoryPool *pool) { |   VariantData *addElement(MemoryPool *pool) { | ||||||
|     if (isNull()) toArray(); |     if (isNull()) | ||||||
|     if (!isArray()) return 0; |       toArray(); | ||||||
|  |     if (!isArray()) | ||||||
|  |       return 0; | ||||||
|     return _content.asCollection.add(pool); |     return _content.asCollection.add(pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -345,15 +349,19 @@ class VariantData { | |||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
|   VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) { |   VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) { | ||||||
|     if (isNull()) toObject(); |     if (isNull()) | ||||||
|     if (!isObject()) return 0; |       toObject(); | ||||||
|  |     if (!isObject()) | ||||||
|  |       return 0; | ||||||
|     VariantData *var = _content.asCollection.get(key); |     VariantData *var = _content.asCollection.get(key); | ||||||
|     if (var) return var; |     if (var) | ||||||
|  |       return var; | ||||||
|     return _content.asCollection.add(key, pool); |     return _content.asCollection.add(key, pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { |   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { | ||||||
|     if (_flags & VALUE_IS_OWNED) _content.asString += stringDistance; |     if (_flags & VALUE_IS_OWNED) | ||||||
|  |       _content.asString += stringDistance; | ||||||
|     if (_flags & COLLECTION_MASK) |     if (_flags & COLLECTION_MASK) | ||||||
|       _content.asCollection.movePointers(stringDistance, variantDistance); |       _content.asCollection.movePointers(stringDistance, variantDistance); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -30,7 +30,8 @@ inline CollectionData *variantAsObject(VariantData *var) { | |||||||
|  |  | ||||||
| inline bool variantCopyFrom(VariantData *dst, const VariantData *src, | inline bool variantCopyFrom(VariantData *dst, const VariantData *src, | ||||||
|                             MemoryPool *pool) { |                             MemoryPool *pool) { | ||||||
|   if (!dst) return false; |   if (!dst) | ||||||
|  |     return false; | ||||||
|   if (!src) { |   if (!src) { | ||||||
|     dst->setNull(); |     dst->setNull(); | ||||||
|     return true; |     return true; | ||||||
| @@ -39,8 +40,10 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src, | |||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantEquals(const VariantData *a, const VariantData *b) { | inline bool variantEquals(const VariantData *a, const VariantData *b) { | ||||||
|   if (a == b) return true; |   if (a == b) | ||||||
|   if (!a || !b) return false; |     return true; | ||||||
|  |   if (!a || !b) | ||||||
|  |     return false; | ||||||
|   return a->equals(*b); |   return a->equals(*b); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -74,20 +77,23 @@ inline bool variantIsNull(const VariantData *var) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetBoolean(VariantData *var, bool value) { | inline bool variantSetBoolean(VariantData *var, bool value) { | ||||||
|   if (!var) return false; |   if (!var) | ||||||
|  |     return false; | ||||||
|   var->setBoolean(value); |   var->setBoolean(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetFloat(VariantData *var, Float value) { | inline bool variantSetFloat(VariantData *var, Float value) { | ||||||
|   if (!var) return false; |   if (!var) | ||||||
|  |     return false; | ||||||
|   var->setFloat(value); |   var->setFloat(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetLinkedRaw(VariantData *var, | inline bool variantSetLinkedRaw(VariantData *var, | ||||||
|                                 SerializedValue<const char *> value) { |                                 SerializedValue<const char *> value) { | ||||||
|   if (!var) return false; |   if (!var) | ||||||
|  |     return false; | ||||||
|   var->setLinkedRaw(value); |   var->setLinkedRaw(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| @@ -100,24 +106,28 @@ inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value, | |||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline bool variantSetSignedInteger(VariantData *var, T value) { | inline bool variantSetSignedInteger(VariantData *var, T value) { | ||||||
|   if (!var) return false; |   if (!var) | ||||||
|  |     return false; | ||||||
|   var->setSignedInteger(value); |   var->setSignedInteger(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetLinkedString(VariantData *var, const char *value) { | inline bool variantSetLinkedString(VariantData *var, const char *value) { | ||||||
|   if (!var) return false; |   if (!var) | ||||||
|  |     return false; | ||||||
|   var->setLinkedString(value); |   var->setLinkedString(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void variantSetNull(VariantData *var) { | inline void variantSetNull(VariantData *var) { | ||||||
|   if (!var) return; |   if (!var) | ||||||
|  |     return; | ||||||
|   var->setNull(); |   var->setNull(); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetOwnedString(VariantData *var, char *value) { | inline bool variantSetOwnedString(VariantData *var, char *value) { | ||||||
|   if (!var) return false; |   if (!var) | ||||||
|  |     return false; | ||||||
|   var->setOwnedString(value); |   var->setOwnedString(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| @@ -128,7 +138,8 @@ inline bool variantSetOwnedString(VariantData *var, T value, MemoryPool *pool) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetUnsignedInteger(VariantData *var, UInt value) { | inline bool variantSetUnsignedInteger(VariantData *var, UInt value) { | ||||||
|   if (!var) return false; |   if (!var) | ||||||
|  |     return false; | ||||||
|   var->setUnsignedInteger(value); |   var->setUnsignedInteger(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| @@ -138,12 +149,14 @@ inline size_t variantSize(const VariantData *var) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline CollectionData *variantToArray(VariantData *var) { | inline CollectionData *variantToArray(VariantData *var) { | ||||||
|   if (!var) return 0; |   if (!var) | ||||||
|  |     return 0; | ||||||
|   return &var->toArray(); |   return &var->toArray(); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline CollectionData *variantToObject(VariantData *var) { | inline CollectionData *variantToObject(VariantData *var) { | ||||||
|   if (!var) return 0; |   if (!var) | ||||||
|  |     return 0; | ||||||
|   return &var->toObject(); |   return &var->toObject(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -324,7 +324,8 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   FORCE_INLINE VariantRef getOrAddMember(const TString &) const; |   FORCE_INLINE VariantRef getOrAddMember(const TString &) const; | ||||||
|  |  | ||||||
|   FORCE_INLINE void remove(size_t index) const { |   FORCE_INLINE void remove(size_t index) const { | ||||||
|     if (_data) _data->remove(index); |     if (_data) | ||||||
|  |       _data->remove(index); | ||||||
|   } |   } | ||||||
|   // remove(char*) const |   // remove(char*) const | ||||||
|   // remove(const char*) const |   // remove(const char*) const | ||||||
| @@ -332,14 +333,16 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   template <typename TChar> |   template <typename TChar> | ||||||
|   FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove( |   FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove( | ||||||
|       TChar *key) const { |       TChar *key) const { | ||||||
|     if (_data) _data->remove(adaptString(key)); |     if (_data) | ||||||
|  |       _data->remove(adaptString(key)); | ||||||
|   } |   } | ||||||
|   // remove(const std::string&) const |   // remove(const std::string&) const | ||||||
|   // remove(const String&) const |   // remove(const String&) const | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove( |   FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove( | ||||||
|       const TString &key) const { |       const TString &key) const { | ||||||
|     if (_data) _data->remove(adaptString(key)); |     if (_data) | ||||||
|  |       _data->remove(adaptString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   | |||||||
| @@ -49,7 +49,8 @@ class VariantSlot { | |||||||
|   VariantSlot* next(size_t distance) { |   VariantSlot* next(size_t distance) { | ||||||
|     VariantSlot* slot = this; |     VariantSlot* slot = this; | ||||||
|     while (distance--) { |     while (distance--) { | ||||||
|       if (!slot->_next) return 0; |       if (!slot->_next) | ||||||
|  |         return 0; | ||||||
|       slot += slot->_next; |       slot += slot->_next; | ||||||
|     } |     } | ||||||
|     return slot; |     return slot; | ||||||
| @@ -93,8 +94,10 @@ class VariantSlot { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { |   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { | ||||||
|     if (_flags & KEY_IS_OWNED) _key += stringDistance; |     if (_flags & KEY_IS_OWNED) | ||||||
|     if (_flags & VALUE_IS_OWNED) _content.asString += stringDistance; |       _key += stringDistance; | ||||||
|  |     if (_flags & VALUE_IS_OWNED) | ||||||
|  |       _content.asString += stringDistance; | ||||||
|     if (_flags & COLLECTION_MASK) |     if (_flags & COLLECTION_MASK) | ||||||
|       _content.asCollection.movePointers(stringDistance, variantDistance); |       _content.asCollection.movePointers(stringDistance, variantDistance); | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user