Epic refactoring in progress

This commit is contained in:
Benoit Blanchon
2014-10-26 21:18:09 +01:00
parent cdf3777aa8
commit e0980292ef
29 changed files with 477 additions and 541 deletions

View File

@ -6,22 +6,26 @@
#pragma once #pragma once
// TODO: cleanup
namespace ArduinoJson { namespace ArduinoJson {
class JsonArray; class JsonArray;
class JsonBuffer; class JsonBuffer;
class JsonObject; class JsonPair;
class JsonObjectIterator;
class JsonObjectKeyValue;
class JsonValue; class JsonValue;
template <typename T> class JsonObject;
class JsonIterator;
template <typename T>
class JsonConstIterator;
namespace Internals { namespace Internals {
class IndentedPrint; class IndentedPrint;
class JsonArrayConstIterator;
class JsonArrayImpl;
class JsonArrayIterator;
class JsonNode; class JsonNode;
class JsonObjectImpl;
class JsonObjectIterator;
class JsonParser; class JsonParser;
class JsonValueImpl;
class JsonWriter; class JsonWriter;
struct JsonArrayNode;
} }
} }

View File

@ -6,33 +6,33 @@
#pragma once #pragma once
#include "JsonValueInternal.hpp" #include "JsonArrayNode.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
class JsonArrayConstIterator { class JsonArrayConstIterator {
public: public:
explicit JsonArrayConstIterator(Internals::JsonNode *node) : _value(node) {} explicit JsonArrayConstIterator(JsonArrayNode *node) : _node(node) {}
JsonValue operator*() const { return _value; } const JsonValueImpl &operator*() const { return _node->value; }
JsonValue *operator->() { return &_value; } const JsonValueImpl *operator->() { return &_node->value; }
bool operator==(const JsonArrayConstIterator &other) const { bool operator==(const JsonArrayConstIterator &other) const {
return _value.isSameAs(other._value); return _node == other._node;
} }
bool operator!=(const JsonArrayConstIterator &other) const { bool operator!=(const JsonArrayConstIterator &other) const {
return !_value.isSameAs(other._value); return _node != other._node;
} }
JsonArrayConstIterator &operator++() { JsonArrayConstIterator &operator++() {
_value.moveToNext(); _node = _node->next;
return *this; return *this;
} }
private: private:
JsonValueInternal _value; JsonArrayNode *_node;
}; };
} }
} }

View File

@ -0,0 +1,41 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonBuffer.hpp"
#include "JsonArrayIterator.hpp"
#include "JsonArrayConstIterator.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonArrayImpl {
public:
typedef JsonValueImpl *value_type;
typedef JsonArrayIterator iterator;
typedef JsonArrayConstIterator const_iterator;
JsonArrayImpl(JsonBuffer *buffer) : _buffer(buffer) {}
value_type *operator[](int index) const;
value_type *add();
JsonArrayImpl *createNestedArray();
JsonObjectImpl *createNestedObject();
iterator begin() { return iterator(_firstChild); }
iterator end() { return iterator(0); }
const_iterator begin() const { return const_iterator(_firstChild); }
const_iterator end() const { return const_iterator(0); }
private:
JsonBuffer *_buffer;
Internals::JsonArrayNode *_firstChild;
};
}
}

View File

@ -6,33 +6,33 @@
#pragma once #pragma once
#include "JsonValueInternal.hpp" #include "JsonArrayNode.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
class JsonArrayIterator { class JsonArrayIterator {
public: public:
explicit JsonArrayIterator(Internals::JsonNode *node) : _value(node) {} explicit JsonArrayIterator(Internals::JsonArrayNode *node) : _node(node) {}
JsonValue operator*() const { return _value; } JsonValueImpl &operator*() const { return _node->value; }
JsonValue *operator->() { return &_value; } JsonValueImpl *operator->() { return &_node->value; }
bool operator==(const JsonArrayIterator &other) const { bool operator==(const JsonArrayIterator &other) const {
return _value.isSameAs(other._value); return _node == other._node;
} }
bool operator!=(const JsonArrayIterator &other) const { bool operator!=(const JsonArrayIterator &other) const {
return !_value.isSameAs(other._value); return _node != other._node;
} }
JsonArrayIterator &operator++() { JsonArrayIterator &operator++() {
_value.moveToNext(); _node = _node->next;
return *this; return *this;
} }
private: private:
JsonValueInternal _value; JsonArrayNode *_node;
}; };
} }
} }

View File

@ -0,0 +1,19 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonValue.hpp"
namespace ArduinoJson {
namespace Internals {
struct JsonArrayNode {
JsonArrayNode *next;
JsonValueImpl value;
};
}
}

