mirror of
https://github.com/eledio-devices/thirdparty-ArduinoJson.git
synced 2025-11-01 00:38:27 +01:00
166 lines
3.5 KiB
C++
166 lines
3.5 KiB
C++
// Copyright Benoit Blanchon 2014-2016
|
|
// MIT License
|
|
//
|
|
// Arduino JSON library
|
|
// https://github.com/bblanchon/ArduinoJson
|
|
// If you like this project, please add a star!
|
|
|
|
#pragma once
|
|
|
|
#include "../Polyfills/attributes.hpp"
|
|
#include "../Polyfills/math.hpp"
|
|
#include "../Polyfills/normalize.hpp"
|
|
#include "../Print.hpp"
|
|
#include "Encoding.hpp"
|
|
#include "JsonFloat.hpp"
|
|
#include "JsonInteger.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.
|
|
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);
|
|
}
|
|
}
|
|
|
|
void writeFloat(JsonFloat value, int digits = 2) {
|
|
if (Polyfills::isNaN(value)) return writeRaw("NaN");
|
|
|
|
if (value < 0.0) {
|
|
writeRaw('-');
|
|
value = -value;
|
|
}
|
|
|
|
if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
|
|
|
|
short powersOf10;
|
|
if (value > 1000 || value < 0.001) {
|
|
powersOf10 = Polyfills::normalize(value);
|
|
} else {
|
|
powersOf10 = 0;
|
|
}
|
|
|
|
// Extract the integer part of the value and print it
|
|
JsonUInt int_part = static_cast<JsonUInt>(value);
|
|
JsonFloat remainder = value - static_cast<JsonFloat>(int_part);
|
|
writeInteger(int_part);
|
|
|
|
// Print the decimal point, but only if there are digits beyond
|
|
if (digits > 0) {
|
|
writeRaw('.');
|
|
}
|
|
|
|
// Extract digits from the remainder one at a time
|
|
while (digits-- > 0) {
|
|
// Extract digit
|
|
remainder *= 10.0;
|
|
char currentDigit = char(remainder);
|
|
remainder -= static_cast<JsonFloat>(currentDigit);
|
|
|
|
// Round up last digit (so that print(1.999, 2) prints as "2.00")
|
|
if (digits == 0 && remainder >= 0.5) currentDigit++;
|
|
|
|
// Print
|
|
writeRaw(char('0' + currentDigit));
|
|
}
|
|
|
|
if (powersOf10 < 0) {
|
|
writeRaw("e-");
|
|
writeInteger(-powersOf10);
|
|
}
|
|
|
|
if (powersOf10 > 0) {
|
|
writeRaw('e');
|
|
writeInteger(powersOf10);
|
|
}
|
|
}
|
|
|
|
void writeInteger(JsonUInt value) {
|
|
char buffer[22];
|
|
|
|
uint8_t i = 0;
|
|
do {
|
|
buffer[i++] = static_cast<char>(value % 10 + '0');
|
|
value /= 10;
|
|
} while (value);
|
|
|
|
while (i > 0) {
|
|
writeRaw(buffer[--i]);
|
|
}
|
|
}
|
|
|
|
void writeRaw(const char *s) {
|
|
_length += _sink.print(s);
|
|
}
|
|
void writeRaw(char c) {
|
|
_length += _sink.write(c);
|
|
}
|
|
|
|
protected:
|
|
Print &_sink;
|
|
size_t _length;
|
|
|
|
private:
|
|
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
|
};
|
|
}
|
|
}
|