diff --git a/include/ArduinoJson/Internals/JsonPrintable.hpp b/include/ArduinoJson/Internals/JsonPrintable.hpp index 3553d2a7..3e972dc6 100644 --- a/include/ArduinoJson/Internals/JsonPrintable.hpp +++ b/include/ArduinoJson/Internals/JsonPrintable.hpp @@ -7,7 +7,8 @@ #pragma once #include "IndentedPrint.hpp" -#include "PrettyJsonWriter.hpp" +#include "JsonWriter.hpp" +#include "Prettyfier.hpp" #include "StringBuilder.hpp" namespace ArduinoJson { @@ -32,9 +33,8 @@ class JsonPrintable { } size_t prettyPrintTo(IndentedPrint &print) const { - PrettyJsonWriter writer(print); - downcast().writeTo(writer); - return writer.bytesWritten(); + Prettyfier p(print); + return printTo(p); } size_t prettyPrintTo(char *buffer, size_t bufferSize) const { diff --git a/include/ArduinoJson/Internals/PrettyJsonWriter.hpp b/include/ArduinoJson/Internals/PrettyJsonWriter.hpp deleted file mode 100644 index dfacd60a..00000000 --- a/include/ArduinoJson/Internals/PrettyJsonWriter.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright Benoit Blanchon 2014 -// MIT License -// -// Arduino JSON library -// https://github.com/bblanchon/ArduinoJson - -#pragma once - -#include "JsonWriter.hpp" -#include "IndentedPrint.hpp" - -namespace ArduinoJson { -namespace Internals { - -// An indented version of JsonWriter. -class PrettyJsonWriter : public JsonWriter { - public: - explicit PrettyJsonWriter(IndentedPrint &sink) - : JsonWriter(sink), _indenter(sink) {} - - void beginArray() { - JsonWriter::beginArray(); - indent(); - } - - void endArray() { - unindent(); - JsonWriter::endArray(); - } - - void writeColon() { write(": "); } - - void writeComma() { - JsonWriter::writeComma(); - newline(); - } - - void beginObject() { - JsonWriter::beginObject(); - indent(); - } - - void endObject() { - unindent(); - JsonWriter::endObject(); - } - - private: - void indent() { - _indenter.indent(); - newline(); - } - - void unindent() { - newline(); - _indenter.unindent(); - } - - void newline() { _length += _indenter.println(); } - - IndentedPrint &_indenter; -}; -} -} diff --git a/include/ArduinoJson/Internals/Prettyfier.hpp b/include/ArduinoJson/Internals/Prettyfier.hpp new file mode 100644 index 00000000..2d220bf0 --- /dev/null +++ b/include/ArduinoJson/Internals/Prettyfier.hpp @@ -0,0 +1,43 @@ +/* +* Arduino JSON library +* Benoit Blanchon 2014 - MIT License +*/ + +#pragma once + +#include "IndentedPrint.hpp" + +namespace ArduinoJson { +namespace Internals { + +// Converts a compact JSON string into an indented one. +class Prettyfier : public Print { + public: + Prettyfier(IndentedPrint& p) : _sink(p) { + _previousChar = 0; + _inString = false; + } + + virtual size_t write(uint8_t); + + private: + uint8_t _previousChar; + IndentedPrint& _sink; + bool _inString; + + bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; } + + size_t handleStringChar(uint8_t); + size_t handleMarkupChar(uint8_t); + + size_t handleBlockClose(uint8_t); + size_t handleBlockOpen(uint8_t); + size_t handleColumn(); + size_t handleComma(); + size_t handleQuoteOpen(); + size_t handleNormalChar(uint8_t); + size_t indentIfNeeded(); + size_t unindentIfNeeded(); +}; +} +} \ No newline at end of file diff --git a/include/ArduinoJson/JsonArray.hpp b/include/ArduinoJson/JsonArray.hpp index 26f55b57..daff423a 100644 --- a/include/ArduinoJson/JsonArray.hpp +++ b/include/ArduinoJson/JsonArray.hpp @@ -75,8 +75,7 @@ class JsonArray : public Internals::JsonPrintable, static JsonArray &invalid() { return _invalid; } // Serialize the array to the specified JsonWriter. - template - void writeTo(T &writer) const; + void writeTo(Internals::JsonWriter &writer) const; private: // Create an empty JsonArray attached to the specified JsonBuffer. diff --git a/include/ArduinoJson/JsonObject.hpp b/include/ArduinoJson/JsonObject.hpp index 9c264543..fef00140 100644 --- a/include/ArduinoJson/JsonObject.hpp +++ b/include/ArduinoJson/JsonObject.hpp @@ -90,8 +90,7 @@ class JsonObject : public Internals::JsonPrintable, static JsonObject &invalid() { return _invalid; } // Serialize the object to the specified JsonWriter - template - void writeTo(T &writer) const; + void writeTo(Internals::JsonWriter &writer) const; private: // Create an empty JsonArray attached to the specified JsonBuffer. diff --git a/include/ArduinoJson/JsonVariant.hpp b/include/ArduinoJson/JsonVariant.hpp index ba9598d1..9273c65b 100644 --- a/include/ArduinoJson/JsonVariant.hpp +++ b/include/ArduinoJson/JsonVariant.hpp @@ -146,8 +146,7 @@ class JsonVariant : public Internals::JsonPrintable { static JsonVariant &invalid() { return _invalid; } // Serialize the variant to a JsonWriter - template - void writeTo(T &writer) const; + void writeTo(Internals::JsonWriter &writer) const; // Mimics an array or an object. // Returns the size of the array or object if the variant has that type. diff --git a/src/Internals/Prettyfier.cpp b/src/Internals/Prettyfier.cpp new file mode 100644 index 00000000..f33fabd5 --- /dev/null +++ b/src/Internals/Prettyfier.cpp @@ -0,0 +1,85 @@ +/* +* Arduino JSON library +* Benoit Blanchon 2014 - MIT License +*/ + +#include "../../include/ArduinoJson/Internals/Prettyfier.hpp" + +using namespace ArduinoJson::Internals; + +size_t Prettyfier::write(uint8_t c) { + size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); + _previousChar = c; + return n; +} + +inline size_t Prettyfier::handleStringChar(uint8_t c) { + bool isQuote = c == '"' && _previousChar != '\\'; + + if (isQuote) _inString = false; + + return _sink.write(c); +} + +inline size_t Prettyfier::handleMarkupChar(uint8_t c) { + switch (c) { + case '{': + case '[': + return handleBlockOpen(c); + + case '}': + case ']': + return handleBlockClose(c); + + case ':': + return handleColumn(); + + case ',': + return handleComma(); + + case '"': + return handleQuoteOpen(); + + default: + return handleNormalChar(c); + } +} + +inline size_t Prettyfier::handleBlockOpen(uint8_t c) { + return indentIfNeeded() + _sink.write(c); +} + +inline size_t Prettyfier::handleBlockClose(uint8_t c) { + return unindentIfNeeded() + _sink.write(c); +} + +inline size_t Prettyfier::handleColumn() { + return _sink.write(':') + _sink.write(' '); +} + +inline size_t Prettyfier::handleComma() { + return _sink.write(',') + _sink.println(); +} + +inline size_t Prettyfier::handleQuoteOpen() { + _inString = true; + return indentIfNeeded() + _sink.write('"'); +} + +inline size_t Prettyfier::handleNormalChar(uint8_t c) { + return indentIfNeeded() + _sink.write(c); +} + +size_t Prettyfier::indentIfNeeded() { + if (!inEmptyBlock()) return 0; + + _sink.indent(); + return _sink.println(); +} + +size_t Prettyfier::unindentIfNeeded() { + if (inEmptyBlock()) return 0; + + _sink.unindent(); + return _sink.println(); +} \ No newline at end of file diff --git a/src/JsonArray.cpp b/src/JsonArray.cpp index 7e65b405..cea29ee1 100644 --- a/src/JsonArray.cpp +++ b/src/JsonArray.cpp @@ -6,7 +6,6 @@ #include "../include/ArduinoJson/JsonArray.hpp" -#include "../include/ArduinoJson/Internals/PrettyJsonWriter.hpp" #include "../include/ArduinoJson/JsonBuffer.hpp" #include "../include/ArduinoJson/JsonObject.hpp" @@ -44,8 +43,7 @@ JsonObject &JsonArray::createNestedObject() { return object; } -template -void JsonArray::writeTo(T &writer) const { +void JsonArray::writeTo(JsonWriter &writer) const { node_type *child = _firstNode; if (child) { @@ -65,6 +63,3 @@ void JsonArray::writeTo(T &writer) const { writer.writeEmptyArray(); } } - -template void JsonArray::writeTo(JsonWriter &) const; -template void JsonArray::writeTo(PrettyJsonWriter &) const; diff --git a/src/JsonObject.cpp b/src/JsonObject.cpp index c2a527a8..bce43f04 100644 --- a/src/JsonObject.cpp +++ b/src/JsonObject.cpp @@ -9,7 +9,6 @@ #include // for strcmp #include "../include/ArduinoJson/Internals/PlacementNew.hpp" -#include "../include/ArduinoJson/Internals/PrettyJsonWriter.hpp" #include "../include/ArduinoJson/Internals/StringBuilder.hpp" #include "../include/ArduinoJson/JsonArray.hpp" #include "../include/ArduinoJson/JsonBuffer.hpp" @@ -69,8 +68,7 @@ JsonObject::node_type *JsonObject::getOrCreateNodeAt(const char *key) { return newNode; } -template -void JsonObject::writeTo(T &writer) const { +void JsonObject::writeTo(JsonWriter &writer) const { node_type *node = _firstNode; if (node) { @@ -92,6 +90,3 @@ void JsonObject::writeTo(T &writer) const { writer.writeEmptyObject(); } } - -template void JsonObject::writeTo(JsonWriter &writer) const; -template void JsonObject::writeTo(PrettyJsonWriter &writer) const; diff --git a/src/JsonVariant.cpp b/src/JsonVariant.cpp index 35ab9cc9..df66bc99 100644 --- a/src/JsonVariant.cpp +++ b/src/JsonVariant.cpp @@ -6,7 +6,6 @@ #include "../include/ArduinoJson/JsonVariant.hpp" -#include "../include/ArduinoJson/Internals/PrettyJsonWriter.hpp" #include "../include/ArduinoJson/JsonArray.hpp" #include "../include/ArduinoJson/JsonObject.hpp" @@ -91,8 +90,7 @@ JsonVariant &JsonVariant::operator[](const char *key) { return _content.asObject->operator[](key); } -template -void JsonVariant::writeTo(T &writer) const { +void JsonVariant::writeTo(JsonWriter &writer) const { switch (_type) { case JSON_ARRAY: _content.asArray->writeTo(writer); @@ -120,6 +118,3 @@ void JsonVariant::writeTo(T &writer) const { break; } } - -template void JsonVariant::writeTo(JsonWriter &) const; -template void JsonVariant::writeTo(PrettyJsonWriter &) const;