View File

@ -1,163 +0,0 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../ForwardDeclarations.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonNode {
enum JsonNodeType {
JSON_UNDEFINED,
JSON_NULL,
JSON_ARRAY,
JSON_OBJECT,
JSON_KEY_VALUE,
JSON_BOOLEAN,
JSON_STRING,
JSON_LONG,
JSON_PROXY,
JSON_DOUBLE_0_DECIMALS,
JSON_DOUBLE_1_DECIMAL,
JSON_DOUBLE_2_DECIMALS
// etc.
};
union JsonNodeContent {
bool asBoolean;
double asDouble;
long asInteger;
const char *asString;
struct {
const char *key;
JsonNode *value;
} asKeyValue;
struct {
JsonNode *child;
JsonBuffer *buffer;
} asContainer;
struct {
JsonNode *target;
} asProxy;
};
public:
JsonNode() : next(0), type(JSON_UNDEFINED) {}
JsonNode *next;
void writeTo(JsonWriter &); // TODO: <- move in JsonNodeSerializer
void setAsArray(JsonBuffer *buffer) {
type = JSON_ARRAY;
content.asContainer.child = 0;
content.asContainer.buffer = buffer;
}
void setAsBoolean(bool value) {
type = JSON_BOOLEAN;
content.asBoolean = value;
}
void setAsLong(int value) {
type = JSON_LONG;
content.asInteger = value;
}
void setAsString(char const *value) {
type = JSON_STRING;
content.asString = value;
}
void setAsDouble(double value, int decimals) {
type = static_cast<JsonNodeType>(JSON_DOUBLE_0_DECIMALS + decimals);
content.asDouble = value;
}
void setAsObject(JsonBuffer *buffer) {
type = JSON_OBJECT;
content.asContainer.child = 0;
content.asContainer.buffer = buffer;
}
void setAsObjectKeyValue(const char *key, JsonNode *value) {
type = JSON_KEY_VALUE;
content.asKeyValue.key = key;
content.asKeyValue.value = value;
}
bool getAsBoolean() {
return type == JSON_BOOLEAN ? content.asBoolean : false;
}
double getAsDouble() {
return type >= JSON_DOUBLE_0_DECIMALS ? content.asDouble : 0;
}
long getAsInteger() { return type == JSON_LONG ? content.asInteger : 0; }
const char *getAsString() {
return type == JSON_STRING ? content.asString : 0;
}
JsonBuffer *getContainerBuffer() {
if (type == JSON_PROXY) return content.asProxy.target->getContainerBuffer();
return type == JSON_ARRAY || type == JSON_OBJECT
? content.asContainer.buffer
: 0;
}
JsonNode *getContainerChild() {
if (type == JSON_PROXY) return content.asProxy.target->getContainerChild();
return type == JSON_ARRAY || type == JSON_OBJECT ? content.asContainer.child
: 0;
}
const char *getAsObjectKey() {
return type == JSON_KEY_VALUE ? content.asKeyValue.key : 0;
}
JsonNode *getAsObjectValue() {
return type == JSON_KEY_VALUE ? content.asKeyValue.value : 0;
}
JsonNode *getProxyTarget() {
return type == JSON_PROXY ? content.asProxy.target : this;
}
bool isArray() { return type == JSON_ARRAY; }
bool isObject() { return type == JSON_OBJECT; }
void addChild(JsonNode *childToAdd);
void removeChild(JsonNode *childToRemove);
void duplicate(JsonNode *other);
private:
JsonNodeType type;
JsonNodeContent content;
inline void writeArrayTo(
JsonWriter &); // TODO: <- move in JsonNodeSerializer
inline void writeObjectTo(
JsonWriter &); // TODO: <- move in JsonNodeSerializer
void setAsProxyOfSelf();
void setAsProxyOf(JsonNode *target) {
type = JSON_PROXY;
content.asProxy.target = target;
}
};
}
}

View File

@ -1,32 +0,0 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "JsonNode.hpp"
namespace ArduinoJson {
namespace Internals {
// TODO: replace by JsonArrayIterator and JsonObjectIterator
class JsonNodeIterator {
public:
explicit JsonNodeIterator(JsonNode *node) : _node(node) {}
bool operator!=(const JsonNodeIterator &other) const {
return _node != other._node;
}
void operator++() { _node = _node->next; }
JsonNode *operator*() const { return _node; }
JsonNode *operator->() const { return _node; }
private:
JsonNode *_node;
};
}
}

View File

