Implemented reference semantics for JsonVariant

This commit is contained in:
Benoit Blanchon
2018-08-21 17:56:16 +02:00
parent 0454bd1ef6
commit 9cbc891816
53 changed files with 1196 additions and 839 deletions

View File

@@ -4,6 +4,8 @@
#pragma once
#include <stdlib.h> // size_t
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"

View File

@@ -0,0 +1,181 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Numbers/parseFloat.hpp"
#include "../Numbers/parseInteger.hpp"
#include "JsonVariantContent.hpp"
#include "JsonVariantType.hpp"
namespace ArduinoJson {
namespace Internals {
struct JsonVariantData {
JsonVariantType type;
JsonVariantContent content;
void setBoolean(bool value) {
type = JSON_BOOLEAN;
content.asInteger = static_cast<JsonUInt>(value);
}
void setFloat(JsonFloat value) {
type = JSON_FLOAT;
content.asFloat = value;
}
void setInteger(JsonInteger value) {
if (value > 0)
setPostiveInteger(static_cast<JsonUInt>(value));
else
setNegativeInteger(static_cast<JsonUInt>(-value));
}
void setNegativeInteger(JsonUInt value) {
type = JSON_NEGATIVE_INTEGER;
content.asInteger = value;
}
void setPostiveInteger(JsonUInt value) {
type = JSON_POSITIVE_INTEGER;
content.asInteger = value;
}
void setString(const char *value) {
type = JSON_STRING;
content.asString = value;
}
void setRaw(const char *data, size_t size) {
type = JSON_RAW;
content.asRaw.data = data;
content.asRaw.size = size;
}
void setNull() {
type = JSON_NULL;
}
void setArray(JsonArrayData &array) {
type = JSON_ARRAY;
content.asArray = &array;
}
void setObject(JsonObjectData &object) {
type = JSON_OBJECT;
content.asObject = &object;
}
JsonArrayData *asArray() const {
return type == JSON_ARRAY ? content.asArray : 0;
}
JsonObjectData *asObject() const {
return type == JSON_OBJECT ? content.asObject : 0;
}
template <typename T>
T asInteger() const {
switch (type) {
case JSON_NULL:
case JSON_RAW:
return 0;
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return T(content.asInteger);
case JSON_NEGATIVE_INTEGER:
return T(~content.asInteger + 1);
case JSON_STRING:
return parseInteger<T>(content.asString);
default:
return T(content.asFloat);
}
}
template <typename T>
T asFloat() const {
switch (type) {
case JSON_NULL:
case JSON_RAW:
return 0;
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return static_cast<T>(content.asInteger);
case JSON_NEGATIVE_INTEGER:
return -static_cast<T>(content.asInteger);
case JSON_STRING:
return parseFloat<T>(content.asString);
default:
return static_cast<T>(content.asFloat);
}
}
const char *asString() const {
return type == JSON_STRING ? content.asString : NULL;
}
bool isArray() const {
return type == Internals::JSON_ARRAY;
}
bool isBoolean() const {
return type == JSON_BOOLEAN;
}
bool isFloat() const {
return type == JSON_FLOAT || type == JSON_POSITIVE_INTEGER ||
type == JSON_NEGATIVE_INTEGER;
}
bool isInteger() const {
return type == JSON_POSITIVE_INTEGER || type == JSON_NEGATIVE_INTEGER;
}
bool isNull() const {
return type == JSON_NULL;
}
bool isObject() const {
return type == Internals::JSON_OBJECT;
}
bool isString() const {
return type == Internals::JSON_STRING;
}
template <typename Visitor>
void visit(Visitor &visitor) const {
switch (type) {
case JSON_FLOAT:
return visitor.acceptFloat(content.asFloat);
case JSON_ARRAY:
return visitor.acceptArray(*content.asArray);
case JSON_OBJECT:
return visitor.acceptObject(*content.asObject);
case JSON_STRING:
return visitor.acceptString(content.asString);
case JSON_RAW:
return visitor.acceptRawJson(content.asRaw.data, content.asRaw.size);
case JSON_NEGATIVE_INTEGER:
return visitor.acceptNegativeInteger(content.asInteger);
case JSON_POSITIVE_INTEGER:
return visitor.acceptPositiveInteger(content.asInteger);
case JSON_BOOLEAN:
return visitor.acceptBoolean(content.asInteger != 0);
default:
return visitor.acceptNull();
}
}
};
} // namespace Internals
} // namespace ArduinoJson

View File

@@ -1,23 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
template <typename T>
struct JsonVariantDefault {
static T get() {
return T();
}
};
template <typename T>
struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
template <typename T>
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
}
}

View File

@@ -11,10 +11,10 @@ namespace Internals {
// Enumerated type to know the current type of a JsonVariant.
// The value determines which member of JsonVariantContent is used.
enum JsonVariantType {
JSON_UNDEFINED, // JsonVariant has not been initialized
JSON_UNPARSED, // JsonVariant contains an unparsed string
JSON_STRING, // JsonVariant stores a const char*
JSON_BOOLEAN, // JsonVariant stores a bool
JSON_NULL, // JsonVariant has not been initialized
JSON_RAW, // JsonVariant contains a raw string that should not be escaped
JSON_STRING, // JsonVariant stores a const char*
JSON_BOOLEAN, // JsonVariant stores a bool
JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArrayData

View File

@@ -22,7 +22,7 @@ class List {
typedef ListIterator<T> iterator;
typedef ListConstIterator<T> const_iterator;
explicit List(JsonBuffer *buf) : _buffer(buf), _firstNode(NULL) {}
List() : _firstNode(NULL) {}
// Returns the numbers of elements in the list.
// For a JsonObjectData, it would return the number of key-value pairs
@@ -32,8 +32,8 @@ class List {
return nodeCount;
}
iterator add() {
node_type *newNode = new (_buffer) node_type();
iterator add(JsonBuffer *buffer) {
node_type *newNode = new (buffer) node_type();
if (_firstNode) {
node_type *lastNode = _firstNode;
@@ -71,11 +71,6 @@ class List {
}
}
JsonBuffer &buffer() const {
return *_buffer;
}
JsonBuffer *_buffer; // TODO!!
protected:
void clear() {
_firstNode = 0;

View File

@@ -1,53 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../JsonVariant.hpp"
#include "../Memory/JsonBuffer.hpp"
#include "../Polyfills/type_traits.hpp"
#include "../Strings/StringTypes.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename Source, typename Enable = void>
struct ValueSaver {
template <typename Destination>
static bool save(JsonBuffer*, Destination& destination, Source source) {
destination = source;
return true;
}
};
// We duplicate all strings except const char*
template <typename TString>
struct ValueSaver<
TString, typename enable_if<IsString<TString>::value &&
!is_same<const char*, TString>::value>::type> {
template <typename Destination>
static bool save(JsonBuffer* buffer, Destination& dest, TString source) {
const char* dup = makeString(source).save(buffer);
if (!dup) return false;
dest = dup;
return true;
}
};
// We duplicate all SerializedValue<T> except SerializedValue<const char*>
template <typename TString>
struct ValueSaver<
const SerializedValue<TString>&,
typename enable_if<!is_same<const char*, TString>::value>::type> {
template <typename Destination>
static bool save(JsonBuffer* buffer, Destination& dest,
const SerializedValue<TString>& source) {
const char* dup = makeString(source.data(), source.size()).save(buffer);
if (!dup) return false;
dest = SerializedValue<const char*>(dup, source.size());
return true;
}
};
} // namespace Internals
} // namespace ArduinoJson