diff --git a/srcs/Internals/JsonNode.cpp b/srcs/Internals/JsonNode.cpp new file mode 100644 index 00000000..004b8d17 --- /dev/null +++ b/srcs/Internals/JsonNode.cpp @@ -0,0 +1,72 @@ +#include "JsonNode.h" + +#include "JsonWriter.h" +#include "../JsonArray.h" +#include "../JsonObject.h" + +void JsonNode::writeTo(JsonWriter& writer) +{ + switch (type) + { + case JSON_ARRAY: + writeArrayTo(writer); + break; + + case JSON_OBJECT: + writeObjectTo(writer); + break; + + case JSON_STRING: + writer.writeValue(content.asString); + break; + + case JSON_INTEGER: + writer.writeValue(content.asInteger); + break; + + case JSON_BOOLEAN: + writer.writeValue(content.asBoolean); + break; + + case JSON_PROXY: + content.asProxy.target->writeTo(writer); + break; + + default: // >= JSON_DOUBLE_0_DECIMALS + writer.writeValue(content.asDouble, type - JSON_DOUBLE_0_DECIMALS); + break; + } +} + +void JsonNode::writeArrayTo(JsonWriter& writer) +{ + writer.beginArray(); + + JsonNode* child = content.asContainer.child; + + while(child) + { + child->writeTo(writer); + + child = child->next; + } + + writer.endArray(); +} + +void JsonNode::writeObjectTo(JsonWriter& writer) +{ + writer.beginObject(); + + JsonNode* child = content.asContainer.child; + + while (child) + { + writer.writeKey(child->content.asKey.key); + child->content.asKey.value->writeTo(writer); + + child = child->next; + } + + writer.endObject(); +} \ No newline at end of file diff --git a/srcs/Internals/JsonNode.h b/srcs/Internals/JsonNode.h index efa897b2..b11dac02 100644 --- a/srcs/Internals/JsonNode.h +++ b/srcs/Internals/JsonNode.h @@ -19,10 +19,14 @@ enum JsonNodeType // etc. }; +class JsonWriter; + struct JsonNode { - JsonNode* next; - JsonNodeType type; + JsonNode* next; + JsonNodeType type; // <- TODO: hide + + void writeTo(JsonWriter&); union { @@ -49,4 +53,8 @@ struct JsonNode } asProxy; } content; + +private: + inline void writeArrayTo(JsonWriter&); + inline void writeObjectTo(JsonWriter&); }; \ No newline at end of file diff --git a/srcs/Internals/JsonNodeSerializer.cpp b/srcs/Internals/JsonNodeSerializer.cpp deleted file mode 100644 index effb5979..00000000 --- a/srcs/Internals/JsonNodeSerializer.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "JsonNodeSerializer.h" - -#include "EscapedString.h" -#include "JsonNode.h" - -using namespace ArduinoJson::Internals; - -size_t JsonNodeSerializer::serialize(const JsonNode* node) -{ - if (!node) return 0; - - switch (node->type) - { - case JSON_ARRAY: - return serializeArray(node); - - case JSON_OBJECT: - return serializeObject(node); - - case JSON_STRING: - return EscapedString::printTo(node->content.asString, _sink); - - case JSON_INTEGER: - return _sink.print(node->content.asInteger); - - case JSON_BOOLEAN: - return _sink.print(node->content.asBoolean ? "true" : "false"); - - case JSON_PROXY: - return serialize(node->content.asProxy.target); - } - - if (node->type >= JSON_DOUBLE_0_DECIMALS) - { - return _sink.print(node->content.asDouble, node->type - JSON_DOUBLE_0_DECIMALS); - } - - return 0; -} - -size_t JsonNodeSerializer::serializeArray(JsonNode const* node) -{ - size_t n = 0; - - n += _sink.write('['); - - JsonNode* firstChild = node->content.asContainer.child; - - for (JsonNode* child = firstChild; child; child = child->next) - { - n += serialize(child); - - if (child->next) - { - n += _sink.write(','); - } - } - - n += _sink.write(']'); - - return n; -} - -size_t JsonNodeSerializer::serializeObject(const JsonNode* node) -{ - size_t n = 0; - - n += _sink.write('{'); - - JsonNode* firstChild = node->content.asContainer.child; - - for (JsonNode* child = firstChild; child; child = child->next) - { - n += serializeKeyValue(child); - - if (child->next) - { - n += _sink.write(','); - } - } - - n += _sink.write('}'); - - return n; -} - -size_t JsonNodeSerializer::serializeKeyValue(JsonNode const* node) -{ - const char* childKey = node->content.asKey.key; - JsonNode* childValue = node->content.asKey.value; - - return - EscapedString::printTo(childKey, _sink) + - _sink.write(':') + - serialize(childValue); -} \ No newline at end of file diff --git a/srcs/Internals/JsonNodeSerializer.h b/srcs/Internals/JsonNodeSerializer.h deleted file mode 100644 index ef1309e1..00000000 --- a/srcs/Internals/JsonNodeSerializer.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -class Print; -struct JsonNode; - -class JsonNodeSerializer -{ -public: - explicit JsonNodeSerializer(Print& sink) - : _sink(sink) - { - } - - size_t serialize(const JsonNode* node); - -private: - Print& _sink; - - size_t serializeArray(const JsonNode* node); - size_t serializeObject(const JsonNode* node); - size_t serializeKeyValue(const JsonNode* node); -}; - diff --git a/srcs/Internals/JsonWriter.cpp b/srcs/Internals/JsonWriter.cpp new file mode 100644 index 00000000..536bda63 --- /dev/null +++ b/srcs/Internals/JsonWriter.cpp @@ -0,0 +1,66 @@ +#include "JsonWriter.h" +#include "EscapedString.h" + +using namespace ArduinoJson::Internals; + +void JsonWriter::beginArray() +{ + writeCommaIfNeeded(); + _length += _sink.write('['); + _isCommaNeeded = false; +} + +void JsonWriter::endArray() +{ + _length += _sink.write(']'); + _isCommaNeeded = true; +} + +void JsonWriter::beginObject() +{ + writeCommaIfNeeded(); + _length += _sink.write('{'); + _isCommaNeeded = false; +} + +void JsonWriter::endObject() +{ + _length += _sink.write('}'); + _isCommaNeeded = true; +} + +void JsonWriter::writeKey(char const* key) +{ + writeCommaIfNeeded(); + _length += EscapedString::printTo(key, _sink); + _length += _sink.write(':'); + _isCommaNeeded = false; +} + +void JsonWriter::writeValue(char const* value) +{ + writeCommaIfNeeded(); + _length += EscapedString::printTo(value, _sink); + _isCommaNeeded = true; +} + +void JsonWriter::writeValue(long value) +{ + writeCommaIfNeeded(); + _length += _sink.print(value); + _isCommaNeeded = true; +} + +void JsonWriter::writeValue(bool value) +{ + writeCommaIfNeeded(); + _length += _sink.print(value ? "true" : "false"); + _isCommaNeeded = true; +} + +void JsonWriter::writeValue(double value, int decimals) +{ + writeCommaIfNeeded(); + _length += _sink.print(value, decimals); + _isCommaNeeded = true; +} \ No newline at end of file diff --git a/srcs/Internals/JsonWriter.h b/srcs/Internals/JsonWriter.h new file mode 100644 index 00000000..7a65b3a2 --- /dev/null +++ b/srcs/Internals/JsonWriter.h @@ -0,0 +1,42 @@ +#pragma once + +#include "../Arduino/Print.h" + +class JsonWriter +{ +public: + explicit JsonWriter(Print& sink) + : _sink(sink), _length(0), _isCommaNeeded(false) + { + } + + size_t bytesWritten() + { + return _length; + } + + void beginArray(); + void endArray(); + + void beginObject(); + void endObject(); + + void writeKey(const char* key); + + void writeValue(const char* value); + void writeValue(long value); + void writeValue(bool value); + void writeValue(double value, int decimals); + +private: + Print& _sink; + size_t _length; + bool _isCommaNeeded; + + void writeCommaIfNeeded() + { + if (_isCommaNeeded) + _length += _sink.write(','); + } +}; + diff --git a/srcs/JsonContainer.cpp b/srcs/JsonContainer.cpp index 33ef4fa7..77628861 100644 --- a/srcs/JsonContainer.cpp +++ b/srcs/JsonContainer.cpp @@ -1,7 +1,7 @@ #include "JsonContainer.h" #include "JsonBuffer.h" -#include "Internals/JsonNodeSerializer.h" +#include "Internals/JsonWriter.h" #include "Internals/StringBuilder.h" size_t JsonContainer::printTo(char* buffer, size_t bufferSize) const @@ -12,8 +12,9 @@ size_t JsonContainer::printTo(char* buffer, size_t bufferSize) const size_t JsonContainer::printTo(Print& p) const { - JsonNodeSerializer serializer(p); - return serializer.serialize(_node); + JsonWriter writer(p); + _node->writeTo(writer); + return writer.bytesWritten(); } JsonNode* JsonContainer::createNode(JsonNodeType type) diff --git a/srcs/JsonObject.cpp b/srcs/JsonObject.cpp index fc570c40..eedfd48f 100644 --- a/srcs/JsonObject.cpp +++ b/srcs/JsonObject.cpp @@ -6,7 +6,6 @@ #include "JsonValue.h" #include "Internals/EscapedString.h" #include "Internals/JsonNode.h" -#include "Internals/JsonNodeSerializer.h" #include "Internals/StringBuilder.h" using namespace ArduinoJson::Internals; diff --git a/srcs/srcs.vcxproj b/srcs/srcs.vcxproj index 3b029490..36440c22 100644 --- a/srcs/srcs.vcxproj +++ b/srcs/srcs.vcxproj @@ -78,7 +78,7 @@ - + @@ -90,9 +90,10 @@ + - + diff --git a/srcs/srcs.vcxproj.filters b/srcs/srcs.vcxproj.filters index 5ad72fd5..35f07402 100644 --- a/srcs/srcs.vcxproj.filters +++ b/srcs/srcs.vcxproj.filters @@ -33,9 +33,6 @@ Header Files - - Header Files - Header Files @@ -54,6 +51,9 @@ Header Files + + Header Files + @@ -68,9 +68,6 @@ Source Files - - Source Files - Source Files @@ -83,5 +80,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file