@ -1,31 +0,0 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "JsonNode.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonNodeWrapper {
protected:
JsonNodeWrapper() : _node(0) {}
explicit JsonNodeWrapper(JsonNode *node) : _node(node) {}
void duplicate(const JsonNodeWrapper &other) {
if (!_node) {
_node = other._node;
} else {
_node->duplicate(other._node);
}
}
JsonNode *_node;
};
}
}

View File

@ -6,33 +6,34 @@
#pragma once #pragma once
#include "JsonPairInternal.hpp" #include "JsonObjectNode.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
class JsonObjectConstIterator { class JsonObjectConstIterator {
public: public:
explicit JsonObjectConstIterator(Internals::JsonNode *node) : _pair(node) {} explicit JsonObjectConstIterator(Internals::JsonObjectNode *node)
: _node(node) {}
JsonPair operator*() const { return _pair; } JsonPair operator*() const { return _node->pair; }
JsonPair *operator->() { return &_pair; } JsonPair *operator->() { return &_node->pair; }
bool operator==(const JsonObjectConstIterator &other) const { bool operator==(const JsonObjectConstIterator &other) const {
return _pair.isSameAs(other._pair); return _node == other._node;
} }
bool operator!=(const JsonObjectConstIterator &other) const { bool operator!=(const JsonObjectConstIterator &other) const {
return !_pair.isSameAs(other._pair); return _node != other._node;
} }
JsonObjectConstIterator &operator++() { JsonObjectConstIterator &operator++() {
_pair.moveToNext(); _node = _node->next;
return *this; return *this;
} }
private: private:
JsonPairInternal _pair; JsonObjectNode *_node;
}; };
} }
} }

View File

@ -6,33 +6,31 @@
#pragma once #pragma once
#include "JsonPairInternal.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
class JsonObjectIterator { class JsonObjectIterator {
public: public:
explicit JsonObjectIterator(Internals::JsonNode *node) : _pair(node) {} explicit JsonObjectIterator(Internals::JsonObjectNode *node) : _node(node) {}
JsonPair operator*() const { return _pair; } JsonPair &operator*() const { return _node->pair; }
JsonPair *operator->() { return &_pair; } JsonPair *operator->() { return &_node->pair; }
bool operator==(const JsonObjectIterator &other) const { bool operator==(const JsonObjectIterator &other) const {
return _pair.isSameAs(other._pair); return _node == other._node;
} }
bool operator!=(const JsonObjectIterator &other) const { bool operator!=(const JsonObjectIterator &other) const {
return !_pair.isSameAs(other._pair); return _node != other._node;
} }
JsonObjectIterator &operator++() { JsonObjectIterator &operator++() {
_pair.moveToNext(); _node = _node->next;
return *this; return *this;
} }
private: private:
JsonPairInternal _pair; JsonObjectNode *_node;
}; };
} }
} }

View File

@ -0,0 +1,19 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonPair.hpp"
namespace ArduinoJson {
namespace Internals {
struct JsonObjectNode {
JsonObjectNode *next;
JsonPair pair;
};
}
}

View File

@ -1,22 +0,0 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonPair.hpp"
namespace ArduinoJson {
class JsonPairInternal : public JsonPair {
public:
explicit JsonPairInternal(Internals::JsonNode* node) : JsonPair(node) {}
void moveToNext() { _node = _node->next; }
bool isSameAs(const JsonPairInternal& other) const {
return _node == other._node;
}
};
}

View File

@ -7,7 +7,7 @@
#pragma once #pragma once
#include "../ForwardDeclarations.hpp" #include "../ForwardDeclarations.hpp"
#include "JsonNode.hpp" #include "../JsonBuffer.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
@ -16,24 +16,23 @@ class JsonParser {
public: public:
JsonParser(JsonBuffer *buffer, char *json) : _buffer(buffer), _ptr(json) {} JsonParser(JsonBuffer *buffer, char *json) : _buffer(buffer), _ptr(json) {}
JsonNode *parseAnything(); JsonArray parseArray();
JsonObject parseObject();
private: private:
JsonBuffer *_buffer;
char *_ptr;
bool isEnd() { return *_ptr == 0; } bool isEnd() { return *_ptr == 0; }
bool skip(char charToSkip); bool skip(char charToSkip);
void skipSpaces(); void skipSpaces();
inline JsonNode *parseArray(); void parseValueTo(JsonValue);
inline JsonNode *parseBoolean(); inline void parseBooleanTo(JsonValue &destination);
inline JsonNode *parseNull(); inline void parseNullTo(JsonValue &destination);
inline JsonNode *parseNumber(); inline void parseNumberTo(JsonValue &destination);
inline JsonNode *parseObject(); inline const char *parseString();
inline JsonNode *parseObjectKeyValue();
inline JsonNode *parseString(); JsonBuffer *_buffer;
char *_ptr;
}; };
} }
} }

