Added support of String class (issue #55, #56, #70, #77)

This commit is contained in:
Benoit Blanchon
2015-05-25 15:38:58 +02:00
parent 756c279cdc
commit 1b5be892b9
22 changed files with 351 additions and 119 deletions

View File

@ -0,0 +1,19 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#ifndef ARDUINO
#include <string>
typedef std::string String;
#else
#include <WString.h>
#endif

View File

@ -7,7 +7,7 @@
#pragma once
#ifdef _MSC_VER
#define JSON_FORCE_INLINE __forceinline
#define FORCE_INLINE __forceinline
#else
#define JSON_FORCE_INLINE __attribute__((always_inline))
#define FORCE_INLINE __attribute__((always_inline))
#endif

View File

@ -29,7 +29,7 @@ class JsonParser {
void skipSpaces();
bool parseAnythingTo(JsonVariant *destination);
JSON_FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
const char *parseString();

View File

@ -23,6 +23,11 @@ inline char const* JsonVariantContent::as<char const*>() const {
return asString;
}
template <>
inline String JsonVariantContent::as<String>() const {
return asString;
}
template <>
inline double JsonVariantContent::as<double>() const {
return asDouble;

View File

@ -48,22 +48,7 @@ class List {
const_iterator end() const { return const_iterator(NULL); }
protected:
node_type *addNewNode() {
if (!_buffer) return NULL;
node_type *newNode = new (_buffer) node_type();
if (_firstNode) {
node_type *lastNode = _firstNode;
while (lastNode->next) lastNode = lastNode->next;
lastNode->next = newNode;
} else {
_firstNode = newNode;
}
return newNode;
}
node_type *addNewNode();
void removeNode(node_type *nodeToRemove);
JsonBuffer *_buffer;

View File

@ -42,27 +42,27 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
: Internals::List<JsonVariant>(buffer) {}
// Gets the value at the specified index
JSON_FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
// Gets or sets the value at specified index
JSON_FORCE_INLINE JsonArraySubscript operator[](size_t index);
FORCE_INLINE JsonArraySubscript operator[](size_t index);
// Adds the specified value at the end of the array.
JSON_FORCE_INLINE bool add(const JsonVariant value);
FORCE_INLINE bool add(const JsonVariant value);
// Sets the value at specified index.
JSON_FORCE_INLINE void set(size_t index, const JsonVariant value);
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;
FORCE_INLINE JsonVariant get(size_t index) const;
// Gets the value at the specified index.
template <typename T>
JSON_FORCE_INLINE T get(size_t index) const;
FORCE_INLINE T get(size_t index) const;
// Check the type of the value at specified index.
template <typename T>
JSON_FORCE_INLINE T is(size_t index) const;
FORCE_INLINE T is(size_t index) const;
// Creates a JsonArray and adds a reference at the end of the array.
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()

View File

@ -11,25 +11,32 @@
namespace ArduinoJson {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
public:
JSON_FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
: _array(array), _index(index) {}
JSON_FORCE_INLINE JsonArraySubscript& operator=(const JsonVariant& value) {
FORCE_INLINE JsonArraySubscript& operator=(const JsonVariant& value) {
_array.set(_index, value);
return *this;
}
JSON_FORCE_INLINE bool success() const { return _index < _array.size(); }
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& other) {
// to prevent Visual Studio warning C4512: assignment operator could not be
// generated
_array.set(_index, other._array.get(other._index));
return *this;
}
JSON_FORCE_INLINE operator JsonVariant() const { return _array.get(_index); }
FORCE_INLINE bool success() const { return _index < _array.size(); }
FORCE_INLINE operator JsonVariant() const { return _array.get(_index); }
template <typename T>
JSON_FORCE_INLINE T as() const {
FORCE_INLINE T as() const {
return _array.get<T>(_index);
}
template <typename T>
JSON_FORCE_INLINE T is() const {
FORCE_INLINE T is() const {
return _array.is<T>(_index);
}

View File

@ -9,6 +9,8 @@
#include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t
#include "Arduino/String.hpp"
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
@ -55,6 +57,11 @@ class JsonBuffer {
// allocation fails.
JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
// Same as above with a String class
JsonArray &parseArray(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
return parseArray(const_cast<char *>(json.c_str()), nesting);
}
// Allocates and populate a JsonObject from a JSON string.
//
// The First argument is a pointer to the JSON string, the memory must be
@ -67,6 +74,12 @@ class JsonBuffer {
// allocation fails.
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
// Same as above with a String class
JsonObject &parseObject(const String &json,
uint8_t nestingLimit = DEFAULT_LIMIT) {
return parseObject(const_cast<char *>(json.c_str()), nestingLimit);
}
// Allocates n bytes in the JsonBuffer.
// Return a pointer to the allocated memory or NULL if allocation fails.
virtual void *alloc(size_t size) = 0;

View File

@ -6,6 +6,7 @@
#pragma once
#include "Arduino/String.hpp"
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
@ -35,62 +36,59 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
public Internals::List<JsonPair>,
public Internals::JsonBufferAllocated {
public:
typedef const char *key_type;
typedef JsonPair value_type;
// Create an empty JsonArray attached to the specified JsonBuffer.
// You should not use this constructor directly.
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
JSON_FORCE_INLINE explicit JsonObject(JsonBuffer *buffer)
FORCE_INLINE explicit JsonObject(JsonBuffer* buffer)
: Internals::List<JsonPair>(buffer) {}
// Gets or sets the value associated with the specified key.
JSON_FORCE_INLINE JsonObjectSubscript operator[](key_type key);
FORCE_INLINE JsonObjectSubscript operator[](JsonObjectKey key);
// Gets the value associated with the specified key.
JSON_FORCE_INLINE const JsonObjectSubscript operator[](key_type key) const;
FORCE_INLINE const JsonObjectSubscript operator[](JsonObjectKey key) const;
// Sets the specified key with the specified value.
JSON_FORCE_INLINE bool set(key_type key, const JsonVariant value);
FORCE_INLINE bool set(JsonObjectKey key, JsonVariant value);
// Gets the value associated with the specified key.
JSON_FORCE_INLINE JsonVariant get(key_type key) const;
FORCE_INLINE JsonVariant get(JsonObjectKey) const;
// Gets the value associated with the specified key.
template <typename T>
JSON_FORCE_INLINE T get(key_type key) const;
FORCE_INLINE T get(JsonObjectKey) const;
// Checks the type of the value associated with the specified key.
template <typename T>
JSON_FORCE_INLINE T is(key_type key) const;
FORCE_INLINE bool is(JsonObjectKey) const;
// Creates and adds a JsonArray.
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
JsonArray &createNestedArray(key_type key);
JsonArray& createNestedArray(JsonObjectKey key);
// Creates and adds a JsonObject.
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
JsonObject &createNestedObject(key_type key);
JsonObject& createNestedObject(JsonObjectKey key);
// Tells weither the specified key is present and associated with a value.
JSON_FORCE_INLINE bool containsKey(key_type key) const;
FORCE_INLINE bool containsKey(JsonObjectKey key) const;
// Removes the specified key and the associated value.
void remove(key_type key);
void remove(JsonObjectKey key);
// Returns a reference an invalid JsonObject.
// This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail.
static JsonObject &invalid() { return _invalid; }
static JsonObject& invalid() { return _invalid; }
// Serialize the object to the specified JsonWriter
void writeTo(Internals::JsonWriter &writer) const;
void writeTo(Internals::JsonWriter& writer) const;
private:
// Returns the list node that matches the specified key.
node_type *getNodeAt(key_type key) const;
node_type* getNodeAt(JsonObjectKey key) const;
node_type *getOrCreateNodeAt(const char *key);
node_type* getOrCreateNodeAt(JsonObjectKey key);
// The instance returned by JsonObject::invalid()
static JsonObject _invalid;

View File

@ -11,38 +11,41 @@
namespace ArduinoJson {
inline JsonVariant JsonObject::get(key_type key) const {
inline JsonVariant JsonObject::get(JsonObjectKey key) const {
node_type *node = getNodeAt(key);
return node ? node->content.value : JsonVariant();
}
template <typename T>
inline T JsonObject::get(key_type key) const {
inline T JsonObject::get(JsonObjectKey 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 {
inline bool JsonObject::is(JsonObjectKey key) const {
node_type *node = getNodeAt(key);
return node ? node->content.value.is<T>() : false;
}
inline JsonObjectSubscript JsonObject::operator[](key_type key) {
inline JsonObjectSubscript JsonObject::operator[](JsonObjectKey key) {
return JsonObjectSubscript(*this, key);
}
inline const JsonObjectSubscript JsonObject::operator[](key_type key) const {
inline const JsonObjectSubscript JsonObject::operator[](
JsonObjectKey key) const {
return JsonObjectSubscript(*const_cast<JsonObject *>(this), key);
}
inline bool JsonObject::containsKey(key_type key) const {
inline bool JsonObject::containsKey(JsonObjectKey key) const {
return getNodeAt(key) != NULL;
}
inline void JsonObject::remove(key_type key) { removeNode(getNodeAt(key)); }
inline void JsonObject::remove(JsonObjectKey key) {
removeNode(getNodeAt(key));
}
inline bool JsonObject::set(const char *key, const JsonVariant value) {
inline bool JsonObject::set(JsonObjectKey key, const JsonVariant value) {
node_type *node = getOrCreateNodeAt(key);
if (!node) return false;
@ -57,6 +60,12 @@ inline const JsonObjectSubscript JsonVariantBase<TImplem>::operator[](
return asObject()[key];
}
template <typename TImplem>
inline const JsonObjectSubscript JsonVariantBase<TImplem>::operator[](
const String &key) const {
return asObject()[key];
}
template <>
inline JsonObject const &JsonVariant::invalid<JsonObject const &>() {
return JsonObject::invalid();

View File

@ -0,0 +1,24 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "Arduino/String.hpp"
namespace ArduinoJson {
class JsonObjectKey {
public:
JsonObjectKey() {}
JsonObjectKey(const char* key) : _data(key) {}
JsonObjectKey(const String& key) : _data(key.c_str()) {}
operator const char*() const { return _data; }
private:
const char* _data;
};
}

View File

@ -11,30 +11,38 @@
namespace ArduinoJson {
class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript> {
public:
JSON_FORCE_INLINE JsonObjectSubscript(JsonObject& object, const char* key)
FORCE_INLINE JsonObjectSubscript(JsonObject& object, JsonObjectKey key)
: _object(object), _key(key) {}
JSON_FORCE_INLINE JsonObjectSubscript& operator=(const JsonVariant& value) {
FORCE_INLINE JsonObjectSubscript& operator=(const JsonVariant& value) {
_object.set(_key, value);
return *this;
}
JSON_FORCE_INLINE bool success() const { return _object.containsKey(_key); }
FORCE_INLINE JsonObjectSubscript& operator=(
const JsonObjectSubscript& other) {
// to prevent Visual Studio warning C4512: assignment operator could not be
// generated
_object.set(_key, other._object.get(other._key));
return *this;
}
JSON_FORCE_INLINE operator JsonVariant() const { return _object.get(_key); }
FORCE_INLINE bool success() const { return _object.containsKey(_key); }
FORCE_INLINE operator JsonVariant() const { return _object.get(_key); }
template <typename T>
JSON_FORCE_INLINE T as() const {
FORCE_INLINE T as() const {
return _object.get<T>(_key);
}
template <typename T>
JSON_FORCE_INLINE T is() const {
FORCE_INLINE T is() const {
return _object.is<T>(_key);
}
private:
JsonObject& _object;
const char* _key;
JsonObjectKey _key;
};
}

View File

@ -6,13 +6,14 @@
#pragma once
#include "JsonObjectKey.hpp"
#include "JsonVariant.hpp"
namespace ArduinoJson {
// A key value pair for JsonObject.
struct JsonPair {
const char* key;
JsonObjectKey key;
JsonVariant value;
};
}

View File

@ -9,6 +9,7 @@
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include "Arduino/String.hpp"
#include "Internals/JsonPrintable.hpp"
#include "Internals/JsonVariantContent.hpp"
#include "Internals/JsonVariantType.hpp"
@ -31,46 +32,47 @@ class JsonVariant : public Internals::JsonPrintable<JsonVariant>,
public JsonVariantBase<JsonVariant> {
public:
// Creates an uninitialized JsonVariant
JSON_FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
// Create a JsonVariant containing a boolean value.
// It will be serialized as "true" or "false" in JSON.
JSON_FORCE_INLINE JsonVariant(bool value);
FORCE_INLINE JsonVariant(bool value);
// Create a JsonVariant containing a floating point value.
// The second argument specifies the number of decimal digits to write in
// the JSON string.
JSON_FORCE_INLINE JsonVariant(float value, uint8_t decimals = 2);
JSON_FORCE_INLINE JsonVariant(double value, uint8_t decimals = 2);
FORCE_INLINE JsonVariant(float value, uint8_t decimals = 2);
FORCE_INLINE JsonVariant(double value, uint8_t decimals = 2);
// Create a JsonVariant containing an integer value.
JSON_FORCE_INLINE JsonVariant(signed char value);
JSON_FORCE_INLINE JsonVariant(signed long value);
JSON_FORCE_INLINE JsonVariant(signed int value);
JSON_FORCE_INLINE JsonVariant(signed short value);
JSON_FORCE_INLINE JsonVariant(unsigned char value);
JSON_FORCE_INLINE JsonVariant(unsigned long value);
JSON_FORCE_INLINE JsonVariant(unsigned int value);
JSON_FORCE_INLINE JsonVariant(unsigned short value);
FORCE_INLINE JsonVariant(signed char value);
FORCE_INLINE JsonVariant(signed long value);
FORCE_INLINE JsonVariant(signed int value);
FORCE_INLINE JsonVariant(signed short value);
FORCE_INLINE JsonVariant(unsigned char value);
FORCE_INLINE JsonVariant(unsigned long value);
FORCE_INLINE JsonVariant(unsigned int value);
FORCE_INLINE JsonVariant(unsigned short value);
// Create a JsonVariant containing a string.
JSON_FORCE_INLINE JsonVariant(const char *value);
FORCE_INLINE JsonVariant(const char *value);
FORCE_INLINE JsonVariant(const String &value);
// Create a JsonVariant containing a reference to an array.
JSON_FORCE_INLINE JsonVariant(JsonArray &array);
FORCE_INLINE JsonVariant(JsonArray &array);
// Create a JsonVariant containing a reference to an object.
JSON_FORCE_INLINE JsonVariant(JsonObject &object);
FORCE_INLINE JsonVariant(JsonObject &object);
// Get the variant as the specified type.
// See cast operators for details.
template <typename T>
JSON_FORCE_INLINE T as() const;
FORCE_INLINE T as() const;
// Tells weither the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
template <typename T>
JSON_FORCE_INLINE bool is() const;
FORCE_INLINE bool is() const;
// Serialize the variant to a JsonWriter
void writeTo(Internals::JsonWriter &writer) const;

View File

@ -20,6 +20,11 @@ inline JsonVariant::JsonVariant(const char *value) {
_content.asString = value;
}
inline JsonVariant::JsonVariant(const String &value) {
_type = Internals::JSON_STRING;
_content.asString = value.c_str();
}
inline JsonVariant::JsonVariant(double value, uint8_t decimals) {
_type = static_cast<Internals::JsonVariantType>(
Internals::JSON_DOUBLE_0_DECIMALS + decimals);
@ -107,6 +112,11 @@ inline bool JsonVariant::is<char const *>() const {
return _type == Internals::JSON_STRING;
}
template <>
inline bool JsonVariant::is<String>() const {
return _type == Internals::JSON_STRING;
}
template <>
inline bool JsonVariant::is<double>() const {
return _type >= Internals::JSON_DOUBLE_0_DECIMALS;

View File

@ -7,6 +7,7 @@
#pragma once
#include "Internals/ForceInline.hpp"
#include "JsonObjectKey.hpp"
namespace ArduinoJson {
@ -19,50 +20,45 @@ 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>(); }
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>(); }
FORCE_INLINE operator double() const { return as<double>(); }
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>();
}
FORCE_INLINE operator signed long() const { return as<signed long>(); }
FORCE_INLINE operator signed char() const { return as<signed char>(); }
FORCE_INLINE operator signed int() const { return as<signed int>(); }
FORCE_INLINE operator signed short() const { return as<signed short>(); }
FORCE_INLINE operator unsigned char() const { return as<unsigned char>(); }
FORCE_INLINE operator unsigned int() const { return as<unsigned int>(); }
FORCE_INLINE operator unsigned long() const { return as<unsigned long>(); }
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 *>(); }
FORCE_INLINE operator const char *() const { return as<const char *>(); }
FORCE_INLINE const char *asString() const { return as<const char *>(); }
FORCE_INLINE operator String() const { return as<String>(); }
// 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 &>(); }
FORCE_INLINE operator JsonArray &() const { return as<JsonArray &>(); }
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 &>(); }
FORCE_INLINE operator JsonObject &() const { return as<JsonObject &>(); }
FORCE_INLINE JsonObject &asObject() const { return as<JsonObject &>(); }
template <typename T>
JSON_FORCE_INLINE const T as() const {
FORCE_INLINE const T as() const {
return impl()->template as<T>();
}
@ -74,13 +70,17 @@ class JsonVariantBase {
// 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;
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;
FORCE_INLINE const JsonObjectSubscript operator[](const char *key) const;
FORCE_INLINE const JsonObjectSubscript operator[](const String &key) const;
protected:
JsonVariantBase() {}
private:
const TImpl *impl() const { return static_cast<const TImpl *>(this); }