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