mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-26 08:47:31 +02:00
156 lines
3.2 KiB
C++
156 lines
3.2 KiB
C++
// ArduinoJson - arduinojson.org
|
|
// Copyright Benoit Blanchon 2014-2019
|
|
// MIT License
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#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 <typename Print>
|
|
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 <typename TFloat>
|
|
void writeFloat(TFloat value) {
|
|
if (isNaN(value)) return writeRaw("NaN");
|
|
|
|
if (value < 0.0) {
|
|
writeRaw('-');
|
|
value = -value;
|
|
}
|
|
|
|
if (isInfinity(value)) return writeRaw("Infinity");
|
|
|
|
FloatParts<TFloat> 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 <typename UInt>
|
|
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
|
|
};
|
|
} // namespace Internals
|
|
} // namespace ArduinoJson
|