View File

@ -0,0 +1,23 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../ForwardDeclarations.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonSerializer {
public:
static writeTo(JsonValue& value, JsonWriter&);
private:
inline void writeArrayTo(JsonValue& value, JsonWriter&);
inline void writeObjectTo(JsonValue& value, JsonWriter&);
};
}
}

View File

@ -0,0 +1,23 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../ForwardDeclarations.hpp"
namespace ArduinoJson {
namespace Internals {
union JsonValueContent {
bool asBoolean;
double asDouble;
long asInteger;
const char* asString;
JsonArrayImpl* asArray;
JsonObjectImpl* asObject;
};
}
}

View File

@ -0,0 +1,79 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include <stddef.h>
#include "../ForwardDeclarations.hpp"
#include "JsonValueContent.hpp"
#include "JsonValueType.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonValueImpl {
public:
JsonValueImpl() : _type(JSON_UNDEFINED) {}
void set(bool value) {
_type = JSON_BOOLEAN;
_content.asBoolean = value;
}
void set(const char *value) {
_type = JSON_STRING;
_content.asString = value;
}
void set(double value, int decimals = 2) {
_type = static_cast<JsonValueType>(JSON_DOUBLE_0_DECIMALS + decimals);
_content.asDouble = value;
}
void set(long value) {
_type = JSON_LONG;
_content.asInteger = value;
}
void set(JsonArrayImpl *array) {
_type = JSON_ARRAY;
_content.asArray = array;
}
void set(JsonObjectImpl *object) {
_type = JSON_OBJECT;
_content.asObject = object;
}
operator bool() const {
return _type == JSON_BOOLEAN ? _content.asBoolean : false;
}
operator char const *() const {
return _type == JSON_STRING ? _content.asString : NULL;
}
operator double() const {
return _type >= JSON_DOUBLE_0_DECIMALS ? _content.asDouble : 0;
}
operator long() const { return _type == JSON_LONG ? _content.asInteger : 0; }
operator JsonArrayImpl *() const {
return _type == JSON_ARRAY ? _content.asArray : NULL;
}
operator JsonObjectImpl *() const {
return _type == JSON_OBJECT ? _content.asObject : NULL;
}
private:
Internals::JsonValueType _type;
Internals::JsonValueContent _content;
};
}
}

View File

@ -1,25 +0,0 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonValue.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonValueInternal : public JsonValue {
public:
explicit JsonValueInternal(Internals::JsonNode* node) : JsonValue(node) {}
void moveToNext() { _node = _node->next; }
bool isSameAs(const JsonValueInternal& other) const {
return _node == other._node;
}
};
}
}

View File

@ -0,0 +1,25 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
namespace ArduinoJson {
namespace Internals {
enum JsonValueType {
JSON_UNDEFINED,
JSON_ARRAY,
JSON_OBJECT,
JSON_BOOLEAN,
JSON_STRING,
JSON_LONG,
JSON_DOUBLE_0_DECIMALS
// JSON_DOUBLE_1_DECIMAL
// JSON_DOUBLE_2_DECIMALS
// etc.
};
}
}

View File

