Added deserializeMsgPack() (issue #358)

This commit is contained in:
Benoit Blanchon
2018-04-10 17:43:27 +02:00
parent 923d3e8a84
commit cb723840d9
58 changed files with 1311 additions and 89 deletions

View File

@@ -1,22 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// A dummy Print implementation used in measureJson()
class DummyPrint {
public:
size_t print(char) {
return 1;
}
size_t print(const char* s) {
return strlen(s);
}
};
} // namespace Internals
} // namespace ArduinoJson

View File

@@ -1,35 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../StringTraits/StringTraits.hpp"
namespace ArduinoJson {
namespace Internals {
// A Print implementation that allows to write in a String
template <typename TString>
class DynamicStringBuilder {
public:
DynamicStringBuilder(TString &str) : _str(str) {}
size_t print(char c) {
StringTraits<TString>::append(_str, c);
return 1;
}
size_t print(const char *s) {
size_t initialLen = _str.length();
StringTraits<TString>::append(_str, s);
return _str.length() - initialLen;
}
private:
DynamicStringBuilder &operator=(const DynamicStringBuilder &);
TString &_str;
};
}
}

View File

@@ -1,89 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
#include "../Polyfills/math.hpp"
#include "../TypeTraits/FloatTraits.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename TFloat>
struct FloatParts {
uint32_t integral;
uint32_t decimal;
int16_t exponent;
int8_t decimalPlaces;
FloatParts(TFloat value) {
uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000;
decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6;
exponent = normalize(value);
integral = uint32_t(value);
// reduce number of decimal places by the number of integral places
for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) {
maxDecimalPart /= 10;
decimalPlaces--;
}
TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart);
decimal = uint32_t(remainder);
remainder = remainder - TFloat(decimal);
// rounding:
// increment by 1 if remainder >= 0.5
decimal += uint32_t(remainder * 2);
if (decimal >= maxDecimalPart) {
decimal = 0;
integral++;
if (exponent && integral >= 10) {
exponent++;
integral = 1;
}
}
// remove trailing zeros
while (decimal % 10 == 0 && decimalPlaces > 0) {
decimal /= 10;
decimalPlaces--;
}
}
static int16_t normalize(TFloat& value) {
typedef FloatTraits<TFloat> traits;
int16_t powersOf10 = 0;
int8_t index = sizeof(TFloat) == 8 ? 8 : 5;
int bit = 1 << index;
if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
for (; index >= 0; index--) {
if (value >= traits::positiveBinaryPowerOfTen(index)) {
value *= traits::negativeBinaryPowerOfTen(index);
powersOf10 = int16_t(powersOf10 + bit);
}
bit >>= 1;
}
}
if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
for (; index >= 0; index--) {
if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) {
value *= traits::positiveBinaryPowerOfTen(index);
powersOf10 = int16_t(powersOf10 - bit);
}
bit >>= 1;
}
}
return powersOf10;
}
};
}
}

View File

@@ -1,68 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// 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 print(char c) {
size_t n = 0;
if (isNewLine) n += writeTabs();
n += sink->print(c);
isNewLine = c == '\n';
return n;
}
size_t print(const char *s) {
// TODO: optimize
size_t n = 0;
while (*s) n += print(*s++);
return n;
}
// 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->print(' ');
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 Internals
} // namespace ArduinoJson

View File

