// ArduinoJson - arduinojson.org // Copyright Benoit Blanchon 2014-2018 // MIT License #pragma once #include #include "../Data/Encoding.hpp" #include "../Data/JsonInteger.hpp" #include "../Polyfills/attributes.hpp" #include "../Serialization/FloatParts.hpp" namespace ArduinoJson { namespace Internals { // Writes the JSON tokens to a Print implementation // This class is used by: // - JsonArray::writeTo() // - JsonObject::writeTo() // - JsonVariant::writeTo() // Its derived by PrettyJsonWriter that overrides some members to add // indentation. template class JsonWriter { public: explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} // Returns the number of bytes sent to the Print implementation. // This is very handy for implementations of printTo() that must return the // number of bytes written. size_t bytesWritten() const { return _length; } void beginArray() { writeRaw('['); } void endArray() { writeRaw(']'); } void beginObject() { writeRaw('{'); } void endObject() { writeRaw('}'); } void writeColon() { writeRaw(':'); } void writeComma() { writeRaw(','); } void writeBoolean(bool value) { writeRaw(value ? "true" : "false"); } void writeString(const char *value) { if (!value) { writeRaw("null"); } else { writeRaw('\"'); while (*value) writeChar(*value++); writeRaw('\"'); } } void writeChar(char c) { char specialChar = Encoding::escapeChar(c); if (specialChar) { writeRaw('\\'); writeRaw(specialChar); } else { writeRaw(c); } } template void writeFloat(TFloat value) { if (isNaN(value)) return writeRaw("NaN"); if (value < 0.0) { writeRaw('-'); value = -value; } if (isInfinity(value)) return writeRaw("Infinity"); FloatParts parts(value); writeInteger(parts.integral); if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces); if (parts.exponent < 0) { writeRaw("e-"); writeInteger(-parts.exponent); } if (parts.exponent > 0) { writeRaw('e'); writeInteger(parts.exponent); } } template void writeInteger(UInt value) { char buffer[22]; char *end = buffer + sizeof(buffer) - 1; char *ptr = end; *ptr = 0; do { *--ptr = char(value % 10 + '0'); value = UInt(value / 10); } while (value); writeRaw(ptr); } void writeDecimals(uint32_t value, int8_t width) { // buffer should be big enough for all digits, the dot and the null // terminator char buffer[16]; char *ptr = buffer + sizeof(buffer) - 1; // write the string in reverse order *ptr = 0; while (width--) { *--ptr = char(value % 10 + '0'); value /= 10; } *--ptr = '.'; // and dump it in the right order writeRaw(ptr); } void writeRaw(const char *s) { _length += _sink.print(s); } void writeRaw(char c) { _length += _sink.print(c); } protected: Print &_sink; size_t _length; private: JsonWriter &operator=(const JsonWriter &); // cannot be assigned }; } }