Redesigned JsonVariant to leverage converting constructors instead of assignment operators

This commit is contained in:
Benoit Blanchon
2015-05-23 15:32:50 +02:00
parent 08d05df00e
commit 756c279cdc
44 changed files with 934 additions and 649 deletions

View File

@ -38,25 +38,27 @@ bool JsonParser::skip(const char *wordToSkip) {
return *charToSkip == '\0';
}
void JsonParser::parseAnythingTo(JsonVariant &destination) {
if (_nestingLimit == 0) return;
bool JsonParser::parseAnythingTo(JsonVariant *destination) {
if (_nestingLimit == 0) return false;
_nestingLimit--;
bool success = parseAnythingToUnsafe(destination);
_nestingLimit++;
return success;
}
inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) {
skipSpaces();
switch (*_ptr) {
case '[':
destination = parseArray();
break;
return parseArrayTo(destination);
case '{':
destination = parseObject();
break;
return parseObjectTo(destination);
case 't':
case 'f':
parseBooleanTo(destination);
break;
return parseBooleanTo(destination);
case '-':
case '.':
@ -70,20 +72,14 @@ void JsonParser::parseAnythingTo(JsonVariant &destination) {
case '7':
case '8':
case '9':
parseNumberTo(destination);
break;
return parseNumberTo(destination);
case 'n':
parseNullTo(destination);
break;
return parseNullTo(destination);
case '\'':
case '\"':
destination = parseString();
break;
default:
return parseStringTo(destination);
}
_nestingLimit++;
}
JsonArray &JsonParser::parseArray() {
@ -97,9 +93,9 @@ JsonArray &JsonParser::parseArray() {
// Read each value
for (;;) {
// 1 - Parse value
JsonVariant &value = array.add();
parseAnythingTo(value);
if (!value.success()) goto ERROR_INVALID_VALUE;
JsonVariant value;
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
if (!array.add(value)) goto ERROR_NO_MEMORY;
// 2 - More values?
if (skip(']')) goto SUCCES_NON_EMPTY_ARRAY;
@ -113,9 +109,18 @@ SUCCES_NON_EMPTY_ARRAY:
ERROR_INVALID_VALUE:
ERROR_MISSING_BRACKET:
ERROR_MISSING_COMMA:
ERROR_NO_MEMORY:
return JsonArray::invalid();
}
bool JsonParser::parseArrayTo(JsonVariant *destination) {
JsonArray &array = parseArray();
if (!array.success()) return false;
*destination = array;
return true;
}
JsonObject &JsonParser::parseObject() {
// Create an empty object
JsonObject &object = _buffer->createObject();
@ -132,9 +137,9 @@ JsonObject &JsonParser::parseObject() {
if (!skip(':')) goto ERROR_MISSING_COLON;
// 2 - Parse value
JsonVariant &value = object.add(key);
parseAnythingTo(value);
if (!value.success()) goto ERROR_INVALID_VALUE;
JsonVariant value;
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
if (!object.set(key, value)) goto ERROR_NO_MEMORY;
// 3 - More keys/values?
if (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT;
@ -150,19 +155,31 @@ ERROR_INVALID_VALUE:
ERROR_MISSING_BRACE:
ERROR_MISSING_COLON:
ERROR_MISSING_COMMA:
ERROR_NO_MEMORY:
return JsonObject::invalid();
}
void JsonParser::parseBooleanTo(JsonVariant &destination) {
if (skip("true"))
destination = true;
else if (skip("false"))
destination = false;
else
destination = JsonVariant::invalid();
bool JsonParser::parseObjectTo(JsonVariant *destination) {
JsonObject &object = parseObject();
if (!object.success()) return false;
*destination = object;
return true;
}
void JsonParser::parseNumberTo(JsonVariant &destination) {
bool JsonParser::parseBooleanTo(JsonVariant *destination) {
if (skip("true")) {
*destination = true;
return true;
} else if (skip("false")) {
*destination = false;
return true;
} else {
return false;
}
}
bool JsonParser::parseNumberTo(JsonVariant *destination) {
char *endOfLong;
long longValue = strtol(_ptr, &endOfLong, 10);
char stopChar = *endOfLong;
@ -176,22 +193,28 @@ void JsonParser::parseNumberTo(JsonVariant &destination) {
// Count the decimal digits
uint8_t decimals = static_cast<uint8_t>(_ptr - endOfLong - 1);
// Set the variant as a double
destination.set(doubleValue, decimals);
*destination = JsonVariant(doubleValue, decimals);
} else {
// No => set the variant as a long
_ptr = endOfLong;
destination = longValue;
*destination = longValue;
}
return true;
}
void JsonParser::parseNullTo(JsonVariant &destination) {
bool JsonParser::parseNullTo(JsonVariant *destination) {
const char *NULL_STRING = NULL;
if (skip("null"))
destination = NULL_STRING;
else
destination = JsonVariant::invalid();
if (!skip("null")) return false;
*destination = NULL_STRING;
return true;
}
const char *JsonParser::parseString() {
return QuotedString::extractFrom(_ptr, &_ptr);
}
bool JsonParser::parseStringTo(JsonVariant *destination) {
const char *value = parseString();
*destination = value;
return value != NULL;
}

View File

@ -13,8 +13,8 @@ using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
template <typename T>
int List<T>::size() const {
int nodeCount = 0;
size_t List<T>::size() const {
size_t nodeCount = 0;
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
return nodeCount;
}

View File

@ -33,7 +33,7 @@ inline size_t Prettyfier::handleMarkupChar(uint8_t c) {
return handleBlockClose(c);
case ':':
return handleColumn();
return handleColon();
case ',':
return handleComma();
@ -54,7 +54,7 @@ inline size_t Prettyfier::handleBlockClose(uint8_t c) {
return unindentIfNeeded() + _sink.write(c);
}
inline size_t Prettyfier::handleColumn() {
inline size_t Prettyfier::handleColon() {
return _sink.write(':') + _sink.write(' ');
}

View File

@ -14,18 +14,10 @@ using namespace ArduinoJson::Internals;
JsonArray JsonArray::_invalid(NULL);
JsonVariant &JsonArray::at(int index) const {
node_type *node = getNodeAt(index);
return node ? node->content : JsonVariant::invalid();
}
JsonVariant &JsonArray::add() {
node_type *node = createNode();
if (!node) return JsonVariant::invalid();
addNode(node);
return node->content;
JsonArray::node_type *JsonArray::getNodeAt(size_t index) const {
node_type *node = _firstNode;
while (node && index--) node = node->next;
return node;
}
JsonArray &JsonArray::createNestedArray() {
@ -42,13 +34,7 @@ JsonObject &JsonArray::createNestedObject() {
return object;
}
JsonArray::node_type *JsonArray::getNodeAt(int index) const {
node_type *node = _firstNode;
while (node && index--) node = node->next;
return node;
}
void JsonArray::removeAt(int index) { removeNode(getNodeAt(index)); }
void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); }
void JsonArray::writeTo(JsonWriter &writer) const {
writer.beginArray();

View File

@ -17,45 +17,25 @@ using namespace ArduinoJson::Internals;
JsonObject JsonObject::_invalid(NULL);
JsonVariant &JsonObject::at(const char *key) {
node_type *node = getNodeAt(key);
return node ? node->content.value : JsonVariant::invalid();
JsonObject::node_type *JsonObject::getOrCreateNodeAt(const char *key) {
node_type *existingNode = getNodeAt(key);
if (existingNode) return existingNode;
node_type *newNode = addNewNode();
return newNode;
}
const JsonVariant &JsonObject::at(const char *key) const {
node_type *node = getNodeAt(key);
return node ? node->content.value : JsonVariant::invalid();
}
JsonVariant &JsonObject::operator[](const char *key) {
// try to find an existing node
node_type *node = getNodeAt(key);
// not fount => create a new one
if (!node) {
node = createNode();
if (!node) return JsonVariant::invalid();
node->content.key = key;
addNode(node);
}
return node->content.value;
}
void JsonObject::remove(char const *key) { removeNode(getNodeAt(key)); }
JsonArray &JsonObject::createNestedArray(char const *key) {
JsonArray &JsonObject::createNestedArray(const char *key) {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
add(key, array);
set(key, array);
return array;
}
JsonObject &JsonObject::createNestedObject(const char *key) {
if (!_buffer) return JsonObject::invalid();
JsonObject &object = _buffer->createObject();
add(key, object);
set(key, object);
return object;
}

View File

@ -12,84 +12,6 @@
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
JsonVariant JsonVariant::_invalid(JSON_INVALID);
JsonVariant::operator JsonArray &() const {
return _type == JSON_ARRAY ? *_content.asArray : JsonArray::invalid();
}
JsonVariant::operator JsonObject &() const {
return _type == JSON_OBJECT ? *_content.asObject : JsonObject::invalid();
}
JsonVariant::operator bool() const {
return _type == JSON_BOOLEAN ? _content.asBoolean : false;
}
JsonVariant::operator const char *() const {
return _type == JSON_STRING ? _content.asString : NULL;
}
JsonVariant::operator double() const {
return _type >= JSON_DOUBLE_0_DECIMALS ? _content.asDouble : 0;
}
JsonVariant::operator long() const {
return _type == JSON_LONG ? _content.asLong : 0;
}
void JsonVariant::set(bool value) {
if (_type == JSON_INVALID) return;
_type = Internals::JSON_BOOLEAN;
_content.asBoolean = value;
}
void JsonVariant::set(const char *value) {
if (_type == JSON_INVALID) return;
_type = JSON_STRING;
_content.asString = value;
}
void JsonVariant::set(double value, uint8_t decimals) {
if (_type == JSON_INVALID) return;
_type = static_cast<JsonVariantType>(JSON_DOUBLE_0_DECIMALS + decimals);
_content.asDouble = value;
}
void JsonVariant::set(long value) {
if (_type == JSON_INVALID) return;
_type = JSON_LONG;
_content.asLong = value;
}
void JsonVariant::set(JsonArray &array) {
if (_type == JSON_INVALID) return;
_type = array.success() ? JSON_ARRAY : JSON_INVALID;
_content.asArray = &array;
}
void JsonVariant::set(JsonObject &object) {
if (_type == JSON_INVALID) return;
_type = object.success() ? JSON_OBJECT : JSON_INVALID;
_content.asObject = &object;
}
size_t JsonVariant::size() const {
if (_type == JSON_ARRAY) return _content.asArray->size();
if (_type == JSON_OBJECT) return _content.asObject->size();
return 0;
}
JsonVariant &JsonVariant::operator[](int index) {
if (_type != JSON_ARRAY) return JsonVariant::invalid();
return _content.asArray->operator[](index);
}
JsonVariant &JsonVariant::operator[](const char *key) {
if (_type != JSON_OBJECT) return JsonVariant::invalid();
return _content.asObject->operator[](key);
}
void JsonVariant::writeTo(JsonWriter &writer) const {
if (is<const JsonArray &>())
as<const JsonArray &>().writeTo(writer);