mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Reduced the size of the pretty JSON serializer
This commit is contained in:
		| @@ -20,6 +20,8 @@ HEAD | |||||||
| * Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant` | * Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant` | ||||||
| * Added `JsonDocument::isNull()` | * Added `JsonDocument::isNull()` | ||||||
| * Added `JsonDocument::operator[]` | * Added `JsonDocument::operator[]` | ||||||
|  | * Added `ARDUINOJSON_TAB` to configure the indentation character | ||||||
|  | * Reduced the size of the pretty JSON serializer | ||||||
|  |  | ||||||
| > ### BREAKING CHANGES | > ### BREAKING CHANGES | ||||||
| >  | >  | ||||||
|   | |||||||
| @@ -39,13 +39,13 @@ void setup() { | |||||||
|   data.add(48.756080); |   data.add(48.756080); | ||||||
|   data.add(2.302038); |   data.add(2.302038); | ||||||
|  |  | ||||||
|   serializeJson(root, Serial); |   serializeJson(doc, Serial); | ||||||
|   // This prints: |   // This prints: | ||||||
|   // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} |   // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} | ||||||
|  |  | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|  |  | ||||||
|   serializeJsonPretty(root, Serial); |   serializeJsonPretty(doc, Serial); | ||||||
|   // This prints: |   // This prints: | ||||||
|   // { |   // { | ||||||
|   //   "sensor": "gps", |   //   "sensor": "gps", | ||||||
|   | |||||||
| @@ -79,7 +79,7 @@ void loop() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   Serial.print(F("Sending: ")); |   Serial.print(F("Sending: ")); | ||||||
|   serializeJson(root, Serial); |   serializeJson(doc, Serial); | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|  |  | ||||||
|   // Write response headers |   // Write response headers | ||||||
| @@ -89,7 +89,7 @@ void loop() { | |||||||
|   client.println(); |   client.println(); | ||||||
|  |  | ||||||
|   // Write JSON document |   // Write JSON document | ||||||
|   serializeJsonPretty(root, client); |   serializeJsonPretty(doc, client); | ||||||
|  |  | ||||||
|   // Disconnect |   // Disconnect | ||||||
|   client.stop(); |   client.stop(); | ||||||
|   | |||||||
| @@ -75,11 +75,11 @@ void loop() { | |||||||
|   Serial.print(remoteIp); |   Serial.print(remoteIp); | ||||||
|   Serial.print(F(" on port ")); |   Serial.print(F(" on port ")); | ||||||
|   Serial.println(remotePort); |   Serial.println(remotePort); | ||||||
|   serializeJson(root, Serial); |   serializeJson(doc, Serial); | ||||||
|  |  | ||||||
|   // Send UDP packet |   // Send UDP packet | ||||||
|   udp.beginPacket(remoteIp, remotePort); |   udp.beginPacket(remoteIp, remotePort); | ||||||
|   serializeJson(root, udp); |   serializeJson(doc, udp); | ||||||
|   udp.println(); |   udp.println(); | ||||||
|   udp.endPacket(); |   udp.endPacket(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -140,3 +140,7 @@ | |||||||
| #define ARDUINOJSON_LITTLE_ENDIAN 0 | #define ARDUINOJSON_LITTLE_ENDIAN 0 | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #ifndef ARDUINOJSON_TAB | ||||||
|  | #define ARDUINOJSON_TAB "  " | ||||||
|  | #endif | ||||||
|   | |||||||
| @@ -1,69 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { |  | ||||||
|  |  | ||||||
| // Decorator on top of Print to allow indented output. |  | ||||||
| // This class is used by serializeJsonPretty() but can also be used |  | ||||||
| // for your own purpose, like logging. |  | ||||||
| template <typename Print> |  | ||||||
| class IndentedPrint { |  | ||||||
|  public: |  | ||||||
|   explicit IndentedPrint(Print &p) : sink(&p) { |  | ||||||
|     level = 0; |  | ||||||
|     tabSize = 2; |  | ||||||
|     isNewLine = true; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t write(uint8_t c) { |  | ||||||
|     size_t n = 0; |  | ||||||
|     if (isNewLine) n += writeTabs(); |  | ||||||
|     n += sink->write(c); |  | ||||||
|     isNewLine = c == '\n'; |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t write(const uint8_t *s, size_t n) { |  | ||||||
|     // TODO: optimize |  | ||||||
|     size_t bytesWritten = 0; |  | ||||||
|     while (n > 0) { |  | ||||||
|       bytesWritten += write(*s++); |  | ||||||
|       n--; |  | ||||||
|     } |  | ||||||
|     return bytesWritten; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Adds one level of indentation |  | ||||||
|   void indent() { |  | ||||||
|     if (level < MAX_LEVEL) level++; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Removes one level of indentation |  | ||||||
|   void unindent() { |  | ||||||
|     if (level > 0) level--; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Set the number of space printed for each level of indentation |  | ||||||
|   void setTabSize(uint8_t n) { |  | ||||||
|     if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   Print *sink; |  | ||||||
|   uint8_t level : 4; |  | ||||||
|   uint8_t tabSize : 3; |  | ||||||
|   bool isNewLine : 1; |  | ||||||
|  |  | ||||||
|   size_t writeTabs() { |  | ||||||
|     size_t n = 0; |  | ||||||
|     for (int i = 0; i < level * tabSize; i++) n += sink->write(' '); |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   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 |  | ||||||
| }; |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE |  | ||||||
| @@ -7,21 +7,17 @@ | |||||||
| #include "../Misc/Visitable.hpp" | #include "../Misc/Visitable.hpp" | ||||||
| #include "../Serialization/measure.hpp" | #include "../Serialization/measure.hpp" | ||||||
| #include "../Serialization/serialize.hpp" | #include "../Serialization/serialize.hpp" | ||||||
| #include "JsonWriter.hpp" | #include "TextFormatter.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| template <typename TWriter> | template <typename TWriter> | ||||||
| class JsonSerializer { | class JsonSerializer { | ||||||
|  public: |  public: | ||||||
|   JsonSerializer(TWriter &writer) : _writer(writer) {} |   JsonSerializer(TWriter &writer) : _formatter(writer) {} | ||||||
|  |  | ||||||
|   void visitFloat(Float value) { |   FORCE_INLINE void visitArray(const CollectionData &array) { | ||||||
|     _writer.writeFloat(value); |     write('['); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void visitArray(const CollectionData &array) { |  | ||||||
|     _writer.beginArray(); |  | ||||||
|  |  | ||||||
|     VariantSlot *slot = array.head(); |     VariantSlot *slot = array.head(); | ||||||
|  |  | ||||||
| @@ -31,63 +27,74 @@ class JsonSerializer { | |||||||
|       slot = slot->next(); |       slot = slot->next(); | ||||||
|       if (slot == 0) break; |       if (slot == 0) break; | ||||||
|  |  | ||||||
|       _writer.writeComma(); |       write(','); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     _writer.endArray(); |     write(']'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void visitObject(const CollectionData &object) { |   void visitObject(const CollectionData &object) { | ||||||
|     _writer.beginObject(); |     write('{'); | ||||||
|  |  | ||||||
|     VariantSlot *slot = object.head(); |     VariantSlot *slot = object.head(); | ||||||
|  |  | ||||||
|     while (slot != 0) { |     while (slot != 0) { | ||||||
|       _writer.writeString(slot->key()); |       _formatter.writeString(slot->key()); | ||||||
|       _writer.writeColon(); |       write(':'); | ||||||
|       slot->data()->accept(*this); |       slot->data()->accept(*this); | ||||||
|  |  | ||||||
|       slot = slot->next(); |       slot = slot->next(); | ||||||
|       if (slot == 0) break; |       if (slot == 0) break; | ||||||
|  |  | ||||||
|       _writer.writeComma(); |       write(','); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     _writer.endObject(); |     write('}'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void visitFloat(Float value) { | ||||||
|  |     _formatter.writeFloat(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void visitString(const char *value) { |   void visitString(const char *value) { | ||||||
|     _writer.writeString(value); |     _formatter.writeString(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void visitRawJson(const char *data, size_t n) { |   void visitRawJson(const char *data, size_t n) { | ||||||
|     // TODO |     _formatter.writeRaw(data, n); | ||||||
|     for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void visitNegativeInteger(UInt value) { |   void visitNegativeInteger(UInt value) { | ||||||
|     _writer.writeRaw('-'); |     _formatter.writeNegativeInteger(value); | ||||||
|     _writer.writeInteger(value); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void visitPositiveInteger(UInt value) { |   void visitPositiveInteger(UInt value) { | ||||||
|     _writer.writeInteger(value); |     _formatter.writePositiveInteger(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void visitBoolean(bool value) { |   void visitBoolean(bool value) { | ||||||
|     _writer.writeBoolean(value); |     _formatter.writeBoolean(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void visitNull() { |   void visitNull() { | ||||||
|     _writer.writeRaw("null"); |     _formatter.writeRaw("null"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t bytesWritten() const { |   size_t bytesWritten() const { | ||||||
|     return _writer.bytesWritten(); |     return _formatter.bytesWritten(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void write(char c) { | ||||||
|  |     _formatter.writeRaw(c); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void write(const char *s) { | ||||||
|  |     _formatter.writeRaw(s); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   JsonWriter<TWriter> _writer; |   TextFormatter<TWriter> _formatter; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename TSource, typename TDestination> | template <typename TSource, typename TDestination> | ||||||
|   | |||||||
| @@ -4,37 +4,68 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Configuration.hpp" | ||||||
| #include "../Serialization/measure.hpp" | #include "../Serialization/measure.hpp" | ||||||
| #include "../Serialization/serialize.hpp" | #include "../Serialization/serialize.hpp" | ||||||
| #include "./IndentedPrint.hpp" | #include "JsonSerializer.hpp" | ||||||
| #include "./JsonSerializer.hpp" |  | ||||||
| #include "./Prettyfier.hpp" |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| template <typename TPrint> | template <typename TWriter> | ||||||
| class PrettyJsonSerializer_Base { | class PrettyJsonSerializer : public JsonSerializer<TWriter> { | ||||||
|  public: |   typedef JsonSerializer<TWriter> base; | ||||||
|   PrettyJsonSerializer_Base(TPrint &output) |  | ||||||
|       : _indentedPrint(output), _prettyfier(_indentedPrint) {} |  | ||||||
|  |  | ||||||
|  protected: |  | ||||||
|   IndentedPrint<TPrint> _indentedPrint; |  | ||||||
|   Prettyfier<TPrint> _prettyfier; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename TPrint> |  | ||||||
| class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>, |  | ||||||
|                              public JsonSerializer<Prettyfier<TPrint> > { |  | ||||||
|  public: |  public: | ||||||
|   PrettyJsonSerializer(TPrint &output) |   PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {} | ||||||
|       : PrettyJsonSerializer_Base<TPrint>(output), |  | ||||||
|         JsonSerializer<Prettyfier<TPrint> >( |   void visitArray(const CollectionData &array) { | ||||||
|             PrettyJsonSerializer_Base<TPrint>::_prettyfier) {} |     VariantSlot *slot = array.head(); | ||||||
|  |     if (!slot) return base::write("[]"); | ||||||
|  |  | ||||||
|  |     base::write("[\r\n"); | ||||||
|  |     _nesting++; | ||||||
|  |     while (slot != 0) { | ||||||
|  |       indent(); | ||||||
|  |       slot->data()->accept(*this); | ||||||
|  |  | ||||||
|  |       slot = slot->next(); | ||||||
|  |       base::write(slot ? ",\r\n" : "\r\n"); | ||||||
|  |     } | ||||||
|  |     _nesting--; | ||||||
|  |     indent(); | ||||||
|  |     base::write("]"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void visitObject(const CollectionData &object) { | ||||||
|  |     VariantSlot *slot = object.head(); | ||||||
|  |     if (!slot) return base::write("{}"); | ||||||
|  |  | ||||||
|  |     base::write("{\r\n"); | ||||||
|  |     _nesting++; | ||||||
|  |     while (slot != 0) { | ||||||
|  |       indent(); | ||||||
|  |       base::visitString(slot->key()); | ||||||
|  |       base::write(": "); | ||||||
|  |       slot->data()->accept(*this); | ||||||
|  |  | ||||||
|  |       slot = slot->next(); | ||||||
|  |       base::write(slot ? ",\r\n" : "\r\n"); | ||||||
|  |     } | ||||||
|  |     _nesting--; | ||||||
|  |     indent(); | ||||||
|  |     base::write("}"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   void indent() { | ||||||
|  |     for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   uint8_t _nesting; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename TSource, typename TDestination> | template <typename TSource, typename TDestination> | ||||||
| size_t serializeJsonPretty(TSource &source, TDestination &destination) { | size_t serializeJsonPretty(const TSource &source, TDestination &destination) { | ||||||
|   return serialize<PrettyJsonSerializer>(source, destination); |   return serialize<PrettyJsonSerializer>(source, destination); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,143 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include "IndentedPrint.hpp" |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { |  | ||||||
|  |  | ||||||
| // Converts a compact JSON string into an indented one. |  | ||||||
| template <typename TWriter> |  | ||||||
| class Prettyfier { |  | ||||||
|  public: |  | ||||||
|   explicit Prettyfier(IndentedPrint<TWriter>& p) : _sink(p) { |  | ||||||
|     _previousChar = 0; |  | ||||||
|     _inString = false; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t write(uint8_t c) { |  | ||||||
|     size_t n = _inString ? handleStringChar(c) : handleMarkupChar(char(c)); |  | ||||||
|     _previousChar = char(c); |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t write(const uint8_t* s, size_t n) { |  | ||||||
|     // TODO: optimize |  | ||||||
|     size_t bytesWritten = 0; |  | ||||||
|     while (n > 0) { |  | ||||||
|       bytesWritten += write(*s++); |  | ||||||
|       n--; |  | ||||||
|     } |  | ||||||
|     return bytesWritten; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   Prettyfier& operator=(const Prettyfier&);  // cannot be assigned |  | ||||||
|  |  | ||||||
|   bool inEmptyBlock() { |  | ||||||
|     return _previousChar == '{' || _previousChar == '['; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t handleStringChar(uint8_t c) { |  | ||||||
|     bool isQuote = c == '"' && _previousChar != '\\'; |  | ||||||
|  |  | ||||||
|     if (isQuote) _inString = false; |  | ||||||
|  |  | ||||||
|     return _sink.write(c); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t handleMarkupChar(char c) { |  | ||||||
|     switch (c) { |  | ||||||
|       case '{': |  | ||||||
|       case '[': |  | ||||||
|         return writeBlockOpen(c); |  | ||||||
|  |  | ||||||
|       case '}': |  | ||||||
|       case ']': |  | ||||||
|         return writeBlockClose(c); |  | ||||||
|  |  | ||||||
|       case ':': |  | ||||||
|         return writeColon(); |  | ||||||
|  |  | ||||||
|       case ',': |  | ||||||
|         return writeComma(); |  | ||||||
|  |  | ||||||
|       case '"': |  | ||||||
|         return writeQuoteOpen(); |  | ||||||
|  |  | ||||||
|       default: |  | ||||||
|         return writeNormalChar(c); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t writeBlockClose(char c) { |  | ||||||
|     size_t n = 0; |  | ||||||
|     n += unindentIfNeeded(); |  | ||||||
|     n += write(c); |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t writeBlockOpen(char c) { |  | ||||||
|     size_t n = 0; |  | ||||||
|     n += indentIfNeeded(); |  | ||||||
|     n += write(c); |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t writeColon() { |  | ||||||
|     size_t n = 0; |  | ||||||
|     n += write(": "); |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t writeComma() { |  | ||||||
|     size_t n = 0; |  | ||||||
|     n += write(",\r\n"); |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t writeQuoteOpen() { |  | ||||||
|     _inString = true; |  | ||||||
|     size_t n = 0; |  | ||||||
|     n += indentIfNeeded(); |  | ||||||
|     n += write('"'); |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t writeNormalChar(char c) { |  | ||||||
|     size_t n = 0; |  | ||||||
|     n += indentIfNeeded(); |  | ||||||
|     n += write(c); |  | ||||||
|     return n; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t indentIfNeeded() { |  | ||||||
|     if (!inEmptyBlock()) return 0; |  | ||||||
|  |  | ||||||
|     _sink.indent(); |  | ||||||
|     return write("\r\n"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t unindentIfNeeded() { |  | ||||||
|     if (inEmptyBlock()) return 0; |  | ||||||
|  |  | ||||||
|     _sink.unindent(); |  | ||||||
|     return write("\r\n"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t write(char c) { |  | ||||||
|     return _sink.write(static_cast<uint8_t>(c)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   template <size_t N> |  | ||||||
|   size_t write(const char (&s)[N]) { |  | ||||||
|     return _sink.write(reinterpret_cast<const uint8_t*>(s), N - 1); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   char _previousChar; |  | ||||||
|   IndentedPrint<TWriter>& _sink; |  | ||||||
|   bool _inString; |  | ||||||
| }; |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE |  | ||||||
| @@ -14,36 +14,15 @@ | |||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| template <typename TWriter> | template <typename TWriter> | ||||||
| class JsonWriter { | class TextFormatter { | ||||||
|  public: |  public: | ||||||
|   explicit JsonWriter(TWriter &writer) : _writer(writer), _length(0) {} |   explicit TextFormatter(TWriter &writer) : _writer(writer), _length(0) {} | ||||||
| 
 | 
 | ||||||
|   // Returns the number of bytes sent to the TWriter implementation.
 |   // Returns the number of bytes sent to the TWriter implementation.
 | ||||||
|   size_t bytesWritten() const { |   size_t bytesWritten() const { | ||||||
|     return _length; |     return _length; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void beginArray() { |  | ||||||
|     writeRaw('['); |  | ||||||
|   } |  | ||||||
|   void endArray() { |  | ||||||
|     writeRaw(']'); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void beginObject() { |  | ||||||
|     writeRaw('{'); |  | ||||||
|   } |  | ||||||
|   void endObject() { |  | ||||||
|     writeRaw('}'); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void writeColon() { |  | ||||||
|     writeRaw(':'); |  | ||||||
|   } |  | ||||||
|   void writeComma() { |  | ||||||
|     writeRaw(','); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void writeBoolean(bool value) { |   void writeBoolean(bool value) { | ||||||
|     if (value) |     if (value) | ||||||
|       writeRaw("true"); |       writeRaw("true"); | ||||||
| @@ -84,22 +63,27 @@ class JsonWriter { | |||||||
| 
 | 
 | ||||||
|     FloatParts<T> parts(value); |     FloatParts<T> parts(value); | ||||||
| 
 | 
 | ||||||
|     writeInteger(parts.integral); |     writePositiveInteger(parts.integral); | ||||||
|     if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces); |     if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces); | ||||||
| 
 | 
 | ||||||
|     if (parts.exponent < 0) { |     if (parts.exponent < 0) { | ||||||
|       writeRaw("e-"); |       writeRaw("e-"); | ||||||
|       writeInteger(-parts.exponent); |       writePositiveInteger(-parts.exponent); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (parts.exponent > 0) { |     if (parts.exponent > 0) { | ||||||
|       writeRaw('e'); |       writeRaw('e'); | ||||||
|       writeInteger(parts.exponent); |       writePositiveInteger(parts.exponent); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   void writeNegativeInteger(UInt value) { | ||||||
|  |     writeRaw('-'); | ||||||
|  |     writePositiveInteger(value); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   void writeInteger(T value) { |   void writePositiveInteger(T value) { | ||||||
|     char buffer[22]; |     char buffer[22]; | ||||||
|     char *end = buffer + sizeof(buffer); |     char *end = buffer + sizeof(buffer); | ||||||
|     char *begin = end; |     char *begin = end; | ||||||
| @@ -134,10 +118,16 @@ class JsonWriter { | |||||||
|   void writeRaw(const char *s) { |   void writeRaw(const char *s) { | ||||||
|     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s)); |     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s)); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   void writeRaw(const char *s, size_t n) { | ||||||
|  |     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), n); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   void writeRaw(const char *begin, const char *end) { |   void writeRaw(const char *begin, const char *end) { | ||||||
|     _length += _writer.write(reinterpret_cast<const uint8_t *>(begin), |     _length += _writer.write(reinterpret_cast<const uint8_t *>(begin), | ||||||
|                              static_cast<size_t>(end - begin)); |                              static_cast<size_t>(end - begin)); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   template <size_t N> |   template <size_t N> | ||||||
|   void writeRaw(const char (&s)[N]) { |   void writeRaw(const char (&s)[N]) { | ||||||
|     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1); |     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1); | ||||||
| @@ -151,6 +141,6 @@ class JsonWriter { | |||||||
|   size_t _length; |   size_t _length; | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|   JsonWriter &operator=(const JsonWriter &);  // cannot be assigned
 |   TextFormatter &operator=(const TextFormatter &);  // cannot be assigned
 | ||||||
| }; | }; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| @@ -78,7 +78,7 @@ add_subdirectory(JsonDocument) | |||||||
| add_subdirectory(JsonObject) | add_subdirectory(JsonObject) | ||||||
| add_subdirectory(JsonSerializer) | add_subdirectory(JsonSerializer) | ||||||
| add_subdirectory(JsonVariant) | add_subdirectory(JsonVariant) | ||||||
| add_subdirectory(JsonWriter) | add_subdirectory(TextFormatter) | ||||||
| add_subdirectory(MemoryPool) | add_subdirectory(MemoryPool) | ||||||
| add_subdirectory(Misc) | add_subdirectory(Misc) | ||||||
| add_subdirectory(MixedConfiguration) | add_subdirectory(MixedConfiguration) | ||||||
|   | |||||||
| @@ -8,4 +8,4 @@ add_executable(JsonWriterTests | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(JsonWriterTests catch) | target_link_libraries(JsonWriterTests catch) | ||||||
| add_test(JsonWriter JsonWriterTests) | add_test(TextFormatter JsonWriterTests) | ||||||
| @@ -6,7 +6,7 @@ | |||||||
| #include <limits> | #include <limits> | ||||||
| #include <string> | #include <string> | ||||||
| 
 | 
 | ||||||
| #include <ArduinoJson/Json/JsonWriter.hpp> | #include <ArduinoJson/Json/TextFormatter.hpp> | ||||||
| #include <ArduinoJson/Serialization/DynamicStringWriter.hpp> | #include <ArduinoJson/Serialization/DynamicStringWriter.hpp> | ||||||
| 
 | 
 | ||||||
| using namespace ARDUINOJSON_NAMESPACE; | using namespace ARDUINOJSON_NAMESPACE; | ||||||
| @@ -15,13 +15,13 @@ template <typename TFloat> | |||||||
| void check(TFloat input, const std::string& expected) { | void check(TFloat input, const std::string& expected) { | ||||||
|   std::string output; |   std::string output; | ||||||
|   DynamicStringWriter<std::string> sb(output); |   DynamicStringWriter<std::string> sb(output); | ||||||
|   JsonWriter<DynamicStringWriter<std::string> > writer(sb); |   TextFormatter<DynamicStringWriter<std::string> > writer(sb); | ||||||
|   writer.writeFloat(input); |   writer.writeFloat(input); | ||||||
|   REQUIRE(writer.bytesWritten() == output.size()); |   REQUIRE(writer.bytesWritten() == output.size()); | ||||||
|   CHECK(expected == output); |   CHECK(expected == output); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("JsonWriter::writeFloat(double)") { | TEST_CASE("TextFormatter::writeFloat(double)") { | ||||||
|   SECTION("Pi") { |   SECTION("Pi") { | ||||||
|     check<double>(3.14159265359, "3.141592654"); |     check<double>(3.14159265359, "3.141592654"); | ||||||
|   } |   } | ||||||
| @@ -102,7 +102,7 @@ TEST_CASE("JsonWriter::writeFloat(double)") { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("JsonWriter::writeFloat(float)") { | TEST_CASE("TextFormatter::writeFloat(float)") { | ||||||
|   SECTION("Pi") { |   SECTION("Pi") { | ||||||
|     check<float>(3.14159265359f, "3.141593"); |     check<float>(3.14159265359f, "3.141593"); | ||||||
|   } |   } | ||||||
| @@ -4,7 +4,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
| 
 | 
 | ||||||
| #include <ArduinoJson/Json/JsonWriter.hpp> | #include <ArduinoJson/Json/TextFormatter.hpp> | ||||||
| #include <ArduinoJson/Serialization/StaticStringWriter.hpp> | #include <ArduinoJson/Serialization/StaticStringWriter.hpp> | ||||||
| 
 | 
 | ||||||
| using namespace ARDUINOJSON_NAMESPACE; | using namespace ARDUINOJSON_NAMESPACE; | ||||||
| @@ -12,13 +12,13 @@ using namespace ARDUINOJSON_NAMESPACE; | |||||||
| void check(const char* input, std::string expected) { | void check(const char* input, std::string expected) { | ||||||
|   char output[1024]; |   char output[1024]; | ||||||
|   StaticStringWriter sb(output, sizeof(output)); |   StaticStringWriter sb(output, sizeof(output)); | ||||||
|   JsonWriter<StaticStringWriter> writer(sb); |   TextFormatter<StaticStringWriter> writer(sb); | ||||||
|   writer.writeString(input); |   writer.writeString(input); | ||||||
|   REQUIRE(expected == output); |   REQUIRE(expected == output); | ||||||
|   REQUIRE(writer.bytesWritten() == expected.size()); |   REQUIRE(writer.bytesWritten() == expected.size()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("JsonWriter::writeString()") { | TEST_CASE("TextFormatter::writeString()") { | ||||||
|   SECTION("Null") { |   SECTION("Null") { | ||||||
|     check(0, "null"); |     check(0, "null"); | ||||||
|   } |   } | ||||||
		Reference in New Issue
	
	Block a user