mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Fixed errors with Variable Length Arrays (issue #416)
This commit is contained in:
		| @@ -5,6 +5,7 @@ HEAD | ||||
| ---- | ||||
|  | ||||
| * Fixed error when assigning a `volatile int` to a `JsonVariant` (issue #415) | ||||
| * Fixed errors with Variable Length Arrays (issue #416) | ||||
|  | ||||
| v5.8.0 | ||||
| ------ | ||||
|   | ||||
| @@ -94,10 +94,6 @@ struct JsonParserBuilder<TJsonBuffer, char *> { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename TJsonBuffer, size_t N> | ||||
| struct JsonParserBuilder<TJsonBuffer, char[N]> | ||||
|     : JsonParserBuilder<TJsonBuffer, char *> {}; | ||||
|  | ||||
| template <typename TJsonBuffer, typename TString> | ||||
| inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser( | ||||
|     TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) { | ||||
|   | ||||
| @@ -14,8 +14,8 @@ | ||||
| #include "JsonVariant.hpp" | ||||
| #include "Serialization/JsonPrintable.hpp" | ||||
| #include "StringTraits/StringTraits.hpp" | ||||
| #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||
| #include "TypeTraits/EnableIf.hpp" | ||||
| #include "TypeTraits/IsArray.hpp" | ||||
| #include "TypeTraits/IsFloatingPoint.hpp" | ||||
| #include "TypeTraits/IsSame.hpp" | ||||
|  | ||||
| @@ -58,73 +58,70 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|  | ||||
|   // Adds the specified value at the end of the array. | ||||
|   // | ||||
|   // bool add(bool); | ||||
|   // bool add(char); | ||||
|   // bool add(long); | ||||
|   // bool add(int); | ||||
|   // bool add(short); | ||||
|   // bool add(float value); | ||||
|   // bool add(double value); | ||||
|   // bool add(const char*); | ||||
|   // bool add(const char[]); | ||||
|   // bool add(const char[N]); | ||||
|   // bool add(RawJson); | ||||
|   // bool add(const std::string&) | ||||
|   // bool add(const String&) | ||||
|   // bool add(const JsonVariant&); | ||||
|   // bool add(JsonArray&); | ||||
|   // bool add(JsonObject&); | ||||
|   // bool add(TValue); | ||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename T> | ||||
|   bool add(const T &value) { | ||||
|     // reduce the number of template function instanciation to reduce code size | ||||
|     return addNodeImpl<typename TypeTraits::ConstRefOrConstPtr<T>::type>(value); | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type add( | ||||
|       const T &value) { | ||||
|     return add_impl<const T &>(value); | ||||
|   } | ||||
|   // bool add(float value, uint8_t decimals); | ||||
|   // bool add(double value, uint8_t decimals); | ||||
|   // | ||||
|   // bool add(TValue); | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename T> | ||||
|   bool add(const T *value) { | ||||
|     return add_impl<const T *>(value); | ||||
|   } | ||||
|   // | ||||
|   // bool add(TValue value, uint8_t decimals); | ||||
|   // TValue = float, double | ||||
|   template <typename T> | ||||
|   bool add(T value, uint8_t decimals) { | ||||
|     return add(JsonVariant(value, decimals)); | ||||
|     return add_impl<const JsonVariant &>(JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // Sets the value at specified index. | ||||
|   // | ||||
|   // bool set(size_t index, bool value); | ||||
|   // bool set(size_t index, long value); | ||||
|   // bool set(size_t index, int value); | ||||
|   // bool set(size_t index, short value); | ||||
|   // bool set(size_t index, const std::string&) | ||||
|   // bool set(size_t index, const String&) | ||||
|   // bool set(size_t index, const JsonVariant&); | ||||
|   // bool set(size_t index, JsonArray&); | ||||
|   // bool set(size_t index, JsonObject&); | ||||
|   // bool add(size_t index, TValue); | ||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename T> | ||||
|   bool set(size_t index, const T &value) { | ||||
|     // reduce the number of template function instanciation to reduce code size | ||||
|     return setNodeAt<typename TypeTraits::ConstRefOrConstPtr<T>::type>(index, | ||||
|                                                                        value); | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type set( | ||||
|       size_t index, const T &value) { | ||||
|     return set_impl<const T &>(index, value); | ||||
|   } | ||||
|   // bool set(size_t index, float value, uint8_t decimals = 2); | ||||
|   // bool set(size_t index, double value, uint8_t decimals = 2); | ||||
|   // | ||||
|   // bool add(size_t index, TValue); | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename T> | ||||
|   bool set(size_t index, const T *value) { | ||||
|     return set_impl<const T *>(index, value); | ||||
|   } | ||||
|   // | ||||
|   // bool set(size_t index, TValue value, uint8_t decimals); | ||||
|   // TValue = float, double | ||||
|   template <typename T> | ||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, | ||||
|                                 bool>::type | ||||
|   set(size_t index, T value, uint8_t decimals) { | ||||
|     return set(index, JsonVariant(value, decimals)); | ||||
|     return set_impl<const JsonVariant &>(index, JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // Gets the value at the specified index. | ||||
|   template <typename T> | ||||
|   typename Internals::JsonVariantAs<T>::type get(size_t index) const { | ||||
|     node_type *node = getNodeAt(index); | ||||
|     node_type *node = findNode(index); | ||||
|     return node ? node->content.as<T>() | ||||
|                 : Internals::JsonVariantDefault<T>::get(); | ||||
|     ; | ||||
|   } | ||||
|  | ||||
|   // Check the type of the value at specified index. | ||||
|   template <typename T> | ||||
|   bool is(size_t index) const { | ||||
|     node_type *node = getNodeAt(index); | ||||
|     node_type *node = findNode(index); | ||||
|     return node ? node->content.is<T>() : false; | ||||
|   } | ||||
|  | ||||
| @@ -138,7 +135,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|  | ||||
|   // Removes element at specified index. | ||||
|   void removeAt(size_t index) { | ||||
|     removeNode(getNodeAt(index)); | ||||
|     removeNode(findNode(index)); | ||||
|   } | ||||
|  | ||||
|   // Returns a reference an invalid JsonArray. | ||||
| @@ -203,15 +200,15 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   node_type *getNodeAt(size_t index) const { | ||||
|   node_type *findNode(size_t index) const { | ||||
|     node_type *node = _firstNode; | ||||
|     while (node && index--) node = node->next; | ||||
|     return node; | ||||
|   } | ||||
|  | ||||
|   template <typename TValueRef> | ||||
|   bool setNodeAt(size_t index, TValueRef value) { | ||||
|     node_type *node = getNodeAt(index); | ||||
|   bool set_impl(size_t index, TValueRef value) { | ||||
|     node_type *node = findNode(index); | ||||
|     if (!node) return false; | ||||
|  | ||||
|     return Internals::ValueSetter<TValueRef>::set(_buffer, node->content, | ||||
| @@ -219,7 +216,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|   } | ||||
|  | ||||
|   template <typename TValueRef> | ||||
|   bool addNodeImpl(TValueRef value) { | ||||
|   bool add_impl(TValueRef value) { | ||||
|     node_type *node = addNewNode(); | ||||
|     if (!node) return false; | ||||
|  | ||||
|   | ||||
| @@ -26,11 +26,25 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   // Replaces the value | ||||
|   // | ||||
|   // operator=(TValue) | ||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename T> | ||||
|   FORCE_INLINE JsonArraySubscript& operator=(const T& src) { | ||||
|     _array.set(_index, src); | ||||
|     return *this; | ||||
|   } | ||||
|   // | ||||
|   // operator=(TValue) | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename T> | ||||
|   FORCE_INLINE JsonArraySubscript& operator=(const T* src) { | ||||
|     _array.set(_index, src); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE bool success() const { | ||||
|     return _index < _array.size(); | ||||
| @@ -46,9 +60,29 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | ||||
|     return _array.is<T>(_index); | ||||
|   } | ||||
|  | ||||
|   // Replaces the value | ||||
|   // | ||||
|   // bool set(TValue) | ||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE void set(const TValue& value) { | ||||
|     _array.set(_index, value); | ||||
|   FORCE_INLINE bool set(const TValue& value) { | ||||
|     return _array.set(_index, value); | ||||
|   } | ||||
|   // | ||||
|   // bool set(TValue) | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE bool set(const TValue* value) { | ||||
|     return _array.set(_index, value); | ||||
|   } | ||||
|   // | ||||
|   // bool set(TValue, uint8_t decimals); | ||||
|   // TValue = float, double | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { | ||||
|     return _array.set(_index, value, decimals); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   | ||||
| @@ -12,6 +12,8 @@ | ||||
| #include <string.h> | ||||
|  | ||||
| #include "JsonVariant.hpp" | ||||
| #include "TypeTraits/EnableIf.hpp" | ||||
| #include "TypeTraits/IsArray.hpp" | ||||
|  | ||||
| #if defined(__clang__) | ||||
| #pragma clang diagnostic push | ||||
| @@ -51,11 +53,23 @@ class JsonBuffer { | ||||
|   // allocation fails. | ||||
|   JsonObject &createObject(); | ||||
|  | ||||
|   // Duplicate a string | ||||
|   // Duplicates a string | ||||
|   // | ||||
|   // char* strdup(TValue); | ||||
|   // TValue = const std::string&, const String&, | ||||
|   template <typename TString> | ||||
|   char *strdup(const TString &src) { | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 char *>::type | ||||
|   strdup(const TString &src) { | ||||
|     return Internals::StringFuncs<TString>::duplicate(src, this); | ||||
|   } | ||||
|   // | ||||
|   // char* strdup(TValue); | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   char *strdup(const TString *src) { | ||||
|     return Internals::StringFuncs<const TString *>::duplicate(src, this); | ||||
|   } | ||||
|  | ||||
|   // Allocates n bytes in the JsonBuffer. | ||||
|   // Return a pointer to the allocated memory or NULL if allocation fails. | ||||
|   | ||||
| @@ -34,12 +34,27 @@ class JsonBufferBase : public JsonBuffer { | ||||
|   // Returns a reference to the new JsonObject or JsonObject::invalid() if the | ||||
|   // allocation fails. | ||||
|   // With this overload, the JsonBuffer will make a copy of the string | ||||
|   // | ||||
|   // JsonArray& parseArray(TString); | ||||
|   // TString = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   JsonArray &parseArray( | ||||
|       const TString &json, | ||||
|       uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 JsonArray &>::type | ||||
|   parseArray(const TString &json, | ||||
|              uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|     return Internals::makeParser(that(), json, nestingLimit).parseArray(); | ||||
|   } | ||||
|   // | ||||
|   // JsonArray& parseArray(TString); | ||||
|   // TString = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   JsonArray &parseArray( | ||||
|       TString *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|     return Internals::makeParser(that(), json, nestingLimit).parseArray(); | ||||
|   } | ||||
|   // | ||||
|   // JsonArray& parseArray(TString); | ||||
|   // TString = std::istream&, Stream& | ||||
|   template <typename TString> | ||||
|   JsonArray &parseArray( | ||||
|       TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
| @@ -56,12 +71,27 @@ class JsonBufferBase : public JsonBuffer { | ||||
|   // | ||||
|   // Returns a reference to the new JsonObject or JsonObject::invalid() if the | ||||
|   // allocation fails. | ||||
|   // | ||||
|   // JsonObject& parseObject(TString); | ||||
|   // TString = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   JsonObject &parseObject( | ||||
|       const TString &json, | ||||
|       uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 JsonObject &>::type | ||||
|   parseObject(const TString &json, | ||||
|               uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|     return Internals::makeParser(that(), json, nestingLimit).parseObject(); | ||||
|   } | ||||
|   // | ||||
|   // JsonObject& parseObject(TString); | ||||
|   // TString = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   JsonObject &parseObject( | ||||
|       TString *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|     return Internals::makeParser(that(), json, nestingLimit).parseObject(); | ||||
|   } | ||||
|   // | ||||
|   // JsonObject& parseObject(TString); | ||||
|   // TString = std::istream&, Stream& | ||||
|   template <typename TString> | ||||
|   JsonObject &parseObject( | ||||
|       TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
| @@ -70,11 +100,27 @@ class JsonBufferBase : public JsonBuffer { | ||||
|  | ||||
|   // Generalized version of parseArray() and parseObject(), also works for | ||||
|   // integral types. | ||||
|   // | ||||
|   // JsonVariant parse(TString); | ||||
|   // TString = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   JsonVariant parse(const TString &json, | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 JsonVariant>::type | ||||
|   parse(const TString &json, | ||||
|         uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|     return Internals::makeParser(that(), json, nestingLimit).parseVariant(); | ||||
|   } | ||||
|   // | ||||
|   // JsonVariant parse(TString); | ||||
|   // TString = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   JsonVariant parse(TString *json, | ||||
|                     uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|     return Internals::makeParser(that(), json, nestingLimit).parseVariant(); | ||||
|   } | ||||
|   // | ||||
|   // JsonVariant parse(TString); | ||||
|   // TString = std::istream&, Stream& | ||||
|   template <typename TString> | ||||
|   JsonVariant parse(TString &json, | ||||
|                     uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||
|   | ||||
| @@ -14,8 +14,8 @@ | ||||
| #include "JsonPair.hpp" | ||||
| #include "Serialization/JsonPrintable.hpp" | ||||
| #include "StringTraits/StringTraits.hpp" | ||||
| #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||
| #include "TypeTraits/EnableIf.hpp" | ||||
| #include "TypeTraits/IsArray.hpp" | ||||
| #include "TypeTraits/IsFloatingPoint.hpp" | ||||
| #include "TypeTraits/IsSame.hpp" | ||||
|  | ||||
| @@ -47,81 +47,226 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|   explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {} | ||||
|  | ||||
|   // Gets or sets the value associated with the specified key. | ||||
|   // | ||||
|   // JsonObjectSubscript operator[](TKey) | ||||
|   // TKey = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   JsonObjectSubscript<TString> operator[](const TString& key); | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 JsonObjectSubscript<const TString&> >::type | ||||
|   operator[](const TString& key) { | ||||
|     return JsonObjectSubscript<const TString&>(*this, key); | ||||
|   } | ||||
|   // | ||||
|   // JsonObjectSubscript operator[](TKey) | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   JsonObjectSubscript<const TString*> operator[](const TString* key) { | ||||
|     return JsonObjectSubscript<const TString*>(*this, key); | ||||
|   } | ||||
|  | ||||
|   // Gets the value associated with the specified key. | ||||
|   // | ||||
|   // JsonVariant operator[](TKey) const; | ||||
|   // TKey = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   JsonVariant operator[](const TString& key) const { | ||||
|     return get<JsonVariant>(key); | ||||
|   const JsonVariant operator[](const TString& key) const { | ||||
|     return get_impl<const TString&, JsonVariant>(key); | ||||
|   } | ||||
|   // | ||||
|   // JsonVariant operator[](TKey) const; | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   const JsonVariant operator[](const TString* key) const { | ||||
|     return get_impl<const TString*, JsonVariant>(key); | ||||
|   } | ||||
|  | ||||
|   // Sets the specified key with the specified value. | ||||
|   // bool set(TKey key, bool value); | ||||
|   // bool set(TKey key, char value); | ||||
|   // bool set(TKey key, long value); | ||||
|   // bool set(TKey key, int value); | ||||
|   // bool set(TKey key, short value); | ||||
|   // bool set(TKey key, float value); | ||||
|   // bool set(TKey key, double value); | ||||
|   // bool set(TKey key, const char* value); | ||||
|   // bool set(TKey key, RawJson value); | ||||
|   // bool set(Key, String&); | ||||
|   // bool set(Key, JsonArray&); | ||||
|   // bool set(Key, JsonObject&); | ||||
|   // bool set(Key, JsonVariant&); | ||||
|   // | ||||
|   // bool set(TKey, TValue); | ||||
|   // TKey = const std::string&, const String& | ||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue, typename TString> | ||||
|   bool set(const TString& key, const TValue& value) { | ||||
|     // reduce the number of template function instanciation to reduce code size | ||||
|     return setNodeAt<typename TypeTraits::ConstRefOrConstPtr<TString>::type, | ||||
|                      typename TypeTraits::ConstRefOrConstPtr<TValue>::type>( | ||||
|         key, value); | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value && | ||||
|                                     !TypeTraits::IsArray<TValue>::value, | ||||
|                                 bool>::type | ||||
|   set(const TString& key, const TValue& value) { | ||||
|     return set_impl<const TString&, const TValue&>(key, value); | ||||
|   } | ||||
|   // bool set(Key, float value, uint8_t decimals); | ||||
|   // bool set(Key, double value, uint8_t decimals); | ||||
|   // | ||||
|   // bool set(TKey, TValue); | ||||
|   // TKey = const std::string&, const String& | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TValue, typename TString> | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 bool>::type | ||||
|   set(const TString& key, const TValue* value) { | ||||
|     return set_impl<const TString&, const TValue*>(key, value); | ||||
|   } | ||||
|   // | ||||
|   // bool set(TKey, TValue); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue, typename TString> | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, bool>::type | ||||
|   set(const TString* key, const TValue& value) { | ||||
|     return set_impl<const TString*, const TValue&>(key, value); | ||||
|   } | ||||
|   // | ||||
|   // bool set(TKey, TValue); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TValue, typename TString> | ||||
|   bool set(const TString* key, const TValue* value) { | ||||
|     return set_impl<const TString*, const TValue*>(key, value); | ||||
|   } | ||||
|   // | ||||
|   // bool set(TKey, TValue, uint8_t decimals); | ||||
|   // TKey = const std::string&, const String& | ||||
|   // TValue = float, double | ||||
|   template <typename TValue, typename TString> | ||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value && | ||||
|                                     !TypeTraits::IsArray<TString>::value, | ||||
|                                 bool>::type | ||||
|   set(const TString& key, TValue value, uint8_t decimals) { | ||||
|     return set_impl<const TString&, const JsonVariant&>( | ||||
|         key, JsonVariant(value, decimals)); | ||||
|   } | ||||
|   // | ||||
|   // bool set(TKey, TValue, uint8_t decimals); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   // TValue = float, double | ||||
|   template <typename TValue, typename TString> | ||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, | ||||
|                                 bool>::type | ||||
|   set(const TString& key, TValue value, uint8_t decimals) { | ||||
|     return set(key, JsonVariant(value, decimals)); | ||||
|   set(const TString* key, TValue value, uint8_t decimals) { | ||||
|     return set_impl<const TString*, const JsonVariant&>( | ||||
|         key, JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // Gets the value associated with the specified key. | ||||
|   // | ||||
|   // TValue get<TValue>(TKey); | ||||
|   // TKey = const std::string&, const String& | ||||
|   // TValue = bool, char, long, int, short, float, double, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue, typename TString> | ||||
|   typename TypeTraits::EnableIf< | ||||
|       !TypeTraits::IsArray<TString>::value, | ||||
|       typename Internals::JsonVariantAs<TValue>::type>::type | ||||
|   get(const TString& key) const { | ||||
|     return get_impl<const TString&, TValue>(key); | ||||
|   } | ||||
|   // | ||||
|   // TValue get<TValue>(TKey); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   // TValue = bool, char, long, int, short, float, double, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue, typename TString> | ||||
|   typename Internals::JsonVariantAs<TValue>::type get( | ||||
|       const TString& key) const { | ||||
|     node_type* node = getNodeAt(key); | ||||
|     return node ? node->content.value.as<TValue>() | ||||
|                 : Internals::JsonVariantDefault<TValue>::get(); | ||||
|       const TString* key) const { | ||||
|     return get_impl<const TString*, TValue>(key); | ||||
|   } | ||||
|  | ||||
|   // Checks the type of the value associated with the specified key. | ||||
|   // | ||||
|   // | ||||
|   // bool is<TValue>(TKey) const; | ||||
|   // TKey = const std::string&, const String& | ||||
|   // TValue = bool, char, long, int, short, float, double, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue, typename TString> | ||||
|   bool is(const TString& key) const { | ||||
|     node_type* node = getNodeAt(key); | ||||
|     return node ? node->content.value.is<TValue>() : false; | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 bool>::type | ||||
|   is(const TString& key) const { | ||||
|     return is_impl<const TString&, TValue>(key); | ||||
|   } | ||||
|   // | ||||
|   // bool is<TValue>(TKey) const; | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   // TValue = bool, char, long, int, short, float, double, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue, typename TString> | ||||
|   bool is(const TString* key) const { | ||||
|     return is_impl<const TString*, TValue>(key); | ||||
|   } | ||||
|  | ||||
|   // Creates and adds a JsonArray. | ||||
|   // This is a shortcut for JsonBuffer::createArray() and JsonObject::add(). | ||||
|   // | ||||
|   // JsonArray& createNestedArray(TKey); | ||||
|   // TKey = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   JsonArray& createNestedArray(const TString& key); | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 JsonArray&>::type | ||||
|   createNestedArray(const TString& key) { | ||||
|     return createNestedArray_impl<const TString&>(key); | ||||
|   } | ||||
|   // JsonArray& createNestedArray(TKey); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   JsonArray& createNestedArray(const TString* key) { | ||||
|     return createNestedArray_impl<const TString*>(key); | ||||
|   } | ||||
|  | ||||
|   // Creates and adds a JsonObject. | ||||
|   // This is a shortcut for JsonBuffer::createObject() and JsonObject::add(). | ||||
|   // | ||||
|   // JsonObject& createNestedObject(TKey); | ||||
|   // TKey = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   JsonObject& createNestedObject(const TString& key); | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 JsonObject&>::type | ||||
|   createNestedObject(const TString& key) { | ||||
|     return createNestedObject_impl<const TString&>(key); | ||||
|   } | ||||
|   // | ||||
|   // JsonObject& createNestedObject(TKey); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   JsonObject& createNestedObject(const TString* key) { | ||||
|     return createNestedObject_impl<const TString*>(key); | ||||
|   } | ||||
|  | ||||
|   // Tells weither the specified key is present and associated with a value. | ||||
|   // | ||||
|   // bool containsKey(TKey); | ||||
|   // TKey = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   bool containsKey(const TString& key) const { | ||||
|     return getNodeAt(key) != NULL; | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 bool>::type | ||||
|   containsKey(const TString& key) const { | ||||
|     return findNode<const TString&>(key) != NULL; | ||||
|   } | ||||
|   // | ||||
|   // bool containsKey(TKey); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   bool containsKey(const TString* key) const { | ||||
|     return findNode<const TString*>(key) != NULL; | ||||
|   } | ||||
|  | ||||
|   // Removes the specified key and the associated value. | ||||
|   // | ||||
|   // void remove(TKey); | ||||
|   // TKey = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   void remove(const TString& key) { | ||||
|     removeNode(getNodeAt(key)); | ||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, | ||||
|                                 void>::type | ||||
|   remove(const TString& key) { | ||||
|     removeNode(findNode<const TString&>(key)); | ||||
|   } | ||||
|   // | ||||
|   // void remove(TKey); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   void remove(const TString* key) { | ||||
|     removeNode(findNode<const TString*>(key)); | ||||
|   } | ||||
|  | ||||
|   // Returns a reference an invalid JsonObject. | ||||
| @@ -134,15 +279,8 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|  | ||||
|  private: | ||||
|   // Returns the list node that matches the specified key. | ||||
|   template <typename TString> | ||||
|   node_type* getNodeAt(const TString& key) const { | ||||
|     // reduce the number of template function instanciation to reduce code size | ||||
|     return getNodeAtImpl< | ||||
|         typename TypeTraits::ConstRefOrConstPtr<TString>::type>(key); | ||||
|   } | ||||
|  | ||||
|   template <typename TStringRef> | ||||
|   node_type* getNodeAtImpl(TStringRef key) const { | ||||
|   node_type* findNode(TStringRef key) const { | ||||
|     for (node_type* node = _firstNode; node; node = node->next) { | ||||
|       if (Internals::StringFuncs<TStringRef>::equals(key, node->content.key)) | ||||
|         return node; | ||||
| @@ -150,9 +288,17 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|     return NULL; | ||||
|   } | ||||
|  | ||||
|   template <typename TStringRef, typename TValue> | ||||
|   typename Internals::JsonVariantAs<TValue>::type get_impl( | ||||
|       TStringRef key) const { | ||||
|     node_type* node = findNode<TStringRef>(key); | ||||
|     return node ? node->content.value.as<TValue>() | ||||
|                 : Internals::JsonVariantDefault<TValue>::get(); | ||||
|   } | ||||
|  | ||||
|   template <typename TStringRef, typename TValueRef> | ||||
|   bool setNodeAt(TStringRef key, TValueRef value) { | ||||
|     node_type* node = getNodeAtImpl<TStringRef>(key); | ||||
|   bool set_impl(TStringRef key, TValueRef value) { | ||||
|     node_type* node = findNode<TStringRef>(key); | ||||
|     if (!node) { | ||||
|       node = addNewNode(); | ||||
|       if (!node) return false; | ||||
| @@ -164,6 +310,18 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|     return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value, | ||||
|                                                   value); | ||||
|   } | ||||
|  | ||||
|   template <typename TStringRef, typename TValue> | ||||
|   bool is_impl(TStringRef key) const { | ||||
|     node_type* node = findNode<TStringRef>(key); | ||||
|     return node ? node->content.value.is<TValue>() : false; | ||||
|   } | ||||
|  | ||||
|   template <typename TStringRef> | ||||
|   JsonArray& createNestedArray_impl(TStringRef key); | ||||
|  | ||||
|   template <typename TStringRef> | ||||
|   JsonObject& createNestedObject_impl(TStringRef key); | ||||
| }; | ||||
|  | ||||
| namespace Internals { | ||||
|   | ||||
| @@ -13,19 +13,19 @@ | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| template <typename TString> | ||||
| inline JsonObject &JsonObject::createNestedObject(const TString &key) { | ||||
|   if (!_buffer) return JsonObject::invalid(); | ||||
|   JsonObject &object = _buffer->createObject(); | ||||
|   set(key, object); | ||||
|   return object; | ||||
| } | ||||
|  | ||||
| template <typename TString> | ||||
| inline JsonArray &JsonObject::createNestedArray(const TString &key) { | ||||
| template <typename TStringRef> | ||||
| inline JsonArray &JsonObject::createNestedArray_impl(TStringRef key) { | ||||
|   if (!_buffer) return JsonArray::invalid(); | ||||
|   JsonArray &array = _buffer->createArray(); | ||||
|   set(key, array); | ||||
|   return array; | ||||
| } | ||||
|  | ||||
| template <typename TStringRef> | ||||
| inline JsonObject &JsonObject::createNestedObject_impl(TStringRef key) { | ||||
|   if (!_buffer) return JsonObject::invalid(); | ||||
|   JsonObject &object = _buffer->createObject(); | ||||
|   set(key, object); | ||||
|   return object; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -9,7 +9,6 @@ | ||||
|  | ||||
| #include "Configuration.hpp" | ||||
| #include "JsonVariantBase.hpp" | ||||
| #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||
| #include "TypeTraits/EnableIf.hpp" | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| @@ -19,26 +18,39 @@ | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| template <typename TString> | ||||
| template <typename TStringRef> | ||||
| class JsonObjectSubscript | ||||
|     : public JsonVariantBase<JsonObjectSubscript<TString> > { | ||||
|   // const String& | ||||
|   // const std::string& | ||||
|   // const char* | ||||
|   typedef typename TypeTraits::ConstRefOrConstPtr<TString>::type TStringRef; | ||||
|     : public JsonVariantBase<JsonObjectSubscript<TStringRef> > { | ||||
|   typedef JsonObjectSubscript<TStringRef> this_type; | ||||
|  | ||||
|  public: | ||||
|   FORCE_INLINE JsonObjectSubscript(JsonObject& object, TStringRef key) | ||||
|       : _object(object), _key(key) {} | ||||
|  | ||||
|   FORCE_INLINE JsonObjectSubscript<TString>& operator=( | ||||
|       const JsonObjectSubscript<TString>& src) { | ||||
|   FORCE_INLINE this_type& operator=(const this_type& src) { | ||||
|     _object.set(_key, src); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE JsonObjectSubscript<TString>& operator=(const T& src) { | ||||
|   // Set the specified value | ||||
|   // | ||||
|   // operator=(TValue); | ||||
|   // TValue = bool, char, long, int, short, float, double, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE | ||||
|       typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, | ||||
|                                     this_type&>::type | ||||
|       operator=(const TValue& src) { | ||||
|     _object.set(_key, src); | ||||
|     return *this; | ||||
|   } | ||||
|   // | ||||
|   // operator=(TValue); | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE this_type& operator=(const TValue* src) { | ||||
|     _object.set(_key, src); | ||||
|     return *this; | ||||
|   } | ||||
| @@ -49,7 +61,7 @@ class JsonObjectSubscript | ||||
|  | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const { | ||||
|     return _object.get<TValue, TStringRef>(_key); | ||||
|     return _object.get<TValue>(_key); | ||||
|   } | ||||
|  | ||||
|   template <typename TValue> | ||||
| @@ -57,11 +69,29 @@ class JsonObjectSubscript | ||||
|     return _object.is<TValue>(_key); | ||||
|   } | ||||
|  | ||||
|   // Sets the specified value. | ||||
|   // | ||||
|   // bool set(TValue); | ||||
|   // TValue = bool, char, long, int, short, float, double, RawJson, JsonVariant, | ||||
|   //          const std::string&, const String&, | ||||
|   //          const JsonArray&, const JsonObject& | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE bool set(const TValue& value) { | ||||
|   FORCE_INLINE | ||||
|       typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, | ||||
|                                     bool>::type | ||||
|       set(const TValue& value) { | ||||
|     return _object.set(_key, value); | ||||
|   } | ||||
|  | ||||
|   // | ||||
|   // bool set(TValue); | ||||
|   // TValue = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE bool set(const TValue* value) { | ||||
|     return _object.set(_key, value); | ||||
|   } | ||||
|   // | ||||
|   // bool set(TValue, uint8_t decimals); | ||||
|   // TValue = float, double | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { | ||||
|     return _object.set(_key, value, decimals); | ||||
| @@ -73,17 +103,12 @@ class JsonObjectSubscript | ||||
| }; | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_STD_STREAM | ||||
| template <typename TString> | ||||
| template <typename TStringRef> | ||||
| inline std::ostream& operator<<(std::ostream& os, | ||||
|                                 const JsonObjectSubscript<TString>& source) { | ||||
|                                 const JsonObjectSubscript<TStringRef>& source) { | ||||
|   return source.printTo(os); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| template <typename TString> | ||||
| inline JsonObjectSubscript<TString> JsonObject::operator[](const TString& key) { | ||||
|   return JsonObjectSubscript<TString>(*this, key); | ||||
| } | ||||
| }  // namespace ArduinoJson | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
|   | ||||
| @@ -78,20 +78,46 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> { | ||||
|   // Returns the value associated with the specified key if the variant is | ||||
|   // an object. | ||||
|   // Return JsonVariant::invalid() if the variant is not an object. | ||||
|   // | ||||
|   // const JsonObjectSubscript operator[](TKey) const; | ||||
|   // TKey = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   FORCE_INLINE | ||||
|       typename TypeTraits::EnableIf<Internals::StringFuncs<TString>::has_equals, | ||||
|                                     const JsonObjectSubscript<TString> >::type | ||||
|       operator[](const TString &key) const { | ||||
|   FORCE_INLINE typename TypeTraits::EnableIf< | ||||
|       Internals::StringFuncs<TString>::has_equals, | ||||
|       const JsonObjectSubscript<const TString &> >::type | ||||
|   operator[](const TString &key) const { | ||||
|     return asObject()[key]; | ||||
|   } | ||||
|   // | ||||
|   // const JsonObjectSubscript operator[](TKey) const; | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   FORCE_INLINE | ||||
|       typename TypeTraits::EnableIf<Internals::StringFuncs<TString>::has_equals, | ||||
|                                     JsonObjectSubscript<TString> >::type | ||||
|                                     JsonObjectSubscript<const TString &> >::type | ||||
|       operator[](const TString &key) { | ||||
|     return asObject()[key]; | ||||
|   } | ||||
|   // | ||||
|   // JsonObjectSubscript operator[](TKey); | ||||
|   // TKey = const std::string&, const String& | ||||
|   template <typename TString> | ||||
|   FORCE_INLINE typename TypeTraits::EnableIf< | ||||
|       Internals::StringFuncs<TString *>::has_equals, | ||||
|       JsonObjectSubscript<const TString *> >::type | ||||
|   operator[](const TString *key) { | ||||
|     return asObject()[key]; | ||||
|   } | ||||
|   // | ||||
|   // JsonObjectSubscript operator[](TKey); | ||||
|   // TKey = const char*, const char[N], const FlashStringHelper* | ||||
|   template <typename TString> | ||||
|   FORCE_INLINE typename TypeTraits::EnableIf< | ||||
|       Internals::StringFuncs<TString *>::has_equals, | ||||
|       const JsonObjectSubscript<const TString *> >::type | ||||
|   operator[](const TString *key) const { | ||||
|     return asObject()[key]; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   const TImpl *impl() const { | ||||
|   | ||||
| @@ -47,11 +47,5 @@ struct StringFuncs<const char*, void> : CharPtrFuncs {}; | ||||
|  | ||||
| template <> | ||||
| struct StringFuncs<char*, void> : CharPtrFuncs {}; | ||||
|  | ||||
| template <size_t N> | ||||
| struct StringFuncs<char[N], void> : CharPtrFuncs {}; | ||||
|  | ||||
| template <size_t N> | ||||
| struct StringFuncs<const char[N], void> : CharPtrFuncs {}; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -12,20 +12,16 @@ namespace TypeTraits { | ||||
| 
 | ||||
| // A meta-function that return the type T without the const modifier
 | ||||
| template <typename T> | ||||
| struct ConstRefOrConstPtr { | ||||
|   typedef const T& type; | ||||
| struct IsArray { | ||||
|   static const bool value = false; | ||||
| }; | ||||
| template <typename T> | ||||
| struct ConstRefOrConstPtr<T*> { | ||||
|   typedef const T* type; | ||||
| }; | ||||
| template <typename T> | ||||
| struct ConstRefOrConstPtr<T[]> { | ||||
|   typedef const T* type; | ||||
| struct IsArray<T[]> { | ||||
|   static const bool value = true; | ||||
| }; | ||||
| template <typename T, size_t N> | ||||
| struct ConstRefOrConstPtr<T[N]> { | ||||
|   typedef const T* type; | ||||
| struct IsArray<T[N]> { | ||||
|   static const bool value = true; | ||||
| }; | ||||
| } | ||||
| } | ||||
| @@ -49,6 +49,13 @@ TEST_(StoreDouble) { | ||||
|   EXPECT_FALSE(_array[0].is<int>()); | ||||
| } | ||||
|  | ||||
| TEST_(StoreDoubleWithDecimals) { | ||||
|   _array[0].set(123.45, 2); | ||||
|   EXPECT_EQ(123.45, _array[0].as<double>()); | ||||
|   EXPECT_TRUE(_array[0].is<double>()); | ||||
|   EXPECT_FALSE(_array[0].is<int>()); | ||||
| } | ||||
|  | ||||
| TEST_(StoreBoolean) { | ||||
|   _array[0] = true; | ||||
|   EXPECT_EQ(true, _array[0].as<bool>()); | ||||
|   | ||||
| @@ -15,3 +15,9 @@ TEST(StdStream, IsBaseOf) { | ||||
|   ASSERT_FALSE((IsBaseOf<std::istream, std::ostringstream>::value)); | ||||
|   ASSERT_TRUE((IsBaseOf<std::istream, std::istringstream>::value)); | ||||
| } | ||||
|  | ||||
| TEST(StdStream, IsArray) { | ||||
|   ASSERT_FALSE((IsArray<const char*>::value)); | ||||
|   ASSERT_TRUE((IsArray<const char[]>::value)); | ||||
|   ASSERT_TRUE((IsArray<const char[10]>::value)); | ||||
| } | ||||
|   | ||||
							
								
								
									
										357
									
								
								test/VariableLengthArray_Tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								test/VariableLengthArray_Tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,357 @@ | ||||
| // Copyright Benoit Blanchon 2014-2017 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <ArduinoJson.h> | ||||
| #include <gtest/gtest.h> | ||||
|  | ||||
| #if defined(__clang__) | ||||
| #pragma clang diagnostic ignored "-Wvla-extension" | ||||
| #define CONFLICTS_WITH_BUILTIN_OPERATOR | ||||
| #elif defined(__GNUC__) | ||||
| #pragma GCC diagnostic ignored "-Wvla" | ||||
| #else | ||||
| #define VLA_NOT_SUPPORTED | ||||
| #endif | ||||
|  | ||||
| #ifndef VLA_NOT_SUPPORTED | ||||
|  | ||||
| TEST(VariableLengthArray, ParseArray) { | ||||
|   int i = 8; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "[42]"); | ||||
|  | ||||
|   StaticJsonBuffer<JSON_ARRAY_SIZE(1)> jsonBuffer; | ||||
|   JsonArray& arr = jsonBuffer.parseArray(vla); | ||||
|  | ||||
|   EXPECT_TRUE(arr.success()); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, ParseObject) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "{\"a\":42}"); | ||||
|  | ||||
|   StaticJsonBuffer<JSON_OBJECT_SIZE(1)> jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.parseObject(vla); | ||||
|  | ||||
|   EXPECT_TRUE(obj.success()); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, Parse) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "42"); | ||||
|  | ||||
|   StaticJsonBuffer<1> jsonBuffer; | ||||
|   JsonVariant variant = jsonBuffer.parse(vla); | ||||
|  | ||||
|   EXPECT_EQ(42, variant.as<int>()); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonVariant_Constructor) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "42"); | ||||
|  | ||||
|   JsonVariant variant(vla); | ||||
|  | ||||
|   EXPECT_EQ(42, variant.as<int>()); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonVariant_Assign) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "42"); | ||||
|  | ||||
|   JsonVariant variant(666); | ||||
|   variant = vla; | ||||
|  | ||||
|   EXPECT_EQ(42, variant.as<int>()); | ||||
| } | ||||
|  | ||||
| #ifndef CONFLICTS_WITH_BUILTIN_OPERATOR | ||||
| TEST(VariableLengthArray, JsonVariant_Subscript) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonVariant variant = jsonBuffer.parseObject("{\"hello\":\"world\"}"); | ||||
|  | ||||
|   EXPECT_STREQ("world", variant[vla]); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #ifndef CONFLICTS_WITH_BUILTIN_OPERATOR | ||||
| TEST(VariableLengthArray, JsonVariant_Subscript_Const) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   const JsonVariant variant = jsonBuffer.parseObject("{\"hello\":\"world\"}"); | ||||
|  | ||||
|   EXPECT_STREQ("world", variant[vla]); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| TEST(VariableLengthArray, JsonVariant_Equals) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   const JsonVariant variant = "hello"; | ||||
|  | ||||
|   EXPECT_TRUE(vla == variant); | ||||
|   EXPECT_TRUE(variant == vla); | ||||
|   EXPECT_FALSE(vla != variant); | ||||
|   EXPECT_FALSE(variant != vla); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonVariant_Differs) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   const JsonVariant variant = "world"; | ||||
|  | ||||
|   EXPECT_TRUE(vla != variant); | ||||
|   EXPECT_TRUE(variant != vla); | ||||
|   EXPECT_FALSE(vla == variant); | ||||
|   EXPECT_FALSE(variant == vla); | ||||
| } | ||||
|  | ||||
| #ifndef CONFLICTS_WITH_BUILTIN_OPERATOR | ||||
| TEST(VariableLengthArray, JsonObject_Subscript) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj[vla] = "world"; | ||||
|  | ||||
|   EXPECT_STREQ("world", obj["hello"]); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Subscript_Assign) {  // issue #416 | ||||
|   int i = 32; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj["hello"] = vla; | ||||
|  | ||||
|   EXPECT_STREQ("world", obj["hello"].as<char*>()); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Subscript_Set) { | ||||
|   int i = 32; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj["hello"].set(vla); | ||||
|  | ||||
|   EXPECT_STREQ("world", obj["hello"].as<char*>()); | ||||
| } | ||||
|  | ||||
| #ifndef CONFLICTS_WITH_BUILTIN_OPERATOR | ||||
| TEST(VariableLengthArray, JsonObject_Subscript_Const) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   const JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); | ||||
|  | ||||
|   EXPECT_STREQ("world", obj[vla]); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Get) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); | ||||
|  | ||||
|   EXPECT_STREQ("world", obj.get<char*>(vla)); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Set_Key) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj.set(vla, "world"); | ||||
|  | ||||
|   EXPECT_STREQ("world", obj["hello"]); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Set_Value) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj.set("hello", vla); | ||||
|  | ||||
|   EXPECT_STREQ("world", obj["hello"]); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Set_Key_WithDecimals) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj.set(vla, 3.14, 2); | ||||
|  | ||||
|   EXPECT_EQ(3.14, obj["hello"]); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Set_KeyAndValue) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj.set(vla, vla); | ||||
|  | ||||
|   EXPECT_STREQ("world", obj["world"]); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_ContainsKey) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   const JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); | ||||
|  | ||||
|   EXPECT_TRUE(obj.containsKey(vla)); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Remove) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); | ||||
|   obj.remove(vla); | ||||
|  | ||||
|   EXPECT_EQ(0, obj.size()); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_Is) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.parseObject("{\"hello\":42}"); | ||||
|  | ||||
|   EXPECT_TRUE(obj.is<int>(vla)); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_CreateNestedArray) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj.createNestedArray(vla); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonObject_CreateNestedObject) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "hello"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj = jsonBuffer.createObject(); | ||||
|   obj.createNestedObject(vla); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonArray_Add) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonArray& arr = jsonBuffer.createArray(); | ||||
|   arr.add(vla); | ||||
|  | ||||
|   EXPECT_STREQ("world", arr[0]); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonArray_Set) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonArray& arr = jsonBuffer.createArray(); | ||||
|   arr.add("hello"); | ||||
|   arr.set(0, vla); | ||||
|  | ||||
|   EXPECT_STREQ("world", arr[0]); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonArraySubscript_Set) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonArray& arr = jsonBuffer.createArray(); | ||||
|   arr.add("hello"); | ||||
|   arr[0].set(vla); | ||||
|  | ||||
|   EXPECT_STREQ("world", arr[0]); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonArraySubscript_Assign) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonArray& arr = jsonBuffer.createArray(); | ||||
|   arr.add("hello"); | ||||
|   arr[0] = vla; | ||||
|  | ||||
|   EXPECT_STREQ("world", arr[0]); | ||||
| } | ||||
|  | ||||
| TEST(VariableLengthArray, JsonBuffer_strdup) { | ||||
|   int i = 16; | ||||
|   char vla[i]; | ||||
|   strcpy(vla, "world"); | ||||
|  | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   const char* dup = jsonBuffer.strdup(vla); | ||||
|  | ||||
|   EXPECT_NE(static_cast<const void*>(vla), static_cast<const void*>(dup)); | ||||
|   EXPECT_STREQ("world", dup); | ||||
| } | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user