@ -6,9 +6,8 @@
#pragma once #pragma once
#include "Internals/JsonArrayConstIterator.hpp"
#include "Internals/JsonArrayIterator.hpp"
#include "JsonContainer.hpp" #include "JsonContainer.hpp"
#include "Internals/JsonArrayImpl.hpp"
namespace ArduinoJson { namespace ArduinoJson {
class JsonArray : public JsonContainer { class JsonArray : public JsonContainer {
@ -18,33 +17,37 @@ class JsonArray : public JsonContainer {
typedef Internals::JsonArrayConstIterator const_iterator; typedef Internals::JsonArrayConstIterator const_iterator;
JsonArray() {} JsonArray() {}
JsonArray(Internals::JsonArrayImpl* impl) : _impl(impl) {}
explicit JsonArray(Internals::JsonNode *node) value_type operator[](int index) const;
: JsonContainer(node) {} // TODO: hide
JsonValue operator[](int index) const; value_type add();
template <typename T> template <typename T>
void add(T value) { void add(T value) {
addNewValue() = value; add().set(value);
} }
void add(double value, int decimals = 2) { void add(double value, int decimals = 2) { add().set(value, decimals); }
addNewValue().set(value, decimals);
}
JsonArray createNestedArray(); JsonArray createNestedArray();
JsonObject createNestedObject(); JsonObject createNestedObject();
bool success() { return _node && _node->isArray(); } iterator begin() {
if (!_impl) return end();
iterator begin() { return iterator(firstChild()); } return _impl->begin();
}
iterator end() { return iterator(0); } iterator end() { return iterator(0); }
const_iterator begin() const { return const_iterator(firstChild()); } const_iterator begin() const {
if (!_impl) return end();
return const_cast<const Internals::JsonArrayImpl*>(_impl)->begin();
}
const_iterator end() const { return const_iterator(0); } const_iterator end() const { return const_iterator(0); }
private: static JsonArray null() { return JsonArray(NULL); }
JsonValue addNewValue();
private:
Internals::JsonArrayImpl* _impl;
}; };
} }

View File

@ -6,43 +6,39 @@
#pragma once #pragma once
#include <new>
#include "ForwardDeclarations.hpp" #include "ForwardDeclarations.hpp"
#include "JsonArray.hpp" #include "JsonValue.hpp"
#include "JsonObject.hpp"
namespace ArduinoJson { namespace ArduinoJson {
class JsonBuffer { class JsonBuffer {
friend class JsonContainer;
friend class Internals::JsonNode;
friend class Internals::JsonParser;
public: public:
virtual ~JsonBuffer() {} virtual ~JsonBuffer() {}
JsonArray createArray() { return JsonArray(createArrayNode()); } JsonArray createArray();
JsonObject createObject();
JsonObject createObject() { return JsonObject(createObjectNode()); }
JsonValue createValue(); JsonValue createValue();
JsonArray parseArray(char *json); template <typename T>
JsonObject parseObject(char *json); JsonValue createValue(T x) {
JsonValue parseValue(char *json); // TODO: remove JsonValue value;
value = x;
return value;
}
protected: JsonArray parseArray(char* json);
virtual void *allocateNode() = 0; JsonObject parseObject(char* json);
JsonValue parseValue(char* json);
private: template <typename T>
Internals::JsonNode *createNode(); T* create() {
void* p = alloc(sizeof(T));
if (!p) return NULL;
return new (p) T();
}
Internals::JsonNode *createArrayNode(); virtual void* alloc(size_t size) = 0;
Internals::JsonNode *createBoolNode(bool value);
Internals::JsonNode *createDoubleNode(double value, int decimals);
Internals::JsonNode *createLongNode(long value);
Internals::JsonNode *createObjectNode();
Internals::JsonNode *createObjectKeyValueNode(const char *key,
Internals::JsonNode *value);
Internals::JsonNode *createStringNode(const char *value);
}; };
} }

View File

@ -7,40 +7,16 @@
#pragma once #pragma once
#include "Arduino/Printable.hpp" #include "Arduino/Printable.hpp"
#include "Internals/JsonNodeIterator.hpp"
#include "Internals/JsonNodeWrapper.hpp"
namespace ArduinoJson { namespace ArduinoJson {
class JsonContainer : public Printable, public Internals::JsonNodeWrapper { class JsonContainer : public Printable {
public: public:
JsonContainer() {}
explicit JsonContainer(Internals::JsonNode *node) : JsonNodeWrapper(node) {}
size_t size() const;
bool operator==(JsonContainer const &other) const;
size_t printTo(char *buffer, size_t bufferSize) const; size_t printTo(char *buffer, size_t bufferSize) const;
virtual size_t printTo(Print &print) const; virtual size_t printTo(Print &print) const;
size_t prettyPrintTo(char *buffer, size_t bufferSize) const; size_t prettyPrintTo(char *buffer, size_t bufferSize) const;
size_t prettyPrintTo(ArduinoJson::Internals::IndentedPrint &print) const; size_t prettyPrintTo(ArduinoJson::Internals::IndentedPrint &print) const;
size_t prettyPrintTo(Print &print) const; size_t prettyPrintTo(Print &print) const;
protected:
Internals::JsonNodeIterator beginChildren() const {
return Internals::JsonNodeIterator(_node ? _node->getContainerChild() : 0);
}
Internals::JsonNodeIterator endChildren() const {
return Internals::JsonNodeIterator(0);
}
void addChild(Internals::JsonNode *);
void removeChild(Internals::JsonNode *);
Internals::JsonNode *createNode();
Internals::JsonNode *firstChild() const;
}; };
} }

View File

@ -9,6 +9,7 @@
#include "Internals/JsonObjectConstIterator.hpp" #include "Internals/JsonObjectConstIterator.hpp"
#include "Internals/JsonObjectIterator.hpp" #include "Internals/JsonObjectIterator.hpp"
#include "JsonContainer.hpp" #include "JsonContainer.hpp"
#include "Internals/JsonObjectNode.hpp"
namespace ArduinoJson { namespace ArduinoJson {
class JsonObject : public JsonContainer { class JsonObject : public JsonContainer {
@ -17,9 +18,7 @@ class JsonObject : public JsonContainer {
typedef Internals::JsonObjectIterator iterator; typedef Internals::JsonObjectIterator iterator;
typedef Internals::JsonObjectConstIterator const_iterator; typedef Internals::JsonObjectConstIterator const_iterator;
JsonObject() {} JsonObject(JsonBuffer *buffer) : _buffer(buffer) {}
explicit JsonObject(Internals::JsonNode *node) : JsonContainer(node) {}
JsonValue operator[](const char *key); JsonValue operator[](const char *key);
void remove(const char *key); void remove(const char *key);
@ -27,16 +26,17 @@ class JsonObject : public JsonContainer {
JsonArray createNestedArray(const char *key); JsonArray createNestedArray(const char *key);
JsonObject createNestedObject(const char *key); JsonObject createNestedObject(const char *key);
bool success() { return _node && _node->isObject(); } iterator begin() { return iterator(_firstChild); }
iterator begin() { return iterator(firstChild()); }
iterator end() { return iterator(0); } iterator end() { return iterator(0); }
const_iterator begin() const { return const_iterator(firstChild()); } const_iterator begin() const { return const_iterator(_firstChild); }
const_iterator end() const { return const_iterator(0); } const_iterator end() const { return const_iterator(0); }
private: private:
Internals::JsonNode *getPairAt(const char *key); Internals::JsonNode *getPairAt(const char *key);
Internals::JsonNode *getOrCreateValueAt(const char *key); Internals::JsonNode *getOrCreateValueAt(const char *key);
JsonBuffer *_buffer;
Internals::JsonObjectNode *_firstChild;
}; };
} }

View File

@ -6,20 +6,18 @@
#pragma once #pragma once
#include "Internals/JsonValueInternal.hpp" #include "JsonValue.hpp"
namespace ArduinoJson { namespace ArduinoJson {
class JsonPair { class JsonPair {
public: public:
const char *key() const { return _node->getAsObjectKey(); } JsonPair(const char *k) : _key(k) {}
JsonValue value() { const char *key() const { return _key; }
return Internals::JsonValueInternal(_node->getAsObjectValue()); JsonValue &value() { return _value; }
}
protected: private:
explicit JsonPair(Internals::JsonNode *node) : _node(node) {} const char *_key;
JsonValue _value;
Internals::JsonNode *_node;
}; };
} }

View File

@ -6,40 +6,46 @@
#pragma once #pragma once
#include <stddef.h>
#include "ForwardDeclarations.hpp" #include "ForwardDeclarations.hpp"
#include "Internals/JsonNodeWrapper.hpp" #include "Internals/JsonValueImpl.hpp"
namespace ArduinoJson { namespace ArduinoJson {
class JsonValue : public Internals::JsonNodeWrapper { class JsonValue {
public: public:
JsonValue() {} JsonValue() : _impl(NULL) {}
JsonValue(Internals::JsonValueImpl *impl) : _impl(impl) {}
void operator=(bool value); template <typename T>
void operator=(const char *value); void operator=(T value) {
void operator=(double value) { set(value, 2); } if (_impl) _impl->set(value);
void operator=(int value);
void operator=(const JsonValue &value) { duplicate(value); }
void operator=(const Internals::JsonNodeWrapper &object) {
duplicate(object);
} }
operator bool() const; void set(double value, int decimals) {
operator const char *() const; if (_impl) _impl->set(value, decimals);
operator double() const; }
operator long() const;
operator int() const { return operator long(); }
operator JsonArray() const;
operator JsonObject() const;
void set(double value, int decimals);
template <typename T> template <typename T>
T as() { T as() {
return static_cast<T>(*this); return static_cast<T>(*this);
} }
protected: operator bool() const { return _impl ? *_impl : false; }
JsonValue(Internals::JsonNode *node) : Internals::JsonNodeWrapper(node) {} operator int() const { return _impl ? *_impl : 0; }
operator long() const { return _impl ? *_impl : 0; }
operator double() const { return _impl ? *_impl : 0.0; }
operator const char *() const {
return _impl ? *_impl : static_cast<char *>(NULL);
}
operator JsonArray() const;
bool success() { return _impl; }
static JsonValue null() { return JsonValue(NULL); }
private:
Internals::JsonValueImpl *_impl;
}; };
} }

View File

@ -0,0 +1,52 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/JsonValue.hpp"
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
JsonValueImpl *JsonArray::operator[](int index) const {
for (const_iterator it = begin(); it != end(); ++it) {
if (!index) return *it;
index--;
}
return NULL;
}
JsonValueImpl *JsonArray::add() {
if (_buffer) return NULL;
JsonArrayNode *node = _buffer->create<JsonArrayNode>();
if (!node) return NULL;
return &node.value;
}
JsonArrayImpl *JsonArray::createNestedArray() {
JsonNode *node = createNode();
if (node) {
node->setAsArray(_node->getContainerBuffer());
addChild(node);
}
return JsonArray(node);
}
JsonObject JsonArray::createNestedObject() {
JsonNode *node = createNode();
if (node) {
node->setAsObject(_node->getContainerBuffer());
addChild(node);
}
return JsonObject(node);
}

View File

@ -9,9 +9,13 @@
#include <stdlib.h> // for strtol, strtod #include <stdlib.h> // for strtol, strtod
#include <ctype.h> #include <ctype.h>
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonBuffer.hpp" #include "ArduinoJson/JsonBuffer.hpp"
#include "ArduinoJson/JsonValue.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/Internals/QuotedString.hpp" #include "ArduinoJson/Internals/QuotedString.hpp"
using namespace ArduinoJson;
using namespace ArduinoJson::Internals; using namespace ArduinoJson::Internals;
void JsonParser::skipSpaces() { void JsonParser::skipSpaces() {
@ -26,16 +30,18 @@ bool JsonParser::skip(char charToSkip) {
return true; return true;
} }
JsonNode *JsonParser::parseAnything() { void JsonParser::parseValueTo(JsonValue destination) {
skipSpaces(); skipSpaces();
switch (*_ptr) { switch (*_ptr) {
case '[': case '[':
return parseArray(); destination = parseArray();
break;
case 't': case 't':
case 'f': case 'f':
return parseBoolean(); parseBooleanTo(destination);
break;
case '-': case '-':
case '.': case '.':
@ -49,113 +55,106 @@ JsonNode *JsonParser::parseAnything() {
case '7': case '7':
case '8': case '8':
case '9': case '9':
return parseNumber(); parseNumberTo(destination);
break;
case 'n': case 'n':
return parseNull(); parseNullTo(destination);
break;
case '{': case '{':
return parseObject(); destination = parseObject();
break;
case '\'': case '\'':
case '\"': case '\"':
return parseString(); destination = parseString();
break;
default: default:
return NULL; // invalid JSON destination = NULL; // invalid JSON
} }
} }
JsonNode *JsonParser::parseArray() { JsonArray JsonParser::parseArray() {
JsonNode *node = _buffer->createArrayNode();
skip('['); skip('[');
if (isEnd()) return 0; if (isEnd()) return NULL;
if (skip(']')) return node; // empty array JsonArray array = _buffer->createArray();
if (skip(']')) return array; // empty array
for (;;) { for (;;) {
JsonNode *child = parseAnything(); JsonValue child = array.add();
if (!child) return 0; // child parsing failed parseValueTo(child);
if (!child.success()) return NULL;
node->addChild(child); if (skip(']')) return array; // end of the array
if (skip(']')) return node; // end of the array if (!skip(',')) return NULL; // comma is missing
if (!skip(',')) return 0; // comma is missing
} }
} }
JsonNode *JsonParser::parseBoolean() { void JsonParser::parseBooleanTo(JsonValue &destination) {
bool value = *_ptr == 't'; bool value = *_ptr == 't';
// TODO: bug if string ends here !!!
_ptr += value ? 4 : 5; _ptr += value ? 4 : 5;
// 4 = strlen("true") // 4 = strlen("true")
// 5 = strlen("false"); // 5 = strlen("false");
return _buffer->createBoolNode(value); destination = value;
} }
JsonNode *JsonParser::parseNumber() { void JsonParser::parseNumberTo(JsonValue &destination) {
char *endOfLong; char *endOfLong;
long longValue = strtol(_ptr, &endOfLong, 10); long longValue = strtol(_ptr, &endOfLong, 10);
if (*endOfLong == '.') { if (*endOfLong == '.') {
// stopped on a decimal separator // stopped on a decimal separator
double value = strtod(_ptr, &_ptr); double douleValue = strtod(_ptr, &_ptr);
int decimals = _ptr - endOfLong - 1; int decimals = _ptr - endOfLong - 1;
return _buffer->createDoubleNode(value, decimals); destination.set(douleValue, decimals);
} else { } else {
_ptr = endOfLong; _ptr = endOfLong;
return _buffer->createLongNode(longValue); destination = longValue;
} }
} }
JsonNode *JsonParser::parseNull() { void JsonParser::parseNullTo(JsonValue &destination) {
_ptr += 4; // strlen("null") _ptr += 4; // strlen("null")
return _buffer->createStringNode(0); destination = static_cast<const char *>(NULL);
} }
JsonNode *JsonParser::parseObject() { JsonObject JsonParser::parseObject() {
JsonNode *node = _buffer->createObjectNode();
skip('{'); skip('{');
if (isEnd()) return 0; // premature ending if (isEnd()) return NULL; // premature ending
if (skip('}')) return node; // empty object JsonObject object = _buffer->createObject();
if (skip('}')) return object; // empty object
for (;;) { for (;;) {
JsonNode *child = parseObjectKeyValue(); const char *key = parseString();
if (!key) return NULL;
if (!child) return 0; // child parsing failed skip(':')
node->addChild(child); JsonValue value = object[key];
if (skip('}')) return node; // end of the object parseValueTo(value);
if (!value.success()) return NULL;
if (skip('}')) return object; // end of the object
if (!skip(',')) return 0; // comma is missing if (!skip(',')) return 0; // comma is missing
} }
} }
JsonNode *JsonParser::parseObjectKeyValue() { const char *JsonParser::parseString() {
const char *key = QuotedString::extractFrom(_ptr, &_ptr); return QuotedString::extractFrom(_ptr, &_ptr);
if (!key) return 0; // failed to extract key
if (!skip(':')) return 0; // colon is missing
JsonNode *value = parseAnything();
if (!value) return 0; // value parsing failed
return _buffer->createObjectKeyValueNode(key, value);
}
JsonNode *JsonParser::parseString() {
const char *s = QuotedString::extractFrom(_ptr, &_ptr);
return _buffer->createStringNode(s);
} }

View File

@ -12,38 +12,16 @@ using namespace ArduinoJson;
using namespace ArduinoJson::Internals; using namespace ArduinoJson::Internals;
JsonValue JsonArray::operator[](int index) const { JsonValue JsonArray::operator[](int index) const {
for (const_iterator it = begin(); it != end(); ++it) { if (!_impl) return JsonValue::null();
if (!index) return *it; return JsonValue((*_impl)[index]);
index--;
}
return JsonValue();
}
JsonValue JsonArray::addNewValue() {
JsonNode *node = createNode();
if (node) addChild(node);
return JsonValueInternal(node);
} }
JsonArray JsonArray::createNestedArray() { JsonArray JsonArray::createNestedArray() {
JsonNode *node = createNode(); if (!_impl) return JsonArray::null();
return JsonArray(_impl->createNestedArray());
if (node) {
node->setAsArray(_node->getContainerBuffer());
addChild(node);
}
return JsonArray(node);
} }
JsonObject JsonArray::createNestedObject() { JsonObject JsonArray::createNestedObject() {
JsonNode *node = createNode(); if (!_impl) return JsonObject::null();
return JsonObject(_impl->createNestedObject()));
if (node) { }
node->setAsObject(_node->getContainerBuffer());
addChild(node);
}
return JsonObject(node);
}

View File

@ -7,39 +7,9 @@
#include "ArduinoJson/JsonValue.hpp" #include "ArduinoJson/JsonValue.hpp"
#include "ArduinoJson/JsonArray.hpp" #include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/Internals/JsonNode.hpp"
using namespace ArduinoJson; using namespace ArduinoJson;
void JsonValue::operator=(bool value) { JsonValue::operator JsonArray() const {
if (_node) _node->setAsBoolean(value); return _impl ? JsonArray(*_impl) : JsonArray();
} }
void JsonValue::operator=(char const *value) {
if (_node) _node->setAsString(value);
}
void JsonValue::set(double value, int decimals) {
if (_node) _node->setAsDouble(value, decimals);
}
void JsonValue::operator=(int value) {
if (_node) _node->setAsLong(value);
}
JsonValue::operator bool() const {
return _node ? _node->getAsBoolean() : false;
}
JsonValue::operator char const *() const {
return _node ? _node->getAsString() : 0;
}
JsonValue::operator double() const { return _node ? _node->getAsDouble() : 0; }
JsonValue::operator long() const { return _node ? _node->getAsInteger() : 0; }
JsonValue::operator JsonArray() const { return JsonArray(_node); }
JsonValue::operator JsonObject() const { return JsonObject(_node); }