forked from bblanchon/ArduinoJson
Added support for non zero-terminated strings (fixes #704)
This commit is contained in:
@ -31,7 +31,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: SCRIPT=cmake GCC=5 SANITIZE=undefined
|
||||
env: SCRIPT=cmake GCC=5 # SANITIZE=undefined
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
|
@ -12,6 +12,7 @@ HEAD
|
||||
* Added `measureJson()` and `measureJsonPretty()`
|
||||
* Added `deserializeMsgPack()` (issue #358)
|
||||
* Added example `MsgPackParser.ino` (issue #358)
|
||||
* Added support for non zero-terminated strings (issue #704)
|
||||
* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()`
|
||||
* Removed `JsonBuffer::createArray()` and `createObject()`
|
||||
* Removed `printTo()` and `prettyPrintTo()`
|
||||
|
@ -5,12 +5,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
||||
#include "ArduinoJson/StaticJsonDocument.hpp"
|
||||
#include "ArduinoJson/deserializeJson.hpp"
|
||||
#include "ArduinoJson/deserializeMsgPack.hpp"
|
||||
|
||||
#include "ArduinoJson/Json/Deserialization/JsonDeserializer.hpp"
|
||||
#include "ArduinoJson/Json/Serialization/JsonSerializer.hpp"
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
|
@ -1,61 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TInput>
|
||||
void skipSpacesAndComments(TInput& input) {
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
input.move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
switch (input.next()) {
|
||||
// C-style block comment
|
||||
case '*':
|
||||
input.move(); // skip '/'
|
||||
// no need to skip '*'
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '*' && input.next() == '/') {
|
||||
input.move(); // skip '*'
|
||||
input.move(); // skip '/'
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// C++-style line comment
|
||||
case '/':
|
||||
// not need to skip "//"
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '\n') break;
|
||||
}
|
||||
break;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,10 +7,9 @@
|
||||
#include "../../JsonError.hpp"
|
||||
#include "../../JsonVariant.hpp"
|
||||
#include "../../Memory/JsonBuffer.hpp"
|
||||
#include "../../Strings/StringWriter.hpp"
|
||||
#include "../../Reading/Reader.hpp"
|
||||
#include "../../TypeTraits/IsConst.hpp"
|
||||
#include "../Encoding.hpp"
|
||||
#include "./Comments.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
@ -23,11 +22,13 @@ class JsonDeserializer {
|
||||
: _buffer(buffer),
|
||||
_reader(reader),
|
||||
_writer(writer),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
_nestingLimit(nestingLimit),
|
||||
_loaded(false) {}
|
||||
JsonError parse(JsonVariant &variant) {
|
||||
skipSpacesAndComments(_reader);
|
||||
JsonError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
switch (_reader.current()) {
|
||||
switch (current()) {
|
||||
case '[':
|
||||
return parseArray(variant);
|
||||
|
||||
@ -42,15 +43,25 @@ class JsonDeserializer {
|
||||
private:
|
||||
JsonDeserializer &operator=(const JsonDeserializer &); // non-copiable
|
||||
|
||||
static bool eat(TReader &reader, char charToSkip) {
|
||||
skipSpacesAndComments(reader);
|
||||
if (reader.current() != charToSkip) return false;
|
||||
reader.move();
|
||||
return true;
|
||||
char current() {
|
||||
if (!_loaded) {
|
||||
if (_reader.ended())
|
||||
_current = 0;
|
||||
else
|
||||
_current = _reader.read();
|
||||
_loaded = true;
|
||||
}
|
||||
return _current;
|
||||
}
|
||||
|
||||
void move() {
|
||||
_loaded = false;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool eat(char charToSkip) {
|
||||
return eat(_reader, charToSkip);
|
||||
if (current() != charToSkip) return false;
|
||||
move();
|
||||
return true;
|
||||
}
|
||||
|
||||
JsonError parseArray(JsonVariant &variant) {
|
||||
@ -62,6 +73,12 @@ class JsonDeserializer {
|
||||
|
||||
// Check opening braket
|
||||
if (!eat('[')) return JsonError::InvalidInput;
|
||||
|
||||
// Skip spaces
|
||||
JsonError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// Empty array?
|
||||
if (eat(']')) return JsonError::Ok;
|
||||
|
||||
// Read each value
|
||||
@ -69,12 +86,16 @@ class JsonDeserializer {
|
||||
// 1 - Parse value
|
||||
JsonVariant value;
|
||||
_nestingLimit--;
|
||||
JsonError error = parse(value);
|
||||
err = parse(value);
|
||||
_nestingLimit++;
|
||||
if (error != JsonError::Ok) return error;
|
||||
if (err) return err;
|
||||
if (!array->add(value)) return JsonError::NoMemory;
|
||||
|
||||
// 2 - More values?
|
||||
// 2 - Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// 3 - More values?
|
||||
if (eat(']')) return JsonError::Ok;
|
||||
if (!eat(',')) return JsonError::InvalidInput;
|
||||
}
|
||||
@ -89,31 +110,52 @@ class JsonDeserializer {
|
||||
|
||||
// Check opening brace
|
||||
if (!eat('{')) return JsonError::InvalidInput;
|
||||
|
||||
// Skip spaces
|
||||
JsonError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// Empty object?
|
||||
if (eat('}')) return JsonError::Ok;
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// 1 - Parse key
|
||||
// Parse key
|
||||
const char *key;
|
||||
JsonError error = parseString(&key);
|
||||
if (error) return error;
|
||||
err = parseString(&key);
|
||||
if (err) return err;
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// Colon
|
||||
if (!eat(':')) return JsonError::InvalidInput;
|
||||
|
||||
// 2 - Parse value
|
||||
// Parse value
|
||||
JsonVariant value;
|
||||
_nestingLimit--;
|
||||
error = parse(value);
|
||||
err = parse(value);
|
||||
_nestingLimit++;
|
||||
if (error != JsonError::Ok) return error;
|
||||
if (err) return err;
|
||||
if (!object->set(key, value)) return JsonError::NoMemory;
|
||||
|
||||
// 3 - More keys/values?
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// More keys/values?
|
||||
if (eat('}')) return JsonError::Ok;
|
||||
if (!eat(',')) return JsonError::InvalidInput;
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
}
|
||||
}
|
||||
|
||||
JsonError parseValue(JsonVariant &variant) {
|
||||
bool hasQuotes = isQuote(_reader.current());
|
||||
bool hasQuotes = isQuote(current());
|
||||
const char *value;
|
||||
JsonError error = parseString(&value);
|
||||
if (error) return error;
|
||||
@ -128,33 +170,35 @@ class JsonDeserializer {
|
||||
JsonError parseString(const char **result) {
|
||||
typename RemoveReference<TWriter>::type::String str = _writer.startString();
|
||||
|
||||
skipSpacesAndComments(_reader);
|
||||
char c = _reader.current();
|
||||
char c = current();
|
||||
if (c == '\0') return JsonError::IncompleteInput;
|
||||
|
||||
if (isQuote(c)) { // quotes
|
||||
_reader.move();
|
||||
move();
|
||||
char stopChar = c;
|
||||
for (;;) {
|
||||
c = _reader.current();
|
||||
if (c == '\0') break;
|
||||
_reader.move();
|
||||
|
||||
c = current();
|
||||
move();
|
||||
if (c == stopChar) break;
|
||||
|
||||
if (c == '\0') return JsonError::IncompleteInput;
|
||||
|
||||
if (c == '\\') {
|
||||
c = current();
|
||||
if (c == 0) return JsonError::IncompleteInput;
|
||||
// replace char
|
||||
c = Encoding::unescapeChar(_reader.current());
|
||||
c = Encoding::unescapeChar(c);
|
||||
if (c == '\0') return JsonError::InvalidInput;
|
||||
_reader.move();
|
||||
move();
|
||||
}
|
||||
|
||||
str.append(c);
|
||||
}
|
||||
} else if (canBeInNonQuotedString(c)) { // no quotes
|
||||
do {
|
||||
_reader.move();
|
||||
move();
|
||||
str.append(c);
|
||||
c = _reader.current();
|
||||
c = current();
|
||||
} while (canBeInNonQuotedString(c));
|
||||
} else {
|
||||
return JsonError::InvalidInput;
|
||||
@ -178,40 +222,79 @@ class JsonDeserializer {
|
||||
return c == '\'' || c == '\"';
|
||||
}
|
||||
|
||||
JsonError skipSpacesAndComments() {
|
||||
for (;;) {
|
||||
switch (current()) {
|
||||
// end of string
|
||||
case '\0':
|
||||
return JsonError::IncompleteInput;
|
||||
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
move(); // skip '/'
|
||||
switch (current()) {
|
||||
// block comment
|
||||
case '*': {
|
||||
move(); // skip '*'
|
||||
bool wasStar = false;
|
||||
for (;;) {
|
||||
char c = current();
|
||||
if (c == '\0') return JsonError::IncompleteInput;
|
||||
if (c == '/' && wasStar) {
|
||||
move();
|
||||
break;
|
||||
}
|
||||
wasStar = c == '*';
|
||||
move();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// trailing comment
|
||||
case '/':
|
||||
// no need to skip "//"
|
||||
for (;;) {
|
||||
move();
|
||||
char c = current();
|
||||
if (c == '\0') return JsonError::IncompleteInput;
|
||||
if (c == '\n') break;
|
||||
}
|
||||
break;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return JsonError::InvalidInput;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return JsonError::Ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
TReader _reader;
|
||||
TWriter _writer;
|
||||
uint8_t _nestingLimit;
|
||||
char _current;
|
||||
bool _loaded;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString, typename Enable = void>
|
||||
struct JsonParserBuilder {
|
||||
typedef typename StringTraits<TString>::Reader InputReader;
|
||||
typedef JsonDeserializer<InputReader, TJsonBuffer &> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TString &json,
|
||||
template <typename TJsonBuffer, typename TReader, typename TWriter>
|
||||
JsonDeserializer<TReader, TWriter> makeJsonDeserializer(TJsonBuffer *buffer,
|
||||
TReader reader,
|
||||
TWriter writer,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct JsonParserBuilder<TJsonBuffer, TChar *,
|
||||
typename EnableIf<!IsConst<TChar>::value>::type> {
|
||||
typedef typename StringTraits<TChar *>::Reader TReader;
|
||||
typedef StringWriter<TChar> TWriter;
|
||||
typedef JsonDeserializer<TReader, TWriter> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString>
|
||||
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
|
||||
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
|
||||
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
|
||||
return JsonDeserializer<TReader, TWriter>(buffer, reader, writer,
|
||||
nestingLimit);
|
||||
}
|
||||
} // namespace Internals
|
||||
|
@ -4,11 +4,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonError {
|
||||
public:
|
||||
enum Code { Ok, TooDeep, NoMemory, InvalidInput };
|
||||
enum Code { Ok, TooDeep, NoMemory, InvalidInput, IncompleteInput };
|
||||
|
||||
JsonError(Code code) : _code(code) {}
|
||||
|
||||
@ -42,6 +46,8 @@ class JsonError {
|
||||
return "NoMemory";
|
||||
case InvalidInput:
|
||||
return "InvalidInput";
|
||||
case IncompleteInput:
|
||||
return "IncompleteInput";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
|
@ -6,8 +6,9 @@
|
||||
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Strings/StringWriter.hpp"
|
||||
#include "../Reading/Reader.hpp"
|
||||
#include "../TypeTraits/IsConst.hpp"
|
||||
#include "../Writing/Writer.hpp"
|
||||
#include "./MsgPackError.hpp"
|
||||
#include "./endianess.hpp"
|
||||
#include "./ieee754.hpp"
|
||||
@ -29,27 +30,28 @@ class MsgPackDeserializer {
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
MsgPackError parse(JsonVariant &variant) {
|
||||
uint8_t c = readOne();
|
||||
uint8_t code;
|
||||
if (!readByte(code)) return MsgPackError::IncompleteInput;
|
||||
|
||||
if ((c & 0x80) == 0) {
|
||||
variant = c;
|
||||
if ((code & 0x80) == 0) {
|
||||
variant = code;
|
||||
return MsgPackError::Ok;
|
||||
}
|
||||
|
||||
if ((c & 0xe0) == 0xe0) {
|
||||
variant = static_cast<int8_t>(c);
|
||||
if ((code & 0xe0) == 0xe0) {
|
||||
variant = static_cast<int8_t>(code);
|
||||
return MsgPackError::Ok;
|
||||
}
|
||||
|
||||
if ((c & 0xe0) == 0xa0) {
|
||||
return readString(variant, c & 0x1f);
|
||||
if ((code & 0xe0) == 0xa0) {
|
||||
return readString(variant, code & 0x1f);
|
||||
}
|
||||
|
||||
if ((c & 0xf0) == 0x90) return readArray(variant, c & 0x0F);
|
||||
if ((code & 0xf0) == 0x90) return readArray(variant, code & 0x0F);
|
||||
|
||||
if ((c & 0xf0) == 0x80) return readObject(variant, c & 0x0F);
|
||||
if ((code & 0xf0) == 0x80) return readObject(variant, code & 0x0F);
|
||||
|
||||
switch (c) {
|
||||
switch (code) {
|
||||
case 0xc0:
|
||||
variant = static_cast<char *>(0);
|
||||
return MsgPackError::Ok;
|
||||
@ -63,81 +65,65 @@ class MsgPackDeserializer {
|
||||
return MsgPackError::Ok;
|
||||
|
||||
case 0xcc:
|
||||
variant = readInteger<uint8_t>();
|
||||
return MsgPackError::Ok;
|
||||
return readInteger<uint8_t>(variant);
|
||||
|
||||
case 0xcd:
|
||||
variant = readInteger<uint16_t>();
|
||||
return MsgPackError::Ok;
|
||||
return readInteger<uint16_t>(variant);
|
||||
|
||||
case 0xce:
|
||||
variant = readInteger<uint32_t>();
|
||||
return MsgPackError::Ok;
|
||||
return readInteger<uint32_t>(variant);
|
||||
|
||||
case 0xcf:
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
variant = readInteger<uint64_t>();
|
||||
return readInteger<uint64_t>(variant);
|
||||
#else
|
||||
readInteger<uint32_t>();
|
||||
variant = readInteger<uint32_t>();
|
||||
return readInteger<uint32_t>(variant);
|
||||
#endif
|
||||
return MsgPackError::Ok;
|
||||
|
||||
case 0xd0:
|
||||
variant = readInteger<int8_t>();
|
||||
return MsgPackError::Ok;
|
||||
return readInteger<int8_t>(variant);
|
||||
|
||||
case 0xd1:
|
||||
variant = readInteger<int16_t>();
|
||||
return MsgPackError::Ok;
|
||||
return readInteger<int16_t>(variant);
|
||||
|
||||
case 0xd2:
|
||||
variant = readInteger<int32_t>();
|
||||
return MsgPackError::Ok;
|
||||
return readInteger<int32_t>(variant);
|
||||
|
||||
case 0xd3:
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
variant = readInteger<int64_t>();
|
||||
return readInteger<int64_t>(variant);
|
||||
#else
|
||||
readInteger<int32_t>();
|
||||
variant = readInteger<int32_t>();
|
||||
if (!skip(4)) return MsgPackError::IncompleteInput;
|
||||
return readInteger<int32_t>(variant);
|
||||
#endif
|
||||
return MsgPackError::Ok;
|
||||
|
||||
case 0xca:
|
||||
variant = readFloat<float>();
|
||||
return MsgPackError::Ok;
|
||||
return readFloat<float>(variant);
|
||||
|
||||
case 0xcb:
|
||||
variant = readDouble<double>();
|
||||
return MsgPackError::Ok;
|
||||
return readDouble<double>(variant);
|
||||
|
||||
case 0xd9: {
|
||||
uint8_t n = readInteger<uint8_t>();
|
||||
return readString(variant, n);
|
||||
}
|
||||
case 0xd9:
|
||||
return readString<uint8_t>(variant);
|
||||
|
||||
case 0xda: {
|
||||
uint16_t n = readInteger<uint16_t>();
|
||||
return readString(variant, n);
|
||||
}
|
||||
case 0xda:
|
||||
return readString<uint16_t>(variant);
|
||||
|
||||
case 0xdb: {
|
||||
uint32_t n = readInteger<uint32_t>();
|
||||
return readString(variant, n);
|
||||
}
|
||||
case 0xdb:
|
||||
return readString<uint32_t>(variant);
|
||||
|
||||
case 0xdc:
|
||||
return readArray(variant, readInteger<uint16_t>());
|
||||
return readArray<uint16_t>(variant);
|
||||
|
||||
case 0xdd:
|
||||
return readArray(variant, readInteger<uint32_t>());
|
||||
return readArray<uint32_t>(variant);
|
||||
|
||||
case 0xde:
|
||||
return readObject(variant, readInteger<uint16_t>());
|
||||
return readObject<uint16_t>(variant);
|
||||
|
||||
case 0xdf:
|
||||
return readObject(variant, readInteger<uint32_t>());
|
||||
return readObject<uint32_t>(variant);
|
||||
|
||||
default:
|
||||
return MsgPackError::NotSupported;
|
||||
@ -148,65 +134,115 @@ class MsgPackDeserializer {
|
||||
// Prevent VS warning "assignment operator could not be generated"
|
||||
MsgPackDeserializer &operator=(const MsgPackDeserializer &);
|
||||
|
||||
uint8_t readOne() {
|
||||
char c = _reader.current();
|
||||
_reader.move();
|
||||
return static_cast<uint8_t>(c);
|
||||
bool skip(uint8_t n) {
|
||||
while (n--) {
|
||||
if (_reader.ended()) return false;
|
||||
_reader.read();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void read(uint8_t *p, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) p[i] = readOne();
|
||||
bool readByte(uint8_t &value) {
|
||||
if (_reader.ended()) return false;
|
||||
value = static_cast<uint8_t>(_reader.read());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readBytes(uint8_t *p, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (!readByte(p[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read(T &value) {
|
||||
read(reinterpret_cast<uint8_t *>(&value), sizeof(value));
|
||||
bool readBytes(T &value) {
|
||||
return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T readInteger() {
|
||||
T value;
|
||||
read(value);
|
||||
readBytes(value);
|
||||
fixEndianess(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename EnableIf<sizeof(T) == 4, T>::type readFloat() {
|
||||
bool readInteger(T &value) {
|
||||
if (!readBytes(value)) return false;
|
||||
fixEndianess(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MsgPackError readInteger(JsonVariant &variant) {
|
||||
T value;
|
||||
read(value);
|
||||
fixEndianess(value);
|
||||
return value;
|
||||
if (!readInteger(value)) return MsgPackError::IncompleteInput;
|
||||
variant = value;
|
||||
return MsgPackError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename EnableIf<sizeof(T) == 8, T>::type readDouble() {
|
||||
typename EnableIf<sizeof(T) == 4, MsgPackError>::type readFloat(
|
||||
JsonVariant &variant) {
|
||||
T value;
|
||||
read(value);
|
||||
if (!readBytes(value)) return MsgPackError::IncompleteInput;
|
||||
fixEndianess(value);
|
||||
return value;
|
||||
variant = value;
|
||||
return MsgPackError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename EnableIf<sizeof(T) == 4, T>::type readDouble() {
|
||||
typename EnableIf<sizeof(T) == 8, MsgPackError>::type readDouble(
|
||||
JsonVariant &variant) {
|
||||
T value;
|
||||
if (!readBytes(value)) return MsgPackError::IncompleteInput;
|
||||
fixEndianess(value);
|
||||
variant = value;
|
||||
return MsgPackError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename EnableIf<sizeof(T) == 4, MsgPackError>::type readDouble(
|
||||
JsonVariant &variant) {
|
||||
uint8_t i[8]; // input is 8 bytes
|
||||
T value; // output is 4 bytes
|
||||
uint8_t *o = reinterpret_cast<uint8_t *>(&value);
|
||||
read(i, 8);
|
||||
if (!readBytes(i, 8)) return MsgPackError::IncompleteInput;
|
||||
doubleToFloat(i, o);
|
||||
fixEndianess(value);
|
||||
return value;
|
||||
variant = value;
|
||||
return MsgPackError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MsgPackError readString(JsonVariant &variant) {
|
||||
T size;
|
||||
if (!readInteger(size)) return MsgPackError::IncompleteInput;
|
||||
return readString(variant, size);
|
||||
}
|
||||
|
||||
MsgPackError readString(JsonVariant &variant, size_t n) {
|
||||
typename RemoveReference<TWriter>::type::String str = _writer.startString();
|
||||
for (; n; --n) str.append(static_cast<char>(readOne()));
|
||||
for (; n; --n) {
|
||||
uint8_t c;
|
||||
if (!readBytes(c)) return MsgPackError::IncompleteInput;
|
||||
str.append(static_cast<char>(c));
|
||||
}
|
||||
const char *s = str.c_str();
|
||||
if (s == NULL) return MsgPackError::NoMemory;
|
||||
variant = s;
|
||||
return MsgPackError::Ok;
|
||||
}
|
||||
|
||||
template <typename TSize>
|
||||
MsgPackError readArray(JsonVariant &variant) {
|
||||
TSize size;
|
||||
if (!readInteger(size)) return MsgPackError::IncompleteInput;
|
||||
return readArray(variant, size);
|
||||
}
|
||||
|
||||
MsgPackError readArray(JsonVariant &variant, size_t n) {
|
||||
JsonArray *array = new (_buffer) JsonArray(_buffer);
|
||||
if (!array) return MsgPackError::NoMemory;
|
||||
@ -227,6 +263,13 @@ class MsgPackDeserializer {
|
||||
return MsgPackError::Ok;
|
||||
}
|
||||
|
||||
template <typename TSize>
|
||||
MsgPackError readObject(JsonVariant &variant) {
|
||||
TSize size;
|
||||
if (!readInteger(size)) return MsgPackError::IncompleteInput;
|
||||
return readObject(variant, size);
|
||||
}
|
||||
|
||||
MsgPackError readObject(JsonVariant &variant, size_t n) {
|
||||
JsonObject *object = new (_buffer) JsonObject(_buffer);
|
||||
if (!object) return MsgPackError::NoMemory;
|
||||
@ -258,36 +301,10 @@ class MsgPackDeserializer {
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString, typename Enable = void>
|
||||
struct MsgPackDeserializerBuilder {
|
||||
typedef typename StringTraits<TString>::Reader InputReader;
|
||||
typedef MsgPackDeserializer<InputReader, TJsonBuffer &> TParser;
|
||||
|
||||
static TParser makeMsgPackDeserializer(TJsonBuffer *buffer, TString &json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct MsgPackDeserializerBuilder<
|
||||
TJsonBuffer, TChar *, typename EnableIf<!IsConst<TChar>::value>::type> {
|
||||
typedef typename StringTraits<TChar *>::Reader TReader;
|
||||
typedef StringWriter<TChar> TWriter;
|
||||
typedef MsgPackDeserializer<TReader, TWriter> TParser;
|
||||
|
||||
static TParser makeMsgPackDeserializer(TJsonBuffer *buffer, TChar *json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString>
|
||||
inline typename MsgPackDeserializerBuilder<TJsonBuffer, TString>::TParser
|
||||
makeMsgPackDeserializer(TJsonBuffer *buffer, TString &json,
|
||||
uint8_t nestingLimit) {
|
||||
return MsgPackDeserializerBuilder<
|
||||
TJsonBuffer, TString>::makeMsgPackDeserializer(buffer, json,
|
||||
template <typename TJsonBuffer, typename TReader, typename TWriter>
|
||||
MsgPackDeserializer<TReader, TWriter> makeMsgPackDeserializer(
|
||||
TJsonBuffer *buffer, TReader reader, TWriter writer, uint8_t nestingLimit) {
|
||||
return MsgPackDeserializer<TReader, TWriter>(buffer, reader, writer,
|
||||
nestingLimit);
|
||||
}
|
||||
} // namespace Internals
|
||||
|
@ -4,11 +4,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class MsgPackError {
|
||||
public:
|
||||
enum Code { Ok, NotSupported, NoMemory, TooDeep };
|
||||
enum Code { Ok, NotSupported, NoMemory, TooDeep, IncompleteInput };
|
||||
|
||||
MsgPackError() {}
|
||||
|
||||
@ -44,6 +48,8 @@ class MsgPackError {
|
||||
return "NoMemory";
|
||||
case TooDeep:
|
||||
return "TooDeep";
|
||||
case IncompleteInput:
|
||||
return "IncompleteInput";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
|
41
src/ArduinoJson/Reading/ArduinoStreamReader.hpp
Normal file
41
src/ArduinoJson/Reading/ArduinoStreamReader.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct ArduinoStreamReader {
|
||||
Stream& _stream;
|
||||
char _current;
|
||||
bool _ended;
|
||||
|
||||
public:
|
||||
explicit ArduinoStreamReader(Stream& stream)
|
||||
: _stream(stream), _current(0), _ended(false) {}
|
||||
|
||||
char read() {
|
||||
// don't use _stream.read() as it ignores the timeout
|
||||
char c = 0;
|
||||
_ended = _stream.readBytes(&c, 1) == 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ended;
|
||||
}
|
||||
};
|
||||
|
||||
inline ArduinoStreamReader makeReader(Stream& input) {
|
||||
return ArduinoStreamReader(input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#endif
|
64
src/ArduinoJson/Reading/CharPointerReader.hpp
Normal file
64
src/ArduinoJson/Reading/CharPointerReader.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TChar>
|
||||
class UnsafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeCharPointerReader(const TChar* ptr)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// we cannot know
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
class SafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
const TChar* _end;
|
||||
|
||||
public:
|
||||
explicit SafeCharPointerReader(const TChar* ptr, size_t len)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")),
|
||||
_end(_ptr + len) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline UnsafeCharPointerReader<TChar> makeReader(TChar* input) {
|
||||
return UnsafeCharPointerReader<TChar>(input);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline SafeCharPointerReader<TChar> makeReader(TChar* input, size_t n) {
|
||||
return SafeCharPointerReader<TChar>(input, n);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
inline SafeCharPointerReader<char> makeReader(const String& input) {
|
||||
return SafeCharPointerReader<char>(input.c_str(), input.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
56
src/ArduinoJson/Reading/FlashStringReader.hpp
Normal file
56
src/ArduinoJson/Reading/FlashStringReader.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class UnsafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||
|
||||
char read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// this reader cannot detect the end
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class SafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
const char* _end;
|
||||
|
||||
public:
|
||||
explicit SafeFlashStringReader(const __FlashStringHelper* ptr, size_t size)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
|
||||
|
||||
char read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
};
|
||||
|
||||
inline UnsafeFlashStringReader makeReader(const __FlashStringHelper* input) {
|
||||
return UnsafeFlashStringReader(input);
|
||||
}
|
||||
|
||||
inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
|
||||
size_t size) {
|
||||
return SafeFlashStringReader(input, size);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#endif
|
34
src/ArduinoJson/Reading/IteratorReader.hpp
Normal file
34
src/ArduinoJson/Reading/IteratorReader.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TIterator>
|
||||
class IteratorReader {
|
||||
TIterator _ptr, _end;
|
||||
|
||||
public:
|
||||
explicit IteratorReader(TIterator begin, TIterator end)
|
||||
: _ptr(begin), _end(end) {}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
|
||||
char read() {
|
||||
return char(*_ptr++);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TInput>
|
||||
inline IteratorReader<typename TInput::const_iterator> makeReader(
|
||||
const TInput& input) {
|
||||
return IteratorReader<typename TInput::const_iterator>(input.begin(),
|
||||
input.end());
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
11
src/ArduinoJson/Reading/Reader.hpp
Normal file
11
src/ArduinoJson/Reading/Reader.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./ArduinoStreamReader.hpp"
|
||||
#include "./CharPointerReader.hpp"
|
||||
#include "./FlashStringReader.hpp"
|
||||
#include "./IteratorReader.hpp"
|
||||
#include "./StdStreamReader.hpp"
|
40
src/ArduinoJson/Reading/StdStreamReader.hpp
Normal file
40
src/ArduinoJson/Reading/StdStreamReader.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
|
||||
#include <istream>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class StdStreamReader {
|
||||
std::istream& _stream;
|
||||
char _current;
|
||||
|
||||
public:
|
||||
explicit StdStreamReader(std::istream& stream)
|
||||
: _stream(stream), _current(0) {}
|
||||
|
||||
bool ended() const {
|
||||
return _stream.eof();
|
||||
}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(_stream.get());
|
||||
}
|
||||
|
||||
private:
|
||||
StdStreamReader& operator=(const StdStreamReader&); // Visual Studio C4512
|
||||
};
|
||||
|
||||
inline StdStreamReader makeReader(std::istream& input) {
|
||||
return StdStreamReader(input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct ArduinoStreamTraits {
|
||||
class Reader {
|
||||
Stream& _stream;
|
||||
char _current, _next;
|
||||
|
||||
public:
|
||||
Reader(Stream& stream) : _stream(stream), _current(0), _next(0) {}
|
||||
|
||||
void move() {
|
||||
_current = _next;
|
||||
_next = 0;
|
||||
}
|
||||
|
||||
char current() {
|
||||
if (!_current) _current = read();
|
||||
return _current;
|
||||
}
|
||||
|
||||
char next() {
|
||||
// assumes that current() has been called
|
||||
if (!_next) _next = read();
|
||||
return _next;
|
||||
}
|
||||
|
||||
private:
|
||||
char read() {
|
||||
// don't use _stream.read() as it ignores the timeout
|
||||
char c = 0;
|
||||
_stream.readBytes(&c, 1);
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
static const bool has_append = false;
|
||||
static const bool has_equals = false;
|
||||
};
|
||||
|
||||
template <typename TStream>
|
||||
struct StringTraits<
|
||||
TStream,
|
||||
// match any type that is derived from Stream:
|
||||
typename EnableIf<
|
||||
IsBaseOf<Stream, typename RemoveReference<TStream>::type>::value>::type>
|
||||
: ArduinoStreamTraits {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -9,26 +9,6 @@ namespace Internals {
|
||||
|
||||
template <typename TChar>
|
||||
struct CharPointerTraits {
|
||||
class Reader {
|
||||
const TChar* _ptr;
|
||||
|
||||
public:
|
||||
Reader(const TChar* ptr)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")) {}
|
||||
|
||||
void move() {
|
||||
++_ptr;
|
||||
}
|
||||
|
||||
char current() const {
|
||||
return char(_ptr[0]);
|
||||
}
|
||||
|
||||
char next() const {
|
||||
return char(_ptr[1]);
|
||||
}
|
||||
};
|
||||
|
||||
static bool equals(const TChar* str, const char* expected) {
|
||||
return strcmp(reinterpret_cast<const char*>(str), expected) == 0;
|
||||
}
|
||||
|
@ -10,26 +10,6 @@ namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <>
|
||||
struct StringTraits<const __FlashStringHelper*, void> {
|
||||
class Reader {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
Reader(const __FlashStringHelper* ptr)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||
|
||||
void move() {
|
||||
_ptr++;
|
||||
}
|
||||
|
||||
char current() const {
|
||||
return pgm_read_byte_near(_ptr);
|
||||
}
|
||||
|
||||
char next() const {
|
||||
return pgm_read_byte_near(_ptr + 1);
|
||||
}
|
||||
};
|
||||
|
||||
static bool equals(const __FlashStringHelper* str, const char* expected) {
|
||||
return strcmp_P(expected, (const char*)str) == 0;
|
||||
}
|
||||
|
@ -1,60 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
|
||||
#include <istream>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct StdStreamTraits {
|
||||
class Reader {
|
||||
std::istream& _stream;
|
||||
char _current, _next;
|
||||
|
||||
public:
|
||||
Reader(std::istream& stream) : _stream(stream), _current(0), _next(0) {}
|
||||
|
||||
void move() {
|
||||
_current = _next;
|
||||
_next = 0;
|
||||
}
|
||||
|
||||
char current() {
|
||||
if (!_current) _current = read();
|
||||
return _current;
|
||||
}
|
||||
|
||||
char next() {
|
||||
// assumes that current() has been called
|
||||
if (!_next) _next = read();
|
||||
return _next;
|
||||
}
|
||||
|
||||
private:
|
||||
Reader& operator=(const Reader&); // Visual Studio C4512
|
||||
|
||||
char read() {
|
||||
return _stream.eof() ? '\0' : static_cast<char>(_stream.get());
|
||||
}
|
||||
};
|
||||
|
||||
static const bool has_append = false;
|
||||
static const bool has_equals = false;
|
||||
};
|
||||
|
||||
template <typename TStream>
|
||||
struct StringTraits<
|
||||
TStream,
|
||||
// match any type that is derived from std::istream:
|
||||
typename EnableIf<IsBaseOf<
|
||||
std::istream, typename RemoveReference<TStream>::type>::value>::type>
|
||||
: StdStreamTraits {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -35,10 +35,6 @@ struct StdStringTraits {
|
||||
return !str.c_str();
|
||||
}
|
||||
|
||||
struct Reader : CharPointerTraits<char>::Reader {
|
||||
Reader(const TString& str) : CharPointerTraits<char>::Reader(str.c_str()) {}
|
||||
};
|
||||
|
||||
static bool equals(const TString& str, const char* expected) {
|
||||
return 0 == strcmp(str.c_str(), expected);
|
||||
}
|
||||
|
@ -29,8 +29,6 @@ struct StringTraits<TString&, void> : StringTraits<TString> {};
|
||||
}
|
||||
}
|
||||
|
||||
#include "ArduinoStream.hpp"
|
||||
#include "CharPointer.hpp"
|
||||
#include "FlashString.hpp"
|
||||
#include "StdStream.hpp"
|
||||
#include "StdString.hpp"
|
||||
|
27
src/ArduinoJson/Writing/JsonBufferWriter.hpp
Normal file
27
src/ArduinoJson/Writing/JsonBufferWriter.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TJsonBuffer>
|
||||
class JsonBufferWriter {
|
||||
public:
|
||||
JsonBufferWriter(TJsonBuffer& jb) : _jb(&jb) {}
|
||||
|
||||
typedef typename TJsonBuffer::String String;
|
||||
|
||||
String startString() {
|
||||
return _jb->startString();
|
||||
}
|
||||
|
||||
private:
|
||||
TJsonBuffer* _jb;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
44
src/ArduinoJson/Writing/Writer.hpp
Normal file
44
src/ArduinoJson/Writing/Writer.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./JsonBufferWriter.hpp"
|
||||
#include "./StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TJsonBuffer, typename TInput, typename Enable = void>
|
||||
struct Writer {
|
||||
typedef JsonBufferWriter<TJsonBuffer> type;
|
||||
|
||||
static type create(TJsonBuffer& jb, TInput&) {
|
||||
return type(jb);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct Writer<TJsonBuffer, TChar*,
|
||||
typename EnableIf<!IsConst<TChar>::value>::type> {
|
||||
typedef StringWriter<TChar> type;
|
||||
|
||||
static type create(TJsonBuffer&, TChar* input) {
|
||||
return type(input);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TInput>
|
||||
typename Writer<TJsonBuffer, TInput>::type makeWriter(TJsonBuffer& jb,
|
||||
TInput& input) {
|
||||
return Writer<TJsonBuffer, TInput>::create(jb, input);
|
||||
}
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
typename Writer<TJsonBuffer, TChar*>::type makeWriter(TJsonBuffer& jb,
|
||||
TChar* input) {
|
||||
return Writer<TJsonBuffer, TChar*>::create(jb, input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -5,34 +5,53 @@
|
||||
#pragma once
|
||||
|
||||
#include "Json/Deserialization/JsonDeserializer.hpp"
|
||||
#include "Reading/Reader.hpp"
|
||||
#include "Writing/Writer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
// JsonError deserializeJson(TDocument& doc, TString json);
|
||||
// JsonError deserializeJson(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = const std::string&, const String&
|
||||
template <typename TDocument, typename TString>
|
||||
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
|
||||
JsonError>::type
|
||||
deserializeJson(TDocument &doc, const TString &json) {
|
||||
return Internals::makeParser(&doc.buffer(), json, doc.nestingLimit)
|
||||
deserializeJson(TDocument &doc, const TString &input) {
|
||||
using namespace Internals;
|
||||
return makeJsonDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// JsonError deserializeJson(TDocument& doc, TString json);
|
||||
// JsonError deserializeJson(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TDocument, typename TString>
|
||||
JsonError deserializeJson(TDocument &doc, TString *json) {
|
||||
return Internals::makeParser(&doc.buffer(), json, doc.nestingLimit)
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <typename TDocument, typename TChar>
|
||||
JsonError deserializeJson(TDocument &doc, TChar *input) {
|
||||
using namespace Internals;
|
||||
return makeJsonDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// JsonError deserializeJson(TDocument& doc, TString json);
|
||||
// JsonError deserializeJson(TDocument& doc, TChar* input, size_t inputSize);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = std::istream&, Stream&
|
||||
template <typename TDocument, typename TString>
|
||||
JsonError deserializeJson(TDocument &doc, TString &json) {
|
||||
return Internals::makeParser(&doc.buffer(), json, doc.nestingLimit)
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <typename TDocument, typename TChar>
|
||||
JsonError deserializeJson(TDocument &doc, TChar *input, size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return makeJsonDeserializer(&doc.buffer(), makeReader(input, inputSize),
|
||||
makeWriter(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// JsonError deserializeJson(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TStream = std::istream&, Stream&
|
||||
template <typename TDocument, typename TStream>
|
||||
JsonError deserializeJson(TDocument &doc, TStream &input) {
|
||||
using namespace Internals;
|
||||
return makeJsonDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
|
@ -5,36 +5,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "MsgPack/MsgPackDeserializer.hpp"
|
||||
#include "Reading/Reader.hpp"
|
||||
#include "Writing/Writer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
// MsgPackError deserializeMsgPack(TDocument& doc, TString json);
|
||||
// TDocument = DynamicJsonArray | StaticJsonArray
|
||||
// MsgPackError deserializeMsgPack(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = const std::string&, const String&
|
||||
template <typename TDocument, typename TString>
|
||||
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
|
||||
MsgPackError>::type
|
||||
deserializeMsgPack(TDocument &doc, const TString &json) {
|
||||
return Internals::makeMsgPackDeserializer(&doc.buffer(), json,
|
||||
deserializeMsgPack(TDocument &doc, const TString &input) {
|
||||
using namespace Internals;
|
||||
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// MsgPackError deserializeMsgPack(TDocument& doc, TString json);
|
||||
// TDocument = DynamicJsonArray | StaticJsonArray
|
||||
// TString = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TDocument, typename TString>
|
||||
MsgPackError deserializeMsgPack(TDocument &doc, TString *json) {
|
||||
return Internals::makeMsgPackDeserializer(&doc.buffer(), json,
|
||||
// MsgPackError deserializeMsgPack(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <typename TDocument, typename TChar>
|
||||
MsgPackError deserializeMsgPack(TDocument &doc, TChar *input) {
|
||||
using namespace Internals;
|
||||
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// MsgPackError deserializeMsgPack(TDocument& doc, TString json);
|
||||
// TDocument = DynamicJsonArray | StaticJsonArray
|
||||
// TString = std::istream&, Stream&
|
||||
template <typename TDocument, typename TString>
|
||||
MsgPackError deserializeMsgPack(TDocument &doc, TString &json) {
|
||||
return Internals::makeMsgPackDeserializer(&doc.buffer(), json,
|
||||
// MsgPackError deserializeMsgPack(TDocument& doc, TChar* input, size_t
|
||||
// inputSize);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <typename TDocument, typename TChar>
|
||||
MsgPackError deserializeMsgPack(TDocument &doc, TChar *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input, inputSize),
|
||||
makeWriter(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// MsgPackError deserializeMsgPack(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TStream = std::istream&, Stream&
|
||||
template <typename TDocument, typename TStream>
|
||||
MsgPackError deserializeMsgPack(TDocument &doc, TStream &input) {
|
||||
using namespace Internals;
|
||||
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ add_executable(JsonArrayTests
|
||||
remove.cpp
|
||||
set.cpp
|
||||
size.cpp
|
||||
std_string.cpp
|
||||
subscript.cpp
|
||||
)
|
||||
|
||||
|
39
test/JsonArray/std_string.cpp
Normal file
39
test/JsonArray/std_string.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void eraseString(std::string &str) {
|
||||
char *p = const_cast<char *>(str.c_str());
|
||||
while (*p) *p++ = '*';
|
||||
}
|
||||
|
||||
TEST_CASE("std::string") {
|
||||
DynamicJsonDocument doc;
|
||||
JsonArray &array = doc.to<JsonArray>();
|
||||
|
||||
SECTION("add()") {
|
||||
std::string value("hello");
|
||||
array.add(value);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("hello") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("set()") {
|
||||
std::string value("world");
|
||||
array.add("hello");
|
||||
array.set(0, value);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("operator[]") {
|
||||
std::string value("world");
|
||||
array.add("hello");
|
||||
array[0] = value;
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == array[0]);
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ add_executable(JsonDeserializerTests
|
||||
deserializeJsonValue.cpp
|
||||
JsonError.cpp
|
||||
nestingLimit.cpp
|
||||
std_istream.cpp
|
||||
std_string.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonDeserializerTests catch)
|
||||
|
@ -25,6 +25,7 @@ TEST_CASE("JsonError") {
|
||||
TEST_STRINGIFICATION(TooDeep);
|
||||
TEST_STRINGIFICATION(NoMemory);
|
||||
TEST_STRINGIFICATION(InvalidInput);
|
||||
TEST_STRINGIFICATION(IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("as boolean") {
|
||||
@ -32,6 +33,7 @@ TEST_CASE("JsonError") {
|
||||
TEST_BOOLIFICATION(TooDeep, true);
|
||||
TEST_BOOLIFICATION(NoMemory, true);
|
||||
TEST_BOOLIFICATION(InvalidInput, true);
|
||||
TEST_BOOLIFICATION(IncompleteInput, true);
|
||||
}
|
||||
|
||||
SECTION("ostream") {
|
||||
|
@ -164,13 +164,13 @@ TEST_CASE("deserialize JSON array") {
|
||||
SECTION("Closing single quotes missing") {
|
||||
JsonError err = deserializeJson(doc, "[\"]");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Closing double quotes missing") {
|
||||
JsonError err = deserializeJson(doc, "[\']");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,21 +233,21 @@ TEST_CASE("deserialize JSON array") {
|
||||
|
||||
SECTION("/*/") {
|
||||
JsonError err = deserializeJson(doc, "[/*/\n]");
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Unfinished comment") {
|
||||
JsonError err = deserializeJson(doc, "[/*COMMENT]");
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Final slash missing") {
|
||||
JsonError err = deserializeJson(doc, "[/*COMMENT*]");
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Line comments") {
|
||||
SECTION("Trailing comments") {
|
||||
SECTION("Before opening bracket") {
|
||||
JsonError err = deserializeJson(doc, "//COMMENT\n\t[\"hello\"]");
|
||||
JsonArray& arr = doc.as<JsonArray>();
|
||||
@ -311,39 +311,53 @@ TEST_CASE("deserialize JSON array") {
|
||||
|
||||
SECTION("End document with comment") {
|
||||
JsonError err = deserializeJson(doc, "[//COMMENT");
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature null-terminator") {
|
||||
SECTION("After opening bracket") {
|
||||
JsonError err = deserializeJson(doc, "[");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After value") {
|
||||
JsonError err = deserializeJson(doc, "[1");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
JsonError err = deserializeJson(doc, "[1,");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature end of input") {
|
||||
const char* input = "[1,2]";
|
||||
|
||||
SECTION("After opening bracket") {
|
||||
JsonError err = deserializeJson(doc, input, 1);
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After value") {
|
||||
JsonError err = deserializeJson(doc, input, 2);
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
JsonError err = deserializeJson(doc, input, 3);
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Misc") {
|
||||
SECTION("Garbage") {
|
||||
JsonError err = deserializeJson(doc, "%*$£¤");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("The opening bracket is missing") {
|
||||
JsonError err = deserializeJson(doc, "]");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("The closing bracket is missing") {
|
||||
JsonError err = deserializeJson(doc, "[");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Escape sequences") {
|
||||
JsonError err =
|
||||
deserializeJson(doc, "[\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"]");
|
||||
JsonArray& arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "1\"2\\3/4\b5\f6\n7\r8\t9");
|
||||
}
|
||||
|
||||
SECTION("Nested objects") {
|
||||
char jsonString[] =
|
||||
" [ { \"a\" : 1 , \"b\" : 2 } , { \"c\" : 3 , \"d\" : 4 } ] ";
|
||||
|
@ -21,7 +21,7 @@ TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
|
||||
|
||||
JsonError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
REQUIRE(err == JsonError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForArrayWithOneValue") {
|
||||
@ -39,7 +39,7 @@ TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
|
||||
|
||||
JsonError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
REQUIRE(err == JsonError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForArrayWithNestedObject") {
|
||||
@ -51,22 +51,6 @@ TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("CharPtrNull") {
|
||||
StaticJsonDocument<100> doc;
|
||||
|
||||
JsonError err = deserializeJson(doc, static_cast<char*>(0));
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("ConstCharPtrNull") {
|
||||
StaticJsonDocument<100> doc;
|
||||
|
||||
JsonError err = deserializeJson(doc, static_cast<const char*>(0));
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("CopyStringNotSpaces") {
|
||||
StaticJsonDocument<100> doc;
|
||||
|
||||
|
@ -212,19 +212,39 @@ TEST_CASE("deserialize JSON object") {
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Misc") {
|
||||
SECTION("The opening brace is missing") {
|
||||
JsonError err = deserializeJson(doc, "}");
|
||||
SECTION("Premature null terminator") {
|
||||
SECTION("After opening brace") {
|
||||
JsonError err = deserializeJson(doc, "{");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("The closing brace is missing") {
|
||||
SECTION("After key") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\"");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After value") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":\"world\"");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":\"world\",");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Misc") {
|
||||
SECTION("A quoted key without value") {
|
||||
JsonError err = deserializeJson(doc, "{\"key\"}");
|
||||
|
||||
@ -250,6 +270,200 @@ TEST_CASE("deserialize JSON object") {
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Block comments") {
|
||||
SECTION("Before opening brace") {
|
||||
JsonError err = deserializeJson(doc, "/*COMMENT*/ {\"hello\":\"world\"}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After opening brace") {
|
||||
JsonError err = deserializeJson(doc, "{/*COMMENT*/\"hello\":\"world\"}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before colon") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\"/*COMMENT*/:\"world\"}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":/*COMMENT*/\"world\"}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before closing brace") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":\"world\"/*COMMENT*/}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After closing brace") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":\"world\"}/*COMMENT*/");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before comma") {
|
||||
JsonError err = deserializeJson(
|
||||
doc, "{\"hello\":\"world\"/*COMMENT*/,\"answer\":42}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
REQUIRE(obj["answer"] == 42);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
JsonError err = deserializeJson(
|
||||
doc, "{\"hello\":\"world\",/*COMMENT*/\"answer\":42}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
REQUIRE(obj["answer"] == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Trailing comments") {
|
||||
SECTION("Before opening brace") {
|
||||
JsonError err = deserializeJson(doc, "//COMMENT\n {\"hello\":\"world\"}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After opening brace") {
|
||||
JsonError err = deserializeJson(doc, "{//COMMENT\n\"hello\":\"world\"}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before colon") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\"//COMMENT\n:\"world\"}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\"://COMMENT\n\"world\"}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before closing brace") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":\"world\"//COMMENT\n}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After closing brace") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":\"world\"}//COMMENT\n");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before comma") {
|
||||
JsonError err = deserializeJson(
|
||||
doc, "{\"hello\":\"world\"//COMMENT\n,\"answer\":42}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
REQUIRE(obj["answer"] == 42);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
JsonError err = deserializeJson(
|
||||
doc, "{\"hello\":\"world\",//COMMENT\n\"answer\":42}");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
REQUIRE(obj["answer"] == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Dangling slash") {
|
||||
SECTION("Before opening brace") {
|
||||
JsonError err = deserializeJson(doc, "/{\"hello\":\"world\"}");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("After opening brace") {
|
||||
JsonError err = deserializeJson(doc, "{/\"hello\":\"world\"}");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Before colon") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\"/:\"world\"}");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":/\"world\"}");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Before closing brace") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":\"world\"/}");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("After closing brace") {
|
||||
JsonError err = deserializeJson(doc, "{\"hello\":\"world\"}/");
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before comma") {
|
||||
JsonError err =
|
||||
deserializeJson(doc, "{\"hello\":\"world\"/,\"answer\":42}");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
JsonError err =
|
||||
deserializeJson(doc, "{\"hello\":\"world\",/\"answer\":42}");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonObject") {
|
||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||
deserializeJson(doc, "{}");
|
||||
|
@ -21,7 +21,7 @@ TEST_CASE("deserialize JSON object with StaticJsonDocument") {
|
||||
|
||||
JsonError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
REQUIRE(err == JsonError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForObjectWithOneValue") {
|
||||
@ -39,7 +39,7 @@ TEST_CASE("deserialize JSON object with StaticJsonDocument") {
|
||||
|
||||
JsonError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
REQUIRE(err == JsonError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForObjectWithNestedObject") {
|
||||
@ -51,22 +51,6 @@ TEST_CASE("deserialize JSON object with StaticJsonDocument") {
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("CharPtrNull") {
|
||||
StaticJsonDocument<100> doc;
|
||||
|
||||
JsonError err = deserializeJson(doc, static_cast<char*>(0));
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("ConstCharPtrNull") {
|
||||
StaticJsonDocument<100> doc;
|
||||
|
||||
JsonError err = deserializeJson(doc, static_cast<const char*>(0));
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
char input[] = "{\"hello\":\"world\"}";
|
||||
|
@ -10,18 +10,16 @@ using namespace Catch::Matchers;
|
||||
TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("EmptyObject") {
|
||||
JsonError err = deserializeJson(doc, "{}");
|
||||
SECTION("null char*") {
|
||||
JsonError err = deserializeJson(doc, static_cast<char*>(0));
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("EmptyArray") {
|
||||
JsonError err = deserializeJson(doc, "[]");
|
||||
SECTION("null const char*") {
|
||||
JsonError err = deserializeJson(doc, static_cast<const char*>(0));
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(doc.is<JsonArray>());
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Integer") {
|
||||
@ -58,6 +56,14 @@ TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
|
||||
REQUIRE_THAT(doc.as<char*>(), Equals("hello world"));
|
||||
}
|
||||
|
||||
SECTION("Escape sequences") {
|
||||
JsonError err =
|
||||
deserializeJson(doc, "\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"");
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(doc.as<std::string>() == "1\"2\\3/4\b5\f6\n7\r8\t9");
|
||||
}
|
||||
|
||||
SECTION("True") {
|
||||
JsonError err = deserializeJson(doc, "true");
|
||||
|
||||
@ -74,25 +80,6 @@ TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
|
||||
REQUIRE(doc.as<bool>() == false);
|
||||
}
|
||||
|
||||
SECTION("OpenBrace") {
|
||||
JsonError err = deserializeJson(doc, "{");
|
||||
|
||||
REQUIRE(err != JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Incomplete string") {
|
||||
JsonError err = deserializeJson(doc, "\"hello");
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(doc.is<char*>());
|
||||
REQUIRE_THAT(doc.as<char*>(), Equals("hello"));
|
||||
}
|
||||
|
||||
SECTION("Unterminated escape sequence") {
|
||||
JsonError err = deserializeJson(doc, "\"\\\0\"");
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonVariant") {
|
||||
deserializeJson(doc, "[1,2,3]");
|
||||
deserializeJson(doc, "{}");
|
||||
@ -100,4 +87,86 @@ TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
}
|
||||
|
||||
SECTION("Empty input") {
|
||||
JsonError err = deserializeJson(doc, "");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Just a trailing comment") {
|
||||
JsonError err = deserializeJson(doc, "// comment");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Just a block comment") {
|
||||
JsonError err = deserializeJson(doc, "/*comment*/");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Just a slash") {
|
||||
JsonError err = deserializeJson(doc, "/");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Garbage") {
|
||||
JsonError err = deserializeJson(doc, "%*$£¤");
|
||||
|
||||
REQUIRE(err == JsonError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Premature null-terminator") {
|
||||
SECTION("In escape sequence") {
|
||||
JsonError err = deserializeJson(doc, "\"\\");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In block comment") {
|
||||
JsonError err = deserializeJson(doc, "/* comment");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In double quoted string") {
|
||||
JsonError err = deserializeJson(doc, "\"hello");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In single quoted string") {
|
||||
JsonError err = deserializeJson(doc, "'hello");
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature end of input") {
|
||||
SECTION("In escape sequence") {
|
||||
JsonError err = deserializeJson(doc, "\"\\n\"", 2);
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In block comment") {
|
||||
JsonError err = deserializeJson(doc, "/* comment */", 10);
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In double quoted string") {
|
||||
JsonError err = deserializeJson(doc, "\"hello\"", 6);
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In single quoted string") {
|
||||
JsonError err = deserializeJson(doc, "'hello'", 6);
|
||||
|
||||
REQUIRE(err == JsonError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
73
test/JsonDeserializer/std_istream.cpp
Normal file
73
test/JsonDeserializer/std_istream.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
#include <sstream>
|
||||
|
||||
TEST_CASE("deserializeJson(std::istream&)") {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("array") {
|
||||
std::istringstream json(" [ 42 /* comment */ ] ");
|
||||
|
||||
JsonError err = deserializeJson(doc, json);
|
||||
JsonArray& arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(42 == arr[0]);
|
||||
}
|
||||
|
||||
SECTION("object") {
|
||||
std::istringstream json(" { hello : world // comment\n }");
|
||||
|
||||
JsonError err = deserializeJson(doc, json);
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(1 == obj.size());
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing brace of an empty object") {
|
||||
std::istringstream json("{}123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing brace") {
|
||||
std::istringstream json("{\"hello\":\"world\"}123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing bracket of an empty array") {
|
||||
std::istringstream json("[]123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing bracket") {
|
||||
std::istringstream json("[\"hello\",\"world\"]123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing quote") {
|
||||
std::istringstream json("\"hello\"123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
}
|
35
test/JsonDeserializer/std_string.cpp
Normal file
35
test/JsonDeserializer/std_string.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserializeJson(const std::string&)") {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("should accept const string") {
|
||||
const std::string input("[42]");
|
||||
|
||||
JsonError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("should accept temporary string") {
|
||||
JsonError err = deserializeJson(doc, std::string("[42]"));
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("should duplicate content") {
|
||||
std::string input("[\"hello\"]");
|
||||
|
||||
JsonError err = deserializeJson(doc, input);
|
||||
input[2] = 'X'; // alter the string tomake sure we made a copy
|
||||
|
||||
JsonArray &array = doc.as<JsonArray>();
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(std::string("hello") == array[0]);
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ add_executable(JsonObjectTests
|
||||
remove.cpp
|
||||
set.cpp
|
||||
size.cpp
|
||||
std_string.cpp
|
||||
subscript.cpp
|
||||
)
|
||||
|
||||
|
173
test/JsonObject/std_string.cpp
Normal file
173
test/JsonObject/std_string.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void eraseString(std::string &str) {
|
||||
char *p = const_cast<char *>(str.c_str());
|
||||
while (*p) *p++ = '*';
|
||||
}
|
||||
|
||||
TEST_CASE("std::string") {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("operator[]") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(std::string("value") == obj[std::string("key")]);
|
||||
}
|
||||
|
||||
SECTION("operator[] const") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(std::string("value") == obj[std::string("key")]);
|
||||
}
|
||||
|
||||
SECTION("set(key)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string key("hello");
|
||||
obj.set(key, "world");
|
||||
eraseString(key);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set(value)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string value("world");
|
||||
obj.set("hello", value);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set(key,value)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string key("hello");
|
||||
std::string value("world");
|
||||
obj.set(key, value);
|
||||
eraseString(key);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set(JsonArraySubscript)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
DynamicJsonDocument doc2;
|
||||
JsonArray &arr = doc2.to<JsonArray>();
|
||||
arr.add("world");
|
||||
|
||||
obj.set(std::string("hello"), arr[0]);
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set(JsonObjectSubscript)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
DynamicJsonDocument doc2;
|
||||
JsonObject &obj2 = doc2.to<JsonObject>();
|
||||
obj2.set("x", "world");
|
||||
|
||||
obj.set(std::string("hello"), obj2["x"]);
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("get<T>()") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(std::string("value") == obj.get<const char *>(std::string("key")));
|
||||
}
|
||||
|
||||
SECTION("is<T>()") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(true == obj.is<const char *>(std::string("key")));
|
||||
}
|
||||
|
||||
SECTION("createNestedObject()") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string key = "key";
|
||||
char json[64];
|
||||
obj.createNestedObject(key);
|
||||
eraseString(key);
|
||||
serializeJson(doc, json, sizeof(json));
|
||||
REQUIRE(std::string("{\"key\":{}}") == json);
|
||||
}
|
||||
|
||||
SECTION("createNestedArray()") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string key = "key";
|
||||
char json[64];
|
||||
obj.createNestedArray(key);
|
||||
eraseString(key);
|
||||
serializeJson(doc, json, sizeof(json));
|
||||
REQUIRE(std::string("{\"key\":[]}") == json);
|
||||
}
|
||||
|
||||
SECTION("containsKey()") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
REQUIRE(true == obj.containsKey(std::string("key")));
|
||||
}
|
||||
|
||||
SECTION("remove()") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj["key"] = "value";
|
||||
|
||||
obj.remove(std::string("key"));
|
||||
|
||||
REQUIRE(0 == obj.size());
|
||||
}
|
||||
|
||||
SECTION("operator[], set key") {
|
||||
std::string key("hello");
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj[key] = "world";
|
||||
eraseString(key);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("operator[], set value") {
|
||||
std::string value("world");
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj["hello"] = value;
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("memoryUsage() increases when adding a new key") {
|
||||
std::string key1("hello"), key2("world");
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
|
||||
obj[key1] = 1;
|
||||
size_t sizeBefore = doc.memoryUsage();
|
||||
obj[key2] = 2;
|
||||
size_t sizeAfter = doc.memoryUsage();
|
||||
|
||||
REQUIRE(sizeAfter - sizeBefore >= key2.size());
|
||||
}
|
||||
|
||||
SECTION("memoryUsage() remains when adding the same key") {
|
||||
std::string key("hello");
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
|
||||
obj[key] = 1;
|
||||
size_t sizeBefore = doc.memoryUsage();
|
||||
obj[key] = 2;
|
||||
size_t sizeAfter = doc.memoryUsage();
|
||||
|
||||
REQUIRE(sizeBefore == sizeAfter);
|
||||
}
|
||||
}
|
@ -8,6 +8,8 @@ add_executable(JsonSerializerTests
|
||||
JsonObject.cpp
|
||||
JsonObjectPretty.cpp
|
||||
JsonVariant.cpp
|
||||
std_stream.cpp
|
||||
std_string.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonSerializerTests catch)
|
||||
|
64
test/JsonSerializer/std_stream.cpp
Normal file
64
test/JsonSerializer/std_stream.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
#include <sstream>
|
||||
|
||||
TEST_CASE("operator<<(std::ostream)") {
|
||||
DynamicJsonDocument doc;
|
||||
std::ostringstream os;
|
||||
|
||||
SECTION("JsonVariant containing false") {
|
||||
JsonVariant variant = false;
|
||||
|
||||
os << variant;
|
||||
|
||||
REQUIRE("false" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonVariant containing string") {
|
||||
JsonVariant variant = "coucou";
|
||||
|
||||
os << variant;
|
||||
|
||||
REQUIRE("\"coucou\"" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonObject") {
|
||||
JsonObject& object = doc.to<JsonObject>();
|
||||
object["key"] = "value";
|
||||
|
||||
os << object;
|
||||
|
||||
REQUIRE("{\"key\":\"value\"}" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonObjectSubscript") {
|
||||
JsonObject& object = doc.to<JsonObject>();
|
||||
object["key"] = "value";
|
||||
|
||||
os << object["key"];
|
||||
|
||||
REQUIRE("\"value\"" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonArray") {
|
||||
JsonArray& array = doc.to<JsonArray>();
|
||||
array.add("value");
|
||||
|
||||
os << array;
|
||||
|
||||
REQUIRE("[\"value\"]" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonArraySubscript") {
|
||||
JsonArray& array = doc.to<JsonArray>();
|
||||
array.add("value");
|
||||
|
||||
os << array[0];
|
||||
|
||||
REQUIRE("\"value\"" == os.str());
|
||||
}
|
||||
}
|
47
test/JsonSerializer/std_string.cpp
Normal file
47
test/JsonSerializer/std_string.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("serialize JsonArray to std::string") {
|
||||
DynamicJsonDocument doc;
|
||||
JsonArray &array = doc.to<JsonArray>();
|
||||
array.add(4);
|
||||
array.add(2);
|
||||
|
||||
SECTION("serializeJson()") {
|
||||
std::string json;
|
||||
serializeJson(array, json);
|
||||
|
||||
REQUIRE(std::string("[4,2]") == json);
|
||||
}
|
||||
|
||||
SECTION("serializeJsonPretty") {
|
||||
std::string json;
|
||||
serializeJsonPretty(array, json);
|
||||
|
||||
REQUIRE(std::string("[\r\n 4,\r\n 2\r\n]") == json);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("serialize JsonObject to std::string") {
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj["key"] = "value";
|
||||
|
||||
SECTION("object") {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
|
||||
REQUIRE(std::string("{\"key\":\"value\"}") == json);
|
||||
}
|
||||
|
||||
SECTION("serializeJsonPretty") {
|
||||
std::string json;
|
||||
serializeJsonPretty(doc, json);
|
||||
|
||||
REQUIRE(std::string("{\r\n \"key\": \"value\"\r\n}") == json);
|
||||
}
|
||||
}
|
@ -4,8 +4,6 @@
|
||||
|
||||
add_executable(MiscTests
|
||||
FloatParts.cpp
|
||||
std_stream.cpp
|
||||
std_string.cpp
|
||||
StringBuilder.cpp
|
||||
StringTraits.cpp
|
||||
TypeTraits.cpp
|
||||
|
@ -1,88 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
#include <sstream>
|
||||
|
||||
TEST_CASE("std::stream") {
|
||||
SECTION("JsonVariantFalse") {
|
||||
std::ostringstream os;
|
||||
JsonVariant variant = false;
|
||||
os << variant;
|
||||
REQUIRE("false" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonVariantString") {
|
||||
std::ostringstream os;
|
||||
JsonVariant variant = "coucou";
|
||||
os << variant;
|
||||
REQUIRE("\"coucou\"" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonObject") {
|
||||
std::ostringstream os;
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& object = doc.to<JsonObject>();
|
||||
object["key"] = "value";
|
||||
os << object;
|
||||
REQUIRE("{\"key\":\"value\"}" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonObjectSubscript") {
|
||||
std::ostringstream os;
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& object = doc.to<JsonObject>();
|
||||
object["key"] = "value";
|
||||
os << object["key"];
|
||||
REQUIRE("\"value\"" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonArray") {
|
||||
std::ostringstream os;
|
||||
DynamicJsonDocument doc;
|
||||
JsonArray& array = doc.to<JsonArray>();
|
||||
array.add("value");
|
||||
os << array;
|
||||
REQUIRE("[\"value\"]" == os.str());
|
||||
}
|
||||
|
||||
SECTION("JsonArraySubscript") {
|
||||
std::ostringstream os;
|
||||
DynamicJsonDocument doc;
|
||||
JsonArray& array = doc.to<JsonArray>();
|
||||
array.add("value");
|
||||
os << array[0];
|
||||
REQUIRE("\"value\"" == os.str());
|
||||
}
|
||||
|
||||
SECTION("ParseArray") {
|
||||
std::istringstream json(" [ 42 /* comment */ ] ");
|
||||
DynamicJsonDocument doc;
|
||||
JsonError err = deserializeJson(doc, json);
|
||||
JsonArray& arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(42 == arr[0]);
|
||||
}
|
||||
|
||||
SECTION("ParseObject") {
|
||||
std::istringstream json(" { hello : world // comment\n }");
|
||||
DynamicJsonDocument doc;
|
||||
JsonError err = deserializeJson(doc, json);
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(1 == obj.size());
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("ShouldNotReadPastTheEnd") {
|
||||
std::istringstream json("{}123");
|
||||
DynamicJsonDocument doc;
|
||||
deserializeJson(doc, json);
|
||||
REQUIRE('1' == json.get());
|
||||
}
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void eraseString(std::string &str) {
|
||||
char *p = const_cast<char *>(str.c_str());
|
||||
while (*p) *p++ = '*';
|
||||
}
|
||||
|
||||
TEST_CASE("std::string") {
|
||||
SECTION("deserializeJson duplicates content") {
|
||||
std::string json("[\"hello\"]");
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonError err = deserializeJson(doc, json);
|
||||
eraseString(json);
|
||||
|
||||
JsonArray &array = doc.as<JsonArray>();
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(std::string("hello") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("JsonArray") {
|
||||
DynamicJsonDocument doc;
|
||||
JsonArray &array = doc.to<JsonArray>();
|
||||
|
||||
SECTION("add()") {
|
||||
std::string value("hello");
|
||||
array.add(value);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("hello") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("set()") {
|
||||
std::string value("world");
|
||||
array.add("hello");
|
||||
array.set(0, value);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("operator[]") {
|
||||
std::string value("world");
|
||||
array.add("hello");
|
||||
array[0] = value;
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("serializeJson()") {
|
||||
array.add(4);
|
||||
array.add(2);
|
||||
std::string json;
|
||||
serializeJson(array, json);
|
||||
REQUIRE(std::string("[4,2]") == json);
|
||||
}
|
||||
|
||||
SECTION("serializeJsonPretty()") {
|
||||
array.add(4);
|
||||
array.add(2);
|
||||
std::string json;
|
||||
serializeJsonPretty(array, json);
|
||||
REQUIRE(std::string("[\r\n 4,\r\n 2\r\n]") == json);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonObject") {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("deserializeJson()") {
|
||||
std::string json("{\"hello\":\"world\"}");
|
||||
|
||||
JsonError err = deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
eraseString(json);
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("operator[]") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(std::string("value") == obj[std::string("key")]);
|
||||
}
|
||||
|
||||
SECTION("operator[] const") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(std::string("value") == obj[std::string("key")]);
|
||||
}
|
||||
|
||||
SECTION("set(key)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string key("hello");
|
||||
obj.set(key, "world");
|
||||
eraseString(key);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set(value)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string value("world");
|
||||
obj.set("hello", value);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set(key,value)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string key("hello");
|
||||
std::string value("world");
|
||||
obj.set(key, value);
|
||||
eraseString(key);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set(JsonArraySubscript)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
DynamicJsonDocument doc2;
|
||||
JsonArray &arr = doc2.to<JsonArray>();
|
||||
arr.add("world");
|
||||
|
||||
obj.set(std::string("hello"), arr[0]);
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set(JsonObjectSubscript)") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
DynamicJsonDocument doc2;
|
||||
JsonObject &obj2 = doc2.to<JsonObject>();
|
||||
obj2.set("x", "world");
|
||||
|
||||
obj.set(std::string("hello"), obj2["x"]);
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("get<T>()") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(std::string("value") ==
|
||||
obj.get<const char *>(std::string("key")));
|
||||
}
|
||||
|
||||
SECTION("is<T>()") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(true == obj.is<const char *>(std::string("key")));
|
||||
}
|
||||
|
||||
SECTION("createNestedObject()") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string key = "key";
|
||||
char json[64];
|
||||
obj.createNestedObject(key);
|
||||
eraseString(key);
|
||||
serializeJson(doc, json, sizeof(json));
|
||||
REQUIRE(std::string("{\"key\":{}}") == json);
|
||||
}
|
||||
|
||||
SECTION("createNestedArray()") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
std::string key = "key";
|
||||
char json[64];
|
||||
obj.createNestedArray(key);
|
||||
eraseString(key);
|
||||
serializeJson(doc, json, sizeof(json));
|
||||
REQUIRE(std::string("{\"key\":[]}") == json);
|
||||
}
|
||||
|
||||
SECTION("containsKey()") {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
deserializeJson(doc, json);
|
||||
JsonObject &obj = doc.as<JsonObject>();
|
||||
REQUIRE(true == obj.containsKey(std::string("key")));
|
||||
}
|
||||
|
||||
SECTION("remove()") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj["key"] = "value";
|
||||
|
||||
obj.remove(std::string("key"));
|
||||
|
||||
REQUIRE(0 == obj.size());
|
||||
}
|
||||
|
||||
SECTION("operator[], set key") {
|
||||
std::string key("hello");
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj[key] = "world";
|
||||
eraseString(key);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("operator[], set value") {
|
||||
std::string value("world");
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj["hello"] = value;
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("serializeJson()") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj["key"] = "value";
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
REQUIRE(std::string("{\"key\":\"value\"}") == json);
|
||||
}
|
||||
|
||||
SECTION("serializeJsonPretty()") {
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
obj["key"] = "value";
|
||||
std::string json;
|
||||
serializeJsonPretty(doc, json);
|
||||
REQUIRE(std::string("{\r\n \"key\": \"value\"\r\n}") == json);
|
||||
}
|
||||
|
||||
SECTION("memoryUsage() increases when adding a new key") {
|
||||
std::string key1("hello"), key2("world");
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
|
||||
obj[key1] = 1;
|
||||
size_t sizeBefore = doc.memoryUsage();
|
||||
obj[key2] = 2;
|
||||
size_t sizeAfter = doc.memoryUsage();
|
||||
|
||||
REQUIRE(sizeAfter - sizeBefore >= key2.size());
|
||||
}
|
||||
|
||||
SECTION("memoryUsage() remains when adding the same key") {
|
||||
std::string key("hello");
|
||||
JsonObject &obj = doc.to<JsonObject>();
|
||||
|
||||
obj[key] = 1;
|
||||
size_t sizeBefore = doc.memoryUsage();
|
||||
obj[key] = 2;
|
||||
size_t sizeAfter = doc.memoryUsage();
|
||||
|
||||
REQUIRE(sizeBefore == sizeAfter);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,26 +9,27 @@
|
||||
#define CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
#endif
|
||||
|
||||
TEST_CASE("unsigned char string") {
|
||||
SECTION("JsonBuffer::parseArray") {
|
||||
unsigned char json[] = "[42]";
|
||||
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
|
||||
JsonError err = deserializeJson(doc, json);
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("JsonBuffer::parseObject") {
|
||||
unsigned char json[] = "{\"a\":42}";
|
||||
TEST_CASE("unsigned char[]") {
|
||||
SECTION("deserializeJson()") {
|
||||
unsigned char input[] = "{\"a\":42}";
|
||||
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
JsonError err = deserializeJson(doc, json);
|
||||
JsonError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("JsonVariant constructor") {
|
||||
SECTION("deserializeMsgPack()") {
|
||||
unsigned char input[] = "\xDE\x00\x01\xA5Hello\xA5world";
|
||||
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
|
||||
MsgPackError err = deserializeMsgPack(doc, input);
|
||||
|
||||
REQUIRE(err == MsgPackError::Ok);
|
||||
}
|
||||
|
||||
SECTION("JsonVariant") {
|
||||
SECTION("constructor") {
|
||||
unsigned char value[] = "42";
|
||||
|
||||
JsonVariant variant(value);
|
||||
@ -36,7 +37,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(42 == variant.as<int>());
|
||||
}
|
||||
|
||||
SECTION("JsonVariant assignment operator") {
|
||||
SECTION("operator=") {
|
||||
unsigned char value[] = "42";
|
||||
|
||||
JsonVariant variant(666);
|
||||
@ -46,7 +47,7 @@ TEST_CASE("unsigned char string") {
|
||||
}
|
||||
|
||||
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
SECTION("JsonVariant::operator[]") {
|
||||
SECTION("operator[]") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -58,7 +59,7 @@ TEST_CASE("unsigned char string") {
|
||||
#endif
|
||||
|
||||
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
SECTION("JsonVariant::operator[] const") {
|
||||
SECTION("operator[] const") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -69,7 +70,7 @@ TEST_CASE("unsigned char string") {
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("JsonVariant::operator==") {
|
||||
SECTION("operator==") {
|
||||
unsigned char comparand[] = "hello";
|
||||
|
||||
JsonVariant variant;
|
||||
@ -81,7 +82,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE_FALSE(variant != comparand);
|
||||
}
|
||||
|
||||
SECTION("JsonVariant::operator!=") {
|
||||
SECTION("operator!=") {
|
||||
unsigned char comparand[] = "hello";
|
||||
|
||||
JsonVariant variant;
|
||||
@ -92,9 +93,11 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE_FALSE(comparand == variant);
|
||||
REQUIRE_FALSE(variant == comparand);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonObject") {
|
||||
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
SECTION("JsonObject::operator[]") {
|
||||
SECTION("operator[]") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -103,29 +106,7 @@ TEST_CASE("unsigned char string") {
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("JsonObjectSubscript::operator=") { // issue #416
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj["hello"] = value;
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("JsonObjectSubscript::set()") {
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj["hello"].set(value);
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
SECTION("JsonObject::operator[] const") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
@ -137,7 +118,7 @@ TEST_CASE("unsigned char string") {
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("JsonObject::get()") {
|
||||
SECTION("get()") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -146,7 +127,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(std::string("world") == obj.get<char*>(key));
|
||||
}
|
||||
|
||||
SECTION("JsonObject::set() key") {
|
||||
SECTION("set() key") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -156,7 +137,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("JsonObject::set() value") {
|
||||
SECTION("set() value") {
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -166,7 +147,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("JsonObject::set key&value") {
|
||||
SECTION("set() key&value") {
|
||||
unsigned char key[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -176,7 +157,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(std::string("world") == obj["world"]);
|
||||
}
|
||||
|
||||
SECTION("JsonObject::containsKey()") {
|
||||
SECTION("containsKey()") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -185,7 +166,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(true == obj.containsKey(key));
|
||||
}
|
||||
|
||||
SECTION("JsonObject::remove()") {
|
||||
SECTION("remove()") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -196,7 +177,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(0 == obj.size());
|
||||
}
|
||||
|
||||
SECTION("JsonObject::is()") {
|
||||
SECTION("is()") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -206,7 +187,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(true == obj.is<int>(key));
|
||||
}
|
||||
|
||||
SECTION("JsonObject::createNestedArray()") {
|
||||
SECTION("createNestedArray()") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -214,15 +195,39 @@ TEST_CASE("unsigned char string") {
|
||||
obj.createNestedArray(key);
|
||||
}
|
||||
|
||||
SECTION("JsonObject::createNestedObject()") {
|
||||
SECTION("createNestedObject()") {
|
||||
unsigned char key[] = "hello";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj.createNestedObject(key);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonArray::add()") {
|
||||
SECTION("JsonObjectSubscript") {
|
||||
SECTION("operator=") { // issue #416
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj["hello"] = value;
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set()") {
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj["hello"].set(value);
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonArray") {
|
||||
SECTION("add()") {
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -232,7 +237,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(std::string("world") == arr[0]);
|
||||
}
|
||||
|
||||
SECTION("JsonArray::set()") {
|
||||
SECTION("set()") {
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -242,8 +247,10 @@ TEST_CASE("unsigned char string") {
|
||||
|
||||
REQUIRE(std::string("world") == arr[0]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonArraySubscript::set()") {
|
||||
SECTION("JsonArraySubscript") {
|
||||
SECTION("set()") {
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -254,7 +261,7 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(std::string("world") == arr[0]);
|
||||
}
|
||||
|
||||
SECTION("JsonArraySubscript::operator=") {
|
||||
SECTION("operator=") {
|
||||
unsigned char value[] = "world";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
@ -265,3 +272,4 @@ TEST_CASE("unsigned char string") {
|
||||
REQUIRE(std::string("world") == arr[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,40 +17,30 @@
|
||||
#ifndef VLA_NOT_SUPPORTED
|
||||
|
||||
TEST_CASE("Variable Length Array") {
|
||||
SECTION("ParseArray") {
|
||||
int i = 8;
|
||||
SECTION("deserializeJson()") {
|
||||
int i = 9;
|
||||
char vla[i];
|
||||
strcpy(vla, "[42]");
|
||||
strcpy(vla, "{\"a\":42}");
|
||||
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
JsonError err = deserializeJson(doc, vla);
|
||||
|
||||
REQUIRE(err == JsonError::Ok);
|
||||
}
|
||||
|
||||
SECTION("ParseObject") {
|
||||
SECTION("deserializeMsgPack()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "{\"a\":42}");
|
||||
memcpy(vla, "\xDE\x00\x01\xA5Hello\xA5world", 15);
|
||||
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
JsonError error = deserializeJson(doc, vla);
|
||||
MsgPackError err = deserializeMsgPack(doc, vla);
|
||||
|
||||
REQUIRE(error == JsonError::Ok);
|
||||
REQUIRE(err == MsgPackError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Parse") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "42");
|
||||
|
||||
StaticJsonDocument<> variant;
|
||||
deserializeJson(variant, vla);
|
||||
|
||||
REQUIRE(42 == variant.as<int>());
|
||||
}
|
||||
|
||||
SECTION("JsonVariant_Constructor") {
|
||||
SECTION("JsonVariant") {
|
||||
SECTION("constructor") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "42");
|
||||
@ -60,7 +50,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(42 == variant.as<int>());
|
||||
}
|
||||
|
||||
SECTION("JsonVariant_Assign") {
|
||||
SECTION("operator=") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "42");
|
||||
@ -72,7 +62,7 @@ TEST_CASE("Variable Length Array") {
|
||||
}
|
||||
|
||||
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
SECTION("JsonVariant_Subscript") {
|
||||
SECTION("operator[]") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -86,7 +76,7 @@ TEST_CASE("Variable Length Array") {
|
||||
#endif
|
||||
|
||||
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
SECTION("JsonVariant_Subscript_Const") {
|
||||
SECTION("operator[] const") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -99,7 +89,7 @@ TEST_CASE("Variable Length Array") {
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("JsonVariant_Equals") {
|
||||
SECTION("operator==") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -113,7 +103,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE_FALSE((variant != vla));
|
||||
}
|
||||
|
||||
SECTION("JsonVariant_Differs") {
|
||||
SECTION("operator!=") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -126,9 +116,11 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE_FALSE((vla == variant));
|
||||
REQUIRE_FALSE((variant == vla));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonObject") {
|
||||
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
SECTION("JsonObject_Subscript") {
|
||||
SECTION("operator[]") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -141,32 +133,8 @@ TEST_CASE("Variable Length Array") {
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("JsonObject_Subscript_Assign") { // issue #416
|
||||
int i = 32;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj["hello"] = vla;
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("JsonObject_Subscript_Set") {
|
||||
int i = 32;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj["hello"].set(vla);
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"].as<char*>());
|
||||
}
|
||||
|
||||
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
SECTION("JsonObject_Subscript_Const") {
|
||||
SECTION("operator[] const") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -179,7 +147,7 @@ TEST_CASE("Variable Length Array") {
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("JsonObject_Get") {
|
||||
SECTION("get()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -191,7 +159,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(std::string("world") == obj.get<char*>(vla));
|
||||
}
|
||||
|
||||
SECTION("JsonObject_Set_Key") {
|
||||
SECTION("set() key") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -203,7 +171,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("JsonObject_Set_Value") {
|
||||
SECTION("set() value") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
@ -215,7 +183,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("JsonObject_Set_KeyAndValue") {
|
||||
SECTION("set() key&value") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
@ -227,7 +195,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(std::string("world") == obj["world"]);
|
||||
}
|
||||
|
||||
SECTION("JsonObject_ContainsKey") {
|
||||
SECTION("containsKey()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -239,7 +207,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(true == obj.containsKey(vla));
|
||||
}
|
||||
|
||||
SECTION("JsonObject_Remove") {
|
||||
SECTION("remove()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -252,7 +220,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(0 == obj.size());
|
||||
}
|
||||
|
||||
SECTION("JsonObject_Is") {
|
||||
SECTION("is<T>()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -264,7 +232,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(true == obj.is<int>(vla));
|
||||
}
|
||||
|
||||
SECTION("JsonObject_CreateNestedArray") {
|
||||
SECTION("createNestedArray()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -274,7 +242,7 @@ TEST_CASE("Variable Length Array") {
|
||||
obj.createNestedArray(vla);
|
||||
}
|
||||
|
||||
SECTION("JsonObject_CreateNestedObject") {
|
||||
SECTION("createNestedObject()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
@ -283,8 +251,36 @@ TEST_CASE("Variable Length Array") {
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj.createNestedObject(vla);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonArray_Add") {
|
||||
SECTION("JsonObjectSubscript") {
|
||||
SECTION("operator=") { // issue #416
|
||||
int i = 32;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj["hello"] = vla;
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("set()") {
|
||||
int i = 32;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& obj = doc.to<JsonObject>();
|
||||
obj["hello"].set(vla);
|
||||
|
||||
REQUIRE(std::string("world") == obj["hello"].as<char*>());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonArray") {
|
||||
SECTION("add()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
@ -296,7 +292,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(std::string("world") == arr[0]);
|
||||
}
|
||||
|
||||
SECTION("JsonArray_Set") {
|
||||
SECTION("set()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
@ -308,8 +304,10 @@ TEST_CASE("Variable Length Array") {
|
||||
|
||||
REQUIRE(std::string("world") == arr[0]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonArraySubscript_Set") {
|
||||
SECTION("JsonArraySubscript") {
|
||||
SECTION("set()") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
@ -322,7 +320,7 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(std::string("world") == arr[0]);
|
||||
}
|
||||
|
||||
SECTION("JsonArraySubscript_Assign") {
|
||||
SECTION("operator=") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
@ -335,4 +333,5 @@ TEST_CASE("Variable Length Array") {
|
||||
REQUIRE(std::string("world") == arr[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -3,13 +3,17 @@
|
||||
# MIT License
|
||||
|
||||
add_executable(MsgPackTests
|
||||
deserializationErrors.cpp
|
||||
MsgPackError.cpp
|
||||
deserializeArray.cpp
|
||||
deserializeObject.cpp
|
||||
deserializeVariant.cpp
|
||||
deserializeStaticVariant.cpp
|
||||
deserializeVariant.cpp
|
||||
doubleToFloat.cpp
|
||||
MsgPackError.cpp
|
||||
incompleteInput.cpp
|
||||
nestingLimit.cpp
|
||||
notSupported.cpp
|
||||
std_string.cpp
|
||||
std_istream.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MsgPackTests catch)
|
||||
|
@ -25,6 +25,7 @@ TEST_CASE("MsgPackError") {
|
||||
TEST_STRINGIFICATION(NotSupported);
|
||||
TEST_STRINGIFICATION(NoMemory);
|
||||
TEST_STRINGIFICATION(TooDeep);
|
||||
TEST_STRINGIFICATION(IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("as boolean") {
|
||||
@ -32,6 +33,7 @@ TEST_CASE("MsgPackError") {
|
||||
TEST_BOOLIFICATION(NotSupported, true);
|
||||
TEST_BOOLIFICATION(NoMemory, true);
|
||||
TEST_BOOLIFICATION(TooDeep, true);
|
||||
TEST_BOOLIFICATION(IncompleteInput, true);
|
||||
}
|
||||
|
||||
SECTION("ostream") {
|
||||
|
@ -1,59 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void check(const char* input, MsgPackError expected,
|
||||
uint8_t nestingLimit = 10) {
|
||||
DynamicJsonDocument doc;
|
||||
doc.nestingLimit = nestingLimit;
|
||||
|
||||
MsgPackError error = deserializeMsgPack(doc, input);
|
||||
|
||||
REQUIRE(error == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("Errors returned by deserializeMsgPack()") {
|
||||
SECTION("unsupported") {
|
||||
check("\xc4", MsgPackError::NotSupported); // bin 8
|
||||
check("\xc5", MsgPackError::NotSupported); // bin 16
|
||||
check("\xc6", MsgPackError::NotSupported); // bin 32
|
||||
check("\xc7", MsgPackError::NotSupported); // ext 8
|
||||
check("\xc8", MsgPackError::NotSupported); // ext 16
|
||||
check("\xc9", MsgPackError::NotSupported); // ext 32
|
||||
check("\xd4", MsgPackError::NotSupported); // fixext 1
|
||||
check("\xd5", MsgPackError::NotSupported); // fixext 2
|
||||
check("\xd6", MsgPackError::NotSupported); // fixext 4
|
||||
check("\xd7", MsgPackError::NotSupported); // fixext 8
|
||||
check("\xd8", MsgPackError::NotSupported); // fixext 16
|
||||
}
|
||||
|
||||
SECTION("unsupported in array") {
|
||||
check("\x91\xc4", MsgPackError::NotSupported);
|
||||
}
|
||||
|
||||
SECTION("unsupported in map") {
|
||||
check("\x81\xc4\x00\xA1H", MsgPackError::NotSupported);
|
||||
check("\x81\xA1H\xc4\x00", MsgPackError::NotSupported);
|
||||
}
|
||||
|
||||
SECTION("integer as key") {
|
||||
check("\x81\x01\xA1H", MsgPackError::NotSupported);
|
||||
}
|
||||
|
||||
SECTION("object too deep") {
|
||||
check("\x80", MsgPackError::TooDeep, 0); // {}
|
||||
check("\x80", MsgPackError::Ok, 1); // {}
|
||||
check("\x81\xA1H\x80", MsgPackError::TooDeep, 1); // {H:{}}
|
||||
check("\x81\xA1H\x80", MsgPackError::Ok, 2); // {H:{}}
|
||||
}
|
||||
|
||||
SECTION("array too deep") {
|
||||
check("\x90", MsgPackError::TooDeep, 0); // []
|
||||
check("\x90", MsgPackError::Ok, 1); // []
|
||||
check("\x91\x90", MsgPackError::TooDeep, 1); // [[]]
|
||||
check("\x91\x90", MsgPackError::Ok, 2); // [[]]
|
||||
}
|
||||
}
|
106
test/MsgPack/incompleteInput.cpp
Normal file
106
test/MsgPack/incompleteInput.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
MsgPackError deserialize(const char* input, size_t len) {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
return deserializeMsgPack(doc, input, len);
|
||||
}
|
||||
|
||||
void checkAllSizes(const char* input, size_t len) {
|
||||
REQUIRE(deserialize(input, len) == MsgPackError::Ok);
|
||||
|
||||
while (--len) {
|
||||
REQUIRE(deserialize(input, len) == MsgPackError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeMsgPack() returns IncompleteInput") {
|
||||
SECTION("empty input") {
|
||||
checkAllSizes("\x00", 1);
|
||||
}
|
||||
|
||||
SECTION("fixarray") {
|
||||
checkAllSizes("\x91\x01", 2);
|
||||
}
|
||||
|
||||
SECTION("array 16") {
|
||||
checkAllSizes("\xDC\x00\x01\x01", 4);
|
||||
}
|
||||
|
||||
SECTION("array 32") {
|
||||
checkAllSizes("\xDD\x00\x00\x00\x01\x01", 6);
|
||||
}
|
||||
|
||||
SECTION("fixmap") {
|
||||
checkAllSizes("\x81\xA3one\x01", 6);
|
||||
}
|
||||
|
||||
SECTION("map 16") {
|
||||
checkAllSizes("\xDE\x00\x01\xA3one\x01", 8);
|
||||
}
|
||||
|
||||
SECTION("map 32") {
|
||||
checkAllSizes("\xDF\x00\x00\x00\x01\xA3one\x01", 10);
|
||||
}
|
||||
|
||||
SECTION("uint 8") {
|
||||
checkAllSizes("\xcc\x01", 2);
|
||||
}
|
||||
|
||||
SECTION("uint 16") {
|
||||
checkAllSizes("\xcd\x00\x01", 3);
|
||||
}
|
||||
|
||||
SECTION("uint 32") {
|
||||
checkAllSizes("\xCE\x00\x00\x00\x01", 5);
|
||||
}
|
||||
|
||||
SECTION("uint 64") {
|
||||
checkAllSizes("\xCF\x00\x00\x00\x00\x00\x00\x00\x00", 9);
|
||||
}
|
||||
|
||||
SECTION("int 8") {
|
||||
checkAllSizes("\xD0\x01", 2);
|
||||
}
|
||||
|
||||
SECTION("int 16") {
|
||||
checkAllSizes("\xD1\x00\x01", 3);
|
||||
}
|
||||
|
||||
SECTION("int 32") {
|
||||
checkAllSizes("\xD2\x00\x00\x00\x01", 5);
|
||||
}
|
||||
|
||||
SECTION("int 64") {
|
||||
checkAllSizes("\xD3\x00\x00\x00\x00\x00\x00\x00\x00", 9);
|
||||
}
|
||||
|
||||
SECTION("float 32") {
|
||||
checkAllSizes("\xCA\x40\x48\xF5\xC3", 5);
|
||||
}
|
||||
|
||||
SECTION("float 64") {
|
||||
checkAllSizes("\xCB\x40\x09\x21\xCA\xC0\x83\x12\x6F", 9);
|
||||
}
|
||||
|
||||
SECTION("fixstr") {
|
||||
checkAllSizes("\xABhello world", 12);
|
||||
}
|
||||
|
||||
SECTION("str 8") {
|
||||
checkAllSizes("\xd9\x05hello", 7);
|
||||
}
|
||||
|
||||
SECTION("str 16") {
|
||||
checkAllSizes("\xda\x00\x05hello", 8);
|
||||
}
|
||||
|
||||
SECTION("str 32") {
|
||||
checkAllSizes("\xdb\x00\x00\x00\x05hello", 10);
|
||||
}
|
||||
}
|
31
test/MsgPack/nestingLimit.cpp
Normal file
31
test/MsgPack/nestingLimit.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void check(const char* input, MsgPackError expected, uint8_t limit) {
|
||||
DynamicJsonDocument doc;
|
||||
doc.nestingLimit = limit;
|
||||
|
||||
MsgPackError error = deserializeMsgPack(doc, input);
|
||||
|
||||
REQUIRE(error == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("Errors returned by deserializeMsgPack()") {
|
||||
SECTION("object too deep") {
|
||||
check("\x80", MsgPackError::TooDeep, 0); // {}
|
||||
check("\x80", MsgPackError::Ok, 1); // {}
|
||||
check("\x81\xA1H\x80", MsgPackError::TooDeep, 1); // {H:{}}
|
||||
check("\x81\xA1H\x80", MsgPackError::Ok, 2); // {H:{}}
|
||||
}
|
||||
|
||||
SECTION("array too deep") {
|
||||
check("\x90", MsgPackError::TooDeep, 0); // []
|
||||
check("\x90", MsgPackError::Ok, 1); // []
|
||||
check("\x91\x90", MsgPackError::TooDeep, 1); // [[]]
|
||||
check("\x91\x90", MsgPackError::Ok, 2); // [[]]
|
||||
}
|
||||
}
|
73
test/MsgPack/notSupported.cpp
Normal file
73
test/MsgPack/notSupported.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void checkNotSupported(const char* input) {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
MsgPackError error = deserializeMsgPack(doc, input);
|
||||
|
||||
REQUIRE(error == MsgPackError::NotSupported);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeMsgPack() return NotSupported") {
|
||||
SECTION("bin 8") {
|
||||
checkNotSupported("\xc4");
|
||||
}
|
||||
|
||||
SECTION("bin 16") {
|
||||
checkNotSupported("\xc5");
|
||||
}
|
||||
|
||||
SECTION("bin 32") {
|
||||
checkNotSupported("\xc6");
|
||||
}
|
||||
|
||||
SECTION("ext 8") {
|
||||
checkNotSupported("\xc7");
|
||||
}
|
||||
|
||||
SECTION("ext 16") {
|
||||
checkNotSupported("\xc8");
|
||||
}
|
||||
|
||||
SECTION("ext 32") {
|
||||
checkNotSupported("\xc9");
|
||||
}
|
||||
|
||||
SECTION("fixext 1") {
|
||||
checkNotSupported("\xd4");
|
||||
}
|
||||
|
||||
SECTION("fixext 2") {
|
||||
checkNotSupported("\xd5");
|
||||
}
|
||||
|
||||
SECTION("fixext 4") {
|
||||
checkNotSupported("\xd6");
|
||||
}
|
||||
|
||||
SECTION("fixext 8") {
|
||||
checkNotSupported("\xd7");
|
||||
}
|
||||
|
||||
SECTION("fixext 16") {
|
||||
checkNotSupported("\xd8");
|
||||
}
|
||||
|
||||
SECTION("unsupported in array") {
|
||||
checkNotSupported("\x91\xc4");
|
||||
}
|
||||
|
||||
SECTION("unsupported in map") {
|
||||
checkNotSupported("\x81\xc4\x00\xA1H");
|
||||
checkNotSupported("\x81\xA1H\xc4\x00");
|
||||
}
|
||||
|
||||
SECTION("integer as key") {
|
||||
checkNotSupported("\x81\x01\xA1H");
|
||||
}
|
||||
}
|
29
test/MsgPack/std_istream.cpp
Normal file
29
test/MsgPack/std_istream.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserializeMsgPack(std::istream&)") {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("should accept a zero in input") {
|
||||
std::istringstream input(std::string("\x92\x00\x02", 3));
|
||||
|
||||
MsgPackError err = deserializeMsgPack(doc, input);
|
||||
|
||||
REQUIRE(err == MsgPackError::Ok);
|
||||
JsonArray& arr = doc.as<JsonArray>();
|
||||
REQUIRE(arr[0] == 0);
|
||||
REQUIRE(arr[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("should detect incomplete input") {
|
||||
std::istringstream input("\x92\x00\x02");
|
||||
|
||||
MsgPackError err = deserializeMsgPack(doc, input);
|
||||
|
||||
REQUIRE(err == MsgPackError::IncompleteInput);
|
||||
}
|
||||
}
|
44
test/MsgPack/std_string.cpp
Normal file
44
test/MsgPack/std_string.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserializeMsgPack(const std::string&)") {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("should accept const string") {
|
||||
const std::string input("\x92\x01\x02");
|
||||
|
||||
MsgPackError err = deserializeMsgPack(doc, input);
|
||||
|
||||
REQUIRE(err == MsgPackError::Ok);
|
||||
}
|
||||
|
||||
SECTION("should accept temporary string") {
|
||||
MsgPackError err = deserializeMsgPack(doc, std::string("\x92\x01\x02"));
|
||||
|
||||
REQUIRE(err == MsgPackError::Ok);
|
||||
}
|
||||
|
||||
SECTION("should duplicate content") {
|
||||
std::string input("\x91\xA5hello");
|
||||
|
||||
MsgPackError err = deserializeMsgPack(doc, input);
|
||||
input[2] = 'X'; // alter the string tomake sure we made a copy
|
||||
|
||||
JsonArray& array = doc.as<JsonArray>();
|
||||
REQUIRE(err == MsgPackError::Ok);
|
||||
REQUIRE(std::string("hello") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("should accept a zero in input") {
|
||||
MsgPackError err = deserializeMsgPack(doc, std::string("\x92\x00\x02", 3));
|
||||
|
||||
REQUIRE(err == MsgPackError::Ok);
|
||||
JsonArray& arr = doc.as<JsonArray>();
|
||||
REQUIRE(arr[0] == 0);
|
||||
REQUIRE(arr[1] == 2);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user