@@ -1,199 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "DummyPrint.hpp"
#include "DynamicStringBuilder.hpp"
#include "IndentedPrint.hpp"
#include "JsonWriter.hpp"
#include "Prettyfier.hpp"
#include "StaticStringBuilder.hpp"
#if ARDUINOJSON_ENABLE_STD_STREAM
#include "StreamPrintAdapter.hpp"
#endif
namespace ArduinoJson {
class JsonArray;
class JsonObject;
class JsonVariant;
namespace Internals {
class JsonArraySubscript;
template <typename TKey>
class JsonObjectSubscript;
template <typename Writer>
class JsonSerializer {
public:
static void serialize(const JsonArray &, Writer &);
static void serialize(const JsonArraySubscript &, Writer &);
static void serialize(const JsonObject &, Writer &);
template <typename TKey>
static void serialize(const JsonObjectSubscript<TKey> &, Writer &);
static void serialize(const JsonVariant &, Writer &);
struct Visitor {
Visitor(Writer *writer) : _writer(writer) {}
void acceptFloat(JsonFloat value) {
_writer->writeFloat(value);
}
void acceptArray(const JsonArray &value) {
serialize(value, *_writer);
}
void acceptObject(const JsonObject &value) {
serialize(value, *_writer);
}
void acceptString(const char *value) {
_writer->writeString(value);
}
void acceptRawJson(const char *value) {
_writer->writeRaw(value);
}
void acceptNegativeInteger(JsonUInt value) {
_writer->writeRaw('-');
_writer->writeInteger(value);
}
void acceptPositiveInteger(JsonUInt value) {
_writer->writeInteger(value);
}
void acceptBoolean(bool value) {
_writer->writeBoolean(value);
}
void acceptUndefined() {}
Writer *_writer;
};
};
} // namespace Internals
template <typename TSource, typename TDestination>
typename Internals::EnableIf<!Internals::StringTraits<TDestination>::has_append,
size_t>::type
serializeJson(const TSource &source, TDestination &destination) {
Internals::JsonWriter<TDestination> writer(destination);
Internals::JsonSerializer<Internals::JsonWriter<TDestination> >::serialize(
source, writer);
return writer.bytesWritten();
}
#if ARDUINOJSON_ENABLE_STD_STREAM
template <typename TSource>
std::ostream &serializeJson(const TSource &source, std::ostream &os) {
Internals::StreamPrintAdapter adapter(os);
serializeJson(source, adapter);
return os;
}
#endif
template <typename TSource>
size_t serializeJson(const TSource &source, char *buffer, size_t bufferSize) {
Internals::StaticStringBuilder sb(buffer, bufferSize);
return serializeJson(source, sb);
}
template <typename TSource, size_t N>
size_t serializeJson(const TSource &source, char (&buffer)[N]) {
return serializeJson(source, buffer, N);
}
template <typename TSource, typename TDestination>
typename Internals::EnableIf<Internals::StringTraits<TDestination>::has_append,
size_t>::type
serializeJson(const TSource &source, TDestination &str) {
Internals::DynamicStringBuilder<TDestination> sb(str);
return serializeJson(source, sb);
}
template <typename TSource, typename TDestination>
size_t serializeJsonPretty(const TSource &source,
Internals::IndentedPrint<TDestination> &print) {
Internals::Prettyfier<TDestination> p(print);
return serializeJson(source, p);
}
template <typename TSource>
size_t serializeJsonPretty(const TSource &source, char *buffer,
size_t bufferSize) {
Internals::StaticStringBuilder sb(buffer, bufferSize);
return serializeJsonPretty(source, sb);
}
template <typename TSource, size_t N>
size_t serializeJsonPretty(const TSource &source, char (&buffer)[N]) {
return serializeJsonPretty(source, buffer, N);
}
template <typename TSource, typename TDestination>
typename Internals::EnableIf<!Internals::StringTraits<TDestination>::has_append,
size_t>::type
serializeJsonPretty(const TSource &source, TDestination &print) {
Internals::IndentedPrint<TDestination> indentedPrint(print);
return serializeJsonPretty(source, indentedPrint);
}
template <typename TSource, typename TDestination>
typename Internals::EnableIf<Internals::StringTraits<TDestination>::has_append,
size_t>::type
serializeJsonPretty(const TSource &source, TDestination &str) {
Internals::DynamicStringBuilder<TDestination> sb(str);
return serializeJsonPretty(source, sb);
}
template <typename TSource>
size_t measureJson(const TSource &source) {
Internals::DummyPrint dp;
return serializeJson(source, dp);
}
template <typename TSource>
size_t measureJsonPretty(const TSource &source) {
Internals::DummyPrint dp;
return serializeJsonPretty(source, dp);
}
#if ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream &operator<<(std::ostream &os, const JsonArray &source) {
serializeJson(source, os);
return os;
}
inline std::ostream &operator<<(std::ostream &os, const JsonObject &source) {
serializeJson(source, os);
return os;
}
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
serializeJson(source, os);
return os;
}
namespace Internals {
inline std::ostream &operator<<(std::ostream &os,
const JsonArraySubscript &source) {
serializeJson(source, os);
return os;
}
template <typename TKey>
inline std::ostream &operator<<(std::ostream &os,
const JsonObjectSubscript<TKey> &source) {
serializeJson(source, os);
return os;
}
} // namespace Internals
#endif
} // namespace ArduinoJson

