Compare commits

...

17 Commits

Author SHA1 Message Date
1b8107094f Set version to 6.13.0 2019-11-01 10:32:45 +01:00
8721ac88b1 Reorganized writer classes 2019-10-31 19:27:23 +01:00
6da6f921cd Fixed dangling reference in MemberProxy and ElementProxy (fixes #1120) 2019-10-30 19:09:21 +01:00
ef63757b1a Fixed deserializer that stopped reading at the first 0xFF (closes #1118) 2019-10-29 14:17:11 +01:00
3a169df0a5 Added support for custom reader classes 2019-10-25 11:39:04 +02:00
d4f819f1f0 Added detection of Atmel AVR8/GNU C Compiler (fixes #1112) 2019-10-18 22:10:35 +02:00
16fe3c0acc Improved deserializeMsgPack() speed by reading several bytes at once 2019-10-14 12:02:26 +02:00
fd8f4eb3a6 Moved msgpack.org.md to github.com/bblanchon/ArduinoJson-msgpack.org 2019-10-11 09:07:25 +02:00
b261eca865 esp-idf make system 2019-10-07 09:00:31 +02:00
a37480eec9 Fixed deserializeJson() when input contains duplicate keys (fixes #1095) 2019-09-27 10:07:29 +02:00
713aaa3d68 Added msgpack.org.md
https://github.com/msgpack/website/blob/master/README.md#how-to-list-up-your-project-on-msgpackorg
2019-09-26 09:52:50 +02:00
7d1d0c4e67 Added conversion from JsonArray/JsonObject to bool 2019-09-24 09:38:00 +02:00
4ad05dbaef Replaced GitHub stars badge 2019-09-19 09:28:57 +02:00
38371aae62 Added OSS-Fuzz badge 2019-09-19 09:28:49 +02:00
498a2e4c1e Added support for custom writer classes (closes #1088) 2019-09-13 14:10:21 +02:00
2078871f36 Added missing #include <ArduinoJson/Namespace.hpp> 2019-09-13 12:09:07 +02:00
140525b7a0 Fix deployment scripts 2019-09-05 09:36:18 +02:00
99 changed files with 1213 additions and 502 deletions

View File

@ -1,6 +1,17 @@
ArduinoJson: change log
=======================
v6.13.0 (2019-11-01)
-------
* Added support for custom writer/reader classes (issue #1088)
* Added conversion from `JsonArray` and `JsonObject` to `bool`, to be consistent with `JsonVariant`
* Fixed `deserializeJson()` when input contains duplicate keys (issue #1095)
* Improved `deserializeMsgPack()` speed by reading several bytes at once
* Added detection of Atmel AVR8/GNU C Compiler (issue #1112)
* Fixed deserializer that stopped reading at the first `0xFF` (PR #1118 by @mikee47)
* Fixed dangling reference in copies of `MemberProxy` and `ElementProxy` (issue #1120)
v6.12.0 (2019-09-05)
-------

View File

@ -2,11 +2,12 @@
---
[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.12.0)](https://www.ardu-badge.com/ArduinoJson/6.12.0)
[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.13.0)](https://www.ardu-badge.com/ArduinoJson/6.13.0)
[![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
[![Coverage Status](https://coveralls.io/repos/github/bblanchon/ArduinoJson/badge.svg?branch=6.x)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
[![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat)](https://github.com/bblanchon/ArduinoJson/stargazers)
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).

View File

@ -1,4 +1,4 @@
version: 6.12.0.{build}
version: 6.13.0.{build}
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017

1
component.mk Normal file
View File

@ -0,0 +1 @@
COMPONENT_ADD_INCLUDEDIRS := src

View File

@ -57,7 +57,7 @@ simplify_namespaces() {
perl -p0i -e 's|\} // namespace ARDUINOJSON_NAMESPACE\r?\nnamespace ARDUINOJSON_NAMESPACE \{\r?\n||igs' "$1"
}
cd $(dirname $0)/../
cd $(dirname $0)/../..
INCLUDED=()
process src/ArduinoJson.h true > ../ArduinoJson-$TAG.h
simplify_namespaces ../ArduinoJson-$TAG.h

View File

@ -56,6 +56,6 @@ commit_new_version
add_tag
push
scripts/build-arduino-package.sh
scripts/build-single-header.sh
scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"
extras/scripts/build-arduino-package.sh
extras/scripts/build-single-header.sh
extras/scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"

View File

@ -72,6 +72,7 @@ if(MSVC)
)
endif()
include_directories(Helpers)
add_subdirectory(ElementProxy)
add_subdirectory(IntegrationTests)
add_subdirectory(JsonArray)

View File

@ -0,0 +1,26 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <sstream>
class CustomReader {
std::stringstream _stream;
public:
CustomReader(const char* input) : _stream(input) {}
int read() {
return _stream.get();
}
size_t readBytes(char* buffer, size_t length) {
_stream.read(buffer, static_cast<std::streamsize>(length));
return static_cast<size_t>(_stream.gcount());
}
private:
CustomReader(const CustomReader&);
};

View File

@ -0,0 +1,14 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
// Reproduces Arduino's Stream class
class Stream // : public Print
{
public:
virtual ~Stream() {}
virtual int read() = 0;
virtual size_t readBytes(char *buffer, size_t length) = 0;
};

View File

@ -6,29 +6,53 @@
#include <catch.hpp>
TEST_CASE("JsonArray::isNull()") {
DynamicJsonDocument doc(4096);
SECTION("returns true") {
JsonArray arr;
REQUIRE(arr.isNull() == true);
}
SECTION("returns false") {
DynamicJsonDocument doc(4096);
JsonArray arr = doc.to<JsonArray>();
REQUIRE(arr.isNull() == false);
}
}
TEST_CASE("JsonArrayConst::isNull()") {
DynamicJsonDocument doc(4096);
SECTION("returns true") {
JsonArrayConst arr;
REQUIRE(arr.isNull() == true);
}
SECTION("returns false") {
DynamicJsonDocument doc(4096);
JsonArrayConst arr = doc.to<JsonArray>();
REQUIRE(arr.isNull() == false);
}
}
TEST_CASE("JsonArray::operator bool()") {
SECTION("returns false") {
JsonArray arr;
REQUIRE(static_cast<bool>(arr) == false);
}
SECTION("returns true") {
DynamicJsonDocument doc(4096);
JsonArray arr = doc.to<JsonArray>();
REQUIRE(static_cast<bool>(arr) == true);
}
}
TEST_CASE("JsonArrayConst::operator bool()") {
SECTION("returns false") {
JsonArrayConst arr;
REQUIRE(static_cast<bool>(arr) == false);
}
SECTION("returns true") {
DynamicJsonDocument doc(4096);
JsonArrayConst arr = doc.to<JsonArray>();
REQUIRE(static_cast<bool>(arr) == true);
}
}

View File

@ -6,6 +6,8 @@
#include <catch.hpp>
#include <sstream>
#include "CustomReader.hpp"
TEST_CASE("deserializeJson(const std::string&)") {
DynamicJsonDocument doc(4096);
@ -113,3 +115,14 @@ TEST_CASE("deserializeJson(VLA)") {
REQUIRE(err == DeserializationError::Ok);
}
#endif
TEST_CASE("deserializeJson(CustomReader)") {
DynamicJsonDocument doc(4096);
CustomReader reader("[4,2]");
DeserializationError err = deserializeJson(doc, reader);
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc.size() == 2);
REQUIRE(doc[0] == 4);
REQUIRE(doc[1] == 2);
}

View File

@ -277,6 +277,7 @@ TEST_CASE("deserialize JSON object") {
DeserializationError err = deserializeJson(doc, "{a:{b:{c:1}},a:2}");
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc["a"] == 2);
}
}

View File

@ -6,29 +6,53 @@
#include <catch.hpp>
TEST_CASE("JsonObject::isNull()") {
DynamicJsonDocument doc(4096);
SECTION("returns true") {
JsonObject obj;
REQUIRE(obj.isNull() == true);
}
SECTION("returns false") {
DynamicJsonDocument doc(4096);
JsonObject obj = doc.to<JsonObject>();
REQUIRE(obj.isNull() == false);
}
}
TEST_CASE("JsonObjectConst::isNull()") {
DynamicJsonDocument doc(4096);
SECTION("returns true") {
JsonObjectConst obj;
REQUIRE(obj.isNull() == true);
}
SECTION("returns false") {
DynamicJsonDocument doc(4096);
JsonObjectConst obj = doc.to<JsonObject>();
REQUIRE(obj.isNull() == false);
}
}
TEST_CASE("JsonObject::operator bool()") {
SECTION("returns false") {
JsonObject obj;
REQUIRE(static_cast<bool>(obj) == false);
}
SECTION("returns true") {
DynamicJsonDocument doc(4096);
JsonObject obj = doc.to<JsonObject>();
REQUIRE(static_cast<bool>(obj) == true);
}
}
TEST_CASE("JsonObjectConst::operator bool()") {
SECTION("returns false") {
JsonObjectConst obj;
REQUIRE(static_cast<bool>(obj) == false);
}
SECTION("returns true") {
DynamicJsonDocument doc(4096);
JsonObjectConst obj = doc.to<JsonObject>();
REQUIRE(static_cast<bool>(obj) == true);
}
}

View File

@ -3,6 +3,7 @@
# MIT License
add_executable(JsonSerializerTests
CustomWriter.cpp
JsonArray.cpp
JsonArrayPretty.cpp
JsonObject.cpp

View File

@ -0,0 +1,52 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
class CustomWriter {
public:
CustomWriter() {}
size_t write(uint8_t c) {
_str.append(1, static_cast<char>(c));
return 1;
}
size_t write(const uint8_t *s, size_t n) {
_str.append(reinterpret_cast<const char *>(s), n);
return n;
}
const std::string &str() const {
return _str;
}
private:
CustomWriter(const CustomWriter &); // non-copiable
CustomWriter &operator=(const CustomWriter &);
std::string _str;
};
TEST_CASE("CustomWriter") {
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
array.add(4);
array.add(2);
SECTION("serializeJson()") {
CustomWriter writer;
serializeJson(array, writer);
REQUIRE("[4,2]" == writer.str());
}
SECTION("serializeJsonPretty") {
CustomWriter writer;
serializeJsonPretty(array, writer);
REQUIRE("[\r\n 4,\r\n 2\r\n]" == writer.str());
}
}

View File

@ -5,7 +5,7 @@
add_executable(MiscTests
conflicts.cpp
FloatParts.cpp
StreamReader.cpp
Readers.cpp
StringAdapters.cpp
StringWriter.cpp
TypeTraits.cpp

View File

@ -0,0 +1,225 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#include <ArduinoJson/Deserialization/Reader.hpp>
#include <catch.hpp>
using namespace ARDUINOJSON_NAMESPACE;
TEST_CASE("Reader<std::istringstream>") {
SECTION("read()") {
std::istringstream src("\x01\xFF");
Reader<std::istringstream> reader(src);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
std::istringstream src("ABC");
Reader<std::istringstream> reader(src);
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
std::istringstream src("ABCDEF");
Reader<std::istringstream> reader(src);
char buffer[12] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
TEST_CASE("BoundedReader<const char*>") {
SECTION("read") {
BoundedReader<const char*> reader("\x01\xFF", 2);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
BoundedReader<const char*> reader("ABCD", 3);
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
BoundedReader<const char*> reader("ABCDEF", 6);
char buffer[8] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
TEST_CASE("Reader<const char*>") {
SECTION("read()") {
Reader<const char*> reader("\x01\xFF\x00\x12");
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == 0);
REQUIRE(reader.read() == 0x12);
}
SECTION("readBytes() all at once") {
Reader<const char*> reader("ABCD");
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 3) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
Reader<const char*> reader("ABCDEF");
char buffer[8] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 2) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
TEST_CASE("IteratorReader") {
SECTION("read()") {
std::string src("\x01\xFF");
IteratorReader<std::string::const_iterator> reader(src.begin(), src.end());
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
std::string src("ABC");
IteratorReader<std::string::const_iterator> reader(src.begin(), src.end());
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
std::string src("ABCDEF");
IteratorReader<std::string::const_iterator> reader(src.begin(), src.end());
char buffer[12] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
class StreamStub : public Stream {
public:
StreamStub(const char* s) : _stream(s) {}
int read() {
return _stream.get();
}
size_t readBytes(char* buffer, size_t length) {
_stream.read(buffer, static_cast<std::streamsize>(length));
return static_cast<size_t>(_stream.gcount());
}
private:
std::istringstream _stream;
};
TEST_CASE("Reader<Stream>") {
SECTION("read()") {
StreamStub src("\x01\xFF");
Reader<StreamStub> reader(src);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
StreamStub src("ABC");
Reader<StreamStub> reader(src);
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
StreamStub src("ABCDEF");
Reader<StreamStub> reader(src);
char buffer[12] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}

View File

@ -1,33 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
using namespace ARDUINOJSON_NAMESPACE;
TEST_CASE("StdStreamReader") {
std::istringstream src("\x01\xFF");
StdStreamReader reader(src);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
}
TEST_CASE("SafeCharPointerReader") {
SafeCharPointerReader reader("\x01\xFF", 2);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
}
TEST_CASE("UnsafeCharPointerReader") {
UnsafeCharPointerReader reader("\x01\xFF");
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == 0);
}

View File

@ -49,15 +49,15 @@ TEST_CASE("StaticStringWriter") {
}
}
TEST_CASE("DynamicStringWriter<std::string>") {
TEST_CASE("Writer<std::string>") {
std::string output;
DynamicStringWriter<std::string> sb(output);
Writer<std::string> sb(output);
common_tests(sb, output);
}
TEST_CASE("DynamicStringWriter<custom_string>") {
TEST_CASE("Writer<custom_string>") {
custom_string output;
DynamicStringWriter<custom_string> sb(output);
Writer<custom_string> sb(output);
REQUIRE(4 == print(sb, "ABCD"));
REQUIRE("ABCD" == output);

View File

@ -28,4 +28,59 @@ TEST_CASE("nullptr") {
}
}
TEST_CASE("Issue #1120") {
StaticJsonDocument<500> doc;
constexpr char str[] =
"{\"contents\":[{\"module\":\"Packet\"},{\"module\":\"Analog\"}]}";
deserializeJson(doc, str);
SECTION("MemberProxy<std::string>::isNull()") {
SECTION("returns false") {
auto value = doc[std::string("contents")];
CHECK(value.isNull() == false);
}
SECTION("returns true") {
auto value = doc[std::string("zontents")];
CHECK(value.isNull() == true);
}
}
SECTION("ElementProxy<MemberProxy<const char*> >::isNull()") {
SECTION("returns false") { // Issue #1120
auto value = doc["contents"][1];
CHECK(value.isNull() == false);
}
SECTION("returns true") {
auto value = doc["contents"][2];
CHECK(value.isNull() == true);
}
}
SECTION("MemberProxy<ElementProxy<MemberProxy>, const char*>::isNull()") {
SECTION("returns false") {
auto value = doc["contents"][1]["module"];
CHECK(value.isNull() == false);
}
SECTION("returns true") {
auto value = doc["contents"][1]["zodule"];
CHECK(value.isNull() == true);
}
}
SECTION("MemberProxy<ElementProxy<MemberProxy>, std::string>::isNull()") {
SECTION("returns false") {
auto value = doc["contents"][1][std::string("module")];
CHECK(value.isNull() == false);
}
SECTION("returns true") {
auto value = doc["contents"][1][std::string("zodule")];
CHECK(value.isNull() == true);
}
}
}
#endif

View File

@ -85,3 +85,83 @@ TEST_CASE("memcpy_P") {
CHECK(dst[2] == 'C');
CHECK(dst[3] == 0);
}
TEST_CASE("BoundedReader<const __FlashStringHelper*>") {
using namespace ARDUINOJSON_NAMESPACE;
SECTION("read") {
BoundedReader<const __FlashStringHelper*> reader(F("\x01\xFF"), 2);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
BoundedReader<const __FlashStringHelper*> reader(F("ABCD"), 3);
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
BoundedReader<const __FlashStringHelper*> reader(F("ABCDEF"), 6);
char buffer[8] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
TEST_CASE("Reader<const __FlashStringHelper*>") {
using namespace ARDUINOJSON_NAMESPACE;
SECTION("read()") {
Reader<const __FlashStringHelper*> reader(F("\x01\xFF\x00\x12"));
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == 0);
REQUIRE(reader.read() == 0x12);
}
SECTION("readBytes() all at once") {
Reader<const __FlashStringHelper*> reader(F("ABCD"));
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 3) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
Reader<const __FlashStringHelper*> reader(F("ABCDEF"));
char buffer[8] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 2) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}

View File

@ -5,6 +5,8 @@
#include <ArduinoJson.h>
#include <catch.hpp>
#include "CustomReader.hpp"
TEST_CASE("deserializeMsgPack(const std::string&)") {
DynamicJsonDocument doc(4096);
@ -80,3 +82,14 @@ TEST_CASE("deserializeMsgPack(VLA)") {
REQUIRE(err == DeserializationError::Ok);
}
#endif
TEST_CASE("deserializeMsgPack(CustomReader)") {
DynamicJsonDocument doc(4096);
CustomReader reader("\x92\xA5Hello\xA5world");
DeserializationError err = deserializeMsgPack(doc, reader);
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc.size() == 2);
REQUIRE(doc[0] == "Hello");
REQUIRE(doc[1] == "world");
}

View File

@ -2,10 +2,10 @@
# Copyright Benoit Blanchon 2014-2019
# MIT License
add_executable(JsonWriterTests
add_executable(TextFormatterTests
writeFloat.cpp
writeString.cpp
)
target_link_libraries(JsonWriterTests catch)
add_test(TextFormatter JsonWriterTests)
target_link_libraries(TextFormatterTests catch)
add_test(TextFormatter TextFormatterTests)

View File

@ -9,15 +9,15 @@
#define ARDUINOJSON_ENABLE_NAN 1
#define ARDUINOJSON_ENABLE_INFINITY 1
#include <ArduinoJson/Json/TextFormatter.hpp>
#include <ArduinoJson/Serialization/DynamicStringWriter.hpp>
#include <ArduinoJson/Serialization/Writer.hpp>
using namespace ARDUINOJSON_NAMESPACE;
template <typename TFloat>
void check(TFloat input, const std::string& expected) {
std::string output;
DynamicStringWriter<std::string> sb(output);
TextFormatter<DynamicStringWriter<std::string> > writer(sb);
Writer<std::string> sb(output);
TextFormatter<Writer<std::string> > writer(sb);
writer.writeFloat(input);
REQUIRE(writer.bytesWritten() == output.size());
CHECK(expected == output);

View File

@ -5,7 +5,7 @@
#include <catch.hpp>
#include <ArduinoJson/Json/TextFormatter.hpp>
#include <ArduinoJson/Serialization/StaticStringWriter.hpp>
#include <ArduinoJson/Serialization/Writers/StaticStringWriter.hpp>
using namespace ARDUINOJSON_NAMESPACE;

View File

@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"version": "6.12.0",
"version": "6.13.0",
"authors": {
"name": "Benoit Blanchon",
"url": "https://blog.benoitblanchon.fr"

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=6.12.0
version=6.13.0
author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=An efficient and elegant JSON library for Arduino.

View File

@ -19,4 +19,10 @@ inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
return impl()->addElement().template to<ObjectRef>();
}
template <typename TArray>
inline ElementProxy<TArray> ArrayShortcuts<TArray>::operator[](
size_t index) const {
return ElementProxy<TArray>(*impl(), index);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -36,6 +36,10 @@ class ArrayRefBase {
return _data == 0;
}
FORCE_INLINE operator bool() const {
return _data != 0;
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}

View File

@ -16,7 +16,7 @@ template <typename TArray>
class ArrayShortcuts {
public:
// Returns the element at specified index if the variant is an array.
FORCE_INLINE ElementProxy<const TArray &> operator[](size_t index) const;
FORCE_INLINE ElementProxy<TArray> operator[](size_t index) const;
FORCE_INLINE ObjectRef createNestedObject() const;

View File

@ -161,12 +161,6 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
const size_t _index;
};
template <typename TArray>
inline ElementProxy<const TArray&> ArrayShortcuts<TArray>::operator[](
size_t index) const {
return ElementProxy<const TArray&>(*impl(), index);
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <stddef.h> // size_t
namespace ARDUINOJSON_NAMESPACE {

View File

@ -20,8 +20,11 @@
// Small or big machine?
#ifndef ARDUINOJSON_EMBEDDED_MODE
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
defined(__ARMCC_VERSION)
#if defined(ARDUINO) /* Arduino*/ \
|| defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \
|| defined(__XC) /* MPLAB XC compiler */ \
|| defined(__ARMCC_VERSION) /* Keil ARM Compiler */ \
|| defined(__AVR) /* Atmel AVR8/GNU C Compiler */
#define ARDUINOJSON_EMBEDDED_MODE 1
#else
#define ARDUINOJSON_EMBEDDED_MODE 0

View File

@ -1,31 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
#include <Stream.h>
namespace ARDUINOJSON_NAMESPACE {
struct ArduinoStreamReader {
Stream& _stream;
public:
explicit ArduinoStreamReader(Stream& stream) : _stream(stream) {}
int read() {
// don't use _stream.read() as it ignores the timeout
char c;
return _stream.readBytes(&c, 1) ? c : -1;
}
};
inline ArduinoStreamReader makeReader(Stream& input) {
return ArduinoStreamReader(input);
}
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -1,67 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
struct IsCharOrVoid {
static const bool value =
is_same<T, void>::value || is_same<T, char>::value ||
is_same<T, unsigned char>::value || is_same<T, signed char>::value;
};
template <typename T>
struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
class UnsafeCharPointerReader {
const char* _ptr;
public:
explicit UnsafeCharPointerReader(const char* ptr)
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")) {}
int read() {
return static_cast<unsigned char>(*_ptr++);
}
};
class SafeCharPointerReader {
const char* _ptr;
const char* _end;
public:
explicit SafeCharPointerReader(const char* ptr, size_t len)
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")), _end(_ptr + len) {}
int read() {
if (_ptr < _end)
return static_cast<unsigned char>(*_ptr++);
else
return -1;
}
};
template <typename TChar>
inline typename enable_if<IsCharOrVoid<TChar>::value,
UnsafeCharPointerReader>::type
makeReader(TChar* input) {
return UnsafeCharPointerReader(reinterpret_cast<const char*>(input));
}
template <typename TChar>
inline
typename enable_if<IsCharOrVoid<TChar>::value, SafeCharPointerReader>::type
makeReader(TChar* input, size_t n) {
return SafeCharPointerReader(reinterpret_cast<const char*>(input), n);
}
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
inline SafeCharPointerReader makeReader(const ::String& input) {
return SafeCharPointerReader(input.c_str(), input.length());
}
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ostream>
#endif

View File

@ -1,48 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_PROGMEM
namespace ARDUINOJSON_NAMESPACE {
class UnsafeFlashStringReader {
const char* _ptr;
public:
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
: _ptr(reinterpret_cast<const char*>(ptr)) {}
int read() {
return pgm_read_byte(_ptr++);
}
};
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) {}
int read() {
if (_ptr < _end)
return pgm_read_byte(_ptr++);
else
return -1;
}
};
inline UnsafeFlashStringReader makeReader(const __FlashStringHelper* input) {
return UnsafeFlashStringReader(input);
}
inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
size_t size) {
return SafeFlashStringReader(input, size);
}
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -1,31 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <typename TIterator>
class IteratorReader {
TIterator _ptr, _end;
public:
explicit IteratorReader(TIterator begin, TIterator end)
: _ptr(begin), _end(end) {}
int read() {
if (_ptr < _end)
return static_cast<unsigned char>(*_ptr++);
else
return -1;
}
};
template <typename TInput>
inline IteratorReader<typename TInput::const_iterator> makeReader(
const TInput& input) {
return IteratorReader<typename TInput::const_iterator>(input.begin(),
input.end());
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,7 +4,7 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {

View File

@ -0,0 +1,55 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <stdlib.h> // for size_t
namespace ARDUINOJSON_NAMESPACE {
// The default reader is a simple wrapper for Readers that are not copiable
template <typename TSource, typename Enable = void>
struct Reader {
public:
Reader(TSource& source) : _source(&source) {}
int read() {
return _source->read();
}
size_t readBytes(char* buffer, size_t length) {
return _source->readBytes(buffer, length);
}
private:
TSource* _source;
};
template <typename TSource, typename Enable = void>
struct BoundedReader {
// no default implementation because we need to pass the size to the
// constructor
};
} // namespace ARDUINOJSON_NAMESPACE
#include <ArduinoJson/Deserialization/Readers/IteratorReader.hpp>
#include <ArduinoJson/Deserialization/Readers/RamReader.hpp>
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
#include <ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp>
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp>
#endif
#if ARDUINOJSON_ENABLE_PROGMEM
#include <ArduinoJson/Deserialization/Readers/FlashReader.hpp>
#endif
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ArduinoJson/Deserialization/Readers/StdStreamReader.hpp>
#endif

View File

@ -0,0 +1,31 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <Stream.h>
namespace ARDUINOJSON_NAMESPACE {
template <typename TSource>
struct Reader<TSource,
typename enable_if<is_base_of<Stream, TSource>::value>::type> {
public:
explicit Reader(Stream& stream) : _stream(&stream) {}
int read() {
// don't use _stream.read() as it ignores the timeout
char c;
return _stream->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
}
size_t readBytes(char* buffer, size_t length) {
return _stream->readBytes(buffer, length);
}
private:
Stream* _stream;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,17 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <typename TSource>
struct Reader<TSource,
typename enable_if<is_base_of< ::String, TSource>::value>::type>
: BoundedReader<const char*> {
explicit Reader(const ::String& s)
: BoundedReader<const char*>(s.c_str(), s.length()) {}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,52 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <>
struct Reader<const __FlashStringHelper*, void> {
const char* _ptr;
public:
explicit Reader(const __FlashStringHelper* ptr)
: _ptr(reinterpret_cast<const char*>(ptr)) {}
int read() {
return pgm_read_byte(_ptr++);
}
size_t readBytes(char* buffer, size_t length) {
memcpy_P(buffer, _ptr, length);
_ptr += length;
return length;
}
};
template <>
struct BoundedReader<const __FlashStringHelper*, void> {
const char* _ptr;
const char* _end;
public:
explicit BoundedReader(const __FlashStringHelper* ptr, size_t size)
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
int read() {
if (_ptr < _end)
return pgm_read_byte(_ptr++);
else
return -1;
}
size_t readBytes(char* buffer, size_t length) {
size_t available = static_cast<size_t>(_end - _ptr);
if (available < length) length = available;
memcpy_P(buffer, _ptr, length);
_ptr += length;
return length;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,43 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <typename TIterator>
class IteratorReader {
TIterator _ptr, _end;
public:
explicit IteratorReader(TIterator begin, TIterator end)
: _ptr(begin), _end(end) {}
int read() {
if (_ptr < _end)
return static_cast<unsigned char>(*_ptr++);
else
return -1;
}
size_t readBytes(char* buffer, size_t length) {
size_t i = 0;
while (i < length && _ptr < _end) buffer[i++] = *_ptr++;
return i;
}
};
template <typename T>
struct void_ {
typedef void type;
};
template <typename TSource>
struct Reader<TSource, typename void_<typename TSource::const_iterator>::type>
: IteratorReader<typename TSource::const_iterator> {
explicit Reader(const TSource& source)
: IteratorReader<typename TSource::const_iterator>(source.begin(),
source.end()) {}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,50 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
struct IsCharOrVoid {
static const bool value =
is_same<T, void>::value || is_same<T, char>::value ||
is_same<T, unsigned char>::value || is_same<T, signed char>::value;
};
template <typename T>
struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
template <typename TSource>
struct Reader<TSource*,
typename enable_if<IsCharOrVoid<TSource>::value>::type> {
const char* _ptr;
public:
explicit Reader(const void* ptr)
: _ptr(ptr ? reinterpret_cast<const char*>(ptr) : "") {}
int read() {
return static_cast<unsigned char>(*_ptr++);
}
size_t readBytes(char* buffer, size_t length) {
for (size_t i = 0; i < length; i++) buffer[i] = *_ptr++;
return length;
}
};
template <typename TSource>
struct BoundedReader<TSource*,
typename enable_if<IsCharOrVoid<TSource>::value>::type>
: public IteratorReader<const char*> {
public:
explicit BoundedReader(const void* ptr, size_t len)
: IteratorReader<const char*>(reinterpret_cast<const char*>(ptr),
reinterpret_cast<const char*>(ptr) + len) {}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,29 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <istream>
namespace ARDUINOJSON_NAMESPACE {
template <typename TSource>
struct Reader<TSource, typename enable_if<
is_base_of<std::istream, TSource>::value>::type> {
public:
explicit Reader(std::istream& stream) : _stream(&stream) {}
int read() {
return _stream->get();
}
size_t readBytes(char* buffer, size_t length) {
_stream->read(buffer, static_cast<std::streamsize>(length));
return static_cast<size_t>(_stream->gcount());
}
private:
std::istream* _stream;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,34 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <istream>
namespace ARDUINOJSON_NAMESPACE {
class StdStreamReader {
std::istream& _stream;
char _current;
public:
explicit StdStreamReader(std::istream& stream)
: _stream(stream), _current(0) {}
int read() {
return _stream.get();
}
private:
StdStreamReader& operator=(const StdStreamReader&); // Visual Studio C4512
};
inline StdStreamReader makeReader(std::istream& input) {
return StdStreamReader(input);
}
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -4,13 +4,9 @@
#pragma once
#include <ArduinoJson/Deserialization/ArduinoStreamReader.hpp>
#include <ArduinoJson/Deserialization/CharPointerReader.hpp>
#include <ArduinoJson/Deserialization/DeserializationError.hpp>
#include <ArduinoJson/Deserialization/FlashStringReader.hpp>
#include <ArduinoJson/Deserialization/IteratorReader.hpp>
#include <ArduinoJson/Deserialization/NestingLimit.hpp>
#include <ArduinoJson/Deserialization/StdStreamReader.hpp>
#include <ArduinoJson/Deserialization/Reader.hpp>
#include <ArduinoJson/StringStorage/StringStorage.hpp>
namespace ARDUINOJSON_NAMESPACE {
@ -25,26 +21,17 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
// deserialize(JsonDocument&, const std::string&);
// deserialize(JsonDocument&, const String&);
// deserialize(JsonDocument&, char*);
// deserialize(JsonDocument&, const char*);
// deserialize(JsonDocument&, const __FlashStringHelper*);
template <template <typename, typename> class TDeserializer, typename TString>
typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(JsonDocument &doc, const TString &input,
NestingLimit nestingLimit) {
Reader<TString> reader(input);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
//
// deserialize(JsonDocument&, char*);
// deserialize(JsonDocument&, const char*);
// deserialize(JsonDocument&, const __FlashStringHelper*);
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
doc.memoryPool(), reader,
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
@ -55,9 +42,10 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
size_t inputSize, NestingLimit nestingLimit) {
BoundedReader<TChar *> reader(input, inputSize);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input, inputSize),
doc.memoryPool(), reader,
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
@ -67,9 +55,10 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
template <template <typename, typename> class TDeserializer, typename TStream>
DeserializationError deserialize(JsonDocument &doc, TStream &input,
NestingLimit nestingLimit) {
Reader<TStream> reader(input);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
doc.memoryPool(), reader,
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}

View File

@ -141,11 +141,10 @@ class JsonDocument : public Visitable {
// operator[](const std::string&)
// operator[](const String&)
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value,
MemberProxy<JsonDocument&, const TString&> >::type
operator[](const TString& key) {
return MemberProxy<JsonDocument&, const TString&>(*this, key);
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<JsonDocument&, TString> >::type
operator[](const TString& key) {
return MemberProxy<JsonDocument&, TString>(*this, key);
}
// operator[](char*)

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
class EscapeSequence {

View File

@ -130,15 +130,21 @@ class JsonDeserializer {
// Read each key value pair
for (;;) {
// Allocate slot in object
VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory;
// Parse key
const char *key;
err = parseKey(key);
if (err) return err;
slot->setOwnedKey(make_not_null(key));
VariantData *variant = object.get(adaptString(key));
if (!variant) {
// Allocate slot in object
VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory;
slot->setOwnedKey(make_not_null(key));
variant = slot->data();
}
// Skip spaces
err = skipSpacesAndComments();
@ -147,7 +153,7 @@ class JsonDeserializer {
// Parse value
_nestingLimit--;
err = parseVariant(*slot->data());
err = parseVariant(*variant);
_nestingLimit++;
if (err) return err;

View File

@ -14,7 +14,7 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonSerializer {
public:
JsonSerializer(TWriter &writer) : _formatter(writer) {}
JsonSerializer(TWriter writer) : _formatter(writer) {}
FORCE_INLINE void visitArray(const CollectionData &array) {
write('[');

View File

@ -17,7 +17,7 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class TextFormatter {
public:
explicit TextFormatter(TWriter &writer) : _writer(writer), _length(0) {}
explicit TextFormatter(TWriter writer) : _writer(writer), _length(0) {}
// Returns the number of bytes sent to the TWriter implementation.
size_t bytesWritten() const {
@ -147,7 +147,7 @@ class TextFormatter {
}
protected:
TWriter &_writer;
TWriter _writer;
size_t _length;
private:

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
namespace Utf8 {

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <stddef.h> // size_t
namespace ARDUINOJSON_NAMESPACE {

View File

@ -6,7 +6,7 @@
#include <stddef.h> // for size_t
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Namespace.hpp>
#define JSON_STRING_SIZE(SIZE) (SIZE)

View File

@ -142,10 +142,7 @@ class MsgPackDeserializer {
}
bool readBytes(uint8_t *p, size_t n) {
for (size_t i = 0; i < n; i++) {
if (!readByte(p[i])) return false;
}
return true;
return _reader.readBytes(reinterpret_cast<char *>(p), n) == n;
}
template <typename T>

View File

@ -15,7 +15,7 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class MsgPackSerializer {
public:
MsgPackSerializer(TWriter& writer) : _writer(&writer), _bytesWritten(0) {}
MsgPackSerializer(TWriter writer) : _writer(writer), _bytesWritten(0) {}
template <typename T>
typename enable_if<sizeof(T) == 4>::type visitFloat(T value32) {
@ -150,11 +150,11 @@ class MsgPackSerializer {
private:
void writeByte(uint8_t c) {
_bytesWritten += _writer->write(c);
_bytesWritten += _writer.write(c);
}
void writeBytes(const uint8_t* p, size_t n) {
_bytesWritten += _writer->write(p, n);
_bytesWritten += _writer.write(p, n);
}
template <typename T>
@ -163,7 +163,7 @@ class MsgPackSerializer {
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
}
TWriter* _writer;
TWriter _writer;
size_t _bytesWritten;
};

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {

View File

@ -5,6 +5,7 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {

View File

@ -5,6 +5,7 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Namespace.hpp>
#include <stdint.h> // int64_t

View File

@ -174,22 +174,6 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
TStringRef _key;
};
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
MemberProxy<const TObject &, const TString &> >::type
ObjectShortcuts<TObject>::operator[](const TString &key) const {
return MemberProxy<const TObject &, const TString &>(*impl(), key);
}
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString *>::value,
MemberProxy<const TObject &, TString *> >::type
ObjectShortcuts<TObject>::operator[](TString *key) const {
return MemberProxy<const TObject &, TString *>(*impl(), key);
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER

View File

@ -49,4 +49,21 @@ inline typename enable_if<IsString<TChar*>::value, bool>::type
ObjectShortcuts<TObject>::containsKey(TChar* key) const {
return !impl()->getMember(key).isUndefined();
}
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString*>::value,
MemberProxy<TObject, TString*> >::type
ObjectShortcuts<TObject>::operator[](TString* key) const {
return MemberProxy<TObject, TString*>(*impl(), key);
}
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
MemberProxy<TObject, TString> >::type
ObjectShortcuts<TObject>::operator[](const TString& key) const {
return MemberProxy<TObject, TString>(*impl(), key);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -31,6 +31,10 @@ class ObjectRefBase {
return _data == 0;
}
FORCE_INLINE operator bool() const {
return _data != 0;
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}

View File

@ -31,17 +31,16 @@ class ObjectShortcuts {
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value,
MemberProxy<const TObject &, const TString &> >::type
operator[](const TString &key) const;
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<TObject, TString> >::type
operator[](const TString &key) const;
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value,
MemberProxy<const TObject &, TChar *> >::type
MemberProxy<TObject, TChar *> >::type
operator[](TChar *key) const;
// createNestedArray(const std::string&) const

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
inline bool isdigit(char c) {

View File

@ -4,6 +4,7 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Polyfills/assert.hpp>
namespace ARDUINOJSON_NAMESPACE {

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
// Some libraries #define isnan() and isinf() so we need to check before

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <stddef.h> // for size_t
namespace ARDUINOJSON_NAMESPACE {

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
// Wraps a const char* so that the our functions are picked only if the
// originals are missing

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
inline int8_t safe_strcmp(const char* a, const char* b) {

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <bool Condition, class TrueType, class FalseType>

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T if Condition is true.

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T, T v>

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <stddef.h> // size_t
namespace ARDUINOJSON_NAMESPACE {

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that returns true if Derived inherits from TBase is an

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T without the const modifier

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T without the reference modifier.

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline void swap(T& a, T& b) {

View File

@ -1,82 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <WString.h>
#endif
#if ARDUINOJSON_ENABLE_STD_STRING
#include <string>
#endif
namespace ARDUINOJSON_NAMESPACE {
template <typename>
struct IsWriteableString : false_type {};
// A Print implementation that allows to write in a String
template <typename TString>
class DynamicStringWriter {};
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
template <>
struct IsWriteableString<String> : true_type {};
template <>
class DynamicStringWriter<String> {
public:
DynamicStringWriter(String &str) : _str(&str) {}
size_t write(uint8_t c) {
_str->operator+=(static_cast<char>(c));
return 1;
}
size_t write(const uint8_t *s, size_t n) {
// CAUTION: Arduino String doesn't have append()
// and old version doesn't have size() either
_str->reserve(_str->length() + n);
while (n > 0) {
_str->operator+=(static_cast<char>(*s++));
n--;
}
return n;
}
private:
String *_str;
};
#endif
#if ARDUINOJSON_ENABLE_STD_STRING
template <typename TCharTraits, typename TAllocator>
struct IsWriteableString<std::basic_string<char, TCharTraits, TAllocator> >
: true_type {};
template <typename TCharTraits, typename TAllocator>
class DynamicStringWriter<std::basic_string<char, TCharTraits, TAllocator> > {
typedef std::basic_string<char, TCharTraits, TAllocator> string_type;
public:
DynamicStringWriter(string_type &str) : _str(&str) {}
size_t write(uint8_t c) {
_str->operator+=(static_cast<char>(c));
return 1;
}
size_t write(const uint8_t *s, size_t n) {
_str->append(reinterpret_cast<const char *>(s), n);
return n;
}
private:
string_type *_str;
};
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,38 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Configuration.hpp>
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ostream>
namespace ARDUINOJSON_NAMESPACE {
class StreamWriter {
public:
explicit StreamWriter(std::ostream& os) : _os(os) {}
size_t write(uint8_t c) {
_os << c;
return 1;
}
size_t write(const uint8_t* s, size_t n) {
_os.write(reinterpret_cast<const char*>(s),
static_cast<std::streamsize>(n));
return n;
}
private:
// cannot be assigned
StreamWriter& operator=(const StreamWriter&);
std::ostream& _os;
};
} // namespace ARDUINOJSON_NAMESPACE
#endif // ARDUINOJSON_ENABLE_STD_STREAM

View File

@ -0,0 +1,47 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
// The default writer is a simple wrapper for Writers that are not copiable
template <typename TDestination, typename Enable = void>
class Writer {
public:
explicit Writer(TDestination& dest) : _dest(&dest) {}
size_t write(uint8_t c) {
return _dest->write(c);
}
size_t write(const uint8_t* s, size_t n) {
return _dest->write(s, n);
}
private:
TDestination* _dest;
};
} // namespace ARDUINOJSON_NAMESPACE
#include <ArduinoJson/Serialization/Writers/StaticStringWriter.hpp>
#if ARDUINOJSON_ENABLE_STD_STRING
#include <ArduinoJson/Serialization/Writers/StdStringWriter.hpp>
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp>
#endif
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ArduinoJson/Serialization/Writers/StdStreamWriter.hpp>
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
#include <ArduinoJson/Serialization/Writers/PrintWriter.hpp>
#endif

View File

@ -0,0 +1,36 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <WString.h>
namespace ARDUINOJSON_NAMESPACE {
template <>
class Writer< ::String, void> {
public:
explicit Writer(::String &str) : _str(&str) {}
size_t write(uint8_t c) {
_str->operator+=(static_cast<char>(c));
return 1;
}
size_t write(const uint8_t *s, size_t n) {
// CAUTION: Arduino String doesn't have append()
// and old version doesn't have size() either
_str->reserve(_str->length() + n);
while (n > 0) {
_str->operator+=(static_cast<char>(*s++));
n--;
}
return n;
}
private:
::String *_str;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
class DummyWriter {

View File

@ -0,0 +1,28 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <typename TDestination>
class Writer<
TDestination,
typename enable_if<is_base_of< ::Print, TDestination>::value>::type> {
public:
explicit Writer(::Print& print) : _print(&print) {}
size_t write(uint8_t c) {
return _print->write(c);
}
size_t write(const uint8_t* s, size_t n) {
return _print->write(s, n);
}
private:
::Print* _print;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A Print implementation that allows to write in a char[]

View File

@ -0,0 +1,32 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ostream>
namespace ARDUINOJSON_NAMESPACE {
template <typename TDestination>
class Writer<
TDestination,
typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
public:
explicit Writer(std::ostream& os) : _os(&os) {}
size_t write(uint8_t c) {
_os->put(static_cast<char>(c));
return 1;
}
size_t write(const uint8_t* s, size_t n) {
_os->write(reinterpret_cast<const char*>(s),
static_cast<std::streamsize>(n));
return n;
}
private:
std::ostream* _os;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,40 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <string>
namespace ARDUINOJSON_NAMESPACE {
template <class T>
struct is_std_string : false_type {};
template <class TCharTraits, class TAllocator>
struct is_std_string<std::basic_string<char, TCharTraits, TAllocator> >
: true_type {};
template <typename TDestination>
class Writer<TDestination,
typename enable_if<is_std_string<TDestination>::value>::type> {
public:
Writer(TDestination &str) : _str(&str) {}
size_t write(uint8_t c) {
_str->operator+=(static_cast<char>(c));
return 1;
}
size_t write(const uint8_t *s, size_t n) {
_str->append(reinterpret_cast<const char *>(s), n);
return n;
}
private:
TDestination *_str;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,7 +4,7 @@
#pragma once
#include <ArduinoJson/Serialization/DummyWriter.hpp>
#include <ArduinoJson/Serialization/Writers/DummyWriter.hpp>
namespace ARDUINOJSON_NAMESPACE {

View File

@ -4,37 +4,24 @@
#pragma once
#include <ArduinoJson/Serialization/DynamicStringWriter.hpp>
#include <ArduinoJson/Serialization/StaticStringWriter.hpp>
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ArduinoJson/Serialization/StreamWriter.hpp>
#endif
#include <ArduinoJson/Serialization/Writer.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <template <typename> class TSerializer, typename TSource,
typename TDestination>
size_t doSerialize(const TSource &source, TDestination &destination) {
TSerializer<TDestination> serializer(destination);
typename TWriter>
size_t doSerialize(const TSource &source, TWriter writer) {
TSerializer<TWriter> serializer(writer);
source.accept(serializer);
return serializer.bytesWritten();
}
#if ARDUINOJSON_ENABLE_STD_STREAM
template <template <typename> class TSerializer, typename TSource>
size_t serialize(const TSource &source, std::ostream &destination) {
StreamWriter writer(destination);
template <template <typename> class TSerializer, typename TSource,
typename TDestination>
size_t serialize(const TSource &source, TDestination &destination) {
Writer<TDestination> writer(destination);
return doSerialize<TSerializer>(source, writer);
}
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
template <template <typename> class TSerializer, typename TSource>
size_t serialize(const TSource &source, Print &destination) {
return doSerialize<TSerializer>(source, destination);
}
#endif
template <template <typename> class TSerializer, typename TSource>
size_t serialize(const TSource &source, char *buffer, size_t bufferSize) {
@ -48,12 +35,4 @@ size_t serialize(const TSource &source, char (&buffer)[N]) {
return doSerialize<TSerializer>(source, writer);
}
template <template <typename> class TSerializer, typename TSource,
typename TString>
typename enable_if<IsWriteableString<TString>::value, size_t>::type serialize(
const TSource &source, TString &str) {
DynamicStringWriter<TString> writer(str);
return doSerialize<TSerializer>(source, writer);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
class StringMover {

View File

@ -0,0 +1,37 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <WString.h>
#endif
#if ARDUINOJSON_ENABLE_STD_STRING
#include <string>
#endif
namespace ARDUINOJSON_NAMESPACE {
template <typename>
struct IsWriteableString : false_type {};
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
template <>
struct IsWriteableString< ::String> : true_type {};
#endif
#if ARDUINOJSON_ENABLE_STD_STRING
template <typename TCharTraits, typename TAllocator>
struct IsWriteableString<std::basic_string<char, TCharTraits, TAllocator> >
: true_type {};
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
class SizedFlashStringAdapter {

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <string.h> // strcmp
namespace ARDUINOJSON_NAMESPACE {

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <string>
namespace ARDUINOJSON_NAMESPACE {

View File

@ -4,7 +4,7 @@
#pragma once
#include <ArduinoJson/Serialization/DynamicStringWriter.hpp>
#include <ArduinoJson/Strings/IsWriteableString.hpp>
namespace ARDUINOJSON_NAMESPACE {

View File

@ -4,7 +4,7 @@
#pragma once
#include <ArduinoJson/Serialization/DynamicStringWriter.hpp>
#include <ArduinoJson/Strings/IsWriteableString.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>

View File

@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
class ArrayRef;
class ObjectRef;

View File

@ -4,7 +4,7 @@
#pragma once
#define ARDUINOJSON_VERSION "6.12.0"
#define ARDUINOJSON_VERSION "6.13.0"
#define ARDUINOJSON_VERSION_MAJOR 6
#define ARDUINOJSON_VERSION_MINOR 12
#define ARDUINOJSON_VERSION_MINOR 13
#define ARDUINOJSON_VERSION_REVISION 0