mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	Redesigned JsonVariant to leverage converting constructors instead of assignment operators
This commit is contained in:
		
							
								
								
									
										14
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,5 +1,15 @@ | ||||
| Arduino JSON: change log | ||||
| ======================== | ||||
| ArduinoJson: change log | ||||
| ======================= | ||||
|  | ||||
| v5.0 (currently in development) | ||||
| ---- | ||||
|  | ||||
| * Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators. | ||||
|  | ||||
| **BREAKING CHANGES**: | ||||
| - `JsonObject::add()` was renamed to `set()` | ||||
| - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()` | ||||
| - Number of digits of floating point value are now set with `double_with_n_digits()` | ||||
|  | ||||
| v4.4 | ||||
| ---- | ||||
|   | ||||
| @@ -15,7 +15,9 @@ Features | ||||
| * JSON decoding | ||||
| * JSON encoding (with optional indentation) | ||||
| * Elegant API, very easy to use  | ||||
| * Fixed memory allocation (no malloc) | ||||
| * Efficient (no malloc, nor copy) | ||||
| * Portable (written in C++98) | ||||
| * Self-contained (no external dependency) | ||||
| * Small footprint | ||||
| * MIT License | ||||
|  | ||||
|   | ||||
| @@ -16,8 +16,8 @@ void setup() { | ||||
|   root["time"] = 1351824120; | ||||
|  | ||||
|   JsonArray& data = root.createNestedArray("data"); | ||||
|   data.add(48.756080, 6);  // 6 is the number of decimals to print | ||||
|   data.add(2.302038, 6);   // if not specified, 2 digits are printed | ||||
|   data.add(double_with_n_digits(48.756080, 6)); | ||||
|   data.add(double_with_n_digits(2.302038, 6)); | ||||
|  | ||||
|   root.printTo(Serial); | ||||
|   // This prints: | ||||
|   | ||||
| @@ -4,9 +4,9 @@ | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #include "../include/ArduinoJson/DynamicJsonBuffer.hpp" | ||||
| #include "../include/ArduinoJson/JsonArray.hpp" | ||||
| #include "../include/ArduinoJson/JsonObject.hpp" | ||||
| #include "../include/ArduinoJson/StaticJsonBuffer.hpp" | ||||
| #include "ArduinoJson/DynamicJsonBuffer.hpp" | ||||
| #include "ArduinoJson/JsonArray.hpp" | ||||
| #include "ArduinoJson/JsonObject.hpp" | ||||
| #include "ArduinoJson/StaticJsonBuffer.hpp" | ||||
|  | ||||
| using namespace ArduinoJson; | ||||
|   | ||||
							
								
								
									
										13
									
								
								include/ArduinoJson/Internals/ForceInline.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								include/ArduinoJson/Internals/ForceInline.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #define JSON_FORCE_INLINE __forceinline | ||||
| #else | ||||
| #define JSON_FORCE_INLINE __attribute__((always_inline)) | ||||
| #endif | ||||
| @@ -28,11 +28,17 @@ class JsonParser { | ||||
|   bool skip(const char *wordToSkip); | ||||
|   void skipSpaces(); | ||||
|  | ||||
|   void parseAnythingTo(JsonVariant &destination); | ||||
|   inline void parseBooleanTo(JsonVariant &destination); | ||||
|   inline void parseNullTo(JsonVariant &destination); | ||||
|   inline void parseNumberTo(JsonVariant &destination); | ||||
|   inline const char *parseString(); | ||||
|   bool parseAnythingTo(JsonVariant *destination); | ||||
|   JSON_FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination); | ||||
|  | ||||
|   const char *parseString(); | ||||
|  | ||||
|   inline bool parseArrayTo(JsonVariant *destination); | ||||
|   inline bool parseBooleanTo(JsonVariant *destination); | ||||
|   inline bool parseNullTo(JsonVariant *destination); | ||||
|   inline bool parseNumberTo(JsonVariant *destination); | ||||
|   inline bool parseObjectTo(JsonVariant *destination); | ||||
|   inline bool parseStringTo(JsonVariant *destination); | ||||
|  | ||||
|   JsonBuffer *_buffer; | ||||
|   char *_ptr; | ||||
|   | ||||
| @@ -23,6 +23,11 @@ union JsonVariantContent { | ||||
|   const char* asString;  // asString can be null | ||||
|   JsonArray* asArray;    // asArray cannot be null | ||||
|   JsonObject* asObject;  // asObject cannot be null | ||||
|  | ||||
|   template <typename T> | ||||
|   T as() const; | ||||
| }; | ||||
| } | ||||
| } | ||||
|  | ||||
| #include "JsonVariantContent.ipp" | ||||
|   | ||||
							
								
								
									
										96
									
								
								include/ArduinoJson/Internals/JsonVariantContent.ipp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								include/ArduinoJson/Internals/JsonVariantContent.ipp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| // Forward declarations | ||||
| class JsonArray; | ||||
| class JsonObject; | ||||
|  | ||||
| namespace Internals { | ||||
| template <> | ||||
| inline bool JsonVariantContent::as<bool>() const { | ||||
|   return asBoolean; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline char const* JsonVariantContent::as<char const*>() const { | ||||
|   return asString; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline double JsonVariantContent::as<double>() const { | ||||
|   return asDouble; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline float JsonVariantContent::as<float>() const { | ||||
|   return static_cast<float>(asDouble); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline JsonArray& JsonVariantContent::as<JsonArray&>() const { | ||||
|   return *asArray; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline const JsonArray& JsonVariantContent::as<JsonArray const&>() const { | ||||
|   return *asArray; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline JsonObject& JsonVariantContent::as<JsonObject&>() const { | ||||
|   return *asObject; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline const JsonObject& JsonVariantContent::as<JsonObject const&>() const { | ||||
|   return *asObject; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline signed char JsonVariantContent::as<signed char>() const { | ||||
|   return static_cast<signed char>(asLong); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline signed int JsonVariantContent::as<signed int>() const { | ||||
|   return static_cast<signed int>(asLong); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline signed long JsonVariantContent::as<signed long>() const { | ||||
|   return static_cast<signed long>(asLong); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline signed short JsonVariantContent::as<signed short>() const { | ||||
|   return static_cast<signed short>(asLong); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline unsigned char JsonVariantContent::as<unsigned char>() const { | ||||
|   return static_cast<unsigned char>(asLong); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline unsigned int JsonVariantContent::as<unsigned int>() const { | ||||
|   return static_cast<unsigned int>(asLong); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline unsigned long JsonVariantContent::as<unsigned long>() const { | ||||
|   return static_cast<unsigned long>(asLong); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline unsigned short JsonVariantContent::as<unsigned short>() const { | ||||
|   return static_cast<unsigned short>(asLong); | ||||
| } | ||||
| } | ||||
| } | ||||
| @@ -7,12 +7,14 @@ | ||||
| #pragma once | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| class JsonArray; | ||||
| class JsonObject; | ||||
|  | ||||
| namespace Internals { | ||||
|  | ||||
| // Enumerated type to know the current type of a JsonVariant. | ||||
| // The value determines which member of JsonVariantContent is used. | ||||
| enum JsonVariantType { | ||||
|   JSON_INVALID,    // a special state for JsonVariant::invalid() | ||||
|   JSON_UNDEFINED,  // the JsonVariant has not been initialized | ||||
|   JSON_ARRAY,      // the JsonVariant stores a pointer to a JsonArray | ||||
|   JSON_OBJECT,     // the JsonVariant stores a pointer to a JsonObject | ||||
|   | ||||
| @@ -39,7 +39,7 @@ class List { | ||||
|  | ||||
|   // Returns the numbers of elements in the list. | ||||
|   // For a JsonObject, it would return the number of key-value pairs | ||||
|   int size() const; | ||||
|   size_t size() const; | ||||
|  | ||||
|   iterator begin() { return iterator(_firstNode); } | ||||
|   iterator end() { return iterator(NULL); } | ||||
| @@ -48,19 +48,20 @@ class List { | ||||
|   const_iterator end() const { return const_iterator(NULL); } | ||||
|  | ||||
|  protected: | ||||
|   node_type *createNode() { | ||||
|   node_type *addNewNode() { | ||||
|     if (!_buffer) return NULL; | ||||
|     return new (_buffer) node_type(); | ||||
|   } | ||||
|  | ||||
|   void addNode(node_type *nodeToAdd) { | ||||
|     node_type *newNode = new (_buffer) node_type(); | ||||
|  | ||||
|     if (_firstNode) { | ||||
|       node_type *lastNode = _firstNode; | ||||
|       while (lastNode->next) lastNode = lastNode->next; | ||||
|       lastNode->next = nodeToAdd; | ||||
|       lastNode->next = newNode; | ||||
|     } else { | ||||
|       _firstNode = nodeToAdd; | ||||
|       _firstNode = newNode; | ||||
|     } | ||||
|  | ||||
|     return newNode; | ||||
|   } | ||||
|  | ||||
|   void removeNode(node_type *nodeToRemove); | ||||
|   | ||||
| @@ -31,7 +31,7 @@ class Prettyfier : public Print { | ||||
|  | ||||
|   size_t handleBlockClose(uint8_t); | ||||
|   size_t handleBlockOpen(uint8_t); | ||||
|   size_t handleColumn(); | ||||
|   size_t handleColon(); | ||||
|   size_t handleComma(); | ||||
|   size_t handleQuoteOpen(); | ||||
|   size_t handleNormalChar(uint8_t); | ||||
|   | ||||
| @@ -22,6 +22,7 @@ namespace ArduinoJson { | ||||
| // Forward declarations | ||||
| class JsonObject; | ||||
| class JsonBuffer; | ||||
| class JsonArraySubscript; | ||||
|  | ||||
| // An array of JsonVariant. | ||||
| // | ||||
| @@ -33,35 +34,35 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|                   public Internals::ReferenceType, | ||||
|                   public Internals::List<JsonVariant>, | ||||
|                   public Internals::JsonBufferAllocated { | ||||
|   // JsonBuffer is a friend because it needs to call the private constructor. | ||||
|   friend class JsonBuffer; | ||||
|  | ||||
|  public: | ||||
|   // Returns the JsonVariant at the specified index (synonym for operator[]) | ||||
|   JsonVariant &at(int index) const; | ||||
|   // Create an empty JsonArray attached to the specified JsonBuffer. | ||||
|   // You should not call this constructor directly. | ||||
|   // Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray(). | ||||
|   explicit JsonArray(JsonBuffer *buffer) | ||||
|       : Internals::List<JsonVariant>(buffer) {} | ||||
|  | ||||
|   // Returns the JsonVariant at the specified index (synonym for at()) | ||||
|   JsonVariant &operator[](int index) const { return at(index); } | ||||
|   // Gets the value at the specified index | ||||
|   JSON_FORCE_INLINE const JsonArraySubscript operator[](size_t index) const; | ||||
|  | ||||
|   // Adds an uninitialized JsonVariant at the end of the array. | ||||
|   // Return a reference or JsonVariant::invalid() if allocation fails. | ||||
|   JsonVariant &add(); | ||||
|   // Gets or sets the value at specified index | ||||
|   JSON_FORCE_INLINE JsonArraySubscript operator[](size_t index); | ||||
|  | ||||
|   // Adds the specified value at the end of the array. | ||||
|   JSON_FORCE_INLINE bool add(const JsonVariant value); | ||||
|  | ||||
|   // Sets the value at specified index. | ||||
|   JSON_FORCE_INLINE void set(size_t index, const JsonVariant value); | ||||
|  | ||||
|   // Gets the value at the specified index. | ||||
|   JSON_FORCE_INLINE JsonVariant get(size_t index) const; | ||||
|  | ||||
|   // Gets the value at the specified index. | ||||
|   template <typename T> | ||||
|   void add(T value) { | ||||
|     add().set(value); | ||||
|   } | ||||
|   JSON_FORCE_INLINE T get(size_t index) const; | ||||
|  | ||||
|   // Adds the specified double value at the end of the array. | ||||
|   // The value will be printed with the specified number of decimal digits. | ||||
|   void add(double value, uint8_t decimals) { add().set(value, decimals); } | ||||
|  | ||||
|   // Adds a reference to the specified JsonArray at the end of the array. | ||||
|   void add(JsonArray &array) { add().set(array); } | ||||
|  | ||||
|   // Adds a reference to the specified JsonObject at the end of the array. | ||||
|   void add(JsonObject &obejct) { add().set(obejct); } | ||||
|   // Check the type of the value at specified index. | ||||
|   template <typename T> | ||||
|   JSON_FORCE_INLINE T is(size_t index) const; | ||||
|  | ||||
|   // Creates a JsonArray and adds a reference at the end of the array. | ||||
|   // It's a shortcut for JsonBuffer::createArray() and JsonArray::add() | ||||
| @@ -72,7 +73,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|   JsonObject &createNestedObject(); | ||||
|  | ||||
|   // Removes element at specified index. | ||||
|   void removeAt(int index); | ||||
|   void removeAt(size_t index); | ||||
|  | ||||
|   // Returns a reference an invalid JsonArray. | ||||
|   // This object is meant to replace a NULL pointer. | ||||
| @@ -83,13 +84,11 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|   void writeTo(Internals::JsonWriter &writer) const; | ||||
|  | ||||
|  private: | ||||
|   // Create an empty JsonArray attached to the specified JsonBuffer. | ||||
|   explicit JsonArray(JsonBuffer *buffer) | ||||
|       : Internals::List<JsonVariant>(buffer) {} | ||||
|  | ||||
|   node_type *getNodeAt(int index) const; | ||||
|   node_type *getNodeAt(size_t index) const; | ||||
|  | ||||
|   // The instance returned by JsonArray::invalid() | ||||
|   static JsonArray _invalid; | ||||
| }; | ||||
| } | ||||
|  | ||||
| #include "JsonArray.ipp" | ||||
|   | ||||
							
								
								
									
										65
									
								
								include/ArduinoJson/JsonArray.ipp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								include/ArduinoJson/JsonArray.ipp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "JsonArray.hpp" | ||||
| #include "JsonArraySubscript.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| inline JsonArraySubscript JsonArray::operator[](size_t index) { | ||||
|   return JsonArraySubscript(*this, index); | ||||
| } | ||||
|  | ||||
| inline const JsonArraySubscript JsonArray::operator[](size_t index) const { | ||||
|   return JsonArraySubscript(*const_cast<JsonArray *>(this), index); | ||||
| } | ||||
|  | ||||
| inline bool JsonArray::add(const JsonVariant value) { | ||||
|   node_type *node = addNewNode(); | ||||
|   if (node) node->content = value; | ||||
|   return node != NULL; | ||||
| } | ||||
|  | ||||
| inline JsonVariant JsonArray::get(size_t index) const { | ||||
|   node_type *node = getNodeAt(index); | ||||
|   return node ? node->content : JsonVariant(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline T JsonArray::get(size_t index) const { | ||||
|   node_type *node = getNodeAt(index); | ||||
|   return node ? node->content.as<T>() : JsonVariant::invalid<T>(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline T JsonArray::is(size_t index) const { | ||||
|   node_type *node = getNodeAt(index); | ||||
|   return node ? node->content.is<T>() : false; | ||||
| } | ||||
|  | ||||
| inline void JsonArray::set(size_t index, const JsonVariant value) { | ||||
|   node_type *node = getNodeAt(index); | ||||
|   if (node) node->content = value; | ||||
| } | ||||
|  | ||||
| template <typename TImplem> | ||||
| inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[]( | ||||
|     int index) const { | ||||
|   return asArray()[index]; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline JsonArray &JsonVariant::invalid<JsonArray &>() { | ||||
|   return JsonArray::invalid(); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline JsonArray const &JsonVariant::invalid<JsonArray const &>() { | ||||
|   return JsonArray::invalid(); | ||||
| } | ||||
| } | ||||
							
								
								
									
										40
									
								
								include/ArduinoJson/JsonArraySubscript.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								include/ArduinoJson/JsonArraySubscript.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "JsonVariantBase.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | ||||
|  public: | ||||
|   JSON_FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) | ||||
|       : _array(array), _index(index) {} | ||||
|  | ||||
|   JSON_FORCE_INLINE JsonArraySubscript& operator=(const JsonVariant& value) { | ||||
|     _array.set(_index, value); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   JSON_FORCE_INLINE bool success() const { return _index < _array.size(); } | ||||
|  | ||||
|   JSON_FORCE_INLINE operator JsonVariant() const { return _array.get(_index); } | ||||
|  | ||||
|   template <typename T> | ||||
|   JSON_FORCE_INLINE T as() const { | ||||
|     return _array.get<T>(_index); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   JSON_FORCE_INLINE T is() const { | ||||
|     return _array.is<T>(_index); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   JsonArray& _array; | ||||
|   const size_t _index; | ||||
| }; | ||||
| } | ||||
| @@ -22,6 +22,7 @@ namespace ArduinoJson { | ||||
| // Forward declarations | ||||
| class JsonArray; | ||||
| class JsonBuffer; | ||||
| class JsonObjectSubscript; | ||||
|  | ||||
| // A dictionary of JsonVariant indexed by string (char*) | ||||
| // | ||||
| @@ -33,44 +34,35 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|                    public Internals::ReferenceType, | ||||
|                    public Internals::List<JsonPair>, | ||||
|                    public Internals::JsonBufferAllocated { | ||||
|   // JsonBuffer is a friend because it needs to call the private constructor. | ||||
|   friend class JsonBuffer; | ||||
|  | ||||
|  public: | ||||
|   typedef const char *key_type; | ||||
|   typedef JsonPair value_type; | ||||
|  | ||||
|   // Gets the JsonVariant associated with the specified key. | ||||
|   // Returns a reference or JsonVariant::invalid() if not found. | ||||
|   JsonVariant &at(key_type key); | ||||
|   // Create an empty JsonArray attached to the specified JsonBuffer. | ||||
|   // You should not use this constructor directly. | ||||
|   // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). | ||||
|   JSON_FORCE_INLINE explicit JsonObject(JsonBuffer *buffer) | ||||
|       : Internals::List<JsonPair>(buffer) {} | ||||
|  | ||||
|   // Gets the JsonVariant associated with the specified key. | ||||
|   // Returns a constant reference or JsonVariant::invalid() if not found. | ||||
|   const JsonVariant &at(key_type key) const; | ||||
|   // Gets or sets the value associated with the specified key. | ||||
|   JSON_FORCE_INLINE JsonObjectSubscript operator[](key_type key); | ||||
|  | ||||
|   // Gets or create the JsonVariant associated with the specified key. | ||||
|   // Returns a reference or JsonVariant::invalid() if allocation failed. | ||||
|   JsonVariant &operator[](key_type key); | ||||
|   // Gets the value associated with the specified key. | ||||
|   JSON_FORCE_INLINE const JsonObjectSubscript operator[](key_type key) const; | ||||
|  | ||||
|   // Gets the JsonVariant associated with the specified key. | ||||
|   // Returns a constant reference or JsonVariant::invalid() if not found. | ||||
|   const JsonVariant &operator[](key_type key) const { return at(key); } | ||||
|   // Sets the specified key with the specified value. | ||||
|   JSON_FORCE_INLINE bool set(key_type key, const JsonVariant value); | ||||
|  | ||||
|   // Adds an uninitialized JsonVariant associated with the specified key. | ||||
|   // Return a reference or JsonVariant::invalid() if allocation fails. | ||||
|   JsonVariant &add(key_type key) { return (*this)[key]; } | ||||
|   // Gets the value associated with the specified key. | ||||
|   JSON_FORCE_INLINE JsonVariant get(key_type key) const; | ||||
|  | ||||
|   // Adds the specified key with the specified value. | ||||
|   // Gets the value associated with the specified key. | ||||
|   template <typename T> | ||||
|   void add(key_type key, T value) { | ||||
|     add(key).set(value); | ||||
|   } | ||||
|   JSON_FORCE_INLINE T get(key_type key) const; | ||||
|  | ||||
|   // Adds the specified key with a reference to the specified JsonArray. | ||||
|   void add(key_type key, JsonArray &array) { add(key).set(array); } | ||||
|  | ||||
|   // Adds the specified key with a reference to the specified JsonObject. | ||||
|   void add(key_type key, JsonObject &object) { add(key).set(object); } | ||||
|   // Checks the type of the value associated with the specified key. | ||||
|   template <typename T> | ||||
|   JSON_FORCE_INLINE T is(key_type key) const; | ||||
|  | ||||
|   // Creates and adds a JsonArray. | ||||
|   // This is a shortcut for JsonBuffer::createArray() and JsonObject::add(). | ||||
| @@ -81,7 +73,7 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|   JsonObject &createNestedObject(key_type key); | ||||
|  | ||||
|   // Tells weither the specified key is present and associated with a value. | ||||
|   bool containsKey(key_type key) const { return at(key).success(); } | ||||
|   JSON_FORCE_INLINE bool containsKey(key_type key) const; | ||||
|  | ||||
|   // Removes the specified key and the associated value. | ||||
|   void remove(key_type key); | ||||
| @@ -95,13 +87,14 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|   void writeTo(Internals::JsonWriter &writer) const; | ||||
|  | ||||
|  private: | ||||
|   // Create an empty JsonArray attached to the specified JsonBuffer. | ||||
|   explicit JsonObject(JsonBuffer *buffer) : Internals::List<JsonPair>(buffer) {} | ||||
|  | ||||
|   // Returns the list node that matches the specified key. | ||||
|   node_type *getNodeAt(key_type key) const; | ||||
|  | ||||
|   node_type *getOrCreateNodeAt(const char *key); | ||||
|  | ||||
|   // The instance returned by JsonObject::invalid() | ||||
|   static JsonObject _invalid; | ||||
| }; | ||||
| } | ||||
|  | ||||
| #include "JsonObject.ipp" | ||||
|   | ||||
							
								
								
									
										69
									
								
								include/ArduinoJson/JsonObject.ipp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								include/ArduinoJson/JsonObject.ipp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "JsonObject.hpp" | ||||
| #include "JsonObjectSubscript.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| inline JsonVariant JsonObject::get(key_type key) const { | ||||
|   node_type *node = getNodeAt(key); | ||||
|   return node ? node->content.value : JsonVariant(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline T JsonObject::get(key_type key) const { | ||||
|   node_type *node = getNodeAt(key); | ||||
|   return node ? node->content.value.as<T>() : JsonVariant::invalid<T>(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline T JsonObject::is(key_type key) const { | ||||
|   node_type *node = getNodeAt(key); | ||||
|   return node ? node->content.value.is<T>() : false; | ||||
| } | ||||
|  | ||||
| inline JsonObjectSubscript JsonObject::operator[](key_type key) { | ||||
|   return JsonObjectSubscript(*this, key); | ||||
| } | ||||
|  | ||||
| inline const JsonObjectSubscript JsonObject::operator[](key_type key) const { | ||||
|   return JsonObjectSubscript(*const_cast<JsonObject *>(this), key); | ||||
| } | ||||
|  | ||||
| inline bool JsonObject::containsKey(key_type key) const { | ||||
|   return getNodeAt(key) != NULL; | ||||
| } | ||||
|  | ||||
| inline void JsonObject::remove(key_type key) { removeNode(getNodeAt(key)); } | ||||
|  | ||||
| inline bool JsonObject::set(const char *key, const JsonVariant value) { | ||||
|   node_type *node = getOrCreateNodeAt(key); | ||||
|   if (!node) return false; | ||||
|  | ||||
|   node->content.key = key; | ||||
|   node->content.value = value; | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| template <typename TImplem> | ||||
| inline const JsonObjectSubscript JsonVariantBase<TImplem>::operator[]( | ||||
|     const char *key) const { | ||||
|   return asObject()[key]; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline JsonObject const &JsonVariant::invalid<JsonObject const &>() { | ||||
|   return JsonObject::invalid(); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline JsonObject &JsonVariant::invalid<JsonObject &>() { | ||||
|   return JsonObject::invalid(); | ||||
| } | ||||
| } | ||||
							
								
								
									
										40
									
								
								include/ArduinoJson/JsonObjectSubscript.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								include/ArduinoJson/JsonObjectSubscript.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "JsonVariantBase.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript> { | ||||
|  public: | ||||
|   JSON_FORCE_INLINE JsonObjectSubscript(JsonObject& object, const char* key) | ||||
|       : _object(object), _key(key) {} | ||||
|  | ||||
|   JSON_FORCE_INLINE JsonObjectSubscript& operator=(const JsonVariant& value) { | ||||
|     _object.set(_key, value); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   JSON_FORCE_INLINE bool success() const { return _object.containsKey(_key); } | ||||
|  | ||||
|   JSON_FORCE_INLINE operator JsonVariant() const { return _object.get(_key); } | ||||
|  | ||||
|   template <typename T> | ||||
|   JSON_FORCE_INLINE T as() const { | ||||
|     return _object.get<T>(_key); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   JSON_FORCE_INLINE T is() const { | ||||
|     return _object.is<T>(_key); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   JsonObject& _object; | ||||
|   const char* _key; | ||||
| }; | ||||
| } | ||||
| @@ -12,6 +12,7 @@ | ||||
| #include "Internals/JsonPrintable.hpp" | ||||
| #include "Internals/JsonVariantContent.hpp" | ||||
| #include "Internals/JsonVariantType.hpp" | ||||
| #include "JsonVariantBase.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| @@ -26,261 +27,74 @@ class JsonObject; | ||||
| // - a char, short, int or a long (signed or unsigned) | ||||
| // - a string (const char*) | ||||
| // - a reference to a JsonArray or JsonObject | ||||
| class JsonVariant : public Internals::JsonPrintable<JsonVariant> { | ||||
| class JsonVariant : public Internals::JsonPrintable<JsonVariant>, | ||||
|                     public JsonVariantBase<JsonVariant> { | ||||
|  public: | ||||
|   // Creates an uninitialized JsonVariant | ||||
|   JsonVariant() : _type(Internals::JSON_UNDEFINED) {} | ||||
|   JSON_FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {} | ||||
|  | ||||
|   // Initializes a JsonVariant with the specified value. | ||||
|   template <typename T> | ||||
|   explicit JsonVariant(T value) { | ||||
|     set(value); | ||||
|   } | ||||
|  | ||||
|   // Tells weither the variant is valid. | ||||
|   bool success() const { | ||||
|     return _type != Internals::JSON_INVALID && | ||||
|            _type != Internals::JSON_UNDEFINED; | ||||
|   } | ||||
|  | ||||
|   // Sets the variant to a boolean value. | ||||
|   // Create a JsonVariant containing a boolean value. | ||||
|   // It will be serialized as "true" or "false" in JSON. | ||||
|   void set(bool value); | ||||
|   JSON_FORCE_INLINE JsonVariant(bool value); | ||||
|  | ||||
|   // Sets the variant to a floating point value. | ||||
|   // Create a JsonVariant containing a floating point value. | ||||
|   // The second argument specifies the number of decimal digits to write in | ||||
|   // the JSON string. | ||||
|   void set(double value, uint8_t decimals = 2); | ||||
|   JSON_FORCE_INLINE JsonVariant(float value, uint8_t decimals = 2); | ||||
|   JSON_FORCE_INLINE JsonVariant(double value, uint8_t decimals = 2); | ||||
|  | ||||
|   // Sets the variant to be an integer value. | ||||
|   void set(signed long value); | ||||
|   void set(signed char value) { set(static_cast<long>(value)); } | ||||
|   void set(signed int value) { set(static_cast<long>(value)); } | ||||
|   void set(signed short value) { set(static_cast<long>(value)); } | ||||
|   void set(unsigned char value) { set(static_cast<long>(value)); } | ||||
|   void set(unsigned int value) { set(static_cast<long>(value)); } | ||||
|   void set(unsigned long value) { set(static_cast<long>(value)); } | ||||
|   void set(unsigned short value) { set(static_cast<long>(value)); } | ||||
|   // Create a JsonVariant containing an integer value. | ||||
|   JSON_FORCE_INLINE JsonVariant(signed char value); | ||||
|   JSON_FORCE_INLINE JsonVariant(signed long value); | ||||
|   JSON_FORCE_INLINE JsonVariant(signed int value); | ||||
|   JSON_FORCE_INLINE JsonVariant(signed short value); | ||||
|   JSON_FORCE_INLINE JsonVariant(unsigned char value); | ||||
|   JSON_FORCE_INLINE JsonVariant(unsigned long value); | ||||
|   JSON_FORCE_INLINE JsonVariant(unsigned int value); | ||||
|   JSON_FORCE_INLINE JsonVariant(unsigned short value); | ||||
|  | ||||
|   // Sets the variant to be a string. | ||||
|   void set(const char *value); | ||||
|   // Create a JsonVariant containing a string. | ||||
|   JSON_FORCE_INLINE JsonVariant(const char *value); | ||||
|  | ||||
|   // Sets the variant to be a reference to an array. | ||||
|   void set(JsonArray &array); | ||||
|   // Create a JsonVariant containing a reference to an array. | ||||
|   JSON_FORCE_INLINE JsonVariant(JsonArray &array); | ||||
|  | ||||
|   // Sets the variant to be a reference to an object. | ||||
|   void set(JsonObject &object); | ||||
|  | ||||
|   // Sets the variant to the specified value. | ||||
|   template <typename T> | ||||
|   JsonVariant &operator=(T value) { | ||||
|     set(value); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   // Sets the variant to be a reference to an array. | ||||
|   JsonVariant &operator=(JsonArray &array) { | ||||
|     set(array); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   // Sets the variant to be a reference to an object. | ||||
|   JsonVariant &operator=(JsonObject &object) { | ||||
|     set(object); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   // Gets the variant as a boolean value. | ||||
|   // Returns false if the variant is not a boolean value. | ||||
|   operator bool() const; | ||||
|  | ||||
|   // Gets the variant as a floating-point value. | ||||
|   // Returns 0.0 if the variant is not a floating-point value | ||||
|   operator double() const; | ||||
|   operator float() const { return static_cast<float>(as<double>()); } | ||||
|  | ||||
|   // Gets the variant as an integer value. | ||||
|   // Returns 0 if the variant is not an integer value. | ||||
|   operator signed long() const; | ||||
|   operator signed char() const { return cast_long_to<signed char>(); } | ||||
|   operator signed int() const { return cast_long_to<signed int>(); } | ||||
|   operator signed short() const { return cast_long_to<signed short>(); } | ||||
|   operator unsigned char() const { return cast_long_to<unsigned char>(); } | ||||
|   operator unsigned int() const { return cast_long_to<unsigned int>(); } | ||||
|   operator unsigned long() const { return cast_long_to<unsigned long>(); } | ||||
|   operator unsigned short() const { return cast_long_to<unsigned short>(); } | ||||
|  | ||||
|   // Gets the variant as a string. | ||||
|   // Returns NULL if variant is not a string. | ||||
|   operator const char *() const; | ||||
|   const char *asString() const { return as<const char *>(); } | ||||
|  | ||||
|   // Gets the variant as an array. | ||||
|   // Returns a reference to the JsonArray or JsonArray::invalid() if the variant | ||||
|   // is not an array. | ||||
|   operator JsonArray &() const; | ||||
|   JsonArray &asArray() const { return as<JsonArray &>(); } | ||||
|  | ||||
|   // Gets the variant as an object. | ||||
|   // Returns a reference to the JsonObject or JsonObject::invalid() if the | ||||
|   // variant is not an object. | ||||
|   operator JsonObject &() const; | ||||
|   JsonObject &asObject() const { return as<JsonObject &>(); } | ||||
|   // Create a JsonVariant containing a reference to an object. | ||||
|   JSON_FORCE_INLINE JsonVariant(JsonObject &object); | ||||
|  | ||||
|   // Get the variant as the specified type. | ||||
|   // See cast operators for details. | ||||
|   template <typename T> | ||||
|   T as() const { | ||||
|     return static_cast<T>(*this); | ||||
|   } | ||||
|   JSON_FORCE_INLINE T as() const; | ||||
|  | ||||
|   // Tells weither the variant has the specified type. | ||||
|   // Returns true if the variant has type type T, false otherwise. | ||||
|   template <typename T> | ||||
|   bool is() const { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   // Returns an invalid variant. | ||||
|   // This is meant to replace a NULL pointer. | ||||
|   static JsonVariant &invalid() { return _invalid; } | ||||
|   JSON_FORCE_INLINE bool is() const; | ||||
|  | ||||
|   // Serialize the variant to a JsonWriter | ||||
|   void writeTo(Internals::JsonWriter &writer) const; | ||||
|  | ||||
|   // Mimics an array or an object. | ||||
|   // Returns the size of the array or object if the variant has that type. | ||||
|   // Returns 0 if the variant is neither an array nor an object | ||||
|   size_t size() const; | ||||
|  | ||||
|   // Mimics an array. | ||||
|   // Returns the element at specified index if the variant is an array. | ||||
|   // Returns JsonVariant::invalid() if the variant is not an array. | ||||
|   JsonVariant &operator[](int index); | ||||
|  | ||||
|   // Mimics an object. | ||||
|   // Returns the value associated with the specified key if the variant is an | ||||
|   // object. | ||||
|   // Return JsonVariant::invalid() if the variant is not an object. | ||||
|   JsonVariant &operator[](const char *key); | ||||
|   // TODO: rename | ||||
|   template <typename T> | ||||
|   static T invalid(); | ||||
|  | ||||
|  private: | ||||
|   // Special constructor used only to create _invalid. | ||||
|   explicit JsonVariant(Internals::JsonVariantType type) : _type(type) {} | ||||
|  | ||||
|   // Helper for interger cast operators | ||||
|   template <typename T> | ||||
|   T cast_long_to() const { | ||||
|     return static_cast<T>(as<long>()); | ||||
|   } | ||||
|  | ||||
|   // The current type of the variant | ||||
|   Internals::JsonVariantType _type; | ||||
|  | ||||
|   // The various alternatives for the value of the variant. | ||||
|   Internals::JsonVariantContent _content; | ||||
|  | ||||
|   // The instance returned by JsonVariant::invalid() | ||||
|   static JsonVariant _invalid; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<long>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| inline JsonVariant float_with_n_digits(float value, uint8_t digits) { | ||||
|   return JsonVariant(value, digits); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<double>() const { | ||||
|   return _type >= Internals::JSON_DOUBLE_0_DECIMALS; | ||||
| inline JsonVariant double_with_n_digits(double value, uint8_t digits) { | ||||
|   return JsonVariant(value, digits); | ||||
| } | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<bool>() const { | ||||
|   return _type == Internals::JSON_BOOLEAN; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<const char *>() const { | ||||
|   return _type == Internals::JSON_STRING; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<JsonArray &>() const { | ||||
|   return _type == Internals::JSON_ARRAY; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<const JsonArray &>() const { | ||||
|   return _type == Internals::JSON_ARRAY; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<JsonObject &>() const { | ||||
|   return _type == Internals::JSON_OBJECT; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<const JsonObject &>() const { | ||||
|   return _type == Internals::JSON_OBJECT; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator==(const JsonVariant &left, T right) { | ||||
|   return left.as<T>() == right; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator==(T left, const JsonVariant &right) { | ||||
|   return left == right.as<T>(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator!=(const JsonVariant &left, T right) { | ||||
|   return left.as<T>() != right; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator!=(T left, const JsonVariant &right) { | ||||
|   return left != right.as<T>(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator<=(const JsonVariant &left, T right) { | ||||
|   return left.as<T>() <= right; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator<=(T left, const JsonVariant &right) { | ||||
|   return left <= right.as<T>(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator>=(const JsonVariant &left, T right) { | ||||
|   return left.as<T>() >= right; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator>=(T left, const JsonVariant &right) { | ||||
|   return left >= right.as<T>(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator<(const JsonVariant &left, T right) { | ||||
|   return left.as<T>() < right; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator<(T left, const JsonVariant &right) { | ||||
|   return left < right.as<T>(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator>(const JsonVariant &left, T right) { | ||||
|   return left.as<T>() > right; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool operator>(T left, const JsonVariant &right) { | ||||
|   return left > right.as<T>(); | ||||
| } | ||||
| } | ||||
| // Include inline implementations | ||||
| #include "JsonVariant.ipp" | ||||
|   | ||||
							
								
								
									
										179
									
								
								include/ArduinoJson/JsonVariant.ipp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								include/ArduinoJson/JsonVariant.ipp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "JsonVariant.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| inline JsonVariant::JsonVariant(bool value) { | ||||
|   _type = Internals::JSON_BOOLEAN; | ||||
|   _content.asBoolean = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(const char *value) { | ||||
|   _type = Internals::JSON_STRING; | ||||
|   _content.asString = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(double value, uint8_t decimals) { | ||||
|   _type = static_cast<Internals::JsonVariantType>( | ||||
|       Internals::JSON_DOUBLE_0_DECIMALS + decimals); | ||||
|   _content.asDouble = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(float value, uint8_t decimals) { | ||||
|   _type = static_cast<Internals::JsonVariantType>( | ||||
|       Internals::JSON_DOUBLE_0_DECIMALS + decimals); | ||||
|   _content.asDouble = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(JsonArray &array) { | ||||
|   _type = Internals::JSON_ARRAY; | ||||
|   _content.asArray = &array; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(JsonObject &object) { | ||||
|   _type = Internals::JSON_OBJECT; | ||||
|   _content.asObject = &object; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(signed char value) { | ||||
|   _type = Internals::JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(signed int value) { | ||||
|   _type = Internals::JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(signed long value) { | ||||
|   _type = Internals::JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(signed short value) { | ||||
|   _type = Internals::JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(unsigned char value) { | ||||
|   _type = Internals::JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(unsigned int value) { | ||||
|   _type = Internals::JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(unsigned long value) { | ||||
|   _type = Internals::JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(unsigned short value) { | ||||
|   _type = Internals::JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline T JsonVariant::as() const { | ||||
|   return is<T>() ? _content.as<T>() : invalid<T>(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline T JsonVariant::invalid() { | ||||
|   return T(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool JsonVariant::is() const { | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<bool>() const { | ||||
|   return _type == Internals::JSON_BOOLEAN; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<char const *>() const { | ||||
|   return _type == Internals::JSON_STRING; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<double>() const { | ||||
|   return _type >= Internals::JSON_DOUBLE_0_DECIMALS; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<float>() const { | ||||
|   return _type >= Internals::JSON_DOUBLE_0_DECIMALS; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<JsonArray &>() const { | ||||
|   return _type == Internals::JSON_ARRAY; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<JsonArray const &>() const { | ||||
|   return _type == Internals::JSON_ARRAY; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<JsonObject &>() const { | ||||
|   return _type == Internals::JSON_OBJECT; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<JsonObject const &>() const { | ||||
|   return _type == Internals::JSON_OBJECT; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<signed char>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<signed int>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<signed long>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<signed short>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<unsigned char>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<unsigned int>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<unsigned long>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline bool JsonVariant::is<unsigned short>() const { | ||||
|   return _type == Internals::JSON_LONG; | ||||
| } | ||||
| } | ||||
							
								
								
									
										148
									
								
								include/ArduinoJson/JsonVariantBase.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								include/ArduinoJson/JsonVariantBase.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Internals/ForceInline.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| // Forward declarations. | ||||
| class JsonArraySubscript; | ||||
| class JsonObjectSubscript; | ||||
|  | ||||
| template <typename TImpl> | ||||
| class JsonVariantBase { | ||||
|  public: | ||||
|   // Gets the variant as a boolean value. | ||||
|   // Returns false if the variant is not a boolean value. | ||||
|   JSON_FORCE_INLINE operator bool() const { return as<bool>(); } | ||||
|  | ||||
|   // Gets the variant as a floating-point value. | ||||
|   // Returns 0.0 if the variant is not a floating-point value | ||||
|   JSON_FORCE_INLINE operator double() const { return as<double>(); } | ||||
|   JSON_FORCE_INLINE operator float() const { return as<float>(); } | ||||
|  | ||||
|   // Gets the variant as an integer value. | ||||
|   // Returns 0 if the variant is not an integer value. | ||||
|   JSON_FORCE_INLINE operator signed long() const { return as<signed long>(); } | ||||
|   JSON_FORCE_INLINE operator signed char() const { return as<signed char>(); } | ||||
|   JSON_FORCE_INLINE operator signed int() const { return as<signed int>(); } | ||||
|   JSON_FORCE_INLINE operator signed short() const { return as<signed short>(); } | ||||
|   JSON_FORCE_INLINE operator unsigned char() const { | ||||
|     return as<unsigned char>(); | ||||
|   } | ||||
|   JSON_FORCE_INLINE operator unsigned int() const { return as<unsigned int>(); } | ||||
|   JSON_FORCE_INLINE operator unsigned long() const { | ||||
|     return as<unsigned long>(); | ||||
|   } | ||||
|   JSON_FORCE_INLINE operator unsigned short() const { | ||||
|     return as<unsigned short>(); | ||||
|   } | ||||
|  | ||||
|   // Gets the variant as a string. | ||||
|   // Returns NULL if variant is not a string. | ||||
|   JSON_FORCE_INLINE operator const char *() const { return as<const char *>(); } | ||||
|   JSON_FORCE_INLINE const char *asString() const { return as<const char *>(); } | ||||
|  | ||||
|   // Gets the variant as an array. | ||||
|   // Returns a reference to the JsonArray or JsonArray::invalid() if the | ||||
|   // variant | ||||
|   // is not an array. | ||||
|   JSON_FORCE_INLINE operator JsonArray &() const { return as<JsonArray &>(); } | ||||
|   JSON_FORCE_INLINE JsonArray &asArray() const { return as<JsonArray &>(); } | ||||
|  | ||||
|   // Gets the variant as an object. | ||||
|   // Returns a reference to the JsonObject or JsonObject::invalid() if the | ||||
|   // variant is not an object. | ||||
|   JSON_FORCE_INLINE operator JsonObject &() const { return as<JsonObject &>(); } | ||||
|   JSON_FORCE_INLINE JsonObject &asObject() const { return as<JsonObject &>(); } | ||||
|  | ||||
|   template <typename T> | ||||
|   JSON_FORCE_INLINE const T as() const { | ||||
|     return impl()->template as<T>(); | ||||
|   } | ||||
|  | ||||
|   // Mimics an array or an object. | ||||
|   // Returns the size of the array or object if the variant has that type. | ||||
|   // Returns 0 if the variant is neither an array nor an object | ||||
|   size_t size() const { return asArray().size() + asObject().size(); } | ||||
|  | ||||
|   // Mimics an array. | ||||
|   // Returns the element at specified index if the variant is an array. | ||||
|   // Returns JsonVariant::invalid() if the variant is not an array. | ||||
|   JSON_FORCE_INLINE const JsonArraySubscript operator[](int index) const; | ||||
|  | ||||
|   // Mimics an object. | ||||
|   // Returns the value associated with the specified key if the variant is | ||||
|   // an object. | ||||
|   // Return JsonVariant::invalid() if the variant is not an object. | ||||
|   JSON_FORCE_INLINE const JsonObjectSubscript operator[](const char *key) const; | ||||
|  | ||||
|  private: | ||||
|   const TImpl *impl() const { return static_cast<const TImpl *>(this); } | ||||
| }; | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator==(const JsonVariantBase<TImpl> &left, TComparand right) { | ||||
|   return left.template as<TComparand>() == right; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator==(TComparand left, const JsonVariantBase<TImpl> &right) { | ||||
|   return left == right.template as<TComparand>(); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator!=(const JsonVariantBase<TImpl> &left, TComparand right) { | ||||
|   return left.template as<TComparand>() != right; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator!=(TComparand left, const JsonVariantBase<TImpl> &right) { | ||||
|   return left != right.template as<TComparand>(); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator<=(const JsonVariantBase<TImpl> &left, TComparand right) { | ||||
|   return left.template as<TComparand>() <= right; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator<=(TComparand left, const JsonVariantBase<TImpl> &right) { | ||||
|   return left <= right.template as<TComparand>(); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator>=(const JsonVariantBase<TImpl> &left, TComparand right) { | ||||
|   return left.template as<TComparand>() >= right; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator>=(TComparand left, const JsonVariantBase<TImpl> &right) { | ||||
|   return left >= right.template as<TComparand>(); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator<(const JsonVariantBase<TImpl> &left, TComparand right) { | ||||
|   return left.template as<TComparand>() < right; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator<(TComparand left, const JsonVariantBase<TImpl> &right) { | ||||
|   return left < right.template as<TComparand>(); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator>(const JsonVariantBase<TImpl> &left, TComparand right) { | ||||
|   return left.template as<TComparand>() > right; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator>(TComparand left, const JsonVariantBase<TImpl> &right) { | ||||
|   return left > right.template as<TComparand>(); | ||||
| } | ||||
| } | ||||
| @@ -38,25 +38,27 @@ bool JsonParser::skip(const char *wordToSkip) { | ||||
|   return *charToSkip == '\0'; | ||||
| } | ||||
|  | ||||
| void JsonParser::parseAnythingTo(JsonVariant &destination) { | ||||
|   if (_nestingLimit == 0) return; | ||||
| bool JsonParser::parseAnythingTo(JsonVariant *destination) { | ||||
|   if (_nestingLimit == 0) return false; | ||||
|   _nestingLimit--; | ||||
|   bool success = parseAnythingToUnsafe(destination); | ||||
|   _nestingLimit++; | ||||
|   return success; | ||||
| } | ||||
|  | ||||
| inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { | ||||
|   skipSpaces(); | ||||
|  | ||||
|   switch (*_ptr) { | ||||
|     case '[': | ||||
|       destination = parseArray(); | ||||
|       break; | ||||
|       return parseArrayTo(destination); | ||||
|  | ||||
|     case '{': | ||||
|       destination = parseObject(); | ||||
|       break; | ||||
|       return parseObjectTo(destination); | ||||
|  | ||||
|     case 't': | ||||
|     case 'f': | ||||
|       parseBooleanTo(destination); | ||||
|       break; | ||||
|       return parseBooleanTo(destination); | ||||
|  | ||||
|     case '-': | ||||
|     case '.': | ||||
| @@ -70,20 +72,14 @@ void JsonParser::parseAnythingTo(JsonVariant &destination) { | ||||
|     case '7': | ||||
|     case '8': | ||||
|     case '9': | ||||
|       parseNumberTo(destination); | ||||
|       break; | ||||
|       return parseNumberTo(destination); | ||||
|  | ||||
|     case 'n': | ||||
|       parseNullTo(destination); | ||||
|       break; | ||||
|       return parseNullTo(destination); | ||||
|  | ||||
|     case '\'': | ||||
|     case '\"': | ||||
|       destination = parseString(); | ||||
|       break; | ||||
|     default: | ||||
|       return parseStringTo(destination); | ||||
|   } | ||||
|  | ||||
|   _nestingLimit++; | ||||
| } | ||||
|  | ||||
| JsonArray &JsonParser::parseArray() { | ||||
| @@ -97,9 +93,9 @@ JsonArray &JsonParser::parseArray() { | ||||
|   // Read each value | ||||
|   for (;;) { | ||||
|     // 1 - Parse value | ||||
|     JsonVariant &value = array.add(); | ||||
|     parseAnythingTo(value); | ||||
|     if (!value.success()) goto ERROR_INVALID_VALUE; | ||||
|     JsonVariant value; | ||||
|     if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE; | ||||
|     if (!array.add(value)) goto ERROR_NO_MEMORY; | ||||
|  | ||||
|     // 2 - More values? | ||||
|     if (skip(']')) goto SUCCES_NON_EMPTY_ARRAY; | ||||
| @@ -113,9 +109,18 @@ SUCCES_NON_EMPTY_ARRAY: | ||||
| ERROR_INVALID_VALUE: | ||||
| ERROR_MISSING_BRACKET: | ||||
| ERROR_MISSING_COMMA: | ||||
| ERROR_NO_MEMORY: | ||||
|   return JsonArray::invalid(); | ||||
| } | ||||
|  | ||||
| bool JsonParser::parseArrayTo(JsonVariant *destination) { | ||||
|   JsonArray &array = parseArray(); | ||||
|   if (!array.success()) return false; | ||||
|  | ||||
|   *destination = array; | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| JsonObject &JsonParser::parseObject() { | ||||
|   // Create an empty object | ||||
|   JsonObject &object = _buffer->createObject(); | ||||
| @@ -132,9 +137,9 @@ JsonObject &JsonParser::parseObject() { | ||||
|     if (!skip(':')) goto ERROR_MISSING_COLON; | ||||
|  | ||||
|     // 2 - Parse value | ||||
|     JsonVariant &value = object.add(key); | ||||
|     parseAnythingTo(value); | ||||
|     if (!value.success()) goto ERROR_INVALID_VALUE; | ||||
|     JsonVariant value; | ||||
|     if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE; | ||||
|     if (!object.set(key, value)) goto ERROR_NO_MEMORY; | ||||
|  | ||||
|     // 3 - More keys/values? | ||||
|     if (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT; | ||||
| @@ -150,19 +155,31 @@ ERROR_INVALID_VALUE: | ||||
| ERROR_MISSING_BRACE: | ||||
| ERROR_MISSING_COLON: | ||||
| ERROR_MISSING_COMMA: | ||||
| ERROR_NO_MEMORY: | ||||
|   return JsonObject::invalid(); | ||||
| } | ||||
|  | ||||
| void JsonParser::parseBooleanTo(JsonVariant &destination) { | ||||
|   if (skip("true")) | ||||
|     destination = true; | ||||
|   else if (skip("false")) | ||||
|     destination = false; | ||||
|   else | ||||
|     destination = JsonVariant::invalid(); | ||||
| bool JsonParser::parseObjectTo(JsonVariant *destination) { | ||||
|   JsonObject &object = parseObject(); | ||||
|   if (!object.success()) return false; | ||||
|  | ||||
|   *destination = object; | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| void JsonParser::parseNumberTo(JsonVariant &destination) { | ||||
| bool JsonParser::parseBooleanTo(JsonVariant *destination) { | ||||
|   if (skip("true")) { | ||||
|     *destination = true; | ||||
|     return true; | ||||
|   } else if (skip("false")) { | ||||
|     *destination = false; | ||||
|     return true; | ||||
|   } else { | ||||
|     return false; | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool JsonParser::parseNumberTo(JsonVariant *destination) { | ||||
|   char *endOfLong; | ||||
|   long longValue = strtol(_ptr, &endOfLong, 10); | ||||
|   char stopChar = *endOfLong; | ||||
| @@ -176,22 +193,28 @@ void JsonParser::parseNumberTo(JsonVariant &destination) { | ||||
|     // Count the decimal digits | ||||
|     uint8_t decimals = static_cast<uint8_t>(_ptr - endOfLong - 1); | ||||
|     // Set the variant as a double | ||||
|     destination.set(doubleValue, decimals); | ||||
|     *destination = JsonVariant(doubleValue, decimals); | ||||
|   } else { | ||||
|     // No => set the variant as a long | ||||
|     _ptr = endOfLong; | ||||
|     destination = longValue; | ||||
|     *destination = longValue; | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| void JsonParser::parseNullTo(JsonVariant &destination) { | ||||
| bool JsonParser::parseNullTo(JsonVariant *destination) { | ||||
|   const char *NULL_STRING = NULL; | ||||
|   if (skip("null")) | ||||
|     destination = NULL_STRING; | ||||
|   else | ||||
|     destination = JsonVariant::invalid(); | ||||
|   if (!skip("null")) return false; | ||||
|   *destination = NULL_STRING; | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| const char *JsonParser::parseString() { | ||||
|   return QuotedString::extractFrom(_ptr, &_ptr); | ||||
| } | ||||
|  | ||||
| bool JsonParser::parseStringTo(JsonVariant *destination) { | ||||
|   const char *value = parseString(); | ||||
|   *destination = value; | ||||
|   return value != NULL; | ||||
| } | ||||
|   | ||||
| @@ -13,8 +13,8 @@ using namespace ArduinoJson; | ||||
| using namespace ArduinoJson::Internals; | ||||
|  | ||||
| template <typename T> | ||||
| int List<T>::size() const { | ||||
|   int nodeCount = 0; | ||||
| size_t List<T>::size() const { | ||||
|   size_t nodeCount = 0; | ||||
|   for (node_type *node = _firstNode; node; node = node->next) nodeCount++; | ||||
|   return nodeCount; | ||||
| } | ||||
|   | ||||
| @@ -33,7 +33,7 @@ inline size_t Prettyfier::handleMarkupChar(uint8_t c) { | ||||
|       return handleBlockClose(c); | ||||
|  | ||||
|     case ':': | ||||
|       return handleColumn(); | ||||
|       return handleColon(); | ||||
|  | ||||
|     case ',': | ||||
|       return handleComma(); | ||||
| @@ -54,7 +54,7 @@ inline size_t Prettyfier::handleBlockClose(uint8_t c) { | ||||
|   return unindentIfNeeded() + _sink.write(c); | ||||
| } | ||||
|  | ||||
| inline size_t Prettyfier::handleColumn() { | ||||
| inline size_t Prettyfier::handleColon() { | ||||
|   return _sink.write(':') + _sink.write(' '); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -14,18 +14,10 @@ using namespace ArduinoJson::Internals; | ||||
|  | ||||
| JsonArray JsonArray::_invalid(NULL); | ||||
|  | ||||
| JsonVariant &JsonArray::at(int index) const { | ||||
|   node_type *node = getNodeAt(index); | ||||
|   return node ? node->content : JsonVariant::invalid(); | ||||
| } | ||||
|  | ||||
| JsonVariant &JsonArray::add() { | ||||
|   node_type *node = createNode(); | ||||
|   if (!node) return JsonVariant::invalid(); | ||||
|  | ||||
|   addNode(node); | ||||
|  | ||||
|   return node->content; | ||||
| JsonArray::node_type *JsonArray::getNodeAt(size_t index) const { | ||||
|   node_type *node = _firstNode; | ||||
|   while (node && index--) node = node->next; | ||||
|   return node; | ||||
| } | ||||
|  | ||||
| JsonArray &JsonArray::createNestedArray() { | ||||
| @@ -42,13 +34,7 @@ JsonObject &JsonArray::createNestedObject() { | ||||
|   return object; | ||||
| } | ||||
|  | ||||
| JsonArray::node_type *JsonArray::getNodeAt(int index) const { | ||||
|   node_type *node = _firstNode; | ||||
|   while (node && index--) node = node->next; | ||||
|   return node; | ||||
| } | ||||
|  | ||||
| void JsonArray::removeAt(int index) { removeNode(getNodeAt(index)); } | ||||
| void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); } | ||||
|  | ||||
| void JsonArray::writeTo(JsonWriter &writer) const { | ||||
|   writer.beginArray(); | ||||
|   | ||||
| @@ -17,45 +17,25 @@ using namespace ArduinoJson::Internals; | ||||
|  | ||||
| JsonObject JsonObject::_invalid(NULL); | ||||
|  | ||||
| JsonVariant &JsonObject::at(const char *key) { | ||||
|   node_type *node = getNodeAt(key); | ||||
|   return node ? node->content.value : JsonVariant::invalid(); | ||||
| JsonObject::node_type *JsonObject::getOrCreateNodeAt(const char *key) { | ||||
|   node_type *existingNode = getNodeAt(key); | ||||
|   if (existingNode) return existingNode; | ||||
|  | ||||
|   node_type *newNode = addNewNode(); | ||||
|   return newNode; | ||||
| } | ||||
|  | ||||
| const JsonVariant &JsonObject::at(const char *key) const { | ||||
|   node_type *node = getNodeAt(key); | ||||
|   return node ? node->content.value : JsonVariant::invalid(); | ||||
| } | ||||
|  | ||||
| JsonVariant &JsonObject::operator[](const char *key) { | ||||
|   // try to find an existing node | ||||
|   node_type *node = getNodeAt(key); | ||||
|  | ||||
|   // not fount => create a new one | ||||
|   if (!node) { | ||||
|     node = createNode(); | ||||
|     if (!node) return JsonVariant::invalid(); | ||||
|  | ||||
|     node->content.key = key; | ||||
|     addNode(node); | ||||
|   } | ||||
|  | ||||
|   return node->content.value; | ||||
| } | ||||
|  | ||||
| void JsonObject::remove(char const *key) { removeNode(getNodeAt(key)); } | ||||
|  | ||||
| JsonArray &JsonObject::createNestedArray(char const *key) { | ||||
| JsonArray &JsonObject::createNestedArray(const char *key) { | ||||
|   if (!_buffer) return JsonArray::invalid(); | ||||
|   JsonArray &array = _buffer->createArray(); | ||||
|   add(key, array); | ||||
|   set(key, array); | ||||
|   return array; | ||||
| } | ||||
|  | ||||
| JsonObject &JsonObject::createNestedObject(const char *key) { | ||||
|   if (!_buffer) return JsonObject::invalid(); | ||||
|   JsonObject &object = _buffer->createObject(); | ||||
|   add(key, object); | ||||
|   set(key, object); | ||||
|   return object; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -12,84 +12,6 @@ | ||||
| using namespace ArduinoJson; | ||||
| using namespace ArduinoJson::Internals; | ||||
|  | ||||
| JsonVariant JsonVariant::_invalid(JSON_INVALID); | ||||
|  | ||||
| JsonVariant::operator JsonArray &() const { | ||||
|   return _type == JSON_ARRAY ? *_content.asArray : JsonArray::invalid(); | ||||
| } | ||||
|  | ||||
| JsonVariant::operator JsonObject &() const { | ||||
|   return _type == JSON_OBJECT ? *_content.asObject : JsonObject::invalid(); | ||||
| } | ||||
|  | ||||
| JsonVariant::operator bool() const { | ||||
|   return _type == JSON_BOOLEAN ? _content.asBoolean : false; | ||||
| } | ||||
|  | ||||
| JsonVariant::operator const char *() const { | ||||
|   return _type == JSON_STRING ? _content.asString : NULL; | ||||
| } | ||||
|  | ||||
| JsonVariant::operator double() const { | ||||
|   return _type >= JSON_DOUBLE_0_DECIMALS ? _content.asDouble : 0; | ||||
| } | ||||
|  | ||||
| JsonVariant::operator long() const { | ||||
|   return _type == JSON_LONG ? _content.asLong : 0; | ||||
| } | ||||
|  | ||||
| void JsonVariant::set(bool value) { | ||||
|   if (_type == JSON_INVALID) return; | ||||
|   _type = Internals::JSON_BOOLEAN; | ||||
|   _content.asBoolean = value; | ||||
| } | ||||
|  | ||||
| void JsonVariant::set(const char *value) { | ||||
|   if (_type == JSON_INVALID) return; | ||||
|   _type = JSON_STRING; | ||||
|   _content.asString = value; | ||||
| } | ||||
|  | ||||
| void JsonVariant::set(double value, uint8_t decimals) { | ||||
|   if (_type == JSON_INVALID) return; | ||||
|   _type = static_cast<JsonVariantType>(JSON_DOUBLE_0_DECIMALS + decimals); | ||||
|   _content.asDouble = value; | ||||
| } | ||||
|  | ||||
| void JsonVariant::set(long value) { | ||||
|   if (_type == JSON_INVALID) return; | ||||
|   _type = JSON_LONG; | ||||
|   _content.asLong = value; | ||||
| } | ||||
|  | ||||
| void JsonVariant::set(JsonArray &array) { | ||||
|   if (_type == JSON_INVALID) return; | ||||
|   _type = array.success() ? JSON_ARRAY : JSON_INVALID; | ||||
|   _content.asArray = &array; | ||||
| } | ||||
|  | ||||
| void JsonVariant::set(JsonObject &object) { | ||||
|   if (_type == JSON_INVALID) return; | ||||
|   _type = object.success() ? JSON_OBJECT : JSON_INVALID; | ||||
|   _content.asObject = &object; | ||||
| } | ||||
|  | ||||
| size_t JsonVariant::size() const { | ||||
|   if (_type == JSON_ARRAY) return _content.asArray->size(); | ||||
|   if (_type == JSON_OBJECT) return _content.asObject->size(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| JsonVariant &JsonVariant::operator[](int index) { | ||||
|   if (_type != JSON_ARRAY) return JsonVariant::invalid(); | ||||
|   return _content.asArray->operator[](index); | ||||
| } | ||||
|  | ||||
| JsonVariant &JsonVariant::operator[](const char *key) { | ||||
|   if (_type != JSON_OBJECT) return JsonVariant::invalid(); | ||||
|   return _content.asObject->operator[](key); | ||||
| } | ||||
|  | ||||
| void JsonVariant::writeTo(JsonWriter &writer) const { | ||||
|   if (is<const JsonArray &>()) | ||||
|     as<const JsonArray &>().writeTo(writer); | ||||
|   | ||||
| @@ -13,12 +13,12 @@ TEST(DynamicJsonBuffer_Object_Tests, GrowsWithObject) { | ||||
|   JsonObject &obj = json.createObject(); | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size()); | ||||
|  | ||||
|   obj["hello"]; | ||||
|   obj["hello"] = 1; | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size()); | ||||
|  | ||||
|   obj["world"]; | ||||
|   obj["world"] = 2; | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size()); | ||||
|  | ||||
|   obj["world"];  // <- same value, should not grow | ||||
|   obj["world"] = 3;  // <- same key, should not grow | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size()); | ||||
| } | ||||
|   | ||||
| @@ -37,7 +37,7 @@ class GbathreeBug : public testing::Test { | ||||
| TEST_F(GbathreeBug, Success) { EXPECT_TRUE(_object.success()); } | ||||
|  | ||||
| TEST_F(GbathreeBug, ProtocolName) { | ||||
|   EXPECT_STREQ("fluorescence", _object.at("protocol_name").asString()); | ||||
|   EXPECT_STREQ("fluorescence", _object["protocol_name"]); | ||||
| } | ||||
|  | ||||
| TEST_F(GbathreeBug, Repeats) { EXPECT_EQ(1, _object["repeats"]); } | ||||
| @@ -69,7 +69,7 @@ TEST_F(GbathreeBug, Calintensity) { EXPECT_EQ(255, _object["calintensity"]); } | ||||
| TEST_F(GbathreeBug, Pulses) { | ||||
|   // "pulses":[50,50,50] | ||||
|  | ||||
|   JsonArray& array = _object.at("pulses"); | ||||
|   JsonArray& array = _object["pulses"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|  | ||||
|   EXPECT_EQ(3, array.size()); | ||||
| @@ -82,7 +82,7 @@ TEST_F(GbathreeBug, Pulses) { | ||||
| TEST_F(GbathreeBug, Act) { | ||||
|   // "act":[2,1,2,2] | ||||
|  | ||||
|   JsonArray& array = _object.at("act"); | ||||
|   JsonArray& array = _object["act"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|  | ||||
|   EXPECT_EQ(4, array.size()); | ||||
| @@ -95,7 +95,7 @@ TEST_F(GbathreeBug, Act) { | ||||
| TEST_F(GbathreeBug, Detectors) { | ||||
|   // "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]] | ||||
|  | ||||
|   JsonArray& array = _object.at("detectors"); | ||||
|   JsonArray& array = _object["detectors"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|   EXPECT_EQ(4, array.size()); | ||||
|  | ||||
| @@ -110,7 +110,7 @@ TEST_F(GbathreeBug, Detectors) { | ||||
| TEST_F(GbathreeBug, Alta) { | ||||
|   // alta:[2,2,2,2] | ||||
|  | ||||
|   JsonArray& array = _object.at("alta"); | ||||
|   JsonArray& array = _object["alta"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|  | ||||
|   EXPECT_EQ(4, array.size()); | ||||
| @@ -123,7 +123,7 @@ TEST_F(GbathreeBug, Alta) { | ||||
| TEST_F(GbathreeBug, Altb) { | ||||
|   // altb:[2,2,2,2] | ||||
|  | ||||
|   JsonArray& array = _object.at("altb"); | ||||
|   JsonArray& array = _object["altb"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|  | ||||
|   EXPECT_EQ(4, array.size()); | ||||
| @@ -136,7 +136,7 @@ TEST_F(GbathreeBug, Altb) { | ||||
| TEST_F(GbathreeBug, Measlights) { | ||||
|   // "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]] | ||||
|  | ||||
|   JsonArray& array = _object.at("measlights"); | ||||
|   JsonArray& array = _object["measlights"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|   EXPECT_EQ(4, array.size()); | ||||
|  | ||||
| @@ -152,7 +152,7 @@ TEST_F(GbathreeBug, Measlights) { | ||||
| TEST_F(GbathreeBug, Measlights2) { | ||||
|   // "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]] | ||||
|  | ||||
|   JsonArray& array = _object.at("measlights2"); | ||||
|   JsonArray& array = _object["measlights2"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|   EXPECT_EQ(4, array.size()); | ||||
|  | ||||
| @@ -167,7 +167,7 @@ TEST_F(GbathreeBug, Measlights2) { | ||||
| TEST_F(GbathreeBug, Altc) { | ||||
|   // altc:[2,2,2,2] | ||||
|  | ||||
|   JsonArray& array = _object.at("altc"); | ||||
|   JsonArray& array = _object["altc"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|  | ||||
|   EXPECT_EQ(4, array.size()); | ||||
| @@ -180,7 +180,7 @@ TEST_F(GbathreeBug, Altc) { | ||||
| TEST_F(GbathreeBug, Altd) { | ||||
|   // altd:[2,2,2,2] | ||||
|  | ||||
|   JsonArray& array = _object.at("altd"); | ||||
|   JsonArray& array = _object["altd"]; | ||||
|   EXPECT_TRUE(array.success()); | ||||
|  | ||||
|   EXPECT_EQ(4, array.size()); | ||||
|   | ||||
| @@ -67,6 +67,12 @@ TEST_F(JsonArray_Container_Tests, Grow_WhenValuesAreAdded) { | ||||
|   sizeMustBe(2); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonArray_Container_Tests, DontGrow_WhenValuesAreReplaced) { | ||||
|   _array.add("hello"); | ||||
|   _array[0] = "world"; | ||||
|   sizeMustBe(1); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonArray_Container_Tests, CanStoreIntegers) { | ||||
|   _array.add(123); | ||||
|   _array.add(456); | ||||
|   | ||||
| @@ -7,10 +7,6 @@ | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson.h> | ||||
|  | ||||
| TEST(JsonArray_Invalid_Tests, AtFails) { | ||||
|   ASSERT_FALSE(JsonArray::invalid().at(0).success()); | ||||
| } | ||||
|  | ||||
| TEST(JsonArray_Invalid_Tests, SubscriptFails) { | ||||
|   ASSERT_FALSE(JsonArray::invalid()[0].success()); | ||||
| } | ||||
| @@ -33,4 +29,4 @@ TEST(JsonArray_Invalid_Tests, PrintToWritesBrackets) { | ||||
|   char buffer[32]; | ||||
|   JsonArray::invalid().printTo(buffer, sizeof(buffer)); | ||||
|   ASSERT_STREQ("[]", buffer); | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -63,7 +63,7 @@ TEST_F(JsonArray_PrintTo_Tests, OneDoubleDefaultDigits) { | ||||
| } | ||||
|  | ||||
| TEST_F(JsonArray_PrintTo_Tests, OneDoubleFourDigits) { | ||||
|   array.add(3.14159265358979323846, 4); | ||||
|   array.add(double_with_n_digits(3.14159265358979323846, 4)); | ||||
|   outputMustBe("[3.1416]"); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,24 +21,24 @@ TEST_F(JsonObject_Container_Tests, InitialSizeIsZero) { | ||||
| } | ||||
|  | ||||
| TEST_F(JsonObject_Container_Tests, Grow_WhenValuesAreAdded) { | ||||
|   _object["hello"]; | ||||
|   _object["hello"] = 1; | ||||
|   EXPECT_EQ(1, _object.size()); | ||||
|  | ||||
|   _object["world"]; | ||||
|   _object.set("world", 2); | ||||
|   EXPECT_EQ(2, _object.size()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonObject_Container_Tests, DoNotGrow_WhenSameValueIsAdded) { | ||||
|   _object["hello"]; | ||||
|   _object["hello"] = 1; | ||||
|   EXPECT_EQ(1, _object.size()); | ||||
|  | ||||
|   _object["hello"]; | ||||
|   _object["hello"] = 2; | ||||
|   EXPECT_EQ(1, _object.size()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonObject_Container_Tests, Shrink_WhenValuesAreRemoved) { | ||||
|   _object["hello"]; | ||||
|   _object["world"]; | ||||
|   _object["hello"] = 1; | ||||
|   _object["world"] = 2; | ||||
|  | ||||
|   _object.remove("hello"); | ||||
|   EXPECT_EQ(1, _object.size()); | ||||
| @@ -49,8 +49,8 @@ TEST_F(JsonObject_Container_Tests, Shrink_WhenValuesAreRemoved) { | ||||
|  | ||||
| TEST_F(JsonObject_Container_Tests, | ||||
|        DoNotShrink_WhenRemoveIsCalledWithAWrongKey) { | ||||
|   _object["hello"]; | ||||
|   _object["world"]; | ||||
|   _object["hello"] = 1; | ||||
|   _object["world"] = 2; | ||||
|  | ||||
|   _object.remove(":-P"); | ||||
|  | ||||
| @@ -111,16 +111,11 @@ TEST_F(JsonObject_Container_Tests, CanStoreInnerObjects) { | ||||
|   EXPECT_EQ(&innerObject2, &_object["world"].asObject()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonObject_Container_Tests, ContainsKeyReturnFalseForNonExistingKey) { | ||||
| TEST_F(JsonObject_Container_Tests, ContainsKeyReturnsFalseForNonExistingKey) { | ||||
|   EXPECT_FALSE(_object.containsKey("hello")); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonObject_Container_Tests, ContainsKeyReturnTrueForDefinedValue) { | ||||
|   _object.add("hello", 42); | ||||
| TEST_F(JsonObject_Container_Tests, ContainsKeyReturnsTrueForDefinedValue) { | ||||
|   _object.set("hello", 42); | ||||
|   EXPECT_TRUE(_object.containsKey("hello")); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonObject_Container_Tests, ContainsKeyReturnFalseForUndefinedValue) { | ||||
|   _object.add("hello"); | ||||
|   EXPECT_FALSE(_object.containsKey("hello")); | ||||
| } | ||||
|   | ||||
| @@ -7,18 +7,14 @@ | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson.h> | ||||
|  | ||||
| TEST(JsonObject_Invalid_Tests, AtFails) { | ||||
|   ASSERT_FALSE(JsonObject::invalid().at(0).success()); | ||||
| } | ||||
|  | ||||
| TEST(JsonObject_Invalid_Tests, SubscriptFails) { | ||||
|   ASSERT_FALSE(JsonObject::invalid()[0].success()); | ||||
| } | ||||
|  | ||||
| TEST(JsonObject_Invalid_Tests, AddFails) { | ||||
|   JsonObject& array = JsonObject::invalid(); | ||||
|   array.add("hello", "world"); | ||||
|   ASSERT_EQ(0, array.size()); | ||||
|   JsonObject& object = JsonObject::invalid(); | ||||
|   object.set("hello", "world"); | ||||
|   ASSERT_EQ(0, object.size()); | ||||
| } | ||||
|  | ||||
| TEST(JsonObject_Invalid_Tests, CreateNestedArrayFails) { | ||||
| @@ -33,4 +29,4 @@ TEST(JsonObject_Invalid_Tests, PrintToWritesBraces) { | ||||
|   char buffer[32]; | ||||
|   JsonObject::invalid().printTo(buffer, sizeof(buffer)); | ||||
|   ASSERT_STREQ("{}", buffer); | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -88,7 +88,7 @@ TEST_F(JsonObject_PrintTo_Tests, OneInteger) { | ||||
| } | ||||
|  | ||||
| TEST_F(JsonObject_PrintTo_Tests, OneDoubleFourDigits) { | ||||
|   object["key"].set(3.14159265358979323846, 4); | ||||
|   object["key"] = double_with_n_digits(3.14159265358979323846, 4); | ||||
|   outputMustBe("{\"key\":3.1416}"); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -35,11 +35,11 @@ class JsonParser_Array_Tests : public testing::Test { | ||||
|  | ||||
|   template <typename T> | ||||
|   void elementAtIndexMustBe(int index, T expected) { | ||||
|     EXPECT_EQ(expected, _array->at(index).as<T>()); | ||||
|     EXPECT_EQ(expected, (*_array)[index].as<T>()); | ||||
|   } | ||||
|  | ||||
|   void elementAtIndexMustBe(int index, const char *expected) { | ||||
|     EXPECT_STREQ(expected, _array->at(index).as<const char *>()); | ||||
|     EXPECT_STREQ(expected, (*_array)[index].as<const char *>()); | ||||
|   } | ||||
|  | ||||
|   DynamicJsonBuffer _jsonBuffer; | ||||
|   | ||||
| @@ -21,12 +21,12 @@ class JsonParser_Object_Test : public testing::Test { | ||||
|   void sizeMustBe(int expected) { EXPECT_EQ(expected, _object->size()); } | ||||
|  | ||||
|   void keyMustHaveValue(const char *key, const char *expected) { | ||||
|     EXPECT_STREQ(expected, _object->at(key).as<const char *>()); | ||||
|     EXPECT_STREQ(expected, (*_object)[key]); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   void keyMustHaveValue(const char *key, T expected) { | ||||
|     EXPECT_EQ(expected, _object->at(key).as<T>()); | ||||
|     EXPECT_EQ(expected, (*_object)[key].as<T>()); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   | ||||
| @@ -1,75 +0,0 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson.h> | ||||
| #include "Printers.hpp" | ||||
|  | ||||
| class JsonVariant_Invalid_Tests : public ::testing::Test { | ||||
|  public: | ||||
|   JsonVariant_Invalid_Tests() : variant(JsonVariant::invalid()) {} | ||||
|  | ||||
|  protected: | ||||
|   JsonVariant variant; | ||||
| }; | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, SuccessReturnsFalse) { | ||||
|   EXPECT_FALSE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, AsLongReturns0) { | ||||
|   EXPECT_EQ(0, variant.as<long>()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, AsStringReturnsNull) { | ||||
|   EXPECT_EQ(0, variant.asString()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, AsDoubleReturns0) { | ||||
|   EXPECT_EQ(0, variant.as<double>()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, AsBoolReturnsFalse) { | ||||
|   EXPECT_FALSE(variant.as<bool>()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, AsArrayReturnInvalid) { | ||||
|   EXPECT_EQ(JsonArray::invalid(), variant.asArray()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, AsObjectReturnInvalid) { | ||||
|   EXPECT_EQ(JsonObject::invalid(), variant.asObject()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToLong) { | ||||
|   variant = 0L; | ||||
|   EXPECT_FALSE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToDouble) { | ||||
|   variant = 0.0; | ||||
|   EXPECT_FALSE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToString) { | ||||
|   variant = static_cast<const char*>(NULL); | ||||
|   EXPECT_FALSE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToBool) { | ||||
|   variant = false; | ||||
|   EXPECT_FALSE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToArray) { | ||||
|   variant = JsonArray::invalid(); | ||||
|   EXPECT_FALSE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToObject) { | ||||
|   variant = JsonObject::invalid(); | ||||
|   EXPECT_FALSE(variant.success()); | ||||
| } | ||||
| @@ -42,7 +42,7 @@ TEST_F(JsonVariant_PrintTo_Tests, DoubleDefaultDigits) { | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_PrintTo_Tests, DoubleFourDigits) { | ||||
|   variant.set(3.14159265358979323846, 4); | ||||
|   variant = JsonVariant(3.14159265358979323846, 4); | ||||
|   outputMustBe("3.1416"); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -11,13 +11,13 @@ class JsonVariant_Storage_Tests : public ::testing::Test { | ||||
|  protected: | ||||
|   template <typename T> | ||||
|   void testValue(T expected) { | ||||
|     _actual.set(expected); | ||||
|     _actual = expected; | ||||
|     EXPECT_EQ(expected, _actual.as<T>()); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   void testReference(T &expected) { | ||||
|     _actual.set(expected); | ||||
|     _actual = expected; | ||||
|     EXPECT_EQ(expected, _actual.as<T &>()); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -49,13 +49,6 @@ TEST_F(JsonVariant_Subscript_Tests, Undefined) { | ||||
|   EXPECT_FALSE(_variant[0].success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Subscript_Tests, Invalid) { | ||||
|   _variant = JsonVariant::invalid(); | ||||
|   EXPECT_EQ(0, _variant.size()); | ||||
|   EXPECT_FALSE(_variant["0"].success()); | ||||
|   EXPECT_FALSE(_variant[0].success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Subscript_Tests, String) { | ||||
|   _variant = "hello world"; | ||||
|   EXPECT_EQ(0, _variant.size()); | ||||
|   | ||||
| @@ -13,10 +13,6 @@ class JsonVariant_Undefined_Tests : public ::testing::Test { | ||||
|   JsonVariant variant; | ||||
| }; | ||||
|  | ||||
| TEST_F(JsonVariant_Undefined_Tests, SuccessReturnsFalse) { | ||||
|   EXPECT_FALSE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Undefined_Tests, AsLongReturns0) { | ||||
|   EXPECT_EQ(0, variant.as<long>()); | ||||
| } | ||||
| @@ -40,35 +36,3 @@ TEST_F(JsonVariant_Undefined_Tests, AsArrayReturnInvalid) { | ||||
| TEST_F(JsonVariant_Undefined_Tests, AsObjectReturnInvalid) { | ||||
|   EXPECT_EQ(JsonObject::invalid(), variant.asObject()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Undefined_Tests, CanBeSetToLong) { | ||||
|   variant = 0L; | ||||
|   EXPECT_TRUE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Undefined_Tests, CanBeSetToDouble) { | ||||
|   variant = 0.0; | ||||
|   EXPECT_TRUE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Undefined_Tests, CanBeSetToString) { | ||||
|   variant = static_cast<const char*>(NULL); | ||||
|   EXPECT_TRUE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Undefined_Tests, CanBeSetToBool) { | ||||
|   variant = false; | ||||
|   EXPECT_TRUE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Undefined_Tests, CanBeSetToArray) { | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   variant = jsonBuffer.createArray(); | ||||
|   EXPECT_TRUE(variant.success()); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Undefined_Tests, CanBeSetToObject) { | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   variant = jsonBuffer.createObject(); | ||||
|   EXPECT_TRUE(variant.success()); | ||||
| } | ||||
|   | ||||
| @@ -36,3 +36,15 @@ std::ostream& ArduinoJson::operator<<(std::ostream& os, | ||||
|   v.printTo(adapter); | ||||
|   return os; | ||||
| } | ||||
|  | ||||
| std::ostream& ArduinoJson::operator<<( | ||||
|     std::ostream& os, const ArduinoJson::JsonObjectSubscript& v) { | ||||
|   JsonVariant value = v; | ||||
|   return os << value; | ||||
| } | ||||
|  | ||||
| std::ostream& ArduinoJson::operator<<( | ||||
|     std::ostream& os, const ArduinoJson::JsonArraySubscript& v) { | ||||
|   JsonVariant value = v; | ||||
|   return os << value; | ||||
| } | ||||
|   | ||||
| @@ -6,10 +6,12 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/JsonVariant.hpp> | ||||
| #include <ArduinoJson.h> | ||||
| #include <ostream> | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| std::ostream& operator<<(std::ostream& os, const ArduinoJson::JsonVariant& v); | ||||
| std::ostream& operator<<(std::ostream& os, const ArduinoJson::JsonArray& v); | ||||
| std::ostream& operator<<(std::ostream& os, const JsonVariant& v); | ||||
| std::ostream& operator<<(std::ostream& os, const JsonArray& v); | ||||
| std::ostream& operator<<(std::ostream& os, const JsonObjectSubscript& v); | ||||
| std::ostream& operator<<(std::ostream& os, const JsonArraySubscript& v); | ||||
| } | ||||
|   | ||||
| @@ -14,12 +14,15 @@ TEST(StaticJsonBuffer_CreateObject_Tests, GrowsWithObject) { | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size()); | ||||
|  | ||||
|   obj["hello"]; | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size()); | ||||
|  | ||||
|   obj["hello"] = 1; | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size()); | ||||
|  | ||||
|   obj["world"]; | ||||
|   obj["world"] = 2; | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size()); | ||||
|  | ||||
|   obj["world"];  // <- same value, should not grow | ||||
|   obj["world"] = 3;  // <- same key, should not grow | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size()); | ||||
| } | ||||
|  | ||||
| @@ -41,8 +44,8 @@ TEST(StaticJsonBuffer_CreateObject_Tests, ObjectDoesntGrowWhenFull) { | ||||
|   StaticJsonBuffer<JSON_OBJECT_SIZE(1)> json; | ||||
|  | ||||
|   JsonObject &obj = json.createObject(); | ||||
|   obj["hello"]; | ||||
|   obj["world"]; | ||||
|   obj["hello"] = 1; | ||||
|   obj["world"] = 2; | ||||
|  | ||||
|   ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size()); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user