View File

@@ -1,69 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../JsonArray.hpp"
#include "../JsonArraySubscript.hpp"
#include "../JsonObject.hpp"
#include "../JsonObjectSubscript.hpp"
#include "../JsonVariant.hpp"
#include "JsonSerializer.hpp"
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonArray& array, Writer& writer) {
writer.beginArray();
JsonArray::const_iterator it = array.begin();
while (it != array.end()) {
serialize(*it, writer);
++it;
if (it == array.end()) break;
writer.writeComma();
}
writer.endArray();
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonArraySubscript& arraySubscript, Writer& writer) {
serialize(arraySubscript.as<JsonVariant>(), writer);
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonObject& object, Writer& writer) {
writer.beginObject();
JsonObject::const_iterator it = object.begin();
while (it != object.end()) {
writer.writeString(it->key);
writer.writeColon();
serialize(it->value, writer);
++it;
if (it == object.end()) break;
writer.writeComma();
}
writer.endObject();
}
template <typename Writer>
template <typename TKey>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonObjectSubscript<TKey>& objectSubscript, Writer& writer) {
serialize(objectSubscript.template as<JsonVariant>(), writer);
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonVariant& variant, Writer& writer) {
variant.visit(Visitor(&writer));
}

View File

@@ -1,153 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// 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.
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

View File

@@ -1,133 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "IndentedPrint.hpp"
namespace ArduinoJson {
namespace Internals {
// Converts a compact JSON string into an indented one.
template <typename Print>
class Prettyfier {
public:
explicit Prettyfier(IndentedPrint<Print>& p) : _sink(p) {
_previousChar = 0;
_inString = false;
}
size_t print(char c) {
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c);
_previousChar = c;
return n;
}
size_t print(const char* s) {
// TODO: optimize
size_t n = 0;
while (*s) n += print(*s++);
return n;
}
private:
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
bool inEmptyBlock() {
return _previousChar == '{' || _previousChar == '[';
}
size_t handleStringChar(char c) {
bool isQuote = c == '"' && _previousChar != '\\';
if (isQuote) _inString = false;
return _sink.print(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 += _sink.print(c);
return n;
}
size_t writeBlockOpen(char c) {
size_t n = 0;
n += indentIfNeeded();
n += _sink.print(c);
return n;
}
size_t writeColon() {
size_t n = 0;
n += _sink.print(": ");
return n;
}
size_t writeComma() {
size_t n = 0;
n += _sink.print(",\r\n");
return n;
}
size_t writeQuoteOpen() {
_inString = true;
size_t n = 0;
n += indentIfNeeded();
n += _sink.print('"');
return n;
}
size_t writeNormalChar(char c) {
size_t n = 0;
n += indentIfNeeded();
n += _sink.print(c);
return n;
}
size_t indentIfNeeded() {
if (!inEmptyBlock()) return 0;
_sink.indent();
return _sink.print("\r\n");
}
size_t unindentIfNeeded() {
if (inEmptyBlock()) return 0;
_sink.unindent();
return _sink.print("\r\n");
}
char _previousChar;
IndentedPrint<Print>& _sink;
bool _inString;
};
}
}

View File

@@ -1,36 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// A Print implementation that allows to write in a char[]
class StaticStringBuilder {
public:
StaticStringBuilder(char *buf, size_t size) : end(buf + size - 1), p(buf) {
*p = '\0';
}
size_t print(char c) {
if (p >= end) return 0;
*p++ = c;
*p = '\0';
return 1;
}
size_t print(const char *s) {
char *begin = p;
while (p < end && *s) *p++ = *s++;
*p = '\0';
return size_t(p - begin);
}
private:
char *end;
char *p;
};
}
}

View File

@@ -1,39 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ostream>
namespace ArduinoJson {
namespace Internals {
class StreamPrintAdapter {
public:
explicit StreamPrintAdapter(std::ostream& os) : _os(os) {}
size_t print(char c) {
_os << c;
return 1;
}
size_t print(const char* s) {
_os << s;
return strlen(s);
}
private:
// cannot be assigned
StreamPrintAdapter& operator=(const StreamPrintAdapter&);
std::ostream& _os;
};
}
}
#endif // ARDUINOJSON_ENABLE_STD_STREAM