Update ArduinoJSON, esp-nimble-cpp, Arduino Core, ESP-IDF (#448)
* ArduinoJSON 7.1.0 * Update nimble and arduino core * Update nuki_ble
This commit is contained in:
@@ -1,6 +1,21 @@
|
|||||||
ArduinoJson: change log
|
ArduinoJson: change log
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
v7.1.0 (2024-06-27)
|
||||||
|
------
|
||||||
|
|
||||||
|
* Add `ARDUINOJSON_STRING_LENGTH_SIZE` to the namespace name
|
||||||
|
* Add support for MsgPack binary (PR #2078 by @Sanae6)
|
||||||
|
* Add support for MsgPack extension
|
||||||
|
* Make string support even more generic (PR #2084 by @d-a-v)
|
||||||
|
* Optimize `deserializeMsgPack()`
|
||||||
|
* Allow using a `JsonVariant` as a key or index (issue #2080)
|
||||||
|
Note: works only for reading, not for writing
|
||||||
|
* Support `ElementProxy` and `MemberProxy` in `JsonDocument`'s constructor
|
||||||
|
* Don't add partial objects when allocation fails (issue #2081)
|
||||||
|
* Read MsgPack's 64-bit integers even if `ARDUINOJSON_USE_LONG_LONG` is `0`
|
||||||
|
(they are set to `null` if they don't fit in a `long`)
|
||||||
|
|
||||||
v7.0.4 (2024-03-12)
|
v7.0.4 (2024-03-12)
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ if(ESP_PLATFORM)
|
|||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(ArduinoJson VERSION 7.0.4)
|
project(ArduinoJson VERSION 7.1.0)
|
||||||
|
|
||||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|||||||
46
lib/ArduinoJson/README
Normal file
46
lib/ArduinoJson/README
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
version: 7.0.4.{build}
|
version: 7.1.0.{build}
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
if(NOT DEFINED COVERAGE)
|
||||||
|
set(COVERAGE OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
-pedantic
|
-pedantic
|
||||||
@@ -30,7 +34,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8) AND(NOT ${COVERAGE}))
|
if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9) AND(NOT ${COVERAGE}))
|
||||||
add_compile_options(-g -Og)
|
add_compile_options(-g -Og)
|
||||||
else() # GCC 4.8
|
else() # GCC 4.8
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
|
|||||||
@@ -52,7 +52,16 @@ macro(add_fuzzer name)
|
|||||||
)
|
)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6)
|
# Needs Clang 6+ to compile
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6)
|
||||||
|
if(DEFINED ENV{GITHUB_ACTIONS} AND CMAKE_CXX_COMPILER_VERSION MATCHES "^11\\.")
|
||||||
|
# Clang 11 fails on GitHub Actions with the following error:
|
||||||
|
# > ERROR: UndefinedBehaviorSanitizer failed to allocate 0x0 (0) bytes of SetAlternateSignalStack (error code: 22)
|
||||||
|
# > Sanitizer CHECK failed: /build/llvm-toolchain-11-mnvtwk/llvm-toolchain-11-11.1.0/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp:54 ((0 && "unable to mmap")) != (0) (0, 0)
|
||||||
|
message(WARNING "Fuzzing is disabled on GitHub Actions to workaround a bug in Clang 11")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
add_fuzzer(json)
|
add_fuzzer(json)
|
||||||
add_fuzzer(msgpack)
|
add_fuzzer(msgpack)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
#if !ARDUINOJSON_ENABLE_STRING_VIEW
|
#if !ARDUINOJSON_ENABLE_STRING_VIEW
|
||||||
# error ARDUINOJSON_ENABLE_STRING_VIEW must be set to 1
|
# error ARDUINOJSON_ENABLE_STRING_VIEW must be set to 1
|
||||||
@@ -92,7 +93,7 @@ TEST_CASE("string_view") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("String containing NUL") {
|
SECTION("String containing NUL") {
|
||||||
doc.set(std::string("hello\0world", 11));
|
doc.set("hello\0world"_s);
|
||||||
REQUIRE(doc.as<std::string_view>().size() == 11);
|
REQUIRE(doc.as<std::string_view>().size() == 11);
|
||||||
REQUIRE(doc.as<std::string_view>() == std::string_view("hello\0world", 11));
|
REQUIRE(doc.as<std::string_view>() == std::string_view("hello\0world", 11));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::createNestedArray()") {
|
TEST_CASE("JsonDocument::createNestedArray()") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
@@ -23,7 +25,7 @@ TEST_CASE("JsonDocument::createNestedArray()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createNestedArray(std::string)") {
|
SECTION("createNestedArray(std::string)") {
|
||||||
JsonArray array = doc.createNestedArray(std::string("key"));
|
JsonArray array = doc.createNestedArray("key"_s);
|
||||||
array.add(42);
|
array.add(42);
|
||||||
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}");
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}");
|
||||||
}
|
}
|
||||||
@@ -59,7 +61,7 @@ TEST_CASE("JsonObject::createNestedArray()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createNestedArray(std::string)") {
|
SECTION("createNestedArray(std::string)") {
|
||||||
JsonArray array = object.createNestedArray(std::string("key"));
|
JsonArray array = object.createNestedArray("key"_s);
|
||||||
array.add(42);
|
array.add(42);
|
||||||
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}");
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}");
|
||||||
}
|
}
|
||||||
@@ -93,7 +95,7 @@ TEST_CASE("JsonVariant::createNestedArray()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createNestedArray(std::string)") {
|
SECTION("createNestedArray(std::string)") {
|
||||||
JsonArray array = variant.createNestedArray(std::string("key"));
|
JsonArray array = variant.createNestedArray("key"_s);
|
||||||
array.add(42);
|
array.add(42);
|
||||||
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}");
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::createNestedObject()") {
|
TEST_CASE("JsonDocument::createNestedObject()") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
@@ -23,7 +25,7 @@ TEST_CASE("JsonDocument::createNestedObject()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createNestedObject(std::string)") {
|
SECTION("createNestedObject(std::string)") {
|
||||||
JsonObject object = doc.createNestedObject(std::string("key"));
|
JsonObject object = doc.createNestedObject("key"_s);
|
||||||
object["hello"] = "world";
|
object["hello"] = "world";
|
||||||
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}");
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}");
|
||||||
}
|
}
|
||||||
@@ -59,7 +61,7 @@ TEST_CASE("JsonObject::createNestedObject()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createNestedObject(std::string)") {
|
SECTION("createNestedObject(std::string)") {
|
||||||
JsonObject nestedObject = object.createNestedObject(std::string("key"));
|
JsonObject nestedObject = object.createNestedObject("key"_s);
|
||||||
nestedObject["hello"] = "world";
|
nestedObject["hello"] = "world";
|
||||||
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}");
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}");
|
||||||
}
|
}
|
||||||
@@ -93,7 +95,7 @@ TEST_CASE("JsonVariant::createNestedObject()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createNestedObject(std::string)") {
|
SECTION("createNestedObject(std::string)") {
|
||||||
JsonObject object = variant.createNestedObject(std::string("key"));
|
JsonObject object = variant.createNestedObject("key"_s);
|
||||||
object["hello"] = "world";
|
object["hello"] = "world";
|
||||||
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}");
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
struct FailingAllocator : ArduinoJson::Allocator {
|
struct FailingAllocator : ArduinoJson::Allocator {
|
||||||
static FailingAllocator* instance() {
|
static FailingAllocator* instance() {
|
||||||
static FailingAllocator allocator;
|
static FailingAllocator allocator;
|
||||||
@@ -54,31 +56,31 @@ class AllocatorLogEntry {
|
|||||||
|
|
||||||
inline AllocatorLogEntry Allocate(size_t s) {
|
inline AllocatorLogEntry Allocate(size_t s) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "allocate(%zu)", s);
|
snprintf(buffer, sizeof(buffer), "allocate(%zu)", s);
|
||||||
return AllocatorLogEntry(buffer);
|
return AllocatorLogEntry(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline AllocatorLogEntry AllocateFail(size_t s) {
|
inline AllocatorLogEntry AllocateFail(size_t s) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "allocate(%zu) -> nullptr", s);
|
snprintf(buffer, sizeof(buffer), "allocate(%zu) -> nullptr", s);
|
||||||
return AllocatorLogEntry(buffer);
|
return AllocatorLogEntry(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline AllocatorLogEntry Reallocate(size_t s1, size_t s2) {
|
inline AllocatorLogEntry Reallocate(size_t s1, size_t s2) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "reallocate(%zu, %zu)", s1, s2);
|
snprintf(buffer, sizeof(buffer), "reallocate(%zu, %zu)", s1, s2);
|
||||||
return AllocatorLogEntry(buffer);
|
return AllocatorLogEntry(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline AllocatorLogEntry ReallocateFail(size_t s1, size_t s2) {
|
inline AllocatorLogEntry ReallocateFail(size_t s1, size_t s2) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "reallocate(%zu, %zu) -> nullptr", s1, s2);
|
snprintf(buffer, sizeof(buffer), "reallocate(%zu, %zu) -> nullptr", s1, s2);
|
||||||
return AllocatorLogEntry(buffer);
|
return AllocatorLogEntry(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline AllocatorLogEntry Deallocate(size_t s) {
|
inline AllocatorLogEntry Deallocate(size_t s) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "deallocate(%zu)", s);
|
snprintf(buffer, sizeof(buffer), "deallocate(%zu)", s);
|
||||||
return AllocatorLogEntry(buffer);
|
return AllocatorLogEntry(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,6 +262,7 @@ class TimebombAllocator : public ArduinoJson::Allocator {
|
|||||||
size_t countdown_ = 0;
|
size_t countdown_ = 0;
|
||||||
Allocator* upstream_;
|
Allocator* upstream_;
|
||||||
};
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
inline size_t sizeofPoolList(size_t n = ARDUINOJSON_INITIAL_POOL_COUNT) {
|
inline size_t sizeofPoolList(size_t n = ARDUINOJSON_INITIAL_POOL_COUNT) {
|
||||||
return sizeof(ArduinoJson::detail::VariantPool) * n;
|
return sizeof(ArduinoJson::detail::VariantPool) * n;
|
||||||
|
|||||||
12
lib/ArduinoJson/extras/tests/Helpers/Literals.hpp
Normal file
12
lib/ArduinoJson/extras/tests/Helpers/Literals.hpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// the space before _s is required by GCC 4.8
|
||||||
|
inline std::string operator"" _s(const char* str, size_t len) {
|
||||||
|
return std::string(str, len);
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ TEST_CASE("JsonArray::add(T)") {
|
|||||||
|
|
||||||
array.add(vla);
|
array.add(vla);
|
||||||
|
|
||||||
REQUIRE(std::string("world") == array[0]);
|
REQUIRE("world"_s == array[0]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ TEST_CASE("JsonArray::add(T)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string") {
|
SECTION("should duplicate std::string") {
|
||||||
array.add(std::string("world"));
|
array.add("world"_s);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
@@ -139,7 +140,7 @@ TEST_CASE("JsonArray::add(T)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate serialized(std::string)") {
|
SECTION("should duplicate serialized(std::string)") {
|
||||||
array.add(serialized(std::string("{}")));
|
array.add(serialized("{}"_s));
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("{}")),
|
Allocate(sizeofString("{}")),
|
||||||
@@ -147,7 +148,7 @@ TEST_CASE("JsonArray::add(T)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate serialized(std::string)") {
|
SECTION("should duplicate serialized(std::string)") {
|
||||||
array.add(serialized(std::string("\0XX", 3)));
|
array.add(serialized("\0XX"_s));
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString(" XX")),
|
Allocate(sizeofString(" XX")),
|
||||||
@@ -179,3 +180,52 @@ TEST_CASE("JsonArray::add<T>()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "[42]");
|
REQUIRE(doc.as<std::string>() == "[42]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonObject::add(JsonObject) ") {
|
||||||
|
JsonDocument doc1;
|
||||||
|
doc1["key1"_s] = "value1"_s;
|
||||||
|
|
||||||
|
TimebombAllocator allocator(10);
|
||||||
|
SpyingAllocator spy(&allocator);
|
||||||
|
JsonDocument doc2(&spy);
|
||||||
|
JsonArray array = doc2.to<JsonArray>();
|
||||||
|
|
||||||
|
SECTION("success") {
|
||||||
|
bool result = array.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[{\"key1\":\"value1\"}]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Allocate(sizeofString("key1")),
|
||||||
|
Allocate(sizeofString("value1")),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("partial failure") { // issue #2081
|
||||||
|
allocator.setCountdown(2);
|
||||||
|
|
||||||
|
bool result = array.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Allocate(sizeofString("key1")),
|
||||||
|
AllocateFail(sizeofString("value1")),
|
||||||
|
Deallocate(sizeofString("key1")),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("complete failure") {
|
||||||
|
allocator.setCountdown(0);
|
||||||
|
|
||||||
|
bool result = array.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
AllocateFail(sizeofPool()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("copyArray()") {
|
TEST_CASE("copyArray()") {
|
||||||
SECTION("int[] -> JsonArray") {
|
SECTION("int[] -> JsonArray") {
|
||||||
@@ -18,7 +19,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(array, json);
|
serializeJson(array, json);
|
||||||
CHECK(std::string("[1,2,3]") == json);
|
CHECK("[1,2,3]"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::string[] -> JsonArray") {
|
SECTION("std::string[] -> JsonArray") {
|
||||||
@@ -31,7 +32,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(array, json);
|
serializeJson(array, json);
|
||||||
CHECK(std::string("[\"a\",\"b\",\"c\"]") == json);
|
CHECK("[\"a\",\"b\",\"c\"]"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const char*[] -> JsonArray") {
|
SECTION("const char*[] -> JsonArray") {
|
||||||
@@ -44,7 +45,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(array, json);
|
serializeJson(array, json);
|
||||||
CHECK(std::string("[\"a\",\"b\",\"c\"]") == json);
|
CHECK("[\"a\",\"b\",\"c\"]"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const char[][] -> JsonArray") {
|
SECTION("const char[][] -> JsonArray") {
|
||||||
@@ -57,7 +58,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(array, json);
|
serializeJson(array, json);
|
||||||
CHECK(std::string("[\"a\",\"b\",\"c\"]") == json);
|
CHECK("[\"a\",\"b\",\"c\"]"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const char[][] -> JsonDocument") {
|
SECTION("const char[][] -> JsonDocument") {
|
||||||
@@ -69,7 +70,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
CHECK(std::string("[\"a\",\"b\",\"c\"]") == json);
|
CHECK("[\"a\",\"b\",\"c\"]"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const char[][] -> MemberProxy") {
|
SECTION("const char[][] -> MemberProxy") {
|
||||||
@@ -81,7 +82,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
CHECK(std::string("{\"data\":[\"a\",\"b\",\"c\"]}") == json);
|
CHECK("{\"data\":[\"a\",\"b\",\"c\"]}"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("int[] -> JsonDocument") {
|
SECTION("int[] -> JsonDocument") {
|
||||||
@@ -93,7 +94,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
CHECK(std::string("[1,2,3]") == json);
|
CHECK("[1,2,3]"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("int[] -> MemberProxy") {
|
SECTION("int[] -> MemberProxy") {
|
||||||
@@ -105,7 +106,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
CHECK(std::string("{\"data\":[1,2,3]}") == json);
|
CHECK("{\"data\":[1,2,3]}"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("int[] -> JsonArray, but not enough memory") {
|
SECTION("int[] -> JsonArray, but not enough memory") {
|
||||||
@@ -127,7 +128,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(array, json);
|
serializeJson(array, json);
|
||||||
CHECK(std::string("[[1,2,3],[4,5,6]]") == json);
|
CHECK("[[1,2,3],[4,5,6]]"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("int[][] -> MemberProxy") {
|
SECTION("int[][] -> MemberProxy") {
|
||||||
@@ -139,7 +140,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
CHECK(std::string("{\"data\":[[1,2,3],[4,5,6]]}") == json);
|
CHECK("{\"data\":[[1,2,3],[4,5,6]]}"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("int[][] -> JsonDocument") {
|
SECTION("int[][] -> JsonDocument") {
|
||||||
@@ -151,7 +152,7 @@ TEST_CASE("copyArray()") {
|
|||||||
CHECK(ok);
|
CHECK(ok);
|
||||||
|
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
CHECK(std::string("[[1,2,3],[4,5,6]]") == json);
|
CHECK("[[1,2,3],[4,5,6]]"_s == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("int[][] -> JsonArray, but not enough memory") {
|
SECTION("int[][] -> JsonArray, but not enough memory") {
|
||||||
@@ -223,9 +224,9 @@ TEST_CASE("copyArray()") {
|
|||||||
size_t result = copyArray(array, destination);
|
size_t result = copyArray(array, destination);
|
||||||
|
|
||||||
CHECK(3 == result);
|
CHECK(3 == result);
|
||||||
CHECK(std::string("a12345") == destination[0]);
|
CHECK("a12345"_s == destination[0]);
|
||||||
CHECK(std::string("b123456") == destination[1]);
|
CHECK("b123456"_s == destination[1]);
|
||||||
CHECK(std::string("c123456") == destination[2]); // truncated
|
CHECK("c123456"_s == destination[2]); // truncated
|
||||||
CHECK(std::string("") == destination[3]);
|
CHECK(std::string("") == destination[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,15 @@ TEST_CASE("JsonArray::remove()") {
|
|||||||
JsonArray unboundArray;
|
JsonArray unboundArray;
|
||||||
unboundArray.remove(unboundArray.begin());
|
unboundArray.remove(unboundArray.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("use JsonVariant as index") {
|
||||||
|
array.remove(array[3]); // no effect with null variant
|
||||||
|
array.remove(array[0]); // remove element at index 1
|
||||||
|
|
||||||
|
REQUIRE(2 == array.size());
|
||||||
|
REQUIRE(array[0] == 1);
|
||||||
|
REQUIRE(array[1] == 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Removed elements are recycled") {
|
TEST_CASE("Removed elements are recycled") {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
static void eraseString(std::string& str) {
|
static void eraseString(std::string& str) {
|
||||||
char* p = const_cast<char*>(str.c_str());
|
char* p = const_cast<char*>(str.c_str());
|
||||||
while (*p)
|
while (*p)
|
||||||
@@ -19,7 +21,7 @@ TEST_CASE("std::string") {
|
|||||||
std::string value("hello");
|
std::string value("hello");
|
||||||
array.add(value);
|
array.add(value);
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
REQUIRE(std::string("hello") == array[0]);
|
REQUIRE("hello"_s == array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator[]") {
|
SECTION("operator[]") {
|
||||||
@@ -27,6 +29,6 @@ TEST_CASE("std::string") {
|
|||||||
array.add("hello");
|
array.add("hello");
|
||||||
array[0] = value;
|
array[0] = value;
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
REQUIRE(std::string("world") == array[0]);
|
REQUIRE("world"_s == array[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonArray::operator[]") {
|
TEST_CASE("JsonArray::operator[]") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
@@ -129,7 +130,7 @@ TEST_CASE("JsonArray::operator[]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string") {
|
SECTION("should duplicate std::string") {
|
||||||
array[0] = std::string("world");
|
array[0] = "world"_s;
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
@@ -150,7 +151,7 @@ TEST_CASE("JsonArray::operator[]") {
|
|||||||
array.add("hello");
|
array.add("hello");
|
||||||
array[0].set(vla);
|
array[0].set(vla);
|
||||||
|
|
||||||
REQUIRE(std::string("world") == array[0]);
|
REQUIRE("world"_s == array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator=(VLA)") {
|
SECTION("operator=(VLA)") {
|
||||||
@@ -161,7 +162,16 @@ TEST_CASE("JsonArray::operator[]") {
|
|||||||
array.add("hello");
|
array.add("hello");
|
||||||
array[0] = vla;
|
array[0] = vla;
|
||||||
|
|
||||||
REQUIRE(std::string("world") == array[0]);
|
REQUIRE("world"_s == array[0]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SECTION("Use a JsonVariant as index") {
|
||||||
|
array[0] = 1;
|
||||||
|
array[1] = 2;
|
||||||
|
array[2] = 3;
|
||||||
|
|
||||||
|
REQUIRE(array[array[1]] == 3);
|
||||||
|
REQUIRE(array[array[3]] == nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,15 @@ TEST_CASE("JsonArrayConst::operator[]") {
|
|||||||
doc.add(2);
|
doc.add(2);
|
||||||
doc.add(3);
|
doc.add(3);
|
||||||
|
|
||||||
|
SECTION("int") {
|
||||||
REQUIRE(1 == arr[0].as<int>());
|
REQUIRE(1 == arr[0].as<int>());
|
||||||
REQUIRE(2 == arr[1].as<int>());
|
REQUIRE(2 == arr[1].as<int>());
|
||||||
REQUIRE(3 == arr[2].as<int>());
|
REQUIRE(3 == arr[2].as<int>());
|
||||||
REQUIRE(0 == arr[3].as<int>());
|
REQUIRE(0 == arr[3].as<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("JsonVariant") {
|
||||||
|
REQUIRE(2 == arr[arr[0]].as<int>());
|
||||||
|
REQUIRE(0 == arr[arr[3]].as<int>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
@@ -15,7 +16,7 @@ using ArduinoJson::detail::sizeofObject;
|
|||||||
TEST_CASE("deserializeJson(JsonDocument&)") {
|
TEST_CASE("deserializeJson(JsonDocument&)") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc.add(std::string("hello"));
|
doc.add("hello"_s);
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
auto err = deserializeJson(doc, "[42]");
|
auto err = deserializeJson(doc, "[42]");
|
||||||
@@ -34,7 +35,7 @@ TEST_CASE("deserializeJson(JsonVariant)") {
|
|||||||
SECTION("variant is bound") {
|
SECTION("variant is bound") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc.add(std::string("hello"));
|
doc.add("hello"_s);
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
JsonVariant variant = doc[0];
|
JsonVariant variant = doc[0];
|
||||||
@@ -60,7 +61,7 @@ TEST_CASE("deserializeJson(JsonVariant)") {
|
|||||||
TEST_CASE("deserializeJson(ElementProxy)") {
|
TEST_CASE("deserializeJson(ElementProxy)") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc.add(std::string("hello"));
|
doc.add("hello"_s);
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
SECTION("element already exists") {
|
SECTION("element already exists") {
|
||||||
@@ -85,7 +86,7 @@ TEST_CASE("deserializeJson(ElementProxy)") {
|
|||||||
TEST_CASE("deserializeJson(MemberProxy)") {
|
TEST_CASE("deserializeJson(MemberProxy)") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc[std::string("hello")] = std::string("world");
|
doc["hello"_s] = "world"_s;
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
SECTION("member already exists") {
|
SECTION("member already exists") {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
@@ -732,7 +733,7 @@ TEST_CASE("Overloads") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const std::string&, Filter") {
|
SECTION("const std::string&, Filter") {
|
||||||
deserializeJson(doc, std::string("{}"), Filter(filter));
|
deserializeJson(doc, "{}"_s, Filter(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::istream&, Filter") {
|
SECTION("std::istream&, Filter") {
|
||||||
@@ -760,7 +761,7 @@ TEST_CASE("Overloads") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const std::string&, Filter, NestingLimit") {
|
SECTION("const std::string&, Filter, NestingLimit") {
|
||||||
deserializeJson(doc, std::string("{}"), Filter(filter), NestingLimit(5));
|
deserializeJson(doc, "{}"_s, Filter(filter), NestingLimit(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::istream&, Filter, NestingLimit") {
|
SECTION("std::istream&, Filter, NestingLimit") {
|
||||||
@@ -788,7 +789,7 @@ TEST_CASE("Overloads") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const std::string&, NestingLimit, Filter") {
|
SECTION("const std::string&, NestingLimit, Filter") {
|
||||||
deserializeJson(doc, std::string("{}"), NestingLimit(5), Filter(filter));
|
deserializeJson(doc, "{}"_s, NestingLimit(5), Filter(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::istream&, NestingLimit, Filter") {
|
SECTION("std::istream&, NestingLimit, Filter") {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
#include "CustomReader.hpp"
|
#include "CustomReader.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ TEST_CASE("deserializeJson(const std::string&)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should accept temporary string") {
|
SECTION("should accept temporary string") {
|
||||||
DeserializationError err = deserializeJson(doc, std::string("[42]"));
|
DeserializationError err = deserializeJson(doc, "[42]"_s);
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,7 @@ TEST_CASE("deserializeJson(const std::string&)") {
|
|||||||
|
|
||||||
JsonArray array = doc.as<JsonArray>();
|
JsonArray array = doc.as<JsonArray>();
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
REQUIRE(std::string("hello") == array[0]);
|
REQUIRE("hello"_s == array[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +109,7 @@ TEST_CASE("deserializeJson(std::istream&)") {
|
|||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
REQUIRE(1 == obj.size());
|
REQUIRE(1 == obj.size());
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE("world"_s == obj["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Should not read after the closing brace of an empty object") {
|
SECTION("Should not read after the closing brace of an empty object") {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
#define SHOULD_WORK(expression) REQUIRE(DeserializationError::Ok == expression);
|
#define SHOULD_WORK(expression) REQUIRE(DeserializationError::Ok == expression);
|
||||||
#define SHOULD_FAIL(expression) \
|
#define SHOULD_FAIL(expression) \
|
||||||
REQUIRE(DeserializationError::TooDeep == expression);
|
REQUIRE(DeserializationError::TooDeep == expression);
|
||||||
@@ -63,23 +65,23 @@ TEST_CASE("JsonDeserializer nesting") {
|
|||||||
SECTION("Input = std::string") {
|
SECTION("Input = std::string") {
|
||||||
SECTION("limit = 0") {
|
SECTION("limit = 0") {
|
||||||
DeserializationOption::NestingLimit nesting(0);
|
DeserializationOption::NestingLimit nesting(0);
|
||||||
SHOULD_WORK(deserializeJson(doc, std::string("\"toto\""), nesting));
|
SHOULD_WORK(deserializeJson(doc, "\"toto\""_s, nesting));
|
||||||
SHOULD_WORK(deserializeJson(doc, std::string("123"), nesting));
|
SHOULD_WORK(deserializeJson(doc, "123"_s, nesting));
|
||||||
SHOULD_WORK(deserializeJson(doc, std::string("true"), nesting));
|
SHOULD_WORK(deserializeJson(doc, "true"_s, nesting));
|
||||||
SHOULD_FAIL(deserializeJson(doc, std::string("[]"), nesting));
|
SHOULD_FAIL(deserializeJson(doc, "[]"_s, nesting));
|
||||||
SHOULD_FAIL(deserializeJson(doc, std::string("{}"), nesting));
|
SHOULD_FAIL(deserializeJson(doc, "{}"_s, nesting));
|
||||||
SHOULD_FAIL(deserializeJson(doc, std::string("[\"toto\"]"), nesting));
|
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]"_s, nesting));
|
||||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":1}"), nesting));
|
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}"_s, nesting));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("limit = 1") {
|
SECTION("limit = 1") {
|
||||||
DeserializationOption::NestingLimit nesting(1);
|
DeserializationOption::NestingLimit nesting(1);
|
||||||
SHOULD_WORK(deserializeJson(doc, std::string("[\"toto\"]"), nesting));
|
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]"_s, nesting));
|
||||||
SHOULD_WORK(deserializeJson(doc, std::string("{\"toto\":1}"), nesting));
|
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}"_s, nesting));
|
||||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":{}}"), nesting));
|
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}"_s, nesting));
|
||||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":[]}"), nesting));
|
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}"_s, nesting));
|
||||||
SHOULD_FAIL(deserializeJson(doc, std::string("[[\"toto\"]]"), nesting));
|
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]"_s, nesting));
|
||||||
SHOULD_FAIL(deserializeJson(doc, std::string("[{\"toto\":1}]"), nesting));
|
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]"_s, nesting));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
typedef ArduinoJson::detail::ElementProxy<JsonDocument&> ElementProxy;
|
typedef ArduinoJson::detail::ElementProxy<JsonDocument&> ElementProxy;
|
||||||
|
|
||||||
TEST_CASE("ElementProxy::add()") {
|
TEST_CASE("ElementProxy::add()") {
|
||||||
@@ -121,7 +123,7 @@ TEST_CASE("ElementProxy::remove()") {
|
|||||||
ep["a"] = 1;
|
ep["a"] = 1;
|
||||||
ep["b"] = 2;
|
ep["b"] = 2;
|
||||||
|
|
||||||
ep.remove(std::string("b"));
|
ep.remove("b"_s);
|
||||||
|
|
||||||
REQUIRE(ep.as<std::string>() == "{\"a\":1}");
|
REQUIRE(ep.as<std::string>() == "{\"a\":1}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
@@ -106,8 +107,8 @@ TEST_CASE("MemberProxy::containsKey()") {
|
|||||||
SECTION("containsKey(std::string)") {
|
SECTION("containsKey(std::string)") {
|
||||||
mp["key"] = "value";
|
mp["key"] = "value";
|
||||||
|
|
||||||
REQUIRE(mp.containsKey(std::string("key")) == true);
|
REQUIRE(mp.containsKey("key"_s) == true);
|
||||||
REQUIRE(mp.containsKey(std::string("key")) == true);
|
REQUIRE(mp.containsKey("key"_s) == true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,8 +118,8 @@ TEST_CASE("MemberProxy::operator|()") {
|
|||||||
SECTION("const char*") {
|
SECTION("const char*") {
|
||||||
doc["a"] = "hello";
|
doc["a"] = "hello";
|
||||||
|
|
||||||
REQUIRE((doc["a"] | "world") == std::string("hello"));
|
REQUIRE((doc["a"] | "world") == "hello"_s);
|
||||||
REQUIRE((doc["b"] | "world") == std::string("world"));
|
REQUIRE((doc["b"] | "world") == "world"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Issue #1411") {
|
SECTION("Issue #1411") {
|
||||||
@@ -128,7 +129,7 @@ TEST_CASE("MemberProxy::operator|()") {
|
|||||||
// to trigger the bug
|
// to trigger the bug
|
||||||
const char* sensor = doc["sensor"] | test; // "gps"
|
const char* sensor = doc["sensor"] | test; // "gps"
|
||||||
|
|
||||||
REQUIRE(sensor == std::string("gps"));
|
REQUIRE(sensor == "gps"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Issue #1415") {
|
SECTION("Issue #1415") {
|
||||||
@@ -170,7 +171,7 @@ TEST_CASE("MemberProxy::remove()") {
|
|||||||
mp["a"] = 1;
|
mp["a"] = 1;
|
||||||
mp["b"] = 2;
|
mp["b"] = 2;
|
||||||
|
|
||||||
mp.remove(std::string("b"));
|
mp.remove("b"_s);
|
||||||
|
|
||||||
REQUIRE(mp.as<std::string>() == "{\"a\":1}");
|
REQUIRE(mp.as<std::string>() == "{\"a\":1}");
|
||||||
}
|
}
|
||||||
@@ -286,8 +287,8 @@ TEST_CASE("Deduplicate keys") {
|
|||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
|
|
||||||
SECTION("std::string") {
|
SECTION("std::string") {
|
||||||
doc[0][std::string("example")] = 1;
|
doc[0]["example"_s] = 1;
|
||||||
doc[1][std::string("example")] = 2;
|
doc[1]["example"_s] = 2;
|
||||||
|
|
||||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||||
@@ -351,7 +352,7 @@ TEST_CASE("MemberProxy under memory constraints") {
|
|||||||
SECTION("key allocation fails") {
|
SECTION("key allocation fails") {
|
||||||
killswitch.on();
|
killswitch.on();
|
||||||
|
|
||||||
doc[std::string("hello")] = "world";
|
doc["hello"_s] = "world";
|
||||||
|
|
||||||
REQUIRE(doc.is<JsonObject>());
|
REQUIRE(doc.is<JsonObject>());
|
||||||
REQUIRE(doc.size() == 0);
|
REQUIRE(doc.size() == 0);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
|
|
||||||
@@ -35,8 +36,8 @@ TEST_CASE("JsonDocument::add(T)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::string") {
|
SECTION("std::string") {
|
||||||
doc.add(std::string("example"));
|
doc.add("example"_s);
|
||||||
doc.add(std::string("example"));
|
doc.add("example"_s);
|
||||||
|
|
||||||
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
@@ -90,15 +91,57 @@ TEST_CASE("JsonDocument::add<T>()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "[[1,2]]");
|
REQUIRE(doc.as<std::string>() == "[[1,2]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JsonObject") {
|
|
||||||
JsonObject object = doc.add<JsonObject>();
|
|
||||||
object["hello"] = "world";
|
|
||||||
REQUIRE(doc.as<std::string>() == "[{\"hello\":\"world\"}]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("JsonVariant") {
|
SECTION("JsonVariant") {
|
||||||
JsonVariant variant = doc.add<JsonVariant>();
|
JsonVariant variant = doc.add<JsonVariant>();
|
||||||
variant.set(42);
|
variant.set(42);
|
||||||
REQUIRE(doc.as<std::string>() == "[42]");
|
REQUIRE(doc.as<std::string>() == "[42]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonObject::add(JsonObject) ") {
|
||||||
|
JsonDocument doc1;
|
||||||
|
doc1["hello"_s] = "world"_s;
|
||||||
|
|
||||||
|
TimebombAllocator allocator(10);
|
||||||
|
SpyingAllocator spy(&allocator);
|
||||||
|
JsonDocument doc2(&spy);
|
||||||
|
|
||||||
|
SECTION("success") {
|
||||||
|
bool result = doc2.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[{\"hello\":\"world\"}]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
Allocate(sizeofString("world")),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("partial failure") { // issue #2081
|
||||||
|
allocator.setCountdown(2);
|
||||||
|
|
||||||
|
bool result = doc2.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
AllocateFail(sizeofString("world")),
|
||||||
|
Deallocate(sizeofString("hello")),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("complete failure") {
|
||||||
|
allocator.setCountdown(0);
|
||||||
|
|
||||||
|
bool result = doc2.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
AllocateFail(sizeofPool()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonDocument assignment") {
|
TEST_CASE("JsonDocument assignment") {
|
||||||
SpyingAllocator spyingAllocator;
|
SpyingAllocator spyingAllocator;
|
||||||
@@ -62,7 +63,7 @@ TEST_CASE("JsonDocument assignment") {
|
|||||||
SECTION("Move assign") {
|
SECTION("Move assign") {
|
||||||
{
|
{
|
||||||
JsonDocument doc1(&spyingAllocator);
|
JsonDocument doc1(&spyingAllocator);
|
||||||
doc1[std::string("hello")] = std::string("world");
|
doc1["hello"_s] = "world"_s;
|
||||||
JsonDocument doc2(&spyingAllocator);
|
JsonDocument doc2(&spyingAllocator);
|
||||||
|
|
||||||
doc2 = std::move(doc1);
|
doc2 = std::move(doc1);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::clear()") {
|
TEST_CASE("JsonDocument::clear()") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
@@ -22,7 +23,7 @@ TEST_CASE("JsonDocument::clear()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("releases resources") {
|
SECTION("releases resources") {
|
||||||
doc[std::string("hello")] = std::string("world");
|
doc["hello"_s] = "world"_s;
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
doc.clear();
|
doc.clear();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::addPadding;
|
using ArduinoJson::detail::addPadding;
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ TEST_CASE("JsonDocument constructor") {
|
|||||||
SECTION("JsonDocument(const JsonDocument&)") {
|
SECTION("JsonDocument(const JsonDocument&)") {
|
||||||
{
|
{
|
||||||
JsonDocument doc1(&spyingAllocator);
|
JsonDocument doc1(&spyingAllocator);
|
||||||
doc1.set(std::string("The size of this string is 32!!"));
|
doc1.set("The size of this string is 32!!"_s);
|
||||||
|
|
||||||
JsonDocument doc2(doc1);
|
JsonDocument doc2(doc1);
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ TEST_CASE("JsonDocument constructor") {
|
|||||||
SECTION("JsonDocument(JsonDocument&&)") {
|
SECTION("JsonDocument(JsonDocument&&)") {
|
||||||
{
|
{
|
||||||
JsonDocument doc1(&spyingAllocator);
|
JsonDocument doc1(&spyingAllocator);
|
||||||
doc1.set(std::string("The size of this string is 32!!"));
|
doc1.set("The size of this string is 32!!"_s);
|
||||||
|
|
||||||
JsonDocument doc2(std::move(doc1));
|
JsonDocument doc2(std::move(doc1));
|
||||||
|
|
||||||
@@ -117,4 +118,31 @@ TEST_CASE("JsonDocument constructor") {
|
|||||||
|
|
||||||
REQUIRE(doc2.as<std::string>() == "hello");
|
REQUIRE(doc2.as<std::string>() == "hello");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("JsonDocument(JsonVariantConst)") {
|
||||||
|
JsonDocument doc1;
|
||||||
|
deserializeJson(doc1, "\"hello\"");
|
||||||
|
|
||||||
|
JsonDocument doc2(doc1.as<JsonVariantConst>());
|
||||||
|
|
||||||
|
REQUIRE(doc2.as<std::string>() == "hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("JsonDocument(ElementProxy)") {
|
||||||
|
JsonDocument doc1;
|
||||||
|
deserializeJson(doc1, "[\"hello\",\"world\"]");
|
||||||
|
|
||||||
|
JsonDocument doc2(doc1[1]);
|
||||||
|
|
||||||
|
REQUIRE(doc2.as<std::string>() == "world");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("JsonDocument(MemberProxy)") {
|
||||||
|
JsonDocument doc1;
|
||||||
|
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||||
|
|
||||||
|
JsonDocument doc2(doc1["hello"]);
|
||||||
|
|
||||||
|
REQUIRE(doc2.as<std::string>() == "world");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::containsKey()") {
|
TEST_CASE("JsonDocument::containsKey()") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
@@ -23,7 +25,7 @@ TEST_CASE("JsonDocument::containsKey()") {
|
|||||||
SECTION("returns true when key is a std::string") {
|
SECTION("returns true when key is a std::string") {
|
||||||
doc["hello"] = "world";
|
doc["hello"] = "world";
|
||||||
|
|
||||||
REQUIRE(doc.containsKey(std::string("hello")) == true);
|
REQUIRE(doc.containsKey("hello"_s) == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("returns false on object") {
|
SECTION("returns false on object") {
|
||||||
@@ -41,4 +43,12 @@ TEST_CASE("JsonDocument::containsKey()") {
|
|||||||
SECTION("returns false on null") {
|
SECTION("returns false on null") {
|
||||||
REQUIRE(doc.containsKey("hello") == false);
|
REQUIRE(doc.containsKey("hello") == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("support JsonVariant") {
|
||||||
|
doc["hello"] = "world";
|
||||||
|
doc["key"] = "hello";
|
||||||
|
|
||||||
|
REQUIRE(doc.containsKey(doc["key"]) == true);
|
||||||
|
REQUIRE(doc.containsKey(doc["foo"]) == false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("Issue #1120") {
|
TEST_CASE("Issue #1120") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
constexpr char str[] =
|
constexpr char str[] =
|
||||||
@@ -10,12 +12,12 @@ TEST_CASE("Issue #1120") {
|
|||||||
|
|
||||||
SECTION("MemberProxy<std::string>::isNull()") {
|
SECTION("MemberProxy<std::string>::isNull()") {
|
||||||
SECTION("returns false") {
|
SECTION("returns false") {
|
||||||
auto value = doc[std::string("contents")];
|
auto value = doc["contents"_s];
|
||||||
CHECK(value.isNull() == false);
|
CHECK(value.isNull() == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("returns true") {
|
SECTION("returns true") {
|
||||||
auto value = doc[std::string("zontents")];
|
auto value = doc["zontents"_s];
|
||||||
CHECK(value.isNull() == true);
|
CHECK(value.isNull() == true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,12 +48,12 @@ TEST_CASE("Issue #1120") {
|
|||||||
|
|
||||||
SECTION("MemberProxy<ElementProxy<MemberProxy>, std::string>::isNull()") {
|
SECTION("MemberProxy<ElementProxy<MemberProxy>, std::string>::isNull()") {
|
||||||
SECTION("returns false") {
|
SECTION("returns false") {
|
||||||
auto value = doc["contents"][1][std::string("module")];
|
auto value = doc["contents"][1]["module"_s];
|
||||||
CHECK(value.isNull() == false);
|
CHECK(value.isNull() == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("returns true") {
|
SECTION("returns true") {
|
||||||
auto value = doc["contents"][1][std::string("zodule")];
|
auto value = doc["contents"][1]["zodule"_s];
|
||||||
CHECK(value.isNull() == true);
|
CHECK(value.isNull() == true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::overflowed()") {
|
TEST_CASE("JsonDocument::overflowed()") {
|
||||||
TimebombAllocator timebomb(10);
|
TimebombAllocator timebomb(10);
|
||||||
@@ -30,13 +31,13 @@ TEST_CASE("JsonDocument::overflowed()") {
|
|||||||
|
|
||||||
SECTION("returns true after a failed string copy") {
|
SECTION("returns true after a failed string copy") {
|
||||||
timebomb.setCountdown(0);
|
timebomb.setCountdown(0);
|
||||||
doc.add(std::string("example"));
|
doc.add("example"_s);
|
||||||
CHECK(doc.overflowed() == true);
|
CHECK(doc.overflowed() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("returns false after a successful string copy") {
|
SECTION("returns false after a successful string copy") {
|
||||||
timebomb.setCountdown(3);
|
timebomb.setCountdown(3);
|
||||||
doc.add(std::string("example"));
|
doc.add("example"_s);
|
||||||
CHECK(doc.overflowed() == false);
|
CHECK(doc.overflowed() == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::remove()") {
|
TEST_CASE("JsonDocument::remove()") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
@@ -31,7 +33,7 @@ TEST_CASE("JsonDocument::remove()") {
|
|||||||
doc["a"] = 1;
|
doc["a"] = 1;
|
||||||
doc["b"] = 2;
|
doc["b"] = 2;
|
||||||
|
|
||||||
doc.remove(std::string("b"));
|
doc.remove("b"_s);
|
||||||
|
|
||||||
REQUIRE(doc.as<std::string>() == "{\"a\":1}");
|
REQUIRE(doc.as<std::string>() == "{\"a\":1}");
|
||||||
}
|
}
|
||||||
@@ -49,4 +51,25 @@ TEST_CASE("JsonDocument::remove()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "{\"a\":1}");
|
REQUIRE(doc.as<std::string>() == "{\"a\":1}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SECTION("remove(JsonVariant) from object") {
|
||||||
|
doc["a"] = 1;
|
||||||
|
doc["b"] = 2;
|
||||||
|
doc["c"] = "b";
|
||||||
|
|
||||||
|
doc.remove(doc["c"]);
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "{\"a\":1,\"c\":\"b\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("remove(JsonVariant) from array") {
|
||||||
|
doc[0] = 3;
|
||||||
|
doc[1] = 2;
|
||||||
|
doc[2] = 1;
|
||||||
|
|
||||||
|
doc.remove(doc[2]);
|
||||||
|
doc.remove(doc[3]); // noop
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "[3,1]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
@@ -78,7 +79,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("owned string") {
|
SECTION("owned string") {
|
||||||
doc.set(std::string("abcdefg"));
|
doc.set("abcdefg"_s);
|
||||||
REQUIRE(doc.as<std::string>() == "abcdefg");
|
REQUIRE(doc.as<std::string>() == "abcdefg");
|
||||||
|
|
||||||
doc.shrinkToFit();
|
doc.shrinkToFit();
|
||||||
@@ -114,7 +115,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("owned key") {
|
SECTION("owned key") {
|
||||||
doc[std::string("abcdefg")] = 42;
|
doc["abcdefg"_s] = 42;
|
||||||
|
|
||||||
doc.shrinkToFit();
|
doc.shrinkToFit();
|
||||||
|
|
||||||
@@ -141,7 +142,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("owned string in array") {
|
SECTION("owned string in array") {
|
||||||
doc.add(std::string("abcdefg"));
|
doc.add("abcdefg"_s);
|
||||||
|
|
||||||
doc.shrinkToFit();
|
doc.shrinkToFit();
|
||||||
|
|
||||||
@@ -168,7 +169,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("owned string in object") {
|
SECTION("owned string in object") {
|
||||||
doc["key"] = std::string("abcdefg");
|
doc["key"] = "abcdefg"_s;
|
||||||
|
|
||||||
doc.shrinkToFit();
|
doc.shrinkToFit();
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::operator[]") {
|
TEST_CASE("JsonDocument::operator[]") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
const JsonDocument& cdoc = doc;
|
const JsonDocument& cdoc = doc;
|
||||||
@@ -18,22 +20,36 @@ TEST_CASE("JsonDocument::operator[]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::string") {
|
SECTION("std::string") {
|
||||||
REQUIRE(doc[std::string("hello")] == "world");
|
REQUIRE(doc["hello"_s] == "world");
|
||||||
REQUIRE(cdoc[std::string("hello")] == "world");
|
REQUIRE(cdoc["hello"_s] == "world");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("JsonVariant") {
|
||||||
|
doc["key"] = "hello";
|
||||||
|
REQUIRE(doc[doc["key"]] == "world");
|
||||||
|
REQUIRE(cdoc[cdoc["key"]] == "world");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("supports operator|") {
|
SECTION("supports operator|") {
|
||||||
REQUIRE((doc["hello"] | "nope") == std::string("world"));
|
REQUIRE((doc["hello"] | "nope") == "world"_s);
|
||||||
REQUIRE((doc["world"] | "nope") == std::string("nope"));
|
REQUIRE((doc["world"] | "nope") == "nope"_s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array") {
|
SECTION("array") {
|
||||||
deserializeJson(doc, "[\"hello\",\"world\"]");
|
deserializeJson(doc, "[\"hello\",\"world\"]");
|
||||||
|
|
||||||
|
SECTION("int") {
|
||||||
REQUIRE(doc[1] == "world");
|
REQUIRE(doc[1] == "world");
|
||||||
REQUIRE(cdoc[1] == "world");
|
REQUIRE(cdoc[1] == "world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("JsonVariant") {
|
||||||
|
doc[2] = 1;
|
||||||
|
REQUIRE(doc[doc[2]] == "world");
|
||||||
|
REQUIRE(cdoc[doc[2]] == "world");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("JsonDocument automatically promotes to object") {
|
TEST_CASE("JsonDocument automatically promotes to object") {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ add_executable(JsonObjectTests
|
|||||||
clear.cpp
|
clear.cpp
|
||||||
compare.cpp
|
compare.cpp
|
||||||
containsKey.cpp
|
containsKey.cpp
|
||||||
copy.cpp
|
|
||||||
equals.cpp
|
equals.cpp
|
||||||
isNull.cpp
|
isNull.cpp
|
||||||
iterator.cpp
|
iterator.cpp
|
||||||
nesting.cpp
|
nesting.cpp
|
||||||
remove.cpp
|
remove.cpp
|
||||||
|
set.cpp
|
||||||
size.cpp
|
size.cpp
|
||||||
std_string.cpp
|
std_string.cpp
|
||||||
subscript.cpp
|
subscript.cpp
|
||||||
|
|||||||
@@ -30,4 +30,10 @@ TEST_CASE("JsonObject::containsKey()") {
|
|||||||
REQUIRE(true == obj.containsKey(vla));
|
REQUIRE(true == obj.containsKey(vla));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SECTION("key is a JsonVariant") {
|
||||||
|
doc["key"] = "hello";
|
||||||
|
REQUIRE(true == obj.containsKey(obj["key"]));
|
||||||
|
REQUIRE(false == obj.containsKey(obj["hello"]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,4 +80,10 @@ TEST_CASE("JsonObject::remove()") {
|
|||||||
JsonObject unboundObject;
|
JsonObject unboundObject;
|
||||||
unboundObject.remove(unboundObject.begin());
|
unboundObject.remove(unboundObject.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("remove(JsonVariant)") {
|
||||||
|
obj["key"] = "b";
|
||||||
|
obj.remove(obj["key"]);
|
||||||
|
REQUIRE("{\"a\":0,\"c\":2,\"key\":\"b\"}" == doc.as<std::string>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonObject::set()") {
|
TEST_CASE("JsonObject::set()") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
@@ -22,20 +23,20 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == "world"_s);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy local string value") {
|
SECTION("copy local string value") {
|
||||||
obj1["hello"] = std::string("world");
|
obj1["hello"] = "world"_s;
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == "world"_s);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
@@ -43,13 +44,13 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy local key") {
|
SECTION("copy local key") {
|
||||||
obj1[std::string("hello")] = "world";
|
obj1["hello"_s] = "world";
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == "world"_s);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
@@ -63,7 +64,7 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == "world"_s);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
@@ -78,7 +79,7 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == "world"_s);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
@@ -91,7 +92,7 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
|
|
||||||
obj2.set(static_cast<JsonObjectConst>(obj1));
|
obj2.set(static_cast<JsonObjectConst>(obj1));
|
||||||
|
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == "world"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy fails in the middle of an object") {
|
SECTION("copy fails in the middle of an object") {
|
||||||
@@ -99,8 +100,8 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
JsonDocument doc3(&timebomb);
|
JsonDocument doc3(&timebomb);
|
||||||
JsonObject obj3 = doc3.to<JsonObject>();
|
JsonObject obj3 = doc3.to<JsonObject>();
|
||||||
|
|
||||||
obj1[std::string("a")] = 1;
|
obj1["a"_s] = 1;
|
||||||
obj1[std::string("b")] = 2;
|
obj1["b"_s] = 2;
|
||||||
|
|
||||||
bool success = obj3.set(obj1);
|
bool success = obj3.set(obj1);
|
||||||
|
|
||||||
@@ -113,12 +114,12 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
JsonDocument doc3(&timebomb);
|
JsonDocument doc3(&timebomb);
|
||||||
JsonObject obj3 = doc3.to<JsonObject>();
|
JsonObject obj3 = doc3.to<JsonObject>();
|
||||||
|
|
||||||
obj1["hello"][0] = std::string("world");
|
obj1["hello"][0] = "world"_s;
|
||||||
|
|
||||||
bool success = obj3.set(obj1);
|
bool success = obj3.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == false);
|
REQUIRE(success == false);
|
||||||
REQUIRE(doc3.as<std::string>() == "{\"hello\":[null]}");
|
REQUIRE(doc3.as<std::string>() == "{\"hello\":[]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("destination is null") {
|
SECTION("destination is null") {
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
static void eraseString(std::string& str) {
|
static void eraseString(std::string& str) {
|
||||||
char* p = const_cast<char*>(str.c_str());
|
char* p = const_cast<char*>(str.c_str());
|
||||||
while (*p)
|
while (*p)
|
||||||
@@ -20,7 +22,7 @@ TEST_CASE("std::string") {
|
|||||||
deserializeJson(doc, json);
|
deserializeJson(doc, json);
|
||||||
JsonObject obj = doc.as<JsonObject>();
|
JsonObject obj = doc.as<JsonObject>();
|
||||||
|
|
||||||
REQUIRE(std::string("value") == obj[std::string("key")]);
|
REQUIRE("value"_s == obj["key"_s]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator[] const") {
|
SECTION("operator[] const") {
|
||||||
@@ -29,21 +31,21 @@ TEST_CASE("std::string") {
|
|||||||
deserializeJson(doc, json);
|
deserializeJson(doc, json);
|
||||||
JsonObject obj = doc.as<JsonObject>();
|
JsonObject obj = doc.as<JsonObject>();
|
||||||
|
|
||||||
REQUIRE(std::string("value") == obj[std::string("key")]);
|
REQUIRE("value"_s == obj["key"_s]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("containsKey()") {
|
SECTION("containsKey()") {
|
||||||
char json[] = "{\"key\":\"value\"}";
|
char json[] = "{\"key\":\"value\"}";
|
||||||
deserializeJson(doc, json);
|
deserializeJson(doc, json);
|
||||||
JsonObject obj = doc.as<JsonObject>();
|
JsonObject obj = doc.as<JsonObject>();
|
||||||
REQUIRE(true == obj.containsKey(std::string("key")));
|
REQUIRE(true == obj.containsKey("key"_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("remove()") {
|
SECTION("remove()") {
|
||||||
JsonObject obj = doc.to<JsonObject>();
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
obj["key"] = "value";
|
obj["key"] = "value";
|
||||||
|
|
||||||
obj.remove(std::string("key"));
|
obj.remove("key"_s);
|
||||||
|
|
||||||
REQUIRE(0 == obj.size());
|
REQUIRE(0 == obj.size());
|
||||||
}
|
}
|
||||||
@@ -53,7 +55,7 @@ TEST_CASE("std::string") {
|
|||||||
JsonObject obj = doc.to<JsonObject>();
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
obj[key] = "world";
|
obj[key] = "world";
|
||||||
eraseString(key);
|
eraseString(key);
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE("world"_s == obj["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator[], set value") {
|
SECTION("operator[], set value") {
|
||||||
@@ -61,6 +63,6 @@ TEST_CASE("std::string") {
|
|||||||
JsonObject obj = doc.to<JsonObject>();
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
obj["hello"] = value;
|
obj["hello"] = value;
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE("world"_s == obj["hello"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonObject::operator[]") {
|
TEST_CASE("JsonObject::operator[]") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
@@ -50,7 +51,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
|
|
||||||
REQUIRE(true == obj["hello"].is<const char*>());
|
REQUIRE(true == obj["hello"].is<const char*>());
|
||||||
REQUIRE(false == obj["hello"].is<long>());
|
REQUIRE(false == obj["hello"].is<long>());
|
||||||
REQUIRE(std::string("h3110") == obj["hello"].as<const char*>());
|
REQUIRE("h3110"_s == obj["hello"].as<const char*>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array") {
|
SECTION("array") {
|
||||||
@@ -132,7 +133,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string value") {
|
SECTION("should duplicate std::string value") {
|
||||||
obj["hello"] = std::string("world");
|
obj["hello"] = "world"_s;
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
@@ -140,7 +141,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string key") {
|
SECTION("should duplicate std::string key") {
|
||||||
obj[std::string("hello")] = "world";
|
obj["hello"_s] = "world";
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
@@ -148,7 +149,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string key&value") {
|
SECTION("should duplicate std::string key&value") {
|
||||||
obj[std::string("hello")] = std::string("world");
|
obj["hello"_s] = "world"_s;
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
@@ -197,7 +198,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
|
|
||||||
obj[vla] = "world";
|
obj[vla] = "world";
|
||||||
|
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE("world"_s == obj["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("obj[str] = VLA") { // issue #416
|
SECTION("obj[str] = VLA") { // issue #416
|
||||||
@@ -207,7 +208,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
|
|
||||||
obj["hello"] = vla;
|
obj["hello"] = vla;
|
||||||
|
|
||||||
REQUIRE(std::string("world") == obj["hello"].as<const char*>());
|
REQUIRE("world"_s == obj["hello"].as<const char*>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("obj.set(VLA, str)") {
|
SECTION("obj.set(VLA, str)") {
|
||||||
@@ -217,7 +218,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
|
|
||||||
obj[vla] = "world";
|
obj[vla] = "world";
|
||||||
|
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE("world"_s == obj["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("obj.set(str, VLA)") {
|
SECTION("obj.set(str, VLA)") {
|
||||||
@@ -227,7 +228,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
|
|
||||||
obj["hello"].set(vla);
|
obj["hello"].set(vla);
|
||||||
|
|
||||||
REQUIRE(std::string("world") == obj["hello"].as<const char*>());
|
REQUIRE("world"_s == obj["hello"].as<const char*>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("obj[VLA]") {
|
SECTION("obj[VLA]") {
|
||||||
@@ -238,7 +239,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||||
|
|
||||||
obj = doc.as<JsonObject>();
|
obj = doc.as<JsonObject>();
|
||||||
REQUIRE(std::string("world") == obj[vla]);
|
REQUIRE("world"_s == obj[vla]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -249,4 +250,12 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
REQUIRE(true == obj["hello"]["world"].is<int>());
|
REQUIRE(true == obj["hello"]["world"].is<int>());
|
||||||
REQUIRE(false == obj["hello"]["world"].is<bool>());
|
REQUIRE(false == obj["hello"]["world"].is<bool>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("JsonVariant") {
|
||||||
|
obj["hello"] = "world";
|
||||||
|
doc["key"] = "hello";
|
||||||
|
|
||||||
|
REQUIRE(obj[obj["key"]] == "world");
|
||||||
|
REQUIRE(obj[obj["foo"]] == nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonObjectConst::containsKey()") {
|
TEST_CASE("JsonObjectConst::containsKey()") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc["hello"] = 42;
|
doc["hello"] = 42;
|
||||||
@@ -16,8 +18,8 @@ TEST_CASE("JsonObjectConst::containsKey()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("supports std::string") {
|
SECTION("supports std::string") {
|
||||||
REQUIRE(false == obj.containsKey(std::string("world")));
|
REQUIRE(false == obj.containsKey("world"_s));
|
||||||
REQUIRE(true == obj.containsKey(std::string("hello")));
|
REQUIRE(true == obj.containsKey("hello"_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||||
@@ -29,4 +31,10 @@ TEST_CASE("JsonObjectConst::containsKey()") {
|
|||||||
REQUIRE(true == obj.containsKey(vla));
|
REQUIRE(true == obj.containsKey(vla));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SECTION("supports JsonVariant") {
|
||||||
|
doc["key"] = "hello";
|
||||||
|
REQUIRE(true == obj.containsKey(obj["key"]));
|
||||||
|
REQUIRE(false == obj.containsKey(obj["hello"]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonObjectConst::operator[]") {
|
TEST_CASE("JsonObjectConst::operator[]") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
@@ -17,7 +18,7 @@ TEST_CASE("JsonObjectConst::operator[]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("supports std::string") {
|
SECTION("supports std::string") {
|
||||||
REQUIRE(obj[std::string("hello")] == "world"); // issue #2019
|
REQUIRE(obj["hello"_s] == "world"); // issue #2019
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
||||||
@@ -27,7 +28,13 @@ TEST_CASE("JsonObjectConst::operator[]") {
|
|||||||
char vla[i];
|
char vla[i];
|
||||||
strcpy(vla, "hello");
|
strcpy(vla, "hello");
|
||||||
|
|
||||||
REQUIRE(std::string("world") == obj[vla]);
|
REQUIRE("world"_s == obj[vla]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SECTION("supports JsonVariant") {
|
||||||
|
doc["key"] = "hello";
|
||||||
|
REQUIRE(obj[obj["key"]] == "world");
|
||||||
|
REQUIRE(obj[obj["foo"]] == nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void check(T value, const std::string& expected) {
|
void check(T value, const std::string& expected) {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
@@ -30,42 +32,42 @@ TEST_CASE("serializeJson(JsonVariant)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string") {
|
SECTION("string") {
|
||||||
check(std::string("hello"), "\"hello\"");
|
check("hello"_s, "\"hello\"");
|
||||||
|
|
||||||
SECTION("Escape quotation mark") {
|
SECTION("Escape quotation mark") {
|
||||||
check(std::string("hello \"world\""), "\"hello \\\"world\\\"\"");
|
check("hello \"world\""_s, "\"hello \\\"world\\\"\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Escape reverse solidus") {
|
SECTION("Escape reverse solidus") {
|
||||||
check(std::string("hello\\world"), "\"hello\\\\world\"");
|
check("hello\\world"_s, "\"hello\\\\world\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Don't escape solidus") {
|
SECTION("Don't escape solidus") {
|
||||||
check(std::string("fifty/fifty"), "\"fifty/fifty\"");
|
check("fifty/fifty"_s, "\"fifty/fifty\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Escape backspace") {
|
SECTION("Escape backspace") {
|
||||||
check(std::string("hello\bworld"), "\"hello\\bworld\"");
|
check("hello\bworld"_s, "\"hello\\bworld\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Escape formfeed") {
|
SECTION("Escape formfeed") {
|
||||||
check(std::string("hello\fworld"), "\"hello\\fworld\"");
|
check("hello\fworld"_s, "\"hello\\fworld\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Escape linefeed") {
|
SECTION("Escape linefeed") {
|
||||||
check(std::string("hello\nworld"), "\"hello\\nworld\"");
|
check("hello\nworld"_s, "\"hello\\nworld\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Escape carriage return") {
|
SECTION("Escape carriage return") {
|
||||||
check(std::string("hello\rworld"), "\"hello\\rworld\"");
|
check("hello\rworld"_s, "\"hello\\rworld\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Escape tab") {
|
SECTION("Escape tab") {
|
||||||
check(std::string("hello\tworld"), "\"hello\\tworld\"");
|
check("hello\tworld"_s, "\"hello\\tworld\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("NUL char") {
|
SECTION("NUL char") {
|
||||||
check(std::string("hello\0world", 11), "\"hello\\u0000world\"");
|
check("hello\0world"_s, "\"hello\\u0000world\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +76,7 @@ TEST_CASE("serializeJson(JsonVariant)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SerializedValue<std::string>") {
|
SECTION("SerializedValue<std::string>") {
|
||||||
check(serialized(std::string("[1,2]")), "[1,2]");
|
check(serialized("[1,2]"_s), "[1,2]");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Double") {
|
SECTION("Double") {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("serialize JsonArray to std::string") {
|
TEST_CASE("serialize JsonArray to std::string") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonArray array = doc.to<JsonArray>();
|
JsonArray array = doc.to<JsonArray>();
|
||||||
@@ -48,7 +50,7 @@ TEST_CASE("serialize JsonObject to std::string") {
|
|||||||
|
|
||||||
TEST_CASE("serialize an std::string containing a NUL") {
|
TEST_CASE("serialize an std::string containing a NUL") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc.set(std::string("hello\0world", 11));
|
doc.set("hello\0world"_s);
|
||||||
|
|
||||||
std::string json = "erase me";
|
std::string json = "erase me";
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::add(T)") {
|
TEST_CASE("JsonVariant::add(T)") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonVariant var = doc.to<JsonVariant>();
|
JsonVariant var = doc.to<JsonVariant>();
|
||||||
@@ -23,7 +26,7 @@ TEST_CASE("JsonVariant::add(T)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("add std::string to new variant") {
|
SECTION("add std::string to new variant") {
|
||||||
var.add(std::string("hello"));
|
var.add("hello"_s);
|
||||||
|
|
||||||
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
||||||
}
|
}
|
||||||
@@ -56,15 +59,58 @@ TEST_CASE("JsonVariant::add<T>()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "[[1,2]]");
|
REQUIRE(doc.as<std::string>() == "[[1,2]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JsonObject") {
|
|
||||||
JsonObject object = var.add<JsonObject>();
|
|
||||||
object["hello"] = "world";
|
|
||||||
REQUIRE(doc.as<std::string>() == "[{\"hello\":\"world\"}]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("JsonVariant") {
|
SECTION("JsonVariant") {
|
||||||
JsonVariant variant = var.add<JsonVariant>();
|
JsonVariant variant = var.add<JsonVariant>();
|
||||||
variant.set(42);
|
variant.set(42);
|
||||||
REQUIRE(doc.as<std::string>() == "[42]");
|
REQUIRE(doc.as<std::string>() == "[42]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonObject::add(JsonObject) ") {
|
||||||
|
JsonDocument doc1;
|
||||||
|
doc1["hello"_s] = "world"_s;
|
||||||
|
|
||||||
|
TimebombAllocator allocator(10);
|
||||||
|
SpyingAllocator spy(&allocator);
|
||||||
|
JsonDocument doc2(&spy);
|
||||||
|
JsonVariant variant = doc2.to<JsonVariant>();
|
||||||
|
|
||||||
|
SECTION("success") {
|
||||||
|
bool result = variant.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[{\"hello\":\"world\"}]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
Allocate(sizeofString("world")),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("partial failure") { // issue #2081
|
||||||
|
allocator.setCountdown(2);
|
||||||
|
|
||||||
|
bool result = variant.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
AllocateFail(sizeofString("world")),
|
||||||
|
Deallocate(sizeofString("hello")),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("complete failure") {
|
||||||
|
allocator.setCountdown(0);
|
||||||
|
|
||||||
|
bool result = variant.add(doc1.as<JsonObject>());
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc2.as<std::string>() == "[]");
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
AllocateFail(sizeofPool()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
namespace my {
|
namespace my {
|
||||||
using ArduinoJson::detail::isinf;
|
using ArduinoJson::detail::isinf;
|
||||||
} // namespace my
|
} // namespace my
|
||||||
@@ -25,6 +27,8 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(0 == variant.as<const char*>());
|
REQUIRE(0 == variant.as<const char*>());
|
||||||
REQUIRE("null" == variant.as<std::string>());
|
REQUIRE("null" == variant.as<std::string>());
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(4.2)") {
|
SECTION("set(4.2)") {
|
||||||
@@ -36,6 +40,8 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<long>() == 4L);
|
REQUIRE(variant.as<long>() == 4L);
|
||||||
REQUIRE(variant.as<unsigned>() == 4U);
|
REQUIRE(variant.as<unsigned>() == 4U);
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(0.0)") {
|
SECTION("set(0.0)") {
|
||||||
@@ -44,6 +50,8 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<bool>() == false);
|
REQUIRE(variant.as<bool>() == false);
|
||||||
REQUIRE(variant.as<long>() == 0L);
|
REQUIRE(variant.as<long>() == 0L);
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(false)") {
|
SECTION("set(false)") {
|
||||||
@@ -54,6 +62,8 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<long>() == 0L);
|
REQUIRE(variant.as<long>() == 0L);
|
||||||
REQUIRE(variant.as<std::string>() == "false");
|
REQUIRE(variant.as<std::string>() == "false");
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(true)") {
|
SECTION("set(true)") {
|
||||||
@@ -64,6 +74,8 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<long>() == 1L);
|
REQUIRE(variant.as<long>() == 1L);
|
||||||
REQUIRE(variant.as<std::string>() == "true");
|
REQUIRE(variant.as<std::string>() == "true");
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(42)") {
|
SECTION("set(42)") {
|
||||||
@@ -75,6 +87,8 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<unsigned int>() == 42U); // issue #1601
|
REQUIRE(variant.as<unsigned int>() == 42U); // issue #1601
|
||||||
REQUIRE(variant.as<std::string>() == "42");
|
REQUIRE(variant.as<std::string>() == "42");
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(42L)") {
|
SECTION("set(42L)") {
|
||||||
@@ -144,20 +158,20 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
|
|
||||||
REQUIRE(variant.as<bool>() == true);
|
REQUIRE(variant.as<bool>() == true);
|
||||||
REQUIRE(variant.as<long>() == 0L);
|
REQUIRE(variant.as<long>() == 0L);
|
||||||
REQUIRE(variant.as<const char*>() == std::string("hello"));
|
REQUIRE(variant.as<const char*>() == "hello"_s);
|
||||||
REQUIRE(variant.as<const char*>() == std::string("hello"));
|
REQUIRE(variant.as<const char*>() == "hello"_s);
|
||||||
REQUIRE(variant.as<std::string>() == std::string("hello"));
|
REQUIRE(variant.as<std::string>() == "hello"_s);
|
||||||
REQUIRE(variant.as<JsonString>() == "hello");
|
REQUIRE(variant.as<JsonString>() == "hello");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(std::string(\"4.2\"))") {
|
SECTION("set(std::string(\"4.2\"))") {
|
||||||
variant.set(std::string("4.2"));
|
variant.set("4.2"_s);
|
||||||
|
|
||||||
REQUIRE(variant.as<bool>() == true);
|
REQUIRE(variant.as<bool>() == true);
|
||||||
REQUIRE(variant.as<long>() == 4L);
|
REQUIRE(variant.as<long>() == 4L);
|
||||||
REQUIRE(variant.as<double>() == 4.2);
|
REQUIRE(variant.as<double>() == 4.2);
|
||||||
REQUIRE(variant.as<const char*>() == std::string("4.2"));
|
REQUIRE(variant.as<const char*>() == "4.2"_s);
|
||||||
REQUIRE(variant.as<std::string>() == std::string("4.2"));
|
REQUIRE(variant.as<std::string>() == "4.2"_s);
|
||||||
REQUIRE(variant.as<JsonString>() == "4.2");
|
REQUIRE(variant.as<JsonString>() == "4.2");
|
||||||
REQUIRE(variant.as<JsonString>().isLinked() == false);
|
REQUIRE(variant.as<JsonString>().isLinked() == false);
|
||||||
}
|
}
|
||||||
@@ -199,6 +213,13 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("set(serialized(\"hello\"))") {
|
||||||
|
variant.set(serialized("hello"));
|
||||||
|
|
||||||
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("to<JsonObject>()") {
|
SECTION("to<JsonObject>()") {
|
||||||
JsonObject obj = variant.to<JsonObject>();
|
JsonObject obj = variant.to<JsonObject>();
|
||||||
obj["key"] = "value";
|
obj["key"] = "value";
|
||||||
@@ -208,13 +229,13 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("as<std::string>()") {
|
SECTION("as<std::string>()") {
|
||||||
REQUIRE(variant.as<std::string>() == std::string("{\"key\":\"value\"}"));
|
REQUIRE(variant.as<std::string>() == "{\"key\":\"value\"}"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ObjectAsJsonObject") {
|
SECTION("ObjectAsJsonObject") {
|
||||||
JsonObject o = variant.as<JsonObject>();
|
JsonObject o = variant.as<JsonObject>();
|
||||||
REQUIRE(o.size() == 1);
|
REQUIRE(o.size() == 1);
|
||||||
REQUIRE(o["key"] == std::string("value"));
|
REQUIRE(o["key"] == "value"_s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +249,7 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("as<std::string>()") {
|
SECTION("as<std::string>()") {
|
||||||
REQUIRE(variant.as<std::string>() == std::string("[4,2]"));
|
REQUIRE(variant.as<std::string>() == "[4,2]"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("as<JsonArray>()") {
|
SECTION("as<JsonArray>()") {
|
||||||
@@ -245,7 +266,7 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<long long>() == -9223372036854775807 - 1);
|
REQUIRE(variant.as<long long>() == -9223372036854775807 - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Biggerst int64 positive") {
|
SECTION("Biggest int64 positive") {
|
||||||
variant.set("9223372036854775807");
|
variant.set("9223372036854775807");
|
||||||
REQUIRE(variant.as<long long>() == 9223372036854775807);
|
REQUIRE(variant.as<long long>() == 9223372036854775807);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::clear()") {
|
TEST_CASE("JsonVariant::clear()") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
@@ -28,7 +29,7 @@ TEST_CASE("JsonVariant::clear()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("releases owned string") {
|
SECTION("releases owned string") {
|
||||||
var.set(std::string("hello"));
|
var.set("hello"_s);
|
||||||
var.clear();
|
var.clear();
|
||||||
|
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
|||||||
@@ -113,6 +113,42 @@ TEST_CASE("Compare JsonVariant with JsonVariant") {
|
|||||||
CHECK_FALSE(a == b);
|
CHECK_FALSE(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("MsgPackBinary('abc') vs MsgPackBinary('abc')") {
|
||||||
|
a.set(MsgPackBinary("abc", 4));
|
||||||
|
b.set(MsgPackBinary("abc", 4));
|
||||||
|
|
||||||
|
CHECK(a == b);
|
||||||
|
CHECK(a <= b);
|
||||||
|
CHECK(a >= b);
|
||||||
|
CHECK_FALSE(a != b);
|
||||||
|
CHECK_FALSE(a < b);
|
||||||
|
CHECK_FALSE(a > b);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("MsgPackBinary('abc') vs MsgPackBinary('bcd')") {
|
||||||
|
a.set(MsgPackBinary("abc", 4));
|
||||||
|
b.set(MsgPackBinary("bcd", 4));
|
||||||
|
|
||||||
|
CHECK(a != b);
|
||||||
|
CHECK(a < b);
|
||||||
|
CHECK(a <= b);
|
||||||
|
CHECK_FALSE(a == b);
|
||||||
|
CHECK_FALSE(a > b);
|
||||||
|
CHECK_FALSE(a >= b);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("MsgPackBinary('bcd') vs MsgPackBinary('abc')") {
|
||||||
|
a.set(MsgPackBinary("bcd", 4));
|
||||||
|
b.set(MsgPackBinary("abc", 4));
|
||||||
|
|
||||||
|
CHECK(a != b);
|
||||||
|
CHECK(a > b);
|
||||||
|
CHECK(a >= b);
|
||||||
|
CHECK_FALSE(a < b);
|
||||||
|
CHECK_FALSE(a <= b);
|
||||||
|
CHECK_FALSE(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("false vs true") {
|
SECTION("false vs true") {
|
||||||
a.set(false);
|
a.set(false);
|
||||||
b.set(true);
|
b.set(true);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::containsKey()") {
|
TEST_CASE("JsonVariant::containsKey()") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonVariant var = doc.to<JsonVariant>();
|
JsonVariant var = doc.to<JsonVariant>();
|
||||||
@@ -20,7 +22,15 @@ TEST_CASE("JsonVariant::containsKey()") {
|
|||||||
SECTION("containsKey(std::string)") {
|
SECTION("containsKey(std::string)") {
|
||||||
var["hello"] = "world";
|
var["hello"] = "world";
|
||||||
|
|
||||||
REQUIRE(var.containsKey(std::string("hello")) == true);
|
REQUIRE(var.containsKey("hello"_s) == true);
|
||||||
REQUIRE(var.containsKey(std::string("world")) == false);
|
REQUIRE(var.containsKey("world"_s) == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("containsKey(JsonVariant)") {
|
||||||
|
var["hello"] = "world";
|
||||||
|
var["key"] = "hello";
|
||||||
|
|
||||||
|
REQUIRE(var.containsKey(doc["key"]) == true);
|
||||||
|
REQUIRE(var.containsKey(doc["foo"]) == false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,15 +140,3 @@ TEST_CASE("Custom converter with specialization") {
|
|||||||
REQUIRE(doc["value"]["imag"] == 3);
|
REQUIRE(doc["value"]["imag"] == 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ConverterNeedsWriteableRef") {
|
|
||||||
using namespace ArduinoJson::detail;
|
|
||||||
CHECK(ConverterNeedsWriteableRef<int>::value == false);
|
|
||||||
CHECK(ConverterNeedsWriteableRef<float>::value == false);
|
|
||||||
CHECK(ConverterNeedsWriteableRef<JsonVariant>::value == true);
|
|
||||||
CHECK(ConverterNeedsWriteableRef<JsonVariantConst>::value == false);
|
|
||||||
CHECK(ConverterNeedsWriteableRef<JsonObject>::value == true);
|
|
||||||
CHECK(ConverterNeedsWriteableRef<JsonObjectConst>::value == false);
|
|
||||||
CHECK(ConverterNeedsWriteableRef<JsonArray>::value == true);
|
|
||||||
CHECK(ConverterNeedsWriteableRef<JsonArrayConst>::value == false);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::set(JsonVariant)") {
|
TEST_CASE("JsonVariant::set(JsonVariant)") {
|
||||||
KillswitchAllocator killswitch;
|
KillswitchAllocator killswitch;
|
||||||
SpyingAllocator spyingAllocator(&killswitch);
|
SpyingAllocator spyingAllocator(&killswitch);
|
||||||
@@ -72,7 +74,7 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("stores std::string by copy") {
|
SECTION("stores std::string by copy") {
|
||||||
var1.set(std::string("hello!!"));
|
var1.set("hello!!"_s);
|
||||||
spyingAllocator.clearLog();
|
spyingAllocator.clearLog();
|
||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
@@ -106,7 +108,7 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("stores Serialized<std::string> by copy") {
|
SECTION("stores Serialized<std::string> by copy") {
|
||||||
var1.set(serialized(std::string("hello!!")));
|
var1.set(serialized("hello!!"_s));
|
||||||
spyingAllocator.clearLog();
|
spyingAllocator.clearLog();
|
||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
@@ -117,7 +119,7 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("fails gracefully if raw string allocation fails") {
|
SECTION("fails gracefully if raw string allocation fails") {
|
||||||
var1.set(serialized(std::string("hello!!")));
|
var1.set(serialized("hello!!"_s));
|
||||||
killswitch.on();
|
killswitch.on();
|
||||||
spyingAllocator.clearLog();
|
spyingAllocator.clearLog();
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
|
|
||||||
@@ -15,9 +16,9 @@ TEST_CASE("JsonVariant::remove(int)") {
|
|||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
|
|
||||||
SECTION("release top level strings") {
|
SECTION("release top level strings") {
|
||||||
doc.add(std::string("hello"));
|
doc.add("hello"_s);
|
||||||
doc.add(std::string("hello"));
|
doc.add("hello"_s);
|
||||||
doc.add(std::string("world"));
|
doc.add("world"_s);
|
||||||
|
|
||||||
JsonVariant var = doc.as<JsonVariant>();
|
JsonVariant var = doc.as<JsonVariant>();
|
||||||
REQUIRE(var.as<std::string>() == "[\"hello\",\"hello\",\"world\"]");
|
REQUIRE(var.as<std::string>() == "[\"hello\",\"hello\",\"world\"]");
|
||||||
@@ -43,7 +44,7 @@ TEST_CASE("JsonVariant::remove(int)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("release strings in nested array") {
|
SECTION("release strings in nested array") {
|
||||||
doc[0][0] = std::string("hello");
|
doc[0][0] = "hello"_s;
|
||||||
|
|
||||||
JsonVariant var = doc.as<JsonVariant>();
|
JsonVariant var = doc.as<JsonVariant>();
|
||||||
REQUIRE(var.as<std::string>() == "[[\"hello\"]]");
|
REQUIRE(var.as<std::string>() == "[[\"hello\"]]");
|
||||||
@@ -77,7 +78,34 @@ TEST_CASE("JsonVariant::remove(std::string)") {
|
|||||||
var["a"] = 1;
|
var["a"] = 1;
|
||||||
var["b"] = 2;
|
var["b"] = 2;
|
||||||
|
|
||||||
var.remove(std::string("b"));
|
var.remove("b"_s);
|
||||||
|
|
||||||
REQUIRE(var.as<std::string>() == "{\"a\":1}");
|
REQUIRE(var.as<std::string>() == "{\"a\":1}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::remove(JsonVariant) from object") {
|
||||||
|
JsonDocument doc;
|
||||||
|
JsonVariant var = doc.to<JsonVariant>();
|
||||||
|
|
||||||
|
var["a"] = "a";
|
||||||
|
var["b"] = 2;
|
||||||
|
var["c"] = "b";
|
||||||
|
|
||||||
|
var.remove(var["c"]);
|
||||||
|
|
||||||
|
REQUIRE(var.as<std::string>() == "{\"a\":\"a\",\"c\":\"b\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::remove(JsonVariant) from array") {
|
||||||
|
JsonDocument doc;
|
||||||
|
JsonVariant var = doc.to<JsonVariant>();
|
||||||
|
|
||||||
|
var[0] = 3;
|
||||||
|
var[1] = 2;
|
||||||
|
var[2] = 1;
|
||||||
|
|
||||||
|
var.remove(var[2]);
|
||||||
|
var.remove(var[3]); // noop
|
||||||
|
|
||||||
|
REQUIRE(var.as<std::string>() == "[3,1]");
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
|
|
||||||
@@ -137,14 +138,14 @@ TEST_CASE("JsonVariant::set() with not enough memory") {
|
|||||||
JsonVariant v = doc.to<JsonVariant>();
|
JsonVariant v = doc.to<JsonVariant>();
|
||||||
|
|
||||||
SECTION("std::string") {
|
SECTION("std::string") {
|
||||||
bool result = v.set(std::string("hello world!!"));
|
bool result = v.set("hello world!!"_s);
|
||||||
|
|
||||||
REQUIRE(result == false);
|
REQUIRE(result == false);
|
||||||
REQUIRE(v.isNull());
|
REQUIRE(v.isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Serialized<std::string>") {
|
SECTION("Serialized<std::string>") {
|
||||||
bool result = v.set(serialized(std::string("hello world!!")));
|
bool result = v.set(serialized("hello world!!"_s));
|
||||||
|
|
||||||
REQUIRE(result == false);
|
REQUIRE(result == false);
|
||||||
REQUIRE(v.isNull());
|
REQUIRE(v.isNull());
|
||||||
@@ -178,7 +179,7 @@ TEST_CASE("JsonVariant::set(JsonDocument)") {
|
|||||||
TEST_CASE("JsonVariant::set() releases the previous value") {
|
TEST_CASE("JsonVariant::set() releases the previous value") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc["hello"] = std::string("world");
|
doc["hello"] = "world"_s;
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
JsonVariant v = doc["hello"];
|
JsonVariant v = doc["hello"];
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::operator[]") {
|
TEST_CASE("JsonVariant::operator[]") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonVariant var = doc.to<JsonVariant>();
|
JsonVariant var = doc.to<JsonVariant>();
|
||||||
@@ -31,9 +33,9 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
|
|
||||||
REQUIRE(2 == var.size());
|
REQUIRE(2 == var.size());
|
||||||
var[0].as<std::string>();
|
var[0].as<std::string>();
|
||||||
// REQUIRE(std::string("element at index 0") == );
|
// REQUIRE("element at index 0"_s == );
|
||||||
REQUIRE(std::string("element at index 1") == var[1]);
|
REQUIRE("element at index 1"_s == var[1]);
|
||||||
REQUIRE(std::string("element at index 0") ==
|
REQUIRE("element at index 0"_s ==
|
||||||
var[static_cast<unsigned char>(0)]); // issue #381
|
var[static_cast<unsigned char>(0)]); // issue #381
|
||||||
REQUIRE(var[666].isNull());
|
REQUIRE(var[666].isNull());
|
||||||
REQUIRE(var[3].isNull());
|
REQUIRE(var[3].isNull());
|
||||||
@@ -46,7 +48,7 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
var[1] = "world";
|
var[1] = "world";
|
||||||
|
|
||||||
REQUIRE(var.size() == 2);
|
REQUIRE(var.size() == 2);
|
||||||
REQUIRE(std::string("world") == var[1]);
|
REQUIRE("world"_s == var[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set value in a nested object") {
|
SECTION("set value in a nested object") {
|
||||||
@@ -56,7 +58,7 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
|
|
||||||
REQUIRE(1 == var.size());
|
REQUIRE(1 == var.size());
|
||||||
REQUIRE(1 == var[0].size());
|
REQUIRE(1 == var[0].size());
|
||||||
REQUIRE(std::string("world") == var[0]["hello"]);
|
REQUIRE("world"_s == var[0]["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("variant[0] when variant contains an integer") {
|
SECTION("variant[0] when variant contains an integer") {
|
||||||
@@ -67,6 +69,15 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
REQUIRE(var.is<int>());
|
REQUIRE(var.is<int>());
|
||||||
REQUIRE(var.as<int>() == 123);
|
REQUIRE(var.as<int>() == 123);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("use JsonVariant as index") {
|
||||||
|
array.add("A");
|
||||||
|
array.add("B");
|
||||||
|
array.add(1);
|
||||||
|
|
||||||
|
REQUIRE(var[var[2]] == "B");
|
||||||
|
REQUIRE(var[var[3]].isNull());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("The JsonVariant is a JsonObject") {
|
SECTION("The JsonVariant is a JsonObject") {
|
||||||
@@ -77,8 +88,8 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
object["b"] = "element at key \"b\"";
|
object["b"] = "element at key \"b\"";
|
||||||
|
|
||||||
REQUIRE(2 == var.size());
|
REQUIRE(2 == var.size());
|
||||||
REQUIRE(std::string("element at key \"a\"") == var["a"]);
|
REQUIRE("element at key \"a\""_s == var["a"]);
|
||||||
REQUIRE(std::string("element at key \"b\"") == var["b"]);
|
REQUIRE("element at key \"b\""_s == var["b"]);
|
||||||
REQUIRE(var["c"].isNull());
|
REQUIRE(var["c"].isNull());
|
||||||
REQUIRE(var[0].isNull());
|
REQUIRE(var[0].isNull());
|
||||||
}
|
}
|
||||||
@@ -87,7 +98,7 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
var["hello"] = "world";
|
var["hello"] = "world";
|
||||||
|
|
||||||
REQUIRE(1 == var.size());
|
REQUIRE(1 == var.size());
|
||||||
REQUIRE(std::string("world") == var["hello"]);
|
REQUIRE("world"_s == var["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set value, key is a char[]") {
|
SECTION("set value, key is a char[]") {
|
||||||
@@ -96,13 +107,22 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
key[0] = '!'; // make sure the key is duplicated
|
key[0] = '!'; // make sure the key is duplicated
|
||||||
|
|
||||||
REQUIRE(1 == var.size());
|
REQUIRE(1 == var.size());
|
||||||
REQUIRE(std::string("world") == var["hello"]);
|
REQUIRE("world"_s == var["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("var[key].to<JsonArray>()") {
|
SECTION("var[key].to<JsonArray>()") {
|
||||||
JsonArray arr = var["hello"].to<JsonArray>();
|
JsonArray arr = var["hello"].to<JsonArray>();
|
||||||
REQUIRE(arr.isNull() == false);
|
REQUIRE(arr.isNull() == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("use JsonVariant as key") {
|
||||||
|
object["a"] = "a";
|
||||||
|
object["b"] = "b";
|
||||||
|
object["c"] = "b";
|
||||||
|
|
||||||
|
REQUIRE(var[var["c"]] == "b");
|
||||||
|
REQUIRE(var[var["d"]].isNull());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
||||||
@@ -115,7 +135,7 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||||
JsonVariant variant = doc.as<JsonVariant>();
|
JsonVariant variant = doc.as<JsonVariant>();
|
||||||
|
|
||||||
REQUIRE(std::string("world") == variant[vla]);
|
REQUIRE("world"_s == variant[vla]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("key is a VLA, const JsonVariant") {
|
SECTION("key is a VLA, const JsonVariant") {
|
||||||
@@ -126,7 +146,7 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||||
const JsonVariant variant = doc.as<JsonVariant>();
|
const JsonVariant variant = doc.as<JsonVariant>();
|
||||||
|
|
||||||
REQUIRE(std::string("world") == variant[vla]);
|
REQUIRE("world"_s == variant[vla]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("Unbound JsonVariant") {
|
TEST_CASE("Unbound JsonVariant") {
|
||||||
JsonVariant variant;
|
JsonVariant variant;
|
||||||
|
|
||||||
@@ -21,6 +23,10 @@ TEST_CASE("Unbound JsonVariant") {
|
|||||||
CHECK(variant.as<JsonObject>().isNull());
|
CHECK(variant.as<JsonObject>().isNull());
|
||||||
CHECK(variant.as<JsonObjectConst>().isNull());
|
CHECK(variant.as<JsonObjectConst>().isNull());
|
||||||
CHECK(variant.as<JsonString>().isNull());
|
CHECK(variant.as<JsonString>().isNull());
|
||||||
|
CHECK(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
CHECK(variant.as<MsgPackBinary>().size() == 0);
|
||||||
|
CHECK(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
|
CHECK(variant.as<MsgPackExtension>().size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("is<T>()") {
|
SECTION("is<T>()") {
|
||||||
@@ -44,8 +50,10 @@ TEST_CASE("Unbound JsonVariant") {
|
|||||||
CHECK_FALSE(variant.set(42L));
|
CHECK_FALSE(variant.set(42L));
|
||||||
CHECK_FALSE(variant.set(42U));
|
CHECK_FALSE(variant.set(42U));
|
||||||
CHECK_FALSE(variant.set(serialized("42")));
|
CHECK_FALSE(variant.set(serialized("42")));
|
||||||
CHECK_FALSE(variant.set(serialized(std::string("42"))));
|
CHECK_FALSE(variant.set(serialized("42"_s)));
|
||||||
CHECK_FALSE(variant.set(true));
|
CHECK_FALSE(variant.set(true));
|
||||||
|
CHECK_FALSE(variant.set(MsgPackBinary("hello", 5)));
|
||||||
|
CHECK_FALSE(variant.set(MsgPackExtension(1, "hello", 5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("add()") {
|
SECTION("add()") {
|
||||||
@@ -62,7 +70,7 @@ TEST_CASE("Unbound JsonVariant") {
|
|||||||
CHECK(variant["key"].isNull());
|
CHECK(variant["key"].isNull());
|
||||||
CHECK_FALSE(variant[0].set(1));
|
CHECK_FALSE(variant[0].set(1));
|
||||||
CHECK_FALSE(variant["key"].set(1));
|
CHECK_FALSE(variant["key"].set(1));
|
||||||
CHECK_FALSE(variant[std::string("key")].set(1));
|
CHECK_FALSE(variant["key"_s].set(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("containsKey()") {
|
SECTION("containsKey()") {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonVariantConst::as<T>()") {
|
TEST_CASE("JsonVariantConst::as<T>()") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonVariantConst var = doc.to<JsonVariant>();
|
JsonVariantConst var = doc.to<JsonVariant>();
|
||||||
@@ -14,6 +16,27 @@ TEST_CASE("JsonVariantConst::as<T>()") {
|
|||||||
|
|
||||||
REQUIRE(var.as<bool>() == true);
|
REQUIRE(var.as<bool>() == true);
|
||||||
REQUIRE(var.as<long>() == 0L);
|
REQUIRE(var.as<long>() == 0L);
|
||||||
REQUIRE(var.as<const char*>() == std::string("hello"));
|
REQUIRE(var.as<const char*>() == "hello"_s);
|
||||||
REQUIRE(var.as<std::string>() == std::string("hello"));
|
REQUIRE(var.as<std::string>() == "hello"_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Invalid conversions") {
|
||||||
|
using namespace ArduinoJson::detail;
|
||||||
|
|
||||||
|
JsonVariantConst variant;
|
||||||
|
|
||||||
|
CHECK(is_same<decltype(variant.as<int>()), int>::value);
|
||||||
|
CHECK(is_same<decltype(variant.as<float>()), float>::value);
|
||||||
|
CHECK(is_same<decltype(variant.as<JsonVariantConst>()),
|
||||||
|
JsonVariantConst>::value);
|
||||||
|
CHECK(
|
||||||
|
is_same<decltype(variant.as<JsonObjectConst>()), JsonObjectConst>::value);
|
||||||
|
CHECK(is_same<decltype(variant.as<JsonArrayConst>()), JsonArrayConst>::value);
|
||||||
|
|
||||||
|
CHECK(is_same<decltype(variant.as<JsonVariant>()),
|
||||||
|
InvalidConversion<JsonVariantConst, JsonVariant>>::value);
|
||||||
|
CHECK(is_same<decltype(variant.as<JsonObject>()),
|
||||||
|
InvalidConversion<JsonVariantConst, JsonObject>>::value);
|
||||||
|
CHECK(is_same<decltype(variant.as<JsonArray>()),
|
||||||
|
InvalidConversion<JsonVariantConst, JsonArray>>::value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonVariantConst::containsKey()") {
|
TEST_CASE("JsonVariantConst::containsKey()") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc["hello"] = "world";
|
doc["hello"] = "world";
|
||||||
@@ -17,8 +19,8 @@ TEST_CASE("JsonVariantConst::containsKey()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("support std::string") {
|
SECTION("support std::string") {
|
||||||
REQUIRE(var.containsKey(std::string("hello")) == true);
|
REQUIRE(var.containsKey("hello"_s) == true);
|
||||||
REQUIRE(var.containsKey(std::string("world")) == false);
|
REQUIRE(var.containsKey("world"_s) == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||||
@@ -30,4 +32,10 @@ TEST_CASE("JsonVariantConst::containsKey()") {
|
|||||||
REQUIRE(true == var.containsKey(vla));
|
REQUIRE(true == var.containsKey(vla));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SECTION("support JsonVariant") {
|
||||||
|
doc["key"] = "hello";
|
||||||
|
REQUIRE(var.containsKey(var["key"]) == true);
|
||||||
|
REQUIRE(var.containsKey(var["foo"]) == false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("JsonVariantConst::operator[]") {
|
TEST_CASE("JsonVariantConst::operator[]") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonVariantConst var = doc.to<JsonVariant>();
|
JsonVariantConst var = doc.to<JsonVariant>();
|
||||||
@@ -27,31 +29,41 @@ TEST_CASE("JsonVariantConst::operator[]") {
|
|||||||
array.add("A");
|
array.add("A");
|
||||||
array.add("B");
|
array.add("B");
|
||||||
|
|
||||||
REQUIRE(std::string("A") == var[0]);
|
SECTION("int") {
|
||||||
REQUIRE(std::string("B") == var[1]);
|
REQUIRE("A"_s == var[0]);
|
||||||
REQUIRE(std::string("A") ==
|
REQUIRE("B"_s == var[1]);
|
||||||
var[static_cast<unsigned char>(0)]); // issue #381
|
REQUIRE("A"_s == var[static_cast<unsigned char>(0)]); // issue #381
|
||||||
REQUIRE(var[666].isNull());
|
REQUIRE(var[666].isNull());
|
||||||
REQUIRE(var[3].isNull());
|
REQUIRE(var[3].isNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const char*") {
|
||||||
REQUIRE(var["0"].isNull());
|
REQUIRE(var["0"].isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("JsonVariant") {
|
||||||
|
array.add(1);
|
||||||
|
REQUIRE(var[var[2]] == "B"_s);
|
||||||
|
REQUIRE(var[var[3]].isNull());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("object") {
|
SECTION("object") {
|
||||||
JsonObject object = doc.to<JsonObject>();
|
JsonObject object = doc.to<JsonObject>();
|
||||||
object["a"] = "A";
|
object["a"] = "A";
|
||||||
object["b"] = "B";
|
object["b"] = "B";
|
||||||
|
|
||||||
SECTION("supports const char*") {
|
SECTION("supports const char*") {
|
||||||
REQUIRE(std::string("A") == var["a"]);
|
REQUIRE("A"_s == var["a"]);
|
||||||
REQUIRE(std::string("B") == var["b"]);
|
REQUIRE("B"_s == var["b"]);
|
||||||
REQUIRE(var["c"].isNull());
|
REQUIRE(var["c"].isNull());
|
||||||
REQUIRE(var[0].isNull());
|
REQUIRE(var[0].isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("supports std::string") {
|
SECTION("supports std::string") {
|
||||||
REQUIRE(std::string("A") == var[std::string("a")]);
|
REQUIRE("A"_s == var["a"_s]);
|
||||||
REQUIRE(std::string("B") == var[std::string("b")]);
|
REQUIRE("B"_s == var["b"_s]);
|
||||||
REQUIRE(var[std::string("c")].isNull());
|
REQUIRE(var["c"_s].isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
||||||
@@ -61,8 +73,14 @@ TEST_CASE("JsonVariantConst::operator[]") {
|
|||||||
char vla[i];
|
char vla[i];
|
||||||
strcpy(vla, "a");
|
strcpy(vla, "a");
|
||||||
|
|
||||||
REQUIRE(std::string("A") == var[vla]);
|
REQUIRE("A"_s == var[vla]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SECTION("supports JsonVariant") {
|
||||||
|
object["c"] = "b";
|
||||||
|
REQUIRE(var[var["c"]] == "B");
|
||||||
|
REQUIRE(var[var["d"]].isNull());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
#include "custom_string.hpp"
|
#include "custom_string.hpp"
|
||||||
|
|
||||||
using namespace ArduinoJson::detail;
|
using namespace ArduinoJson::detail;
|
||||||
@@ -36,13 +37,13 @@ void common_tests(StringWriter& writer, const String& output) {
|
|||||||
|
|
||||||
SECTION("OneString") {
|
SECTION("OneString") {
|
||||||
REQUIRE(4 == print(writer, "ABCD"));
|
REQUIRE(4 == print(writer, "ABCD"));
|
||||||
REQUIRE(std::string("ABCD") == output);
|
REQUIRE("ABCD"_s == output);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("TwoStrings") {
|
SECTION("TwoStrings") {
|
||||||
REQUIRE(4 == print(writer, "ABCD"));
|
REQUIRE(4 == print(writer, "ABCD"));
|
||||||
REQUIRE(4 == print(writer, "EFGH"));
|
REQUIRE(4 == print(writer, "EFGH"));
|
||||||
REQUIRE(std::string("ABCDEFGH") == output);
|
REQUIRE("ABCDEFGH"_s == output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,5 +58,10 @@
|
|||||||
// issue #1914
|
// issue #1914
|
||||||
#define V7 7
|
#define V7 7
|
||||||
|
|
||||||
|
// STM32, Mbed, Particle
|
||||||
|
#define A0 16
|
||||||
|
#define A1 17
|
||||||
|
#define A2 18
|
||||||
|
|
||||||
// catch.hpp mutes several warnings, this file also allows to detect them
|
// catch.hpp mutes several warnings, this file also allows to detect them
|
||||||
#include "ArduinoJson.h"
|
#include "ArduinoJson.h"
|
||||||
|
|||||||
@@ -7,6 +7,5 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct custom_char_traits : std::char_traits<char> {};
|
struct custom_char_traits : std::char_traits<char> {};
|
||||||
struct custom_allocator : std::allocator<char> {};
|
|
||||||
typedef std::basic_string<char, custom_char_traits, custom_allocator>
|
typedef std::basic_string<char, custom_char_traits> custom_string;
|
||||||
custom_string;
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
# define CONFLICTS_WITH_BUILTIN_OPERATOR
|
# define CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||||
#endif
|
#endif
|
||||||
@@ -111,7 +113,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||||
JsonVariant variant = doc.as<JsonVariant>();
|
JsonVariant variant = doc.as<JsonVariant>();
|
||||||
|
|
||||||
REQUIRE(std::string("world") == variant[key]);
|
REQUIRE("world"_s == variant[key]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -122,7 +124,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||||
const JsonVariant variant = doc.as<JsonVariant>();
|
const JsonVariant variant = doc.as<JsonVariant>();
|
||||||
|
|
||||||
REQUIRE(std::string("world") == variant[key]);
|
REQUIRE("world"_s == variant[key]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -160,7 +162,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
JsonObject obj = doc.to<JsonObject>();
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
obj[key] = "world";
|
obj[key] = "world";
|
||||||
|
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE("world"_s == obj["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JsonObject::operator[] const") {
|
SECTION("JsonObject::operator[] const") {
|
||||||
@@ -170,7 +172,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||||
|
|
||||||
JsonObject obj = doc.as<JsonObject>();
|
JsonObject obj = doc.as<JsonObject>();
|
||||||
REQUIRE(std::string("world") == obj[key]);
|
REQUIRE("world"_s == obj[key]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -203,7 +205,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
JsonObject obj = doc.to<JsonObject>();
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
obj["hello"] = value;
|
obj["hello"] = value;
|
||||||
|
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE("world"_s == obj["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set()") {
|
SECTION("set()") {
|
||||||
@@ -213,7 +215,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
JsonObject obj = doc.to<JsonObject>();
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
obj["hello"].set(value);
|
obj["hello"].set(value);
|
||||||
|
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE("world"_s == obj["hello"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +227,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
JsonArray arr = doc.to<JsonArray>();
|
JsonArray arr = doc.to<JsonArray>();
|
||||||
arr.add(value);
|
arr.add(value);
|
||||||
|
|
||||||
REQUIRE(std::string("world") == arr[0]);
|
REQUIRE("world"_s == arr[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +240,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
arr.add("hello");
|
arr.add("hello");
|
||||||
arr[0].set(value);
|
arr[0].set(value);
|
||||||
|
|
||||||
REQUIRE(std::string("world") == arr[0]);
|
REQUIRE("world"_s == arr[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator=") {
|
SECTION("operator=") {
|
||||||
@@ -249,7 +251,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
arr.add("hello");
|
arr.add("hello");
|
||||||
arr[0] = value;
|
arr[0] = value;
|
||||||
|
|
||||||
REQUIRE(std::string("world") == arr[0]);
|
REQUIRE("world"_s == arr[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ add_executable(MixedConfigurationTests
|
|||||||
enable_nan_1.cpp
|
enable_nan_1.cpp
|
||||||
enable_progmem_1.cpp
|
enable_progmem_1.cpp
|
||||||
issue1707.cpp
|
issue1707.cpp
|
||||||
|
string_length_size_1.cpp
|
||||||
|
string_length_size_2.cpp
|
||||||
|
string_length_size_4.cpp
|
||||||
use_double_0.cpp
|
use_double_0.cpp
|
||||||
use_double_1.cpp
|
use_double_1.cpp
|
||||||
use_long_long_0.cpp
|
use_long_long_0.cpp
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
#define ARDUINOJSON_STRING_LENGTH_SIZE 1
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
|
TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 1") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
SECTION("set(std::string)") {
|
||||||
|
SECTION("returns true if len <= 255") {
|
||||||
|
auto result = doc.set(std::string(255, '?'));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false if len >= 256") {
|
||||||
|
auto result = doc.set(std::string(256, '?'));
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackBinary)") {
|
||||||
|
SECTION("returns true if size <= 253") {
|
||||||
|
auto str = std::string(253, '?');
|
||||||
|
auto result = doc.set(MsgPackBinary(str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false if size >= 254") {
|
||||||
|
auto str = std::string(254, '?');
|
||||||
|
auto result = doc.set(MsgPackBinary(str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackExtension)") {
|
||||||
|
SECTION("returns true if size <= 252") {
|
||||||
|
auto str = std::string(252, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false if size >= 253") {
|
||||||
|
auto str = std::string(253, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("deserializeJson()") {
|
||||||
|
SECTION("returns Ok if string length <= 255") {
|
||||||
|
auto input = "\"" + std::string(255, '?') + "\"";
|
||||||
|
|
||||||
|
auto err = deserializeJson(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if string length >= 256") {
|
||||||
|
auto input = "\"" + std::string(256, '?') + "\"";
|
||||||
|
|
||||||
|
auto err = deserializeJson(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("deserializeMsgPack()") {
|
||||||
|
SECTION("returns Ok if string length <= 255") {
|
||||||
|
auto input = "\xd9\xff" + std::string(255, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if string length >= 256") {
|
||||||
|
auto input = "\xda\x01\x00"_s + std::string(256, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if binary size <= 253") {
|
||||||
|
auto input = "\xc4\xfd" + std::string(253, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if binary size >= 254") {
|
||||||
|
auto input = "\xc4\xfe" + std::string(254, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if extension size <= 252") {
|
||||||
|
auto input = "\xc7\xfc\x01" + std::string(252, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if binary size >= 253") {
|
||||||
|
auto input = "\xc7\xfd\x01" + std::string(253, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#define ARDUINOJSON_STRING_LENGTH_SIZE 2
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
|
TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 2") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
SECTION("set(std::string)") {
|
||||||
|
SECTION("returns true if len <= 65535") {
|
||||||
|
auto result = doc.set(std::string(65535, '?'));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false if len >= 65536") {
|
||||||
|
auto result = doc.set(std::string(65536, '?'));
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackBinary)") {
|
||||||
|
SECTION("returns true if size <= 65532") {
|
||||||
|
auto str = std::string(65532, '?');
|
||||||
|
auto result = doc.set(MsgPackBinary(str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false if size >= 65533") {
|
||||||
|
auto str = std::string(65533, '?');
|
||||||
|
auto result = doc.set(MsgPackBinary(str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackExtension)") {
|
||||||
|
SECTION("returns true if size <= 65531") {
|
||||||
|
auto str = std::string(65531, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false if size >= 65532") {
|
||||||
|
auto str = std::string(65532, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("deserializeJson()") {
|
||||||
|
SECTION("returns Ok if string length <= 65535") {
|
||||||
|
auto input = "\"" + std::string(65535, '?') + "\"";
|
||||||
|
|
||||||
|
auto err = deserializeJson(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if string length >= 65536") {
|
||||||
|
auto input = "\"" + std::string(65536, '?') + "\"";
|
||||||
|
|
||||||
|
auto err = deserializeJson(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("deserializeMsgPack()") {
|
||||||
|
SECTION("returns Ok if string length <= 65535") {
|
||||||
|
auto input = "\xda\xff\xff" + std::string(65535, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if string length >= 65536") {
|
||||||
|
auto input = "\xdb\x00\x01\x00\x00"_s + std::string(65536, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if binary size <= 65532") {
|
||||||
|
auto input = "\xc5\xff\xfc" + std::string(65532, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if binary size >= 65534") {
|
||||||
|
auto input = "\xc5\xff\xfd" + std::string(65534, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://oss-fuzz.com/testcase?key=5354792971993088
|
||||||
|
SECTION("doesn't overflow if binary size == 0xFFFF") {
|
||||||
|
auto input = "\xc5\xff\xff"_s;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if extension size <= 65531") {
|
||||||
|
auto input = "\xc8\xff\xfb\x01" + std::string(65531, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if extension size >= 65532") {
|
||||||
|
auto input = "\xc8\xff\xfc\x01" + std::string(65532, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
#define ARDUINOJSON_STRING_LENGTH_SIZE 4
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
|
TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 4") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
SECTION("set(std::string)") {
|
||||||
|
SECTION("returns true if string length >= 65536") {
|
||||||
|
auto result = doc.set(std::string(65536, '?'));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackBinary)") {
|
||||||
|
SECTION("returns true if size >= 65536") {
|
||||||
|
auto str = std::string(65536, '?');
|
||||||
|
auto result = doc.set(MsgPackBinary(str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackExtension)") {
|
||||||
|
SECTION("returns true if size >= 65532") {
|
||||||
|
auto str = std::string(65532, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("deserializeJson()") {
|
||||||
|
SECTION("returns Ok if string length >= 65536") {
|
||||||
|
auto input = "\"" + std::string(65536, '?') + "\"";
|
||||||
|
|
||||||
|
auto err = deserializeJson(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("deserializeMsgPack()") {
|
||||||
|
SECTION("returns Ok if string size >= 65536") {
|
||||||
|
auto input = "\xda\xff\xff" + std::string(65536, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if binary size >= 65536") {
|
||||||
|
auto input = "\xc5\xff\xff" + std::string(65536, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if extension size >= 65532") {
|
||||||
|
auto input = "\xc8\xff\xfb\x01" + std::string(65532, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://oss-fuzz.com/testcase?key=5354792971993088
|
||||||
|
SECTION("doesn't overflow if binary size == 0xFFFFFFFF") {
|
||||||
|
auto input = "\xc6\xff\xff\xff\xff"_s;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("doesn't overflow if string size == 0xFFFFFFFF") {
|
||||||
|
auto input = "\xdb\xff\xff\xff\xff???????????????????"_s;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err != DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("bin 32 deserialization") {
|
||||||
|
auto str = std::string(65536, '?');
|
||||||
|
auto input = "\xc6\x00\x01\x00\x00"_s + str;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackBinary>());
|
||||||
|
auto binary = doc.as<MsgPackBinary>();
|
||||||
|
REQUIRE(binary.size() == 65536);
|
||||||
|
REQUIRE(binary.data() != nullptr);
|
||||||
|
REQUIRE(std::string(reinterpret_cast<const char*>(binary.data()),
|
||||||
|
binary.size()) == str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("bin 32 serialization") {
|
||||||
|
auto str = std::string(65536, '?');
|
||||||
|
doc.set(MsgPackBinary(str.data(), str.size()));
|
||||||
|
|
||||||
|
std::string output;
|
||||||
|
auto result = serializeMsgPack(doc, output);
|
||||||
|
|
||||||
|
REQUIRE(result == 5 + str.size());
|
||||||
|
REQUIRE(output == "\xc6\x00\x01\x00\x00"_s + str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 32 deserialization") {
|
||||||
|
auto str = std::string(65536, '?');
|
||||||
|
auto input = "\xc9\x00\x01\x00\x00\x2a"_s + str;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto value = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(value.type() == 42);
|
||||||
|
REQUIRE(value.size() == 65536);
|
||||||
|
REQUIRE(value.data() != nullptr);
|
||||||
|
REQUIRE(std::string(reinterpret_cast<const char*>(value.data()),
|
||||||
|
value.size()) == str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 32 serialization") {
|
||||||
|
auto str = std::string(65536, '?');
|
||||||
|
doc.set(MsgPackExtension(42, str.data(), str.size()));
|
||||||
|
|
||||||
|
std::string output;
|
||||||
|
auto result = serializeMsgPack(doc, output);
|
||||||
|
|
||||||
|
REQUIRE(result == 6 + str.size());
|
||||||
|
REQUIRE(output == "\xc9\x00\x01\x00\x00\x2a"_s + str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,9 +3,12 @@
|
|||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") {
|
TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
|
SECTION("smoke test") {
|
||||||
doc["A"] = 42;
|
doc["A"] = 42;
|
||||||
doc["B"] = 84;
|
doc["B"] = 84;
|
||||||
|
|
||||||
@@ -14,3 +17,26 @@ TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") {
|
|||||||
|
|
||||||
REQUIRE(json == "{\"A\":42,\"B\":84}");
|
REQUIRE(json == "{\"A\":42,\"B\":84}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("deserializeMsgPack()") {
|
||||||
|
SECTION("cf 00 00 00 00 ff ff ff ff") {
|
||||||
|
auto err =
|
||||||
|
deserializeMsgPack(doc, "\xcf\x00\x00\x00\x00\xff\xff\xff\xff"_s);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.as<uint32_t>() == 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("cf 00 00 00 01 00 00 00 00") {
|
||||||
|
auto err =
|
||||||
|
deserializeMsgPack(doc, "\xcf\x00\x00\x00\x01\x00\x00\x00\x00"_s);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
|
||||||
|
REQUIRE(doc.as<JsonInteger>() == 0x100000000);
|
||||||
|
#else
|
||||||
|
REQUIRE(doc.isNull());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void checkValue(const char* input, T expected) {
|
static void checkValue(const char* input, T expected) {
|
||||||
@@ -123,21 +124,171 @@ TEST_CASE("deserialize MsgPack value") {
|
|||||||
|
|
||||||
SECTION("fixstr") {
|
SECTION("fixstr") {
|
||||||
checkValue<std::string>("\xA0", std::string(""));
|
checkValue<std::string>("\xA0", std::string(""));
|
||||||
checkValue<std::string>("\xABhello world", std::string("hello world"));
|
checkValue<std::string>("\xABhello world", "hello world"_s);
|
||||||
checkValue<std::string>("\xBFhello world hello world hello !",
|
checkValue<std::string>("\xBFhello world hello world hello !",
|
||||||
std::string("hello world hello world hello !"));
|
"hello world hello world hello !"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("str 8") {
|
SECTION("str 8") {
|
||||||
checkValue<std::string>("\xd9\x05hello", std::string("hello"));
|
checkValue<std::string>("\xd9\x05hello", "hello"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("str 16") {
|
SECTION("str 16") {
|
||||||
checkValue<std::string>("\xda\x00\x05hello", std::string("hello"));
|
checkValue<std::string>("\xda\x00\x05hello", "hello"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("str 32") {
|
SECTION("str 32") {
|
||||||
checkValue<std::string>("\xdb\x00\x00\x00\x05hello", std::string("hello"));
|
checkValue<std::string>("\xdb\x00\x00\x00\x05hello", "hello"_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("bin 8") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
DeserializationError error = deserializeMsgPack(doc, "\xc4\x01?");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackBinary>());
|
||||||
|
auto binary = doc.as<MsgPackBinary>();
|
||||||
|
REQUIRE(binary.size() == 1);
|
||||||
|
REQUIRE(binary.data() != nullptr);
|
||||||
|
REQUIRE(reinterpret_cast<const char*>(binary.data())[0] == '?');
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("bin 16") {
|
||||||
|
JsonDocument doc;
|
||||||
|
auto str = std::string(256, '?');
|
||||||
|
auto input = "\xc5\x01\x00"_s + str;
|
||||||
|
|
||||||
|
DeserializationError error = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackBinary>());
|
||||||
|
auto binary = doc.as<MsgPackBinary>();
|
||||||
|
REQUIRE(binary.size() == 0x100);
|
||||||
|
REQUIRE(binary.data() != nullptr);
|
||||||
|
REQUIRE(std::string(reinterpret_cast<const char*>(binary.data()),
|
||||||
|
binary.size()) == str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 1") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd4\x01\x02");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 1);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 2") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd5\x01\x02\x03");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 2);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 2);
|
||||||
|
REQUIRE(data[1] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 4") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd6\x01\x02\x03\x04\x05");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 4);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 2);
|
||||||
|
REQUIRE(data[1] == 3);
|
||||||
|
REQUIRE(data[2] == 4);
|
||||||
|
REQUIRE(data[3] == 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 8") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd7\x01????????");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 8);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == '?');
|
||||||
|
REQUIRE(data[7] == '?');
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 16") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd8\x01?????????????????");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 16);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == '?');
|
||||||
|
REQUIRE(data[15] == '?');
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 8") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xc7\x02\x01\x03\x04");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 2);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 3);
|
||||||
|
REQUIRE(data[1] == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 16") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xc8\x00\x02\x01\x03\x04");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 2);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 3);
|
||||||
|
REQUIRE(data[1] == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 32") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xc9\x00\x00\x00\x02\x01\x03\x04");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 2);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 3);
|
||||||
|
REQUIRE(data[1] == 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,12 +349,12 @@ TEST_CASE("deserializeMsgPack() under memory constaints") {
|
|||||||
checkError(0, "\x80", DeserializationError::Ok);
|
checkError(0, "\x80", DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
SECTION("{H:1}") {
|
SECTION("{H:1}") {
|
||||||
checkError(0, "\x81\xA1H\x01", DeserializationError::NoMemory);
|
checkError(1, "\x81\xA1H\x01", DeserializationError::NoMemory);
|
||||||
checkError(3, "\x81\xA1H\x01", DeserializationError::Ok);
|
checkError(2, "\x81\xA1H\x01", DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
SECTION("{H:1,W:2}") {
|
SECTION("{H:1,W:2}") {
|
||||||
checkError(3, "\x82\xA1H\x01\xA1W\x02", DeserializationError::NoMemory);
|
checkError(2, "\x82\xA1H\x01\xA1W\x02", DeserializationError::NoMemory);
|
||||||
checkError(5, "\x82\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
checkError(3, "\x82\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,13 +363,13 @@ TEST_CASE("deserializeMsgPack() under memory constaints") {
|
|||||||
checkError(0, "\xDE\x00\x00", DeserializationError::Ok);
|
checkError(0, "\xDE\x00\x00", DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
SECTION("{H:1}") {
|
SECTION("{H:1}") {
|
||||||
checkError(2, "\xDE\x00\x01\xA1H\x01", DeserializationError::NoMemory);
|
checkError(1, "\xDE\x00\x01\xA1H\x01", DeserializationError::NoMemory);
|
||||||
checkError(3, "\xDE\x00\x01\xA1H\x01", DeserializationError::Ok);
|
checkError(2, "\xDE\x00\x01\xA1H\x01", DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
SECTION("{H:1,W:2}") {
|
SECTION("{H:1,W:2}") {
|
||||||
checkError(3, "\xDE\x00\x02\xA1H\x01\xA1W\x02",
|
checkError(2, "\xDE\x00\x02\xA1H\x01\xA1W\x02",
|
||||||
DeserializationError::NoMemory);
|
DeserializationError::NoMemory);
|
||||||
checkError(5, "\xDE\x00\x02\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
checkError(3, "\xDE\x00\x02\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,14 +378,14 @@ TEST_CASE("deserializeMsgPack() under memory constaints") {
|
|||||||
checkError(0, "\xDF\x00\x00\x00\x00", DeserializationError::Ok);
|
checkError(0, "\xDF\x00\x00\x00\x00", DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
SECTION("{H:1}") {
|
SECTION("{H:1}") {
|
||||||
checkError(2, "\xDF\x00\x00\x00\x01\xA1H\x01",
|
checkError(1, "\xDF\x00\x00\x00\x01\xA1H\x01",
|
||||||
DeserializationError::NoMemory);
|
DeserializationError::NoMemory);
|
||||||
checkError(3, "\xDF\x00\x00\x00\x01\xA1H\x01", DeserializationError::Ok);
|
checkError(2, "\xDF\x00\x00\x00\x01\xA1H\x01", DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
SECTION("{H:1,W:2}") {
|
SECTION("{H:1,W:2}") {
|
||||||
checkError(3, "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
checkError(2, "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
||||||
DeserializationError::NoMemory);
|
DeserializationError::NoMemory);
|
||||||
checkError(5, "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
checkError(3, "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
||||||
DeserializationError::Ok);
|
DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
@@ -15,7 +16,7 @@ using ArduinoJson::detail::sizeofObject;
|
|||||||
TEST_CASE("deserializeMsgPack(JsonDocument&)") {
|
TEST_CASE("deserializeMsgPack(JsonDocument&)") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc.add(std::string("hello"));
|
doc.add("hello"_s);
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
auto err = deserializeMsgPack(doc, "\x91\x2A");
|
auto err = deserializeMsgPack(doc, "\x91\x2A");
|
||||||
@@ -34,7 +35,7 @@ TEST_CASE("deserializeMsgPack(JsonVariant)") {
|
|||||||
SECTION("variant is bound") {
|
SECTION("variant is bound") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc.add(std::string("hello"));
|
doc.add("hello"_s);
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
JsonVariant variant = doc[0];
|
JsonVariant variant = doc[0];
|
||||||
@@ -60,7 +61,7 @@ TEST_CASE("deserializeMsgPack(JsonVariant)") {
|
|||||||
TEST_CASE("deserializeMsgPack(ElementProxy)") {
|
TEST_CASE("deserializeMsgPack(ElementProxy)") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc.add(std::string("hello"));
|
doc.add("hello"_s);
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
SECTION("element already exists") {
|
SECTION("element already exists") {
|
||||||
@@ -85,7 +86,7 @@ TEST_CASE("deserializeMsgPack(ElementProxy)") {
|
|||||||
TEST_CASE("deserializeMsgPack(MemberProxy)") {
|
TEST_CASE("deserializeMsgPack(MemberProxy)") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
doc[std::string("hello")] = std::string("world");
|
doc["hello"_s] = "world"_s;
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
SECTION("member already exists") {
|
SECTION("member already exists") {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ static void check(const char* input, T expected) {
|
|||||||
uint8_t* f = reinterpret_cast<uint8_t*>(&actual);
|
uint8_t* f = reinterpret_cast<uint8_t*>(&actual);
|
||||||
const uint8_t* d = reinterpret_cast<const uint8_t*>(input);
|
const uint8_t* d = reinterpret_cast<const uint8_t*>(input);
|
||||||
doubleToFloat(d, f);
|
doubleToFloat(d, f);
|
||||||
fixEndianess(actual);
|
fixEndianness(actual);
|
||||||
CHECK(actual == expected);
|
CHECK(actual == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
TEST_CASE("deserializeMsgPack() returns InvalidInput") {
|
TEST_CASE("deserializeMsgPack() returns InvalidInput") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
@@ -182,84 +184,18 @@ TEST_CASE("deserializeMsgPack() returns IncompleteInput") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string msgPackToJson(const char* input, size_t inputSize) {
|
TEST_CASE(
|
||||||
JsonDocument doc;
|
"deserializeMsgPack() returns NoMemory when string allocation fails") {
|
||||||
auto err = deserializeMsgPack(doc, input, inputSize);
|
TimebombAllocator allocator(0);
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
JsonDocument doc(&allocator);
|
||||||
return doc.as<std::string>();
|
|
||||||
|
SECTION("fixstr") {
|
||||||
|
DeserializationError err = deserializeMsgPack(doc, "\xA5hello", 9);
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("deserializeMsgPack() replaces unsupported types by null") {
|
|
||||||
SECTION("bin 8") {
|
SECTION("bin 8") {
|
||||||
REQUIRE(msgPackToJson("\x92\xc4\x01X\x2A", 5) == "[null,42]");
|
DeserializationError err = deserializeMsgPack(doc, "\xC4\x01X", 3);
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("bin 16") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xc5\x00\x01X\x2A", 6) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("bin 32") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xc6\x00\x00\x00\x01X\x2A", 8) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("ext 8") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xc7\x01\x01\x01\x2A", 6) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("ext 16") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xc8\x00\x01\x01\x01\x2A", 7) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("ext 32") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xc9\x00\x00\x00\x01\x01\x01\x2A", 9) ==
|
|
||||||
"[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 1") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd4\x01\x01\x2A", 5) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 2") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd5\x01\x01\x02\x2A", 6) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 4") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd6\x01\x01\x02\x03\x04\x2A", 8) ==
|
|
||||||
"[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 8") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd7\x01\x01\x02\x03\x04\x05\x06\x07\x08\x2A",
|
|
||||||
12) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 16") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd8\x01\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A"
|
|
||||||
"\x0B\x0C\x0D\x0E"
|
|
||||||
"\x0F\x10\x2A",
|
|
||||||
20) == "[null,42]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("deserializeMsgPack() returns NoMemory is string length overflows") {
|
|
||||||
JsonDocument doc;
|
|
||||||
auto maxLength = ArduinoJson::detail::StringNode::maxLength;
|
|
||||||
|
|
||||||
SECTION("max length should succeed") {
|
|
||||||
auto len = maxLength;
|
|
||||||
std::string prefix = {'\xdb', char(len >> 24), char(len >> 16),
|
|
||||||
char(len >> 8), char(len)};
|
|
||||||
|
|
||||||
auto err = deserializeMsgPack(doc, prefix + std::string(len, 'a'));
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("one above max length should fail") {
|
|
||||||
auto len = maxLength + 1;
|
|
||||||
std::string prefix = {'\xdb', char(len >> 24), char(len >> 16),
|
|
||||||
char(len >> 8), char(len)};
|
|
||||||
|
|
||||||
auto err = deserializeMsgPack(doc, prefix + std::string(len, 'a'));
|
|
||||||
REQUIRE(err == DeserializationError::NoMemory);
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "CustomReader.hpp"
|
#include "CustomReader.hpp"
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
|
|
||||||
@@ -21,8 +22,7 @@ TEST_CASE("deserializeMsgPack(const std::string&)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should accept temporary string") {
|
SECTION("should accept temporary string") {
|
||||||
DeserializationError err =
|
DeserializationError err = deserializeMsgPack(doc, "\x92\x01\x02"_s);
|
||||||
deserializeMsgPack(doc, std::string("\x92\x01\x02"));
|
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
@@ -35,12 +35,11 @@ TEST_CASE("deserializeMsgPack(const std::string&)") {
|
|||||||
|
|
||||||
JsonArray array = doc.as<JsonArray>();
|
JsonArray array = doc.as<JsonArray>();
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
REQUIRE(std::string("hello") == array[0]);
|
REQUIRE("hello"_s == array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should accept a zero in input") {
|
SECTION("should accept a zero in input") {
|
||||||
DeserializationError err =
|
DeserializationError err = deserializeMsgPack(doc, "\x92\x00\x02"_s);
|
||||||
deserializeMsgPack(doc, std::string("\x92\x00\x02", 3));
|
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
JsonArray arr = doc.as<JsonArray>();
|
JsonArray arr = doc.as<JsonArray>();
|
||||||
@@ -53,7 +52,7 @@ TEST_CASE("deserializeMsgPack(std::istream&)") {
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
SECTION("should accept a zero in input") {
|
SECTION("should accept a zero in input") {
|
||||||
std::istringstream input(std::string("\x92\x00\x02", 3));
|
std::istringstream input("\x92\x00\x02"_s);
|
||||||
|
|
||||||
DeserializationError err = deserializeMsgPack(doc, input);
|
DeserializationError err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
static void check(const JsonArray array, const char* expected_data,
|
static void check(const JsonArray array, const char* expected_data,
|
||||||
size_t expected_len) {
|
size_t expected_len) {
|
||||||
std::string expected(expected_data, expected_data + expected_len);
|
std::string expected(expected_data, expected_data + expected_len);
|
||||||
@@ -57,7 +59,6 @@ TEST_CASE("serialize MsgPack array") {
|
|||||||
array.add(nil);
|
array.add(nil);
|
||||||
REQUIRE(array.size() == 65536);
|
REQUIRE(array.size() == 65536);
|
||||||
|
|
||||||
check(array,
|
check(array, "\xDD\x00\x01\x00\x00"_s + std::string(65536, '\xc0'));
|
||||||
std::string("\xDD\x00\x01\x00\x00", 5) + std::string(65536, '\xc0'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
static void check(const JsonObject object, const char* expected_data,
|
static void check(const JsonObject object, const char* expected_data,
|
||||||
size_t expected_len) {
|
size_t expected_len) {
|
||||||
std::string expected(expected_data, expected_data + expected_len);
|
std::string expected(expected_data, expected_data + expected_len);
|
||||||
@@ -44,7 +46,7 @@ TEST_CASE("serialize MsgPack object") {
|
|||||||
SECTION("map 16") {
|
SECTION("map 16") {
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
char key[16];
|
char key[16];
|
||||||
sprintf(key, "i%X", i);
|
snprintf(key, sizeof(key), "i%X", i);
|
||||||
object[key] = i;
|
object[key] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ TEST_CASE("serialize MsgPack object") {
|
|||||||
//
|
//
|
||||||
// for (int i = 0; i < 65536; ++i) {
|
// for (int i = 0; i < 65536; ++i) {
|
||||||
// char kv[16];
|
// char kv[16];
|
||||||
// sprintf(kv, "%04x", i);
|
// snprintf(kv, sizeof(kv), "%04x", i);
|
||||||
// object[kv] = kv;
|
// object[kv] = kv;
|
||||||
// expected += '\xA4';
|
// expected += '\xA4';
|
||||||
// expected += kv;
|
// expected += kv;
|
||||||
@@ -77,7 +79,7 @@ TEST_CASE("serialize MsgPack object") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("serialized(std::string)") {
|
SECTION("serialized(std::string)") {
|
||||||
object["hello"] = serialized(std::string("\xDB\x00\x01\x00\x00", 5));
|
object["hello"] = serialized("\xDB\x00\x01\x00\x00"_s);
|
||||||
check(object, "\x81\xA5hello\xDB\x00\x01\x00\x00");
|
check(object, "\x81\xA5hello\xDB\x00\x01\x00\x00");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Literals.hpp"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void checkVariant(T value, const char* expected_data,
|
static void checkVariant(T value, const char* expected_data,
|
||||||
size_t expected_len) {
|
size_t expected_len) {
|
||||||
@@ -129,16 +131,15 @@ TEST_CASE("serialize MsgPack value") {
|
|||||||
|
|
||||||
SECTION("str 16") {
|
SECTION("str 16") {
|
||||||
std::string shortest(256, '?');
|
std::string shortest(256, '?');
|
||||||
checkVariant(shortest.c_str(), std::string("\xDA\x01\x00", 3) + shortest);
|
checkVariant(shortest.c_str(), "\xDA\x01\x00"_s + shortest);
|
||||||
|
|
||||||
std::string longest(65535, '?');
|
std::string longest(65535, '?');
|
||||||
checkVariant(longest.c_str(), std::string("\xDA\xFF\xFF", 3) + longest);
|
checkVariant(longest.c_str(), "\xDA\xFF\xFF"_s + longest);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("str 32") {
|
SECTION("str 32") {
|
||||||
std::string shortest(65536, '?');
|
std::string shortest(65536, '?');
|
||||||
checkVariant(shortest.c_str(),
|
checkVariant(shortest.c_str(), "\xDB\x00\x01\x00\x00"_s + shortest);
|
||||||
std::string("\xDB\x00\x01\x00\x00", 5) + shortest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("serialized(const char*)") {
|
SECTION("serialized(const char*)") {
|
||||||
@@ -146,6 +147,56 @@ TEST_CASE("serialize MsgPack value") {
|
|||||||
checkVariant(serialized("\xDB\x00\x01\x00\x00", 5), "\xDB\x00\x01\x00\x00");
|
checkVariant(serialized("\xDB\x00\x01\x00\x00", 5), "\xDB\x00\x01\x00\x00");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("bin 8") {
|
||||||
|
checkVariant(MsgPackBinary("?", 1), "\xC4\x01?");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("bin 16") {
|
||||||
|
auto str = std::string(256, '?');
|
||||||
|
checkVariant(MsgPackBinary(str.data(), str.size()), "\xC5\x01\x00"_s + str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bin 32 is tested in string_length_size_4.cpp
|
||||||
|
|
||||||
|
SECTION("fixext 1") {
|
||||||
|
checkVariant(MsgPackExtension(1, "\x02", 1), "\xD4\x01\x02");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 2") {
|
||||||
|
checkVariant(MsgPackExtension(1, "\x03\x04", 2), "\xD5\x01\x03\x04");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 4") {
|
||||||
|
checkVariant(MsgPackExtension(1, "\x05\x06\x07\x08", 4),
|
||||||
|
"\xD6\x01\x05\x06\x07\x08");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 8") {
|
||||||
|
checkVariant(MsgPackExtension(1, "????????", 8), "\xD7\x01????????");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 16") {
|
||||||
|
checkVariant(MsgPackExtension(1, "????????????????", 16),
|
||||||
|
"\xD8\x01????????????????");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 8") {
|
||||||
|
checkVariant(MsgPackExtension(2, "???", 3), "\xC7\x03\x02???");
|
||||||
|
checkVariant(MsgPackExtension(2, "?????", 5), "\xC7\x05\x02?????");
|
||||||
|
checkVariant(MsgPackExtension(2, "???????", 7), "\xC7\x07\x02???????");
|
||||||
|
checkVariant(MsgPackExtension(2, "?????????", 9), "\xC7\x09\x02?????????");
|
||||||
|
checkVariant(MsgPackExtension(2, "???????????????", 15),
|
||||||
|
"\xC7\x0F\x02???????????????");
|
||||||
|
checkVariant(MsgPackExtension(2, "?????????????????", 17),
|
||||||
|
"\xC7\x11\x02?????????????????");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 16") {
|
||||||
|
auto str = std::string(256, '?');
|
||||||
|
checkVariant(MsgPackExtension(2, str.data(), str.size()),
|
||||||
|
"\xC8\x01\x00\x02"_s + str);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("serialize round double as integer") { // Issue #1718
|
SECTION("serialize round double as integer") { // Issue #1718
|
||||||
checkVariant(-32768.0, "\xD1\x80\x00");
|
checkVariant(-32768.0, "\xD1\x80\x00");
|
||||||
checkVariant(-129.0, "\xD1\xFF\x7F");
|
checkVariant(-129.0, "\xD1\xFF\x7F");
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/StringBuilder.hpp>
|
#include <ArduinoJson/Memory/StringBuilder.hpp>
|
||||||
|
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/Alignment.hpp>
|
#include <ArduinoJson.hpp>
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
|
||||||
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||||
|
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
||||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
version: "7.0.4"
|
version: "7.1.0"
|
||||||
description: >-
|
description: >-
|
||||||
A simple and efficient JSON library for embedded C++.
|
A simple and efficient JSON library for embedded C++.
|
||||||
⭐ 6503 stars on GitHub!
|
⭐ 6624 stars on GitHub!
|
||||||
Supports serialization, deserialization, MessagePack, streams, filtering, and more.
|
Supports serialization, deserialization, MessagePack, streams, filtering, and more.
|
||||||
Fully tested and documented.
|
Fully tested and documented.
|
||||||
url: https://arduinojson.org/
|
url: https://arduinojson.org/
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "ArduinoJson",
|
"name": "ArduinoJson",
|
||||||
"keywords": "json, rest, http, web",
|
"keywords": "json, rest, http, web",
|
||||||
"description": "A simple and efficient JSON library for embedded C++. ⭐ 6503 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.",
|
"description": "A simple and efficient JSON library for embedded C++. ⭐ 6624 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.",
|
||||||
"homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json",
|
"homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||||
},
|
},
|
||||||
"version": "7.0.4",
|
"version": "7.1.0",
|
||||||
"authors": {
|
"authors": {
|
||||||
"name": "Benoit Blanchon",
|
"name": "Benoit Blanchon",
|
||||||
"url": "https://blog.benoitblanchon.fr"
|
"url": "https://blog.benoitblanchon.fr"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
name=ArduinoJson
|
name=ArduinoJson
|
||||||
version=7.0.4
|
version=7.1.0
|
||||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||||
sentence=A simple and efficient JSON library for embedded C++.
|
sentence=A simple and efficient JSON library for embedded C++.
|
||||||
paragraph=⭐ 6503 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.
|
paragraph=⭐ 6624 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.
|
||||||
category=Data Processing
|
category=Data Processing
|
||||||
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
||||||
architectures=*
|
architectures=*
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "ArduinoJson/Array/ElementProxy.hpp"
|
#include "ArduinoJson/Array/ElementProxy.hpp"
|
||||||
#include "ArduinoJson/Array/Utilities.hpp"
|
#include "ArduinoJson/Array/Utilities.hpp"
|
||||||
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
||||||
|
#include "ArduinoJson/Memory/ResourceManagerImpl.hpp"
|
||||||
#include "ArduinoJson/Memory/VariantPoolImpl.hpp"
|
#include "ArduinoJson/Memory/VariantPoolImpl.hpp"
|
||||||
#include "ArduinoJson/Object/MemberProxy.hpp"
|
#include "ArduinoJson/Object/MemberProxy.hpp"
|
||||||
#include "ArduinoJson/Object/ObjectImpl.hpp"
|
#include "ArduinoJson/Object/ObjectImpl.hpp"
|
||||||
@@ -47,7 +48,9 @@
|
|||||||
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
||||||
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
||||||
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
||||||
|
#include "ArduinoJson/MsgPack/MsgPackBinary.hpp"
|
||||||
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
||||||
|
#include "ArduinoJson/MsgPack/MsgPackExtension.hpp"
|
||||||
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
||||||
|
|
||||||
#include "ArduinoJson/compatibility.hpp"
|
#include "ArduinoJson/compatibility.hpp"
|
||||||
|
|||||||
@@ -20,6 +20,17 @@ class ArrayData : public CollectionData {
|
|||||||
return array->addElement(resources);
|
return array->addElement(resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool addValue(T&& value, ResourceManager* resources);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static bool addValue(ArrayData* array, T&& value,
|
||||||
|
ResourceManager* resources) {
|
||||||
|
if (!array)
|
||||||
|
return false;
|
||||||
|
return array->addValue(value, resources);
|
||||||
|
}
|
||||||
|
|
||||||
VariantData* getOrAddElement(size_t index, ResourceManager* resources);
|
VariantData* getOrAddElement(size_t index, ResourceManager* resources);
|
||||||
|
|
||||||
VariantData* getElement(size_t index, const ResourceManager* resources) const;
|
VariantData* getElement(size_t index, const ResourceManager* resources) const;
|
||||||
|
|||||||
@@ -47,4 +47,19 @@ inline void ArrayData::removeElement(size_t index, ResourceManager* resources) {
|
|||||||
remove(at(index, resources), resources);
|
remove(at(index, resources), resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
|
||||||
|
ARDUINOJSON_ASSERT(resources != nullptr);
|
||||||
|
auto slot = resources->allocSlot();
|
||||||
|
if (!slot)
|
||||||
|
return false;
|
||||||
|
JsonVariant variant(slot->data(), resources);
|
||||||
|
if (!variant.set(detail::forward<T>(value))) {
|
||||||
|
resources->freeSlot(slot);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
addSlot(slot, resources);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -44,8 +44,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
// Returns a reference to the new element.
|
// Returns a reference to the new element.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
// https://arduinojson.org/v7/api/jsonarray/add/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename detail::enable_if<!detail::is_same<T, JsonVariant>::value, T>::type
|
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() const {
|
||||||
add() const {
|
|
||||||
return add<JsonVariant>().to<T>();
|
return add<JsonVariant>().to<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +52,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
// Returns a reference to the new element.
|
// Returns a reference to the new element.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
// https://arduinojson.org/v7/api/jsonarray/add/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename detail::enable_if<detail::is_same<T, JsonVariant>::value, T>::type
|
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() const {
|
||||||
add() const {
|
|
||||||
return JsonVariant(detail::ArrayData::addElement(data_, resources_),
|
return JsonVariant(detail::ArrayData::addElement(data_, resources_),
|
||||||
resources_);
|
resources_);
|
||||||
}
|
}
|
||||||
@@ -63,14 +61,14 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
// https://arduinojson.org/v7/api/jsonarray/add/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool add(const T& value) const {
|
bool add(const T& value) const {
|
||||||
return add<JsonVariant>().set(value);
|
return detail::ArrayData::addValue(data_, value, resources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value to the array.
|
// Appends a value to the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
// https://arduinojson.org/v7/api/jsonarray/add/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool add(T* value) const {
|
bool add(T* value) const {
|
||||||
return add<JsonVariant>().set(value);
|
return detail::ArrayData::addValue(data_, value, resources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator to the first element of the array.
|
// Returns an iterator to the first element of the array.
|
||||||
@@ -114,6 +112,15 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
detail::ArrayData::removeElement(data_, index, resources_);
|
detail::ArrayData::removeElement(data_, index, resources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removes the element at the specified index.
|
||||||
|
// https://arduinojson.org/v7/api/jsonarray/remove/
|
||||||
|
template <typename TVariant>
|
||||||
|
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove(
|
||||||
|
TVariant variant) const {
|
||||||
|
if (variant.template is<size_t>())
|
||||||
|
remove(variant.template as<size_t>());
|
||||||
|
}
|
||||||
|
|
||||||
// Removes all the elements of the array.
|
// Removes all the elements of the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/clear/
|
// https://arduinojson.org/v7/api/jsonarray/clear/
|
||||||
void clear() const {
|
void clear() const {
|
||||||
@@ -122,8 +129,23 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
|
|
||||||
// Gets or sets the element at the specified index.
|
// Gets or sets the element at the specified index.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/subscript/
|
// https://arduinojson.org/v7/api/jsonarray/subscript/
|
||||||
detail::ElementProxy<JsonArray> operator[](size_t index) const {
|
template <typename T>
|
||||||
return {*this, index};
|
detail::enable_if_t<detail::is_integral<T>::value,
|
||||||
|
detail::ElementProxy<JsonArray>>
|
||||||
|
operator[](T index) const {
|
||||||
|
return {*this, size_t(index)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets or sets the element at the specified index.
|
||||||
|
// https://arduinojson.org/v7/api/jsonarray/subscript/
|
||||||
|
template <typename TVariant>
|
||||||
|
detail::enable_if_t<detail::IsVariant<TVariant>::value,
|
||||||
|
detail::ElementProxy<JsonArray>>
|
||||||
|
operator[](const TVariant& variant) const {
|
||||||
|
if (variant.template is<size_t>())
|
||||||
|
return operator[](variant.template as<size_t>());
|
||||||
|
else
|
||||||
|
return {*this, size_t(-1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
operator JsonVariantConst() const {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates an unbound reference.
|
// Creates an unbound reference.
|
||||||
JsonArrayConst() : data_(0) {}
|
JsonArrayConst() : data_(0), resources_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
JsonArrayConst(const detail::ArrayData* data,
|
JsonArrayConst(const detail::ArrayData* data,
|
||||||
@@ -45,9 +45,23 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
|||||||
|
|
||||||
// Returns the element at the specified index.
|
// Returns the element at the specified index.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
|
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
|
||||||
JsonVariantConst operator[](size_t index) const {
|
template <typename T>
|
||||||
|
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
|
||||||
|
operator[](T index) const {
|
||||||
return JsonVariantConst(
|
return JsonVariantConst(
|
||||||
detail::ArrayData::getElement(data_, index, resources_), resources_);
|
detail::ArrayData::getElement(data_, size_t(index), resources_),
|
||||||
|
resources_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the element at the specified index.
|
||||||
|
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
|
||||||
|
template <typename TVariant>
|
||||||
|
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
|
||||||
|
operator[](const TVariant& variant) const {
|
||||||
|
if (variant.template is<size_t>())
|
||||||
|
return operator[](variant.template as<size_t>());
|
||||||
|
else
|
||||||
|
return JsonVariantConst();
|
||||||
}
|
}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
operator JsonVariantConst() const {
|
||||||
|
|||||||
@@ -12,16 +12,16 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
// Copies a value to a JsonVariant.
|
// Copies a value to a JsonVariant.
|
||||||
// This is a degenerated form of copyArray() to stop the recursion.
|
// This is a degenerated form of copyArray() to stop the recursion.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline typename detail::enable_if<!detail::is_array<T>::value, bool>::type
|
inline detail::enable_if_t<!detail::is_array<T>::value, bool> copyArray(
|
||||||
copyArray(const T& src, JsonVariant dst) {
|
const T& src, JsonVariant dst) {
|
||||||
return dst.set(src);
|
return dst.set(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies values from an array to a JsonArray or a JsonVariant.
|
// Copies values from an array to a JsonArray or a JsonVariant.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v7/api/misc/copyarray/
|
||||||
template <typename T, size_t N, typename TDestination>
|
template <typename T, size_t N, typename TDestination>
|
||||||
inline typename detail::enable_if<
|
inline detail::enable_if_t<
|
||||||
!detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
|
!detail::is_base_of<JsonDocument, TDestination>::value, bool>
|
||||||
copyArray(T (&src)[N], const TDestination& dst) {
|
copyArray(T (&src)[N], const TDestination& dst) {
|
||||||
return copyArray(src, N, dst);
|
return copyArray(src, N, dst);
|
||||||
}
|
}
|
||||||
@@ -29,8 +29,8 @@ copyArray(T (&src)[N], const TDestination& dst) {
|
|||||||
// Copies values from an array to a JsonArray or a JsonVariant.
|
// Copies values from an array to a JsonArray or a JsonVariant.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v7/api/misc/copyarray/
|
||||||
template <typename T, typename TDestination>
|
template <typename T, typename TDestination>
|
||||||
inline typename detail::enable_if<
|
inline detail::enable_if_t<
|
||||||
!detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
|
!detail::is_base_of<JsonDocument, TDestination>::value, bool>
|
||||||
copyArray(const T* src, size_t len, const TDestination& dst) {
|
copyArray(const T* src, size_t len, const TDestination& dst) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
@@ -63,8 +63,8 @@ inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
|
|||||||
// Copies a value from a JsonVariant.
|
// Copies a value from a JsonVariant.
|
||||||
// This is a degenerated form of copyArray() to stop the recursion.
|
// This is a degenerated form of copyArray() to stop the recursion.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline typename detail::enable_if<!detail::is_array<T>::value, size_t>::type
|
inline detail::enable_if_t<!detail::is_array<T>::value, size_t> copyArray(
|
||||||
copyArray(JsonVariantConst src, T& dst) {
|
JsonVariantConst src, T& dst) {
|
||||||
dst = src.as<T>();
|
dst = src.as<T>();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -103,10 +103,9 @@ inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) {
|
|||||||
// Copies values from a JsonDocument to an array.
|
// Copies values from a JsonDocument to an array.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v7/api/misc/copyarray/
|
||||||
template <typename TSource, typename T>
|
template <typename TSource, typename T>
|
||||||
inline typename detail::enable_if<
|
inline detail::enable_if_t<detail::is_array<T>::value &&
|
||||||
detail::is_array<T>::value &&
|
|
||||||
detail::is_base_of<JsonDocument, TSource>::value,
|
detail::is_base_of<JsonDocument, TSource>::value,
|
||||||
size_t>::type
|
size_t>
|
||||||
copyArray(const TSource& src, T& dst) {
|
copyArray(const TSource& src, T& dst) {
|
||||||
return copyArray(src.template as<JsonArrayConst>(), dst);
|
return copyArray(src.template as<JsonArrayConst>(), dst);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,12 +111,13 @@ class CollectionData {
|
|||||||
return head_;
|
return head_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addSlot(SlotWithId slot, ResourceManager* resources);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
iterator addSlot(ResourceManager*);
|
iterator addSlot(ResourceManager*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SlotWithId getPreviousSlot(VariantSlot*, const ResourceManager*) const;
|
SlotWithId getPreviousSlot(VariantSlot*, const ResourceManager*) const;
|
||||||
void releaseSlot(SlotWithId, ResourceManager*);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const VariantData* collectionToVariant(
|
inline const VariantData* collectionToVariant(
|
||||||
|
|||||||
@@ -63,13 +63,25 @@ inline CollectionData::iterator CollectionData::addSlot(
|
|||||||
return iterator(slot, slot.id());
|
return iterator(slot, slot.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void CollectionData::addSlot(SlotWithId slot,
|
||||||
|
ResourceManager* resources) {
|
||||||
|
if (tail_ != NULL_SLOT) {
|
||||||
|
auto tail = resources->getSlot(tail_);
|
||||||
|
tail->setNext(slot.id());
|
||||||
|
tail_ = slot.id();
|
||||||
|
} else {
|
||||||
|
head_ = slot.id();
|
||||||
|
tail_ = slot.id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void CollectionData::clear(ResourceManager* resources) {
|
inline void CollectionData::clear(ResourceManager* resources) {
|
||||||
auto next = head_;
|
auto next = head_;
|
||||||
while (next != NULL_SLOT) {
|
while (next != NULL_SLOT) {
|
||||||
auto currId = next;
|
auto currId = next;
|
||||||
auto slot = resources->getSlot(next);
|
auto slot = resources->getSlot(next);
|
||||||
next = slot->next();
|
next = slot->next();
|
||||||
releaseSlot(SlotWithId(slot, currId), resources);
|
resources->freeSlot(SlotWithId(slot, currId));
|
||||||
}
|
}
|
||||||
|
|
||||||
head_ = NULL_SLOT;
|
head_ = NULL_SLOT;
|
||||||
@@ -102,7 +114,7 @@ inline void CollectionData::remove(iterator it, ResourceManager* resources) {
|
|||||||
head_ = next;
|
head_ = next;
|
||||||
if (next == NULL_SLOT)
|
if (next == NULL_SLOT)
|
||||||
tail_ = prev.id();
|
tail_ = prev.id();
|
||||||
releaseSlot({it.slot_, it.currentId_}, resources);
|
resources->freeSlot({it.slot_, it.currentId_});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t CollectionData::nesting(const ResourceManager* resources) const {
|
inline size_t CollectionData::nesting(const ResourceManager* resources) const {
|
||||||
@@ -122,12 +134,4 @@ inline size_t CollectionData::size(const ResourceManager* resources) const {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionData::releaseSlot(SlotWithId slot,
|
|
||||||
ResourceManager* resources) {
|
|
||||||
if (slot->ownsKey())
|
|
||||||
resources->dereferenceString(slot->key());
|
|
||||||
slot->data()->setNull(resources);
|
|
||||||
resources->freeSlot(slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -93,11 +93,14 @@
|
|||||||
// https://arduinojson.org/v7/config/slot_id_size/
|
// https://arduinojson.org/v7/config/slot_id_size/
|
||||||
#ifndef ARDUINOJSON_SLOT_ID_SIZE
|
#ifndef ARDUINOJSON_SLOT_ID_SIZE
|
||||||
# if ARDUINOJSON_SIZEOF_POINTER <= 2
|
# if ARDUINOJSON_SIZEOF_POINTER <= 2
|
||||||
# define ARDUINOJSON_SLOT_ID_SIZE 1 // up to 255 slots
|
// 8-bit and 16-bit archs => up to 255 slots
|
||||||
|
# define ARDUINOJSON_SLOT_ID_SIZE 1
|
||||||
# elif ARDUINOJSON_SIZEOF_POINTER == 4
|
# elif ARDUINOJSON_SIZEOF_POINTER == 4
|
||||||
# define ARDUINOJSON_SLOT_ID_SIZE 2 // up to 65535 slots
|
// 32-bit arch => up to 65535 slots
|
||||||
|
# define ARDUINOJSON_SLOT_ID_SIZE 2
|
||||||
# else
|
# else
|
||||||
# define ARDUINOJSON_SLOT_ID_SIZE 4 // up to 4294967295 slots
|
// 64-bit arch => up to 4294967295 slots
|
||||||
|
# define ARDUINOJSON_SLOT_ID_SIZE 4
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -62,9 +62,8 @@ ARDUINOJSON_END_PRIVATE_NAMESPACE
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <typename TInput>
|
template <typename TInput>
|
||||||
Reader<typename remove_reference<TInput>::type> makeReader(TInput&& input) {
|
Reader<remove_reference_t<TInput>> makeReader(TInput&& input) {
|
||||||
return Reader<typename remove_reference<TInput>::type>{
|
return Reader<remove_reference_t<TInput>>{detail::forward<TInput>(input)};
|
||||||
detail::forward<TInput>(input)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <typename TSource>
|
template <typename TSource>
|
||||||
struct Reader<TSource,
|
struct Reader<TSource, enable_if_t<is_base_of<Stream, TSource>::value>> {
|
||||||
typename enable_if<is_base_of<Stream, TSource>::value>::type> {
|
|
||||||
public:
|
public:
|
||||||
explicit Reader(Stream& stream) : stream_(&stream) {}
|
explicit Reader(Stream& stream) : stream_(&stream) {}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <typename TSource>
|
template <typename TSource>
|
||||||
struct Reader<TSource,
|
struct Reader<TSource, enable_if_t<is_base_of<::String, TSource>::value>>
|
||||||
typename enable_if<is_base_of<::String, TSource>::value>::type>
|
|
||||||
: BoundedReader<const char*> {
|
: BoundedReader<const char*> {
|
||||||
explicit Reader(const ::String& s)
|
explicit Reader(const ::String& s)
|
||||||
: BoundedReader<const char*>(s.c_str(), s.length()) {}
|
: BoundedReader<const char*>(s.c_str(), s.length()) {}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <typename TIterator>
|
template <typename TIterator>
|
||||||
@@ -29,13 +31,8 @@ class IteratorReader {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct void_ {
|
|
||||||
typedef void type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TSource>
|
template <typename TSource>
|
||||||
struct Reader<TSource, typename void_<typename TSource::const_iterator>::type>
|
struct Reader<TSource, void_t<typename TSource::const_iterator>>
|
||||||
: IteratorReader<typename TSource::const_iterator> {
|
: IteratorReader<typename TSource::const_iterator> {
|
||||||
explicit Reader(const TSource& source)
|
explicit Reader(const TSource& source)
|
||||||
: IteratorReader<typename TSource::const_iterator>(source.begin(),
|
: IteratorReader<typename TSource::const_iterator>(source.begin(),
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ template <typename T>
|
|||||||
struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
|
struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
|
||||||
|
|
||||||
template <typename TSource>
|
template <typename TSource>
|
||||||
struct Reader<TSource*,
|
struct Reader<TSource*, enable_if_t<IsCharOrVoid<TSource>::value>> {
|
||||||
typename enable_if<IsCharOrVoid<TSource>::value>::type> {
|
|
||||||
const char* ptr_;
|
const char* ptr_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -39,8 +38,7 @@ struct Reader<TSource*,
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename TSource>
|
template <typename TSource>
|
||||||
struct BoundedReader<TSource*,
|
struct BoundedReader<TSource*, enable_if_t<IsCharOrVoid<TSource>::value>>
|
||||||
typename enable_if<IsCharOrVoid<TSource>::value>::type>
|
|
||||||
: public IteratorReader<const char*> {
|
: public IteratorReader<const char*> {
|
||||||
public:
|
public:
|
||||||
explicit BoundedReader(const void* ptr, size_t len)
|
explicit BoundedReader(const void* ptr, size_t len)
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <typename TSource>
|
template <typename TSource>
|
||||||
struct Reader<TSource, typename enable_if<
|
struct Reader<TSource, enable_if_t<is_base_of<std::istream, TSource>::value>> {
|
||||||
is_base_of<std::istream, TSource>::value>::type> {
|
|
||||||
public:
|
public:
|
||||||
explicit Reader(std::istream& stream) : stream_(&stream) {}
|
explicit Reader(std::istream& stream) : stream_(&stream) {}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <typename TVariant>
|
template <typename TVariant>
|
||||||
struct Reader<TVariant, typename enable_if<IsVariant<TVariant>::value>::type>
|
struct Reader<TVariant, enable_if_t<IsVariant<TVariant>::value>>
|
||||||
: Reader<char*, void> {
|
: Reader<char*, void> {
|
||||||
explicit Reader(const TVariant& x)
|
explicit Reader(const TVariant& x)
|
||||||
: Reader<char*, void>(x.template as<const char*>()) {}
|
: Reader<char*, void>(x.template as<const char*>()) {}
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ struct is_deserialize_destination : false_type {};
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct is_deserialize_destination<
|
struct is_deserialize_destination<
|
||||||
T, typename enable_if<is_same<decltype(VariantAttorney::getResourceManager(
|
T, enable_if_t<is_same<decltype(VariantAttorney::getResourceManager(
|
||||||
detail::declval<T&>())),
|
detail::declval<T&>())),
|
||||||
ResourceManager*>::value>::type> : true_type {
|
ResourceManager*>::value>> : true_type {};
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TDestination>
|
template <typename TDestination>
|
||||||
inline void shrinkJsonDocument(TDestination&) {
|
inline void shrinkJsonDocument(TDestination&) {
|
||||||
@@ -62,8 +61,8 @@ DeserializationError doDeserialize(TDestination&& dst, TReader reader,
|
|||||||
|
|
||||||
template <template <typename> class TDeserializer, typename TDestination,
|
template <template <typename> class TDeserializer, typename TDestination,
|
||||||
typename TStream, typename... Args,
|
typename TStream, typename... Args,
|
||||||
typename = typename enable_if< // issue #1897
|
typename = enable_if_t< // issue #1897
|
||||||
!is_integral<typename first_or_void<Args...>::type>::value>::type>
|
!is_integral<typename first_or_void<Args...>::type>::value>>
|
||||||
DeserializationError deserialize(TDestination&& dst, TStream&& input,
|
DeserializationError deserialize(TDestination&& dst, TStream&& input,
|
||||||
Args... args) {
|
Args... args) {
|
||||||
return doDeserialize<TDeserializer>(
|
return doDeserialize<TDeserializer>(
|
||||||
@@ -73,7 +72,7 @@ DeserializationError deserialize(TDestination&& dst, TStream&& input,
|
|||||||
|
|
||||||
template <template <typename> class TDeserializer, typename TDestination,
|
template <template <typename> class TDeserializer, typename TDestination,
|
||||||
typename TChar, typename Size, typename... Args,
|
typename TChar, typename Size, typename... Args,
|
||||||
typename = typename enable_if<is_integral<Size>::value>::type>
|
typename = enable_if_t<is_integral<Size>::value>>
|
||||||
DeserializationError deserialize(TDestination&& dst, TChar* input,
|
DeserializationError deserialize(TDestination&& dst, TChar* input,
|
||||||
Size inputSize, Args... args) {
|
Size inputSize, Args... args) {
|
||||||
return doDeserialize<TDeserializer>(dst, makeReader(input, size_t(inputSize)),
|
return doDeserialize<TDeserializer>(dst, makeReader(input, size_t(inputSize)),
|
||||||
|
|||||||
@@ -37,15 +37,13 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
|
|
||||||
// Construct from variant, array, or object
|
// Construct from variant, array, or object
|
||||||
template <typename T>
|
template <typename T>
|
||||||
JsonDocument(const T& src,
|
JsonDocument(
|
||||||
Allocator* alloc = detail::DefaultAllocator::instance(),
|
const T& src, Allocator* alloc = detail::DefaultAllocator::instance(),
|
||||||
typename detail::enable_if<
|
detail::enable_if_t<detail::IsVariant<T>::value ||
|
||||||
detail::is_same<T, JsonVariant>::value ||
|
|
||||||
detail::is_same<T, JsonVariantConst>::value ||
|
|
||||||
detail::is_same<T, JsonArray>::value ||
|
detail::is_same<T, JsonArray>::value ||
|
||||||
detail::is_same<T, JsonArrayConst>::value ||
|
detail::is_same<T, JsonArrayConst>::value ||
|
||||||
detail::is_same<T, JsonObject>::value ||
|
detail::is_same<T, JsonObject>::value ||
|
||||||
detail::is_same<T, JsonObjectConst>::value>::type* = 0)
|
detail::is_same<T, JsonObjectConst>::value>* = 0)
|
||||||
: JsonDocument(alloc) {
|
: JsonDocument(alloc) {
|
||||||
set(src);
|
set(src);
|
||||||
}
|
}
|
||||||
@@ -139,9 +137,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Replaces the root with the specified value.
|
// Replaces the root with the specified value.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/set/
|
// https://arduinojson.org/v7/api/jsondocument/set/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename detail::enable_if<!detail::is_base_of<JsonDocument, T>::value,
|
detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, bool> set(
|
||||||
bool>::type
|
const T& src) {
|
||||||
set(const T& src) {
|
|
||||||
return to<JsonVariant>().set(src);
|
return to<JsonVariant>().set(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,15 +160,24 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Returns true if the root object contains the specified key.
|
// Returns true if the root object contains the specified key.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/containskey/
|
// https://arduinojson.org/v7/api/jsondocument/containskey/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
bool containsKey(const TString& key) const {
|
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
|
||||||
|
const TString& key) const {
|
||||||
return data_.getMember(detail::adaptString(key), &resources_) != 0;
|
return data_.getMember(detail::adaptString(key), &resources_) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if the root object contains the specified key.
|
||||||
|
// https://arduinojson.org/v7/api/jsondocument/containskey/
|
||||||
|
template <typename TVariant>
|
||||||
|
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
|
||||||
|
const TVariant& key) const {
|
||||||
|
return containsKey(key.template as<const char*>());
|
||||||
|
}
|
||||||
|
|
||||||
// Gets or sets a root object's member.
|
// Gets or sets a root object's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename detail::enable_if<detail::IsString<TString>::value,
|
detail::enable_if_t<detail::IsString<TString>::value,
|
||||||
detail::MemberProxy<JsonDocument&, TString>>::type
|
detail::MemberProxy<JsonDocument&, TString>>
|
||||||
operator[](const TString& key) {
|
operator[](const TString& key) {
|
||||||
return {*this, key};
|
return {*this, key};
|
||||||
}
|
}
|
||||||
@@ -179,8 +185,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Gets or sets a root object's member.
|
// Gets or sets a root object's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
typename detail::enable_if<detail::IsString<TChar*>::value,
|
detail::enable_if_t<detail::IsString<TChar*>::value,
|
||||||
detail::MemberProxy<JsonDocument&, TChar*>>::type
|
detail::MemberProxy<JsonDocument&, TChar*>>
|
||||||
operator[](TChar* key) {
|
operator[](TChar* key) {
|
||||||
return {*this, key};
|
return {*this, key};
|
||||||
}
|
}
|
||||||
@@ -188,8 +194,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Gets a root object's member.
|
// Gets a root object's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename detail::enable_if<detail::IsString<TString>::value,
|
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
|
||||||
JsonVariantConst>::type
|
|
||||||
operator[](const TString& key) const {
|
operator[](const TString& key) const {
|
||||||
return JsonVariantConst(
|
return JsonVariantConst(
|
||||||
data_.getMember(detail::adaptString(key), &resources_), &resources_);
|
data_.getMember(detail::adaptString(key), &resources_), &resources_);
|
||||||
@@ -198,8 +203,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Gets a root object's member.
|
// Gets a root object's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
typename detail::enable_if<detail::IsString<TChar*>::value,
|
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
|
||||||
JsonVariantConst>::type
|
|
||||||
operator[](TChar* key) const {
|
operator[](TChar* key) const {
|
||||||
return JsonVariantConst(
|
return JsonVariantConst(
|
||||||
data_.getMember(detail::adaptString(key), &resources_), &resources_);
|
data_.getMember(detail::adaptString(key), &resources_), &resources_);
|
||||||
@@ -207,8 +211,11 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
|
|
||||||
// Gets or sets a root array's element.
|
// Gets or sets a root array's element.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||||
detail::ElementProxy<JsonDocument&> operator[](size_t index) {
|
template <typename T>
|
||||||
return {*this, index};
|
detail::enable_if_t<detail::is_integral<T>::value,
|
||||||
|
detail::ElementProxy<JsonDocument&>>
|
||||||
|
operator[](T index) {
|
||||||
|
return {*this, size_t(index)};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a root array's member.
|
// Gets a root array's member.
|
||||||
@@ -217,12 +224,23 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
return JsonVariantConst(data_.getElement(index, &resources_), &resources_);
|
return JsonVariantConst(data_.getElement(index, &resources_), &resources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets or sets a root object's member.
|
||||||
|
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||||
|
template <typename TVariant>
|
||||||
|
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
|
||||||
|
operator[](const TVariant& key) const {
|
||||||
|
if (key.template is<const char*>())
|
||||||
|
return operator[](key.template as<const char*>());
|
||||||
|
if (key.template is<size_t>())
|
||||||
|
return operator[](key.template as<size_t>());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// Appends a new (empty) element to the root array.
|
// Appends a new (empty) element to the root array.
|
||||||
// Returns a reference to the new element.
|
// Returns a reference to the new element.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
// https://arduinojson.org/v7/api/jsondocument/add/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename detail::enable_if<!detail::is_same<T, JsonVariant>::value, T>::type
|
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() {
|
||||||
add() {
|
|
||||||
return add<JsonVariant>().to<T>();
|
return add<JsonVariant>().to<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,8 +248,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Returns a reference to the new element.
|
// Returns a reference to the new element.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
// https://arduinojson.org/v7/api/jsondocument/add/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename detail::enable_if<detail::is_same<T, JsonVariant>::value, T>::type
|
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() {
|
||||||
add() {
|
|
||||||
return JsonVariant(data_.addElement(&resources_), &resources_);
|
return JsonVariant(data_.addElement(&resources_), &resources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,27 +256,28 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
// https://arduinojson.org/v7/api/jsondocument/add/
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
bool add(const TValue& value) {
|
bool add(const TValue& value) {
|
||||||
return add<JsonVariant>().set(value);
|
return data_.addValue(value, &resources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value to the root array.
|
// Appends a value to the root array.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
// https://arduinojson.org/v7/api/jsondocument/add/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
bool add(TChar* value) {
|
bool add(TChar* value) {
|
||||||
return add<JsonVariant>().set(value);
|
return data_.addValue(value, &resources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes an element of the root array.
|
// Removes an element of the root array.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
// https://arduinojson.org/v7/api/jsondocument/remove/
|
||||||
void remove(size_t index) {
|
template <typename T>
|
||||||
detail::VariantData::removeElement(getData(), index, getResourceManager());
|
detail::enable_if_t<detail::is_integral<T>::value> remove(T index) {
|
||||||
|
detail::VariantData::removeElement(getData(), size_t(index),
|
||||||
|
getResourceManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a member of the root object.
|
// Removes a member of the root object.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
// https://arduinojson.org/v7/api/jsondocument/remove/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
typename detail::enable_if<detail::IsString<TChar*>::value>::type remove(
|
detail::enable_if_t<detail::IsString<TChar*>::value> remove(TChar* key) {
|
||||||
TChar* key) {
|
|
||||||
detail::VariantData::removeMember(getData(), detail::adaptString(key),
|
detail::VariantData::removeMember(getData(), detail::adaptString(key),
|
||||||
getResourceManager());
|
getResourceManager());
|
||||||
}
|
}
|
||||||
@@ -267,13 +285,23 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Removes a member of the root object.
|
// Removes a member of the root object.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
// https://arduinojson.org/v7/api/jsondocument/remove/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
|
detail::enable_if_t<detail::IsString<TString>::value> remove(
|
||||||
typename detail::enable_if<detail::IsString<TString>::value>::type remove(
|
|
||||||
const TString& key) {
|
const TString& key) {
|
||||||
detail::VariantData::removeMember(getData(), detail::adaptString(key),
|
detail::VariantData::removeMember(getData(), detail::adaptString(key),
|
||||||
getResourceManager());
|
getResourceManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removes a member of the root object or an element of the root array.
|
||||||
|
// https://arduinojson.org/v7/api/jsondocument/remove/
|
||||||
|
template <typename TVariant>
|
||||||
|
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove(
|
||||||
|
const TVariant& key) {
|
||||||
|
if (key.template is<const char*>())
|
||||||
|
remove(key.template as<const char*>());
|
||||||
|
if (key.template is<size_t>())
|
||||||
|
remove(key.template as<size_t>());
|
||||||
|
}
|
||||||
|
|
||||||
operator JsonVariant() {
|
operator JsonVariant() {
|
||||||
return getVariant();
|
return getVariant();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -671,9 +671,8 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||||
// https://arduinojson.org/v7/api/json/deserializejson/
|
// https://arduinojson.org/v7/api/json/deserializejson/
|
||||||
template <typename TDestination, typename... Args>
|
template <typename TDestination, typename... Args>
|
||||||
typename detail::enable_if<
|
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
|
||||||
detail::is_deserialize_destination<TDestination>::value,
|
DeserializationError>
|
||||||
DeserializationError>::type
|
|
||||||
deserializeJson(TDestination&& dst, Args&&... args) {
|
deserializeJson(TDestination&& dst, Args&&... args) {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
|
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
|
||||||
@@ -683,9 +682,8 @@ deserializeJson(TDestination&& dst, Args&&... args) {
|
|||||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||||
// https://arduinojson.org/v7/api/json/deserializejson/
|
// https://arduinojson.org/v7/api/json/deserializejson/
|
||||||
template <typename TDestination, typename TChar, typename... Args>
|
template <typename TDestination, typename TChar, typename... Args>
|
||||||
typename detail::enable_if<
|
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
|
||||||
detail::is_deserialize_destination<TDestination>::value,
|
DeserializationError>
|
||||||
DeserializationError>::type
|
|
||||||
deserializeJson(TDestination&& dst, TChar* input, Args&&... args) {
|
deserializeJson(TDestination&& dst, TChar* input, Args&&... args) {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
|
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user