diff --git a/srcs/Internals/CompactJsonWriter.cpp b/srcs/Internals/CompactJsonWriter.cpp
new file mode 100644
index 00000000..18c74747
--- /dev/null
+++ b/srcs/Internals/CompactJsonWriter.cpp
@@ -0,0 +1 @@
+#include "CompactJsonWriter.h"
diff --git a/srcs/Internals/CompactJsonWriter.h b/srcs/Internals/CompactJsonWriter.h
new file mode 100644
index 00000000..4af2df15
--- /dev/null
+++ b/srcs/Internals/CompactJsonWriter.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "../Internals/JsonWriter.h"
+
+class CompactJsonWriter : public JsonWriter
+{
+public:
+ explicit CompactJsonWriter(Print& sink)
+ : JsonWriter(sink)
+ {
+ }
+
+ virtual void beginArray()
+ {
+ _length += _sink.write('[');
+ }
+
+ virtual void endArray()
+ {
+ _length += _sink.write(']');
+ }
+
+ virtual void writeColon()
+ {
+ _length += _sink.write(':');
+ }
+
+ virtual void writeComma()
+ {
+ _length += _sink.write(',');
+ }
+
+ virtual void beginObject()
+ {
+ _length += _sink.write('{');
+ }
+
+ virtual void endObject()
+ {
+ _length += _sink.write('}');
+ }
+};
+
diff --git a/srcs/Internals/IndentedPrint.cpp b/srcs/Internals/IndentedPrint.cpp
new file mode 100644
index 00000000..75032831
--- /dev/null
+++ b/srcs/Internals/IndentedPrint.cpp
@@ -0,0 +1,45 @@
+#include "IndentedPrint.h"
+
+using namespace ArduinoJson::Generator;
+
+void IndentedPrint::indent()
+{
+ if (level < MAX_LEVEL)
+ level++;
+}
+
+void IndentedPrint::unindent()
+{
+ if (level > 0)
+ level--;
+}
+
+void IndentedPrint::setTabSize(uint8_t n)
+{
+ if (n < MAX_TAB_SIZE)
+ tabSize = n;
+}
+
+size_t IndentedPrint::write(uint8_t c)
+{
+ size_t n = 0;
+
+ if (isNewLine)
+ n += writeTabs();
+
+ n += sink.write(c);
+
+ isNewLine = c == '\n';
+
+ return n;
+}
+
+inline size_t IndentedPrint::writeTabs()
+{
+ size_t n = 0;
+
+ for (int i = 0; i < level*tabSize; i++)
+ n += sink.write(' ');
+
+ return n;
+}
\ No newline at end of file
diff --git a/srcs/Internals/IndentedPrint.h b/srcs/Internals/IndentedPrint.h
new file mode 100644
index 00000000..2f6f0500
--- /dev/null
+++ b/srcs/Internals/IndentedPrint.h
@@ -0,0 +1,53 @@
+/*
+* Arduino JSON library
+* Benoit Blanchon 2014 - MIT License
+*/
+
+#pragma once
+
+#include "../Arduino/Print.h"
+
+namespace ArduinoJson
+{
+ namespace Generator
+ {
+ // Decorator on top of Print to allow indented output.
+ // This class is used by JsonPrintable::prettyPrintTo() but can also be used
+ // for your own purpose, like logging.
+ class IndentedPrint : public Print
+ {
+ public:
+
+ IndentedPrint(Print& p)
+ : sink(p)
+ {
+ level = 0;
+ tabSize = 2;
+ isNewLine = true;
+ }
+
+ virtual size_t write(uint8_t);
+
+ // Adds one level of indentation
+ void indent();
+
+ // Removes one level of indentation
+ void unindent();
+
+ // Set the number of space printed for each level of indentation
+ void setTabSize(uint8_t n);
+
+ private:
+ Print& sink;
+ uint8_t level : 4;
+ uint8_t tabSize : 3;
+ bool isNewLine : 1;
+
+ size_t writeTabs();
+
+ static const int MAX_LEVEL = 15; // because it's only 4 bits
+ static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
+ };
+ }
+}
+
diff --git a/srcs/Internals/JsonNode.cpp b/srcs/Internals/JsonNode.cpp
index 004b8d17..f431c710 100644
--- a/srcs/Internals/JsonNode.cpp
+++ b/srcs/Internals/JsonNode.cpp
@@ -17,15 +17,15 @@ void JsonNode::writeTo(JsonWriter& writer)
break;
case JSON_STRING:
- writer.writeValue(content.asString);
+ writer.writeString(content.asString);
break;
case JSON_INTEGER:
- writer.writeValue(content.asInteger);
+ writer.writeInteger(content.asInteger);
break;
case JSON_BOOLEAN:
- writer.writeValue(content.asBoolean);
+ writer.writeBoolean(content.asBoolean);
break;
case JSON_PROXY:
@@ -33,40 +33,61 @@ void JsonNode::writeTo(JsonWriter& writer)
break;
default: // >= JSON_DOUBLE_0_DECIMALS
- writer.writeValue(content.asDouble, type - JSON_DOUBLE_0_DECIMALS);
+ writer.writeDouble(content.asDouble, type - JSON_DOUBLE_0_DECIMALS);
break;
}
}
void JsonNode::writeArrayTo(JsonWriter& writer)
{
- writer.beginArray();
-
JsonNode* child = content.asContainer.child;
-
- while(child)
+
+ if (child)
{
- child->writeTo(writer);
+ writer.beginArray();
- child = child->next;
+ while (true)
+ {
+ child->writeTo(writer);
+
+ child = child->next;
+ if (!child) break;
+
+ writer.writeComma();
+ }
+
+ writer.endArray();
+ }
+ else
+ {
+ writer.writeEmptyArray();
}
-
- writer.endArray();
}
void JsonNode::writeObjectTo(JsonWriter& writer)
{
- writer.beginObject();
-
JsonNode* child = content.asContainer.child;
- while (child)
+ if (child)
{
- writer.writeKey(child->content.asKey.key);
- child->content.asKey.value->writeTo(writer);
+ writer.beginObject();
- child = child->next;
+ while (true)
+ {
+ writer.writeString(child->content.asKey.key);
+ writer.writeColon();
+ child->content.asKey.value->writeTo(writer);
+
+ child = child->next;
+ if (!child) break;
+
+ writer.writeComma();
+ }
+
+ writer.endObject();
+ }
+ else
+ {
+ writer.writeEmptyObject();
}
-
- writer.endObject();
}
\ No newline at end of file
diff --git a/srcs/Internals/JsonWriter.cpp b/srcs/Internals/JsonWriter.cpp
index 536bda63..d59f067b 100644
--- a/srcs/Internals/JsonWriter.cpp
+++ b/srcs/Internals/JsonWriter.cpp
@@ -3,64 +3,23 @@
using namespace ArduinoJson::Internals;
-void JsonWriter::beginArray()
+void JsonWriter::writeString(char const* value)
{
- 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)
+void JsonWriter::writeInteger(long value)
{
- writeCommaIfNeeded();
+
_length += _sink.print(value);
- _isCommaNeeded = true;
}
-void JsonWriter::writeValue(bool value)
+void JsonWriter::writeBoolean(bool value)
{
- writeCommaIfNeeded();
_length += _sink.print(value ? "true" : "false");
- _isCommaNeeded = true;
}
-void JsonWriter::writeValue(double value, int decimals)
+void JsonWriter::writeDouble(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
index 7a65b3a2..5dfc6b5b 100644
--- a/srcs/Internals/JsonWriter.h
+++ b/srcs/Internals/JsonWriter.h
@@ -6,7 +6,7 @@ class JsonWriter
{
public:
explicit JsonWriter(Print& sink)
- : _sink(sink), _length(0), _isCommaNeeded(false)
+ : _sink(sink), _length(0)
{
}
@@ -15,28 +15,35 @@ public:
return _length;
}
- void beginArray();
- void endArray();
+ virtual void beginArray() = 0;
- void beginObject();
- void endObject();
+ virtual void endArray() = 0;
- void writeKey(const char* key);
+ virtual void beginObject() = 0;
- void writeValue(const char* value);
- void writeValue(long value);
- void writeValue(bool value);
- void writeValue(double value, int decimals);
+ virtual void endObject() = 0;
-private:
+ void writeString(const char* value);
+ void writeInteger(long value);
+ void writeBoolean(bool value);
+ void writeDouble(double value, int decimals);
+
+ virtual void writeColon() = 0;
+
+ virtual void writeComma() = 0;
+
+ void writeEmptyArray()
+ {
+ _length += _sink.print("[]");
+ }
+
+ void writeEmptyObject()
+ {
+ _length += _sink.print("{}");
+ }
+
+protected:
Print& _sink;
size_t _length;
- bool _isCommaNeeded;
-
- void writeCommaIfNeeded()
- {
- if (_isCommaNeeded)
- _length += _sink.write(',');
- }
};
diff --git a/srcs/Internals/PrettyJsonWriter.cpp b/srcs/Internals/PrettyJsonWriter.cpp
new file mode 100644
index 00000000..7965d675
--- /dev/null
+++ b/srcs/Internals/PrettyJsonWriter.cpp
@@ -0,0 +1 @@
+#include "PrettyJsonWriter.h"
diff --git a/srcs/Internals/PrettyJsonWriter.h b/srcs/Internals/PrettyJsonWriter.h
new file mode 100644
index 00000000..d4fe18c5
--- /dev/null
+++ b/srcs/Internals/PrettyJsonWriter.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "JsonWriter.h"
+#include "IndentedPrint.h"
+
+using namespace ArduinoJson::Generator;
+
+class PrettyJsonWriter : public JsonWriter
+{
+public:
+ explicit PrettyJsonWriter(IndentedPrint& sink)
+ : JsonWriter(sink), _indenter(sink)
+ {
+ }
+
+ virtual void beginArray()
+ {
+ _length += _sink.write('[');
+ _indenter.indent();
+ _length += _indenter.println();
+ }
+
+ virtual void endArray()
+ {
+ _length += _indenter.println();
+ _indenter.unindent();
+ _length += _sink.write(']');
+ }
+
+ virtual void writeColon()
+ {
+ _length += _sink.print(": ");
+ }
+
+ virtual void writeComma()
+ {
+ _length += _sink.write(',');
+ _length += _indenter.println();
+ }
+
+ virtual void beginObject()
+ {
+ _length += _sink.write('{');
+ }
+
+ virtual void endObject()
+ {
+ _length += _sink.write('}');
+ _indenter.unindent();
+ }
+
+private:
+ IndentedPrint& _indenter;
+};
diff --git a/srcs/JsonArray.cpp b/srcs/JsonArray.cpp
index 5286ce75..2c8aba1c 100644
--- a/srcs/JsonArray.cpp
+++ b/srcs/JsonArray.cpp
@@ -56,4 +56,17 @@ void JsonArray::add(JsonContainer& innerContainer)
node->content.asProxy.target = innerContainer._node;
addChild(node);
+}
+
+JsonArray JsonArray::createNestedArray()
+{
+ JsonNode* node = createNode(JSON_ARRAY);
+
+ if (node)
+ {
+ node->content.asContainer.buffer = _node->content.asContainer.buffer;
+ addChild(node);
+ }
+
+ return JsonArray(node);
}
\ No newline at end of file
diff --git a/srcs/JsonArray.h b/srcs/JsonArray.h
index 7d694a06..69b2675c 100644
--- a/srcs/JsonArray.h
+++ b/srcs/JsonArray.h
@@ -22,5 +22,7 @@ public:
void add(int value) { add((long) value); }
void add(long value);
void add(JsonContainer& innerContainer);
+
+ JsonArray createNestedArray();
};
diff --git a/srcs/JsonContainer.cpp b/srcs/JsonContainer.cpp
index 77628861..1e2462f2 100644
--- a/srcs/JsonContainer.cpp
+++ b/srcs/JsonContainer.cpp
@@ -1,24 +1,42 @@
#include "JsonContainer.h"
#include "JsonBuffer.h"
-#include "Internals/JsonWriter.h"
#include "Internals/StringBuilder.h"
+#include "Internals/CompactJsonWriter.h"
+#include "Internals/PrettyJsonWriter.h"
+
+using namespace ArduinoJson::Internals;
size_t JsonContainer::printTo(char* buffer, size_t bufferSize) const
{
- ArduinoJson::Internals::StringBuilder sb(buffer, bufferSize);
+ StringBuilder sb(buffer, bufferSize);
return printTo(sb);
}
size_t JsonContainer::printTo(Print& p) const
{
- JsonWriter writer(p);
+ CompactJsonWriter writer(p);
+ _node->writeTo(writer);
+ return writer.bytesWritten();
+}
+
+size_t JsonContainer::prettyPrintTo(char* buffer, size_t bufferSize) const
+{
+ StringBuilder sb(buffer, bufferSize);
+ return prettyPrintTo(sb);
+}
+
+size_t JsonContainer::prettyPrintTo(IndentedPrint& p) const
+{
+ PrettyJsonWriter writer(p);
_node->writeTo(writer);
return writer.bytesWritten();
}
JsonNode* JsonContainer::createNode(JsonNodeType type)
{
+ if (!_node) return 0;
+
JsonBuffer* buffer = _node->content.asContainer.buffer;
return buffer->createNode(type);
}
diff --git a/srcs/JsonContainer.h b/srcs/JsonContainer.h
index 5b4ac9d7..28bce5a5 100644
--- a/srcs/JsonContainer.h
+++ b/srcs/JsonContainer.h
@@ -3,6 +3,7 @@
#include "Arduino/Printable.h"
#include "Internals/JsonNodeIterator.h"
#include "Internals/JsonNode.h"
+#include "Internals/IndentedPrint.h"
struct JsonNode;
class JsonValue;
@@ -31,6 +32,13 @@ public:
size_t printTo(char* buffer, size_t bufferSize) const;
virtual size_t printTo(Print& print) const;
+ size_t prettyPrintTo(char* buffer, size_t bufferSize) const;
+ size_t prettyPrintTo(ArduinoJson::Generator::IndentedPrint& print) const;
+ size_t prettyPrintTo(Print& print) const
+ {
+ return prettyPrintTo(ArduinoJson::Generator::IndentedPrint(print));
+ }
+
protected:
JsonNodeIterator beginChildren() const
diff --git a/srcs/srcs.vcxproj b/srcs/srcs.vcxproj
index 36440c22..44dc01ff 100644
--- a/srcs/srcs.vcxproj
+++ b/srcs/srcs.vcxproj
@@ -74,7 +74,9 @@
+
+
@@ -85,11 +87,14 @@
+
+
+
@@ -99,6 +104,7 @@
+
diff --git a/srcs/srcs.vcxproj.filters b/srcs/srcs.vcxproj.filters
index 35f07402..f0fff5aa 100644
--- a/srcs/srcs.vcxproj.filters
+++ b/srcs/srcs.vcxproj.filters
@@ -54,6 +54,15 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
@@ -86,5 +95,14 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/tests/JsonArray_PrettyPrintTo_Tests.cpp b/tests/JsonArray_PrettyPrintTo_Tests.cpp
new file mode 100644
index 00000000..4debcf4b
--- /dev/null
+++ b/tests/JsonArray_PrettyPrintTo_Tests.cpp
@@ -0,0 +1,93 @@
+/*
+* Arduino JSON library
+* Benoit Blanchon 2014 - MIT License
+*/
+
+#include
+#include
+#include
+#include
+
+class JsonArray_PrettyPrintTo_Tests : public testing::Test
+{
+protected:
+ JsonArray array;
+ StaticJsonBuffer<30> json;
+
+ virtual void SetUp()
+ {
+ array = json.createArray();
+ }
+
+ void outputMustBe(const char* expected)
+ {
+ size_t n = array.prettyPrintTo(buffer, sizeof(buffer));
+ EXPECT_STREQ(expected, buffer);
+ EXPECT_EQ(strlen(expected), n);
+ }
+
+private:
+ char buffer[256];
+};
+
+TEST_F(JsonArray_PrettyPrintTo_Tests, Empty)
+{
+ outputMustBe("[]");
+}
+
+TEST_F(JsonArray_PrettyPrintTo_Tests, OneElement)
+{
+ array.add(1);
+
+ outputMustBe(
+ "[\r\n"
+ " 1\r\n"
+ "]");
+}
+
+TEST_F(JsonArray_PrettyPrintTo_Tests, TwoElements)
+{
+ array.add(1);
+ array.add(2);
+
+ outputMustBe(
+ "[\r\n"
+ " 1,\r\n"
+ " 2\r\n"
+ "]");
+}
+
+TEST_F(JsonArray_PrettyPrintTo_Tests, EmptyNestedArrays)
+{
+ array.createNestedArray();
+ array.createNestedArray();
+
+ outputMustBe(
+ "[\r\n"
+ " [],\r\n"
+ " []\r\n"
+ "]");
+}
+
+TEST_F(JsonArray_PrettyPrintTo_Tests, NestedArrays)
+{
+ JsonArray nested1 = array.createNestedArray();
+ nested1.add(1);
+ nested1.add(2);
+
+ JsonArray nested2 = array.createNestedArray();
+ nested2.add(3);
+ nested2.add(4);
+
+ outputMustBe(
+ "[\r\n"
+ " [\r\n"
+ " 1,\r\n"
+ " 2\r\n"
+ " ],\r\n"
+ " [\r\n"
+ " 3,\r\n"
+ " 4\r\n"
+ " ]\r\n"
+ "]");
+}
\ No newline at end of file
diff --git a/tests/JsonArray_Serialization_Tests.cpp b/tests/JsonArray_PrintTo_Tests.cpp
similarity index 62%
rename from tests/JsonArray_Serialization_Tests.cpp
rename to tests/JsonArray_PrintTo_Tests.cpp
index 13c0f4c3..71246ff3 100644
--- a/tests/JsonArray_Serialization_Tests.cpp
+++ b/tests/JsonArray_PrintTo_Tests.cpp
@@ -8,7 +8,7 @@
#include
#include
-class JsonArray_Serialization_Tests : public testing::Test
+class JsonArray_PrintTo_Tests : public testing::Test
{
protected:
JsonArray array;
@@ -30,26 +30,26 @@ private:
char buffer[256];
};
-TEST_F(JsonArray_Serialization_Tests, Empty)
+TEST_F(JsonArray_PrintTo_Tests, Empty)
{
outputMustBe("[]");
}
-TEST_F(JsonArray_Serialization_Tests, Null)
+TEST_F(JsonArray_PrintTo_Tests, Null)
{
array.add((char*) 0);
outputMustBe("[null]");
}
-TEST_F(JsonArray_Serialization_Tests, OneString)
+TEST_F(JsonArray_PrintTo_Tests, OneString)
{
array.add("hello");
outputMustBe("[\"hello\"]");
}
-TEST_F(JsonArray_Serialization_Tests, TwoStrings)
+TEST_F(JsonArray_PrintTo_Tests, TwoStrings)
{
array.add("hello");
array.add("world");
@@ -57,7 +57,7 @@ TEST_F(JsonArray_Serialization_Tests, TwoStrings)
outputMustBe("[\"hello\",\"world\"]");
}
-TEST_F(JsonArray_Serialization_Tests, OneStringOverCapacity)
+TEST_F(JsonArray_PrintTo_Tests, OneStringOverCapacity)
{
array.add("hello");
array.add("world");
@@ -66,26 +66,26 @@ TEST_F(JsonArray_Serialization_Tests, OneStringOverCapacity)
outputMustBe("[\"hello\",\"world\"]");
}
-TEST_F(JsonArray_Serialization_Tests, OneDoubleDefaultDigits)
+TEST_F(JsonArray_PrintTo_Tests, OneDoubleDefaultDigits)
{
array.add(3.14159265358979323846);
outputMustBe("[3.14]");
}
-TEST_F(JsonArray_Serialization_Tests, OneDoubleFourDigits)
+TEST_F(JsonArray_PrintTo_Tests, OneDoubleFourDigits)
{
array.add(3.14159265358979323846, 4);
outputMustBe("[3.1416]");
}
-TEST_F(JsonArray_Serialization_Tests, OneInteger)
+TEST_F(JsonArray_PrintTo_Tests, OneInteger)
{
array.add(1);
outputMustBe("[1]");
}
-TEST_F(JsonArray_Serialization_Tests, TwoIntegers)
+TEST_F(JsonArray_PrintTo_Tests, TwoIntegers)
{
array.add(1);
array.add(2);
@@ -93,7 +93,7 @@ TEST_F(JsonArray_Serialization_Tests, TwoIntegers)
outputMustBe("[1,2]");
}
-TEST_F(JsonArray_Serialization_Tests, OneIntegerOverCapacity)
+TEST_F(JsonArray_PrintTo_Tests, OneIntegerOverCapacity)
{
array.add(1);
array.add(2);
@@ -102,21 +102,21 @@ TEST_F(JsonArray_Serialization_Tests, OneIntegerOverCapacity)
outputMustBe("[1,2]");
}
-TEST_F(JsonArray_Serialization_Tests, OneTrue)
+TEST_F(JsonArray_PrintTo_Tests, OneTrue)
{
array.add(true);
outputMustBe("[true]");
}
-TEST_F(JsonArray_Serialization_Tests, OneFalse)
+TEST_F(JsonArray_PrintTo_Tests, OneFalse)
{
array.add(false);
outputMustBe("[false]");
}
-TEST_F(JsonArray_Serialization_Tests, TwoBooleans)
+TEST_F(JsonArray_PrintTo_Tests, TwoBooleans)
{
array.add(false);
array.add(true);
@@ -124,7 +124,7 @@ TEST_F(JsonArray_Serialization_Tests, TwoBooleans)
outputMustBe("[false,true]");
}
-TEST_F(JsonArray_Serialization_Tests, OneBooleanOverCapacity)
+TEST_F(JsonArray_PrintTo_Tests, OneBooleanOverCapacity)
{
array.add(false);
array.add(true);
@@ -133,7 +133,7 @@ TEST_F(JsonArray_Serialization_Tests, OneBooleanOverCapacity)
outputMustBe("[false,true]");
}
-TEST_F(JsonArray_Serialization_Tests, OneEmptyNestedArray)
+TEST_F(JsonArray_PrintTo_Tests, OneEmptyNestedArray)
{
JsonArray nestedArray = json.createArray();
@@ -142,7 +142,7 @@ TEST_F(JsonArray_Serialization_Tests, OneEmptyNestedArray)
outputMustBe("[[]]");
}
-TEST_F(JsonArray_Serialization_Tests, OneEmptyNestedHash)
+TEST_F(JsonArray_PrintTo_Tests, OneEmptyNestedHash)
{
JsonObject nestedObject = json.createObject();
diff --git a/tests/tests.vcxproj b/tests/tests.vcxproj
index d8a5b23e..1242bd17 100644
--- a/tests/tests.vcxproj
+++ b/tests/tests.vcxproj
@@ -87,7 +87,8 @@
-
+
+
diff --git a/tests/tests.vcxproj.filters b/tests/tests.vcxproj.filters
index 19a88c17..3b1e3201 100644
--- a/tests/tests.vcxproj.filters
+++ b/tests/tests.vcxproj.filters
@@ -36,9 +36,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -48,5 +45,11 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file