forked from bblanchon/ArduinoJson
Compare commits
4 Commits
replace-ex
...
7.x
Author | SHA1 | Date | |
---|---|---|---|
c07744dc0d | |||
733bc4ee82 | |||
9aa77994b4 | |||
f051f8328d |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -179,19 +179,19 @@ jobs:
|
|||||||
|
|
||||||
conf_test_windows:
|
conf_test_windows:
|
||||||
name: Test configuration on Windows
|
name: Test configuration on Windows
|
||||||
runs-on: windows-2019
|
runs-on: windows-2022
|
||||||
needs: [gcc, clang]
|
needs: [gcc, clang]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: 32-bit
|
- name: 32-bit
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
|
||||||
cl /Isrc extras/conf_test/x86.cpp
|
cl /Isrc extras/conf_test/x86.cpp
|
||||||
shell: cmd
|
shell: cmd
|
||||||
- name: 64-bit
|
- name: 64-bit
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||||
cl /Isrc extras/conf_test/x64.cpp
|
cl /Isrc extras/conf_test/x64.cpp
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
|
38
CHANGELOG.md
38
CHANGELOG.md
@ -1,42 +1,10 @@
|
|||||||
ArduinoJson: change log
|
ArduinoJson: change log
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
HEAD
|
v7.4.2 (2025-06-20)
|
||||||
----
|
------
|
||||||
|
|
||||||
* Optimize storage of static strings
|
* Fix truncated strings on Arduino Due (issue #2181)
|
||||||
|
|
||||||
> ### BREAKING CHANGES
|
|
||||||
>
|
|
||||||
> Static string cannot contain NUL characters anymore (they could since 7.3.0).
|
|
||||||
> This is an extremely rare case, so you probably won't be affected.
|
|
||||||
>
|
|
||||||
> For example, the following code produces different output in 7.3 and 7.4:
|
|
||||||
>
|
|
||||||
> ```cpp
|
|
||||||
> JsonDocument doc;
|
|
||||||
> doc["a\0b"] = "c\0d";
|
|
||||||
> serializeJson(doc, Serial);
|
|
||||||
> // With Arduino 7.3 -> {"a\u0000b":"c\u0000d"}
|
|
||||||
> // With Arduino 7.4 -> {"a":"c"}
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> `JsonString` contructor now only accepts two arguments, not three.
|
|
||||||
> If your code uses `JsonString` to store a string as a pointer, you must remove the size argument.
|
|
||||||
>
|
|
||||||
> For example, if you have something like this:
|
|
||||||
>
|
|
||||||
> ```cpp
|
|
||||||
> doc["key"] = JsonString(str.c_str(), str.size(), true);
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> You must replace with either:
|
|
||||||
>
|
|
||||||
> ```cpp
|
|
||||||
> doc["key"] = JsonString(str.c_str(), true); // store as pointer, cannot contain NUL characters
|
|
||||||
> doc["key"] = JsonString(str.c_str(), str.size()); // store by copy, NUL characters allowed
|
|
||||||
> doc["key"] = str; // same as previous line for supported string classes (`String`, `std::string`, etc.)
|
|
||||||
> ```
|
|
||||||
|
|
||||||
v7.4.1 (2025-04-11)
|
v7.4.1 (2025-04-11)
|
||||||
------
|
------
|
||||||
|
@ -10,7 +10,7 @@ if(ESP_PLATFORM)
|
|||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(ArduinoJson VERSION 7.4.1)
|
project(ArduinoJson VERSION 7.4.2)
|
||||||
|
|
||||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
@ -139,11 +139,6 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/v7/doc/serializati
|
|||||||
|
|
||||||
ArduinoJson is thankful to its sponsors. Please give them a visit; they deserve it!
|
ArduinoJson is thankful to its sponsors. Please give them a visit; they deserve it!
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="https://www.programmingelectronics.com/" rel="sponsored">
|
|
||||||
<img src="https://arduinojson.org/images/2021/10/programmingeleactronicsacademy.png" alt="Programming Electronics Academy" width="200">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
<p>
|
||||||
<a href="https://github.com/1technophile" rel="sponsored">
|
<a href="https://github.com/1technophile" rel="sponsored">
|
||||||
<img alt="1technophile" src="https://avatars.githubusercontent.com/u/12672732?s=40&v=4">
|
<img alt="1technophile" src="https://avatars.githubusercontent.com/u/12672732?s=40&v=4">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: 7.4.1.{build}
|
version: 7.4.2.{build}
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||||
|
@ -12,7 +12,7 @@ static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN");
|
|||||||
|
|
||||||
static_assert(ARDUINOJSON_USE_DOUBLE == 0, "ARDUINOJSON_USE_DOUBLE");
|
static_assert(ARDUINOJSON_USE_DOUBLE == 0, "ARDUINOJSON_USE_DOUBLE");
|
||||||
|
|
||||||
static_assert(sizeof(ArduinoJson::detail::VariantData) == 6, "slot size");
|
static_assert(ArduinoJson::detail::ResourceManager::slotSize == 6, "slot size");
|
||||||
|
|
||||||
void setup() {}
|
void setup() {}
|
||||||
void loop() {}
|
void loop() {}
|
||||||
|
@ -10,7 +10,7 @@ static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN");
|
|||||||
|
|
||||||
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
|
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
|
||||||
|
|
||||||
static_assert(sizeof(VariantData) == 8, "slot size");
|
static_assert(ArduinoJson::detail::ResourceManager::slotSize == 8, "slot size");
|
||||||
|
|
||||||
void setup() {}
|
void setup() {}
|
||||||
void loop() {}
|
void loop() {}
|
||||||
|
@ -10,6 +10,7 @@ static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN");
|
|||||||
|
|
||||||
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
|
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
|
||||||
|
|
||||||
static_assert(sizeof(ArduinoJson::detail::VariantData) == 16, "slot size");
|
static_assert(ArduinoJson::detail::ResourceManager::slotSize == 16,
|
||||||
|
"slot size");
|
||||||
|
|
||||||
int main() {}
|
int main() {}
|
||||||
|
@ -10,6 +10,6 @@ static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN");
|
|||||||
|
|
||||||
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
|
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
|
||||||
|
|
||||||
static_assert(sizeof(ArduinoJson::detail::VariantData) == 8, "slot size");
|
static_assert(ArduinoJson::detail::ResourceManager::slotSize == 8, "slot size");
|
||||||
|
|
||||||
int main() {}
|
int main() {}
|
||||||
|
@ -54,7 +54,7 @@ TEST_CASE("BasicJsonDocument") {
|
|||||||
doc["hello"] = "world";
|
doc["hello"] = "world";
|
||||||
auto copy = doc;
|
auto copy = doc;
|
||||||
REQUIRE(copy.as<std::string>() == "{\"hello\":\"world\"}");
|
REQUIRE(copy.as<std::string>() == "{\"hello\":\"world\"}");
|
||||||
REQUIRE(allocatorLog == "AAAA");
|
REQUIRE(allocatorLog == "AA");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("capacity") {
|
SECTION("capacity") {
|
||||||
|
@ -269,16 +269,10 @@ inline size_t sizeofPoolList(size_t n = ARDUINOJSON_INITIAL_POOL_COUNT) {
|
|||||||
return sizeof(MemoryPool<VariantData>) * n;
|
return sizeof(MemoryPool<VariantData>) * n;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T = ArduinoJson::detail::VariantData>
|
|
||||||
inline size_t sizeofPool(
|
inline size_t sizeofPool(
|
||||||
ArduinoJson::detail::SlotCount n = ARDUINOJSON_POOL_CAPACITY) {
|
ArduinoJson::detail::SlotCount n = ARDUINOJSON_POOL_CAPACITY) {
|
||||||
return ArduinoJson::detail::MemoryPool<T>::slotsToBytes(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t sizeofStaticStringPool(
|
|
||||||
ArduinoJson::detail::SlotCount n = ARDUINOJSON_POOL_CAPACITY) {
|
|
||||||
using namespace ArduinoJson::detail;
|
using namespace ArduinoJson::detail;
|
||||||
return MemoryPool<const char*>::slotsToBytes(n);
|
return MemoryPool<VariantData>::slotsToBytes(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t sizeofStringBuffer(size_t iteration = 1) {
|
inline size_t sizeofStringBuffer(size_t iteration = 1) {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
#include "Literals.hpp"
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using namespace ArduinoJson::detail;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
|
|
||||||
TEST_CASE("JsonArray::add(T)") {
|
TEST_CASE("JsonArray::add(T)") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
@ -33,8 +33,7 @@ TEST_CASE("JsonArray::add(T)") {
|
|||||||
REQUIRE(array[0].is<double>());
|
REQUIRE(array[0].is<double>());
|
||||||
REQUIRE_FALSE(array[0].is<bool>());
|
REQUIRE_FALSE(array[0].is<bool>());
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool<VariantData>()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofPool<EightByteValue>()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +56,6 @@ TEST_CASE("JsonArray::add(T)") {
|
|||||||
REQUIRE(array[0].is<int>() == false);
|
REQUIRE(array[0].is<int>() == false);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using namespace ArduinoJson::detail;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
|
|
||||||
TEST_CASE("deserialize JSON array") {
|
TEST_CASE("deserialize JSON array") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
@ -92,12 +92,8 @@ TEST_CASE("deserialize JSON array") {
|
|||||||
REQUIRE(arr[0].as<double>() == Approx(4.2123456));
|
REQUIRE(arr[0].as<double>() == Approx(4.2123456));
|
||||||
REQUIRE(arr[1] == -7E89);
|
REQUIRE(arr[1] == -7E89);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool<VariantData>()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofPool<EightByteValue>()),
|
Reallocate(sizeofPool(), sizeofPool(4)),
|
||||||
Reallocate(sizeofPool<VariantData>(),
|
|
||||||
sizeofPool<VariantData>(2)),
|
|
||||||
Reallocate(sizeofPool<EightByteValue>(),
|
|
||||||
sizeofPool<EightByteValue>(2)),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +104,6 @@ TEST_CASE("deserializeJson(MemberProxy)") {
|
|||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\",\"value\":[42]}");
|
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\",\"value\":[42]}");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ TEST_CASE("deserializeJson() returns NoMemory if string length overflows") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("deserializeJson() returns NoMemory if 8-bit slot allocation fails") {
|
TEST_CASE("deserializeJson() returns NoMemory if extension allocation fails") {
|
||||||
JsonDocument doc(FailingAllocator::instance());
|
JsonDocument doc(FailingAllocator::instance());
|
||||||
|
|
||||||
SECTION("uint32_t should pass") {
|
SECTION("uint32_t should pass") {
|
||||||
|
@ -825,9 +825,7 @@ TEST_CASE("shrink filter") {
|
|||||||
|
|
||||||
deserializeJson(doc, "{}", DeserializationOption::Filter(filter));
|
deserializeJson(doc, "{}", DeserializationOption::Filter(filter));
|
||||||
|
|
||||||
REQUIRE(spy.log() ==
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
AllocatorLog{
|
Reallocate(sizeofPool(), sizeofObject(1)),
|
||||||
Reallocate(sizeofPool(), sizeofObject(1)),
|
});
|
||||||
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ TEST_CASE("ElementProxy::add()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
|
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ TEST_CASE("MemberProxy::add()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[42]}");
|
REQUIRE(doc.as<std::string>() == "{\"hello\":[42]}");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +34,6 @@ TEST_CASE("MemberProxy::add()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +44,6 @@ TEST_CASE("MemberProxy::add()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -58,8 +55,8 @@ TEST_CASE("MemberProxy::add()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +71,6 @@ TEST_CASE("MemberProxy::add()") {
|
|||||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -403,7 +399,7 @@ TEST_CASE("MemberProxy under memory constraints") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("value slot allocation fails") {
|
SECTION("value slot allocation fails") {
|
||||||
timebomb.setCountdown(2);
|
timebomb.setCountdown(1);
|
||||||
|
|
||||||
// fill the pool entirely, but leave one slot for the key
|
// fill the pool entirely, but leave one slot for the key
|
||||||
doc["foo"][ARDUINOJSON_POOL_CAPACITY - 4] = 1;
|
doc["foo"][ARDUINOJSON_POOL_CAPACITY - 4] = 1;
|
||||||
@ -416,7 +412,6 @@ TEST_CASE("MemberProxy under memory constraints") {
|
|||||||
REQUIRE(doc.overflowed() == true);
|
REQUIRE(doc.overflowed() == true);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
AllocateFail(sizeofPool()),
|
AllocateFail(sizeofPool()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ TEST_CASE("JsonDocument::add(T)") {
|
|||||||
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
|
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,6 @@ TEST_CASE("JsonDocument constructor") {
|
|||||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
||||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +87,6 @@ TEST_CASE("JsonDocument constructor") {
|
|||||||
REQUIRE(doc2.as<std::string>() == "[\"hello\"]");
|
REQUIRE(doc2.as<std::string>() == "[\"hello\"]");
|
||||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +22,10 @@ TEST_CASE("JsonDocument::remove()") {
|
|||||||
|
|
||||||
SECTION("string literal") {
|
SECTION("string literal") {
|
||||||
doc["a"] = 1;
|
doc["a"] = 1;
|
||||||
doc["x"] = 2;
|
doc["a\0b"_s] = 2;
|
||||||
doc["b"] = 3;
|
doc["b"] = 3;
|
||||||
|
|
||||||
doc.remove("x");
|
doc.remove("a\0b");
|
||||||
|
|
||||||
REQUIRE(doc.as<std::string>() == "{\"a\":1,\"b\":3}");
|
REQUIRE(doc.as<std::string>() == "{\"a\":1,\"b\":3}");
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,7 @@ TEST_CASE("JsonDocument::set()") {
|
|||||||
doc.set("example");
|
doc.set("example");
|
||||||
|
|
||||||
REQUIRE(doc.as<const char*>() == "example"_s);
|
REQUIRE(doc.as<const char*>() == "example"_s);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const char*") {
|
SECTION("const char*") {
|
||||||
|
@ -75,11 +75,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
|||||||
doc.shrinkToFit();
|
doc.shrinkToFit();
|
||||||
|
|
||||||
REQUIRE(doc.as<std::string>() == "hello");
|
REQUIRE(doc.as<std::string>() == "hello");
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() == AllocatorLog{});
|
||||||
AllocatorLog{
|
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("owned string") {
|
SECTION("owned string") {
|
||||||
@ -114,9 +110,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
|||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Reallocate(sizeofPool(), sizeofObject(1)),
|
Reallocate(sizeofPool(), sizeofObject(1)),
|
||||||
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,9 +137,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
|||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Reallocate(sizeofPool(), sizeofArray(1)),
|
Reallocate(sizeofPool(), sizeofArray(1)),
|
||||||
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,23 +164,20 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
|||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Reallocate(sizeofPool(), sizeofObject(1)),
|
Reallocate(sizeofPool(), sizeofObject(1)),
|
||||||
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(2)),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("owned string in object") {
|
SECTION("owned string in object") {
|
||||||
doc["key1"_s] = "value"_s;
|
doc["key"] = "abcdefg"_s;
|
||||||
|
|
||||||
doc.shrinkToFit();
|
doc.shrinkToFit();
|
||||||
|
|
||||||
REQUIRE(doc.as<std::string>() == "{\"key1\":\"value\"}");
|
REQUIRE(doc.as<std::string>() == "{\"key\":\"abcdefg\"}");
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("key1")),
|
Allocate(sizeofString("abcdefg")),
|
||||||
Allocate(sizeofString("value")),
|
|
||||||
Reallocate(sizeofPool(), sizeofPool(2)),
|
Reallocate(sizeofPool(), sizeofPool(2)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ TEST_CASE("JsonDocument::operator[]") {
|
|||||||
SECTION("string literal") {
|
SECTION("string literal") {
|
||||||
REQUIRE(doc["abc"] == "ABC");
|
REQUIRE(doc["abc"] == "ABC");
|
||||||
REQUIRE(cdoc["abc"] == "ABC");
|
REQUIRE(cdoc["abc"] == "ABC");
|
||||||
|
REQUIRE(doc["abc\0d"] == "ABCD");
|
||||||
|
REQUIRE(cdoc["abc\0d"] == "ABCD");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::string") {
|
SECTION("std::string") {
|
||||||
@ -112,7 +114,6 @@ TEST_CASE("JsonDocument::operator[] key storage") {
|
|||||||
REQUIRE(doc.as<std::string>() == "{\"hello\":0}");
|
REQUIRE(doc.as<std::string>() == "{\"hello\":0}");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,12 +26,25 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
REQUIRE(obj2["hello"] == "world"_s);
|
REQUIRE(obj2["hello"] == "world"_s);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy local string key and value") {
|
SECTION("copy local string value") {
|
||||||
obj1["hello"_s] = "world"_s;
|
obj1["hello"] = "world"_s;
|
||||||
|
spy.clearLog();
|
||||||
|
|
||||||
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
|
REQUIRE(success == true);
|
||||||
|
REQUIRE(obj2["hello"] == "world"_s);
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Allocate(sizeofString("world")),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("copy local key") {
|
||||||
|
obj1["hello"_s] = "world";
|
||||||
spy.clearLog();
|
spy.clearLog();
|
||||||
|
|
||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
@ -41,7 +54,6 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
Allocate(sizeofString("world")),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +110,7 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy fails in the middle of an array") {
|
SECTION("copy fails in the middle of an array") {
|
||||||
TimebombAllocator timebomb(2);
|
TimebombAllocator timebomb(1);
|
||||||
JsonDocument doc3(&timebomb);
|
JsonDocument doc3(&timebomb);
|
||||||
JsonObject obj3 = doc3.to<JsonObject>();
|
JsonObject obj3 = doc3.to<JsonObject>();
|
||||||
|
|
||||||
|
@ -102,25 +102,21 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
REQUIRE(42 == obj[key]);
|
REQUIRE(42 == obj[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string literals") {
|
SECTION("should not duplicate const char*") {
|
||||||
obj["hello"] = "world";
|
obj["hello"] = "world";
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{Allocate(sizeofPool())});
|
||||||
Allocate(sizeofPool()),
|
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char* value") {
|
SECTION("should duplicate char* value") {
|
||||||
obj["hello"] = const_cast<char*>("world");
|
obj["hello"] = const_cast<char*>("world");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char* key") {
|
SECTION("should duplicate char* key") {
|
||||||
obj[const_cast<char*>("hello")] = 42;
|
obj[const_cast<char*>("hello")] = "world";
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
@ -140,13 +136,12 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
obj["hello"] = "world"_s;
|
obj["hello"] = "world"_s;
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Allocate(sizeofString("world")),
|
Allocate(sizeofString("world")),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string key") {
|
SECTION("should duplicate std::string key") {
|
||||||
obj["hello"_s] = 42;
|
obj["hello"_s] = "world";
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
@ -163,7 +158,7 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate a non-static JsonString key") {
|
SECTION("should duplicate a non-static JsonString key") {
|
||||||
obj[JsonString("hello", false)] = 42;
|
obj[JsonString("hello", false)] = "world";
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofString("hello")),
|
Allocate(sizeofString("hello")),
|
||||||
@ -171,10 +166,9 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should not duplicate a static JsonString key") {
|
SECTION("should not duplicate a static JsonString key") {
|
||||||
obj[JsonString("hello", true)] = 42;
|
obj[JsonString("hello", true)] = "world";
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()),
|
Allocate(sizeofPool()),
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,15 +38,13 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
REQUIRE(var1.as<std::string>() == "{\"value\":[42]}");
|
REQUIRE(var1.as<std::string>() == "{\"value\":[42]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("stores string literals by pointer") {
|
SECTION("stores const char* by reference") {
|
||||||
var1.set("hello!!");
|
var1.set("hello!!");
|
||||||
spyingAllocator.clearLog();
|
spyingAllocator.clearLog();
|
||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
REQUIRE(spyingAllocator.log() == AllocatorLog{});
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("stores char* by copy") {
|
SECTION("stores char* by copy") {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
#include "Literals.hpp"
|
#include "Literals.hpp"
|
||||||
|
|
||||||
using namespace ArduinoJson::detail;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
|
|
||||||
enum ErrorCode { ERROR_01 = 1, ERROR_10 = 10 };
|
enum ErrorCode { ERROR_01 = 1, ERROR_10 = 10 };
|
||||||
|
|
||||||
@ -23,9 +23,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
CHECK(variant ==
|
CHECK(variant ==
|
||||||
"hello"_s); // linked string cannot contain '\0' at the moment
|
"hello"_s); // linked string cannot contain '\0' at the moment
|
||||||
CHECK(spy.log() == AllocatorLog{
|
CHECK(spy.log() == AllocatorLog{});
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const char*") {
|
SECTION("const char*") {
|
||||||
@ -151,9 +149,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "world"); // stores by pointer
|
REQUIRE(variant == "world"); // stores by pointer
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-static JsonString") {
|
SECTION("non-static JsonString") {
|
||||||
@ -197,11 +193,11 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant.is<double>() == true);
|
REQUIRE(variant.is<double>() == true);
|
||||||
REQUIRE(variant.as<double>() == 1.2);
|
REQUIRE(variant.as<double>() == 1.2);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() ==
|
||||||
Allocate(sizeofPool<EightByteValue>()),
|
AllocatorLog{
|
||||||
Reallocate(sizeofPool<EightByteValue>(),
|
Allocate(sizeofPool()),
|
||||||
sizeofPool<EightByteValue>(1)),
|
Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("int32_t") {
|
SECTION("int32_t") {
|
||||||
@ -220,11 +216,11 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant.is<int64_t>() == true);
|
REQUIRE(variant.is<int64_t>() == true);
|
||||||
REQUIRE(variant.as<int64_t>() == -2147483649LL);
|
REQUIRE(variant.as<int64_t>() == -2147483649LL);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() ==
|
||||||
Allocate(sizeofPool<EightByteValue>()),
|
AllocatorLog{
|
||||||
Reallocate(sizeofPool<EightByteValue>(),
|
Allocate(sizeofPool()),
|
||||||
sizeofPool<EightByteValue>(1)),
|
Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("uint32_t") {
|
SECTION("uint32_t") {
|
||||||
@ -243,11 +239,11 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant.is<uint64_t>() == true);
|
REQUIRE(variant.is<uint64_t>() == true);
|
||||||
REQUIRE(variant.as<uint64_t>() == 4294967296);
|
REQUIRE(variant.as<uint64_t>() == 4294967296);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() ==
|
||||||
Allocate(sizeofPool<EightByteValue>()),
|
AllocatorLog{
|
||||||
Reallocate(sizeofPool<EightByteValue>(),
|
Allocate(sizeofPool()),
|
||||||
sizeofPool<EightByteValue>(1)),
|
Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JsonDocument") {
|
SECTION("JsonDocument") {
|
||||||
@ -269,20 +265,6 @@ TEST_CASE("JsonVariant::set() with not enough memory") {
|
|||||||
|
|
||||||
JsonVariant v = doc.to<JsonVariant>();
|
JsonVariant v = doc.to<JsonVariant>();
|
||||||
|
|
||||||
SECTION("string literal") {
|
|
||||||
bool result = v.set("hello world");
|
|
||||||
|
|
||||||
REQUIRE(result == false);
|
|
||||||
REQUIRE(v.isNull());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("static JsonString") {
|
|
||||||
bool result = v.set(JsonString("hello world", true));
|
|
||||||
|
|
||||||
REQUIRE(result == false);
|
|
||||||
REQUIRE(v.isNull());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("std::string") {
|
SECTION("std::string") {
|
||||||
bool result = v.set("hello world!!"_s);
|
bool result = v.set("hello world!!"_s);
|
||||||
|
|
||||||
@ -378,7 +360,7 @@ TEST_CASE("JsonVariant::set() releases the previous value") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("float") {
|
SECTION("float") {
|
||||||
v.set(1.2f);
|
v.set(1.2);
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Deallocate(sizeofString("world")),
|
Deallocate(sizeofString("world")),
|
||||||
});
|
});
|
||||||
@ -393,7 +375,7 @@ TEST_CASE("JsonVariant::set() releases the previous value") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::set() reuses 8-bit slot") {
|
TEST_CASE("JsonVariant::set() reuses extension slot") {
|
||||||
SpyingAllocator spy;
|
SpyingAllocator spy;
|
||||||
JsonDocument doc(&spy);
|
JsonDocument doc(&spy);
|
||||||
JsonVariant variant = doc.to<JsonVariant>();
|
JsonVariant variant = doc.to<JsonVariant>();
|
||||||
|
@ -57,7 +57,7 @@ TEST_CASE("JsonVariantConst::operator[]") {
|
|||||||
SECTION("string literal") {
|
SECTION("string literal") {
|
||||||
REQUIRE(var["ab"] == "AB"_s);
|
REQUIRE(var["ab"] == "AB"_s);
|
||||||
REQUIRE(var["abc"] == "ABC"_s);
|
REQUIRE(var["abc"] == "ABC"_s);
|
||||||
REQUIRE(var["abc\0d"] == "ABC"_s);
|
REQUIRE(var["abc\0d"] == "ABCD"_s);
|
||||||
REQUIRE(var["def"].isNull());
|
REQUIRE(var["def"].isNull());
|
||||||
REQUIRE(var[0].isNull());
|
REQUIRE(var[0].isNull());
|
||||||
}
|
}
|
||||||
|
@ -29,3 +29,23 @@ set_tests_properties(Misc
|
|||||||
PROPERTIES
|
PROPERTIES
|
||||||
LABELS "Catch"
|
LABELS "Catch"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_executable(Issue2181
|
||||||
|
issue2181.cpp # Cannot be linked with other tests
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(Issue2181 PROPERTIES UNITY_BUILD OFF)
|
||||||
|
|
||||||
|
add_test(Issue2181 Issue2181)
|
||||||
|
|
||||||
|
set_tests_properties(Issue2181
|
||||||
|
PROPERTIES
|
||||||
|
LABELS "Catch"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
target_compile_options(Issue2181
|
||||||
|
PRIVATE
|
||||||
|
-Wno-keyword-macro # keyword is hidden by macro definition
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
@ -21,7 +21,7 @@ TEST_CASE("adaptString()") {
|
|||||||
auto s = adaptString("bravo\0alpha");
|
auto s = adaptString("bravo\0alpha");
|
||||||
|
|
||||||
CHECK(s.isNull() == false);
|
CHECK(s.isNull() == false);
|
||||||
CHECK(s.size() == 5);
|
CHECK(s.size() == 11);
|
||||||
CHECK(s.isStatic() == true);
|
CHECK(s.isStatic() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
extras/tests/Misc/issue2181.cpp
Normal file
15
extras/tests/Misc/issue2181.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2025, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#define true 0x1
|
||||||
|
#define false 0x0
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("Issue #2181") {
|
||||||
|
JsonDocument doc;
|
||||||
|
doc["hello"] = "world";
|
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}");
|
||||||
|
}
|
@ -104,8 +104,6 @@ TEST_CASE("deserializeMsgPack(MemberProxy)") {
|
|||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\",\"value\":[42]}");
|
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\",\"value\":[42]}");
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
add_executable(ResourceManagerTests
|
add_executable(ResourceManagerTests
|
||||||
allocVariant.cpp
|
allocVariant.cpp
|
||||||
clear.cpp
|
clear.cpp
|
||||||
saveStaticString.cpp
|
|
||||||
saveString.cpp
|
saveString.cpp
|
||||||
shrinkToFit.cpp
|
shrinkToFit.cpp
|
||||||
size.cpp
|
size.cpp
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Copyright © 2014-2025, Benoit BLANCHON
|
// Copyright © 2014-2025, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson.hpp>
|
#include <ArduinoJson/Memory/StringBuffer.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
@ -22,7 +22,7 @@ TEST_CASE("StringBuffer") {
|
|||||||
sb.save(&variant);
|
sb.save(&variant);
|
||||||
|
|
||||||
REQUIRE(variant.type() == VariantType::TinyString);
|
REQUIRE(variant.type() == VariantType::TinyString);
|
||||||
REQUIRE(variant.asString(&resources) == "hi!");
|
REQUIRE(variant.asString() == "hi!");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Tiny string can't contain NUL") {
|
SECTION("Tiny string can't contain NUL") {
|
||||||
@ -32,7 +32,7 @@ TEST_CASE("StringBuffer") {
|
|||||||
|
|
||||||
REQUIRE(variant.type() == VariantType::OwnedString);
|
REQUIRE(variant.type() == VariantType::OwnedString);
|
||||||
|
|
||||||
auto str = variant.asString(&resources);
|
auto str = variant.asString();
|
||||||
REQUIRE(str.size() == 3);
|
REQUIRE(str.size() == 3);
|
||||||
REQUIRE(str.c_str()[0] == 'a');
|
REQUIRE(str.c_str()[0] == 'a');
|
||||||
REQUIRE(str.c_str()[1] == 0);
|
REQUIRE(str.c_str()[1] == 0);
|
||||||
@ -45,6 +45,6 @@ TEST_CASE("StringBuffer") {
|
|||||||
sb.save(&variant);
|
sb.save(&variant);
|
||||||
|
|
||||||
REQUIRE(variant.type() == VariantType::OwnedString);
|
REQUIRE(variant.type() == VariantType::OwnedString);
|
||||||
REQUIRE(variant.asString(&resources) == "alfa");
|
REQUIRE(variant.asString() == "alfa");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Copyright © 2014-2025, Benoit BLANCHON
|
// Copyright © 2014-2025, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson.hpp>
|
#include <ArduinoJson/Memory/StringBuilder.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
@ -46,7 +46,7 @@ TEST_CASE("StringBuilder") {
|
|||||||
|
|
||||||
REQUIRE(resources.overflowed() == false);
|
REQUIRE(resources.overflowed() == false);
|
||||||
REQUIRE(data.type() == VariantType::TinyString);
|
REQUIRE(data.type() == VariantType::TinyString);
|
||||||
REQUIRE(data.asString(&resources) == "url");
|
REQUIRE(data.asString() == "url");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Short string fits in first allocation") {
|
SECTION("Short string fits in first allocation") {
|
||||||
@ -134,10 +134,9 @@ TEST_CASE("StringBuilder::save() deduplicates strings") {
|
|||||||
auto s2 = saveString(builder, "world");
|
auto s2 = saveString(builder, "world");
|
||||||
auto s3 = saveString(builder, "hello");
|
auto s3 = saveString(builder, "hello");
|
||||||
|
|
||||||
REQUIRE(s1.asString(&resources) == "hello");
|
REQUIRE(s1.asString() == "hello");
|
||||||
REQUIRE(s2.asString(&resources) == "world");
|
REQUIRE(s2.asString() == "world");
|
||||||
REQUIRE(+s1.asString(&resources).c_str() ==
|
REQUIRE(+s1.asString().c_str() == +s3.asString().c_str()); // same address
|
||||||
+s3.asString(&resources).c_str()); // same address
|
|
||||||
|
|
||||||
REQUIRE(spy.log() ==
|
REQUIRE(spy.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
@ -153,10 +152,10 @@ TEST_CASE("StringBuilder::save() deduplicates strings") {
|
|||||||
auto s1 = saveString(builder, "hello world");
|
auto s1 = saveString(builder, "hello world");
|
||||||
auto s2 = saveString(builder, "hello");
|
auto s2 = saveString(builder, "hello");
|
||||||
|
|
||||||
REQUIRE(s1.asString(&resources) == "hello world");
|
REQUIRE(s1.asString() == "hello world");
|
||||||
REQUIRE(s2.asString(&resources) == "hello");
|
REQUIRE(s2.asString() == "hello");
|
||||||
REQUIRE(+s2.asString(&resources).c_str() !=
|
REQUIRE(+s2.asString().c_str() !=
|
||||||
+s1.asString(&resources).c_str()); // different address
|
+s1.asString().c_str()); // different address
|
||||||
|
|
||||||
REQUIRE(spy.log() ==
|
REQUIRE(spy.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
@ -171,10 +170,10 @@ TEST_CASE("StringBuilder::save() deduplicates strings") {
|
|||||||
auto s1 = saveString(builder, "hello world");
|
auto s1 = saveString(builder, "hello world");
|
||||||
auto s2 = saveString(builder, "worl");
|
auto s2 = saveString(builder, "worl");
|
||||||
|
|
||||||
REQUIRE(s1.asString(&resources) == "hello world");
|
REQUIRE(s1.asString() == "hello world");
|
||||||
REQUIRE(s2.asString(&resources) == "worl");
|
REQUIRE(s2.asString() == "worl");
|
||||||
REQUIRE(s2.asString(&resources).c_str() !=
|
REQUIRE(s2.asString().c_str() !=
|
||||||
s1.asString(&resources).c_str()); // different address
|
s1.asString().c_str()); // different address
|
||||||
|
|
||||||
REQUIRE(spy.log() ==
|
REQUIRE(spy.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright © 2014-2025, Benoit BLANCHON
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
|
||||||
#include <catch.hpp>
|
|
||||||
|
|
||||||
#include "Allocators.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson::detail;
|
|
||||||
|
|
||||||
TEST_CASE("ResourceManager::saveStaticString() deduplicates strings") {
|
|
||||||
SpyingAllocator spy;
|
|
||||||
ResourceManager resources(&spy);
|
|
||||||
|
|
||||||
auto str1 = "hello";
|
|
||||||
auto str2 = "world";
|
|
||||||
|
|
||||||
auto id1 = resources.saveStaticString(str1);
|
|
||||||
auto id2 = resources.saveStaticString(str2);
|
|
||||||
REQUIRE(id1 != id2);
|
|
||||||
|
|
||||||
auto id3 = resources.saveStaticString(str1);
|
|
||||||
REQUIRE(id1 == id3);
|
|
||||||
|
|
||||||
resources.shrinkToFit();
|
|
||||||
REQUIRE(spy.log() ==
|
|
||||||
AllocatorLog{
|
|
||||||
Allocate(sizeofStaticStringPool()),
|
|
||||||
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(2)),
|
|
||||||
});
|
|
||||||
REQUIRE(resources.overflowed() == false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ResourceManager::saveStaticString() when allocation fails") {
|
|
||||||
SpyingAllocator spy(FailingAllocator::instance());
|
|
||||||
ResourceManager resources(&spy);
|
|
||||||
|
|
||||||
auto slotId = resources.saveStaticString("hello");
|
|
||||||
|
|
||||||
REQUIRE(slotId == NULL_SLOT);
|
|
||||||
REQUIRE(resources.overflowed() == true);
|
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
|
||||||
AllocateFail(sizeofStaticStringPool()),
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
version: "7.4.1"
|
version: "7.4.2"
|
||||||
description: >-
|
description: >-
|
||||||
A simple and efficient JSON library for embedded C++.
|
A simple and efficient JSON library for embedded C++.
|
||||||
★ 6898 stars on GitHub!
|
★ 6953 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++. ⭐ 6898 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++. ⭐ 6953 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.4.1",
|
"version": "7.4.2",
|
||||||
"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.4.1
|
version=7.4.2
|
||||||
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=⭐ 6898 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.
|
paragraph=⭐ 6953 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=*
|
||||||
|
@ -26,6 +26,15 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Remove true and false macros defined by some cores, such as Arduino Due's
|
||||||
|
// See issues #2181 and arduino/ArduinoCore-sam#50
|
||||||
|
#ifdef true
|
||||||
|
# undef true
|
||||||
|
#endif
|
||||||
|
#ifdef false
|
||||||
|
# undef false
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ArduinoJson/Array/JsonArray.hpp"
|
#include "ArduinoJson/Array/JsonArray.hpp"
|
||||||
#include "ArduinoJson/Object/JsonObject.hpp"
|
#include "ArduinoJson/Object/JsonObject.hpp"
|
||||||
#include "ArduinoJson/Variant/JsonVariantConst.hpp"
|
#include "ArduinoJson/Variant/JsonVariantConst.hpp"
|
||||||
|
@ -73,7 +73,7 @@ inline bool ArrayData::addValue(const T& value, ResourceManager* resources) {
|
|||||||
|
|
||||||
// Returns the size (in bytes) of an array with n elements.
|
// Returns the size (in bytes) of an array with n elements.
|
||||||
constexpr size_t sizeofArray(size_t n) {
|
constexpr size_t sizeofArray(size_t n) {
|
||||||
return n * sizeof(VariantData);
|
return n * ResourceManager::slotSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -274,9 +274,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_DOUBLE
|
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_DOUBLE
|
||||||
# define ARDUINOJSON_USE_8_BYTE_POOL 1
|
# define ARDUINOJSON_USE_EXTENSIONS 1
|
||||||
#else
|
#else
|
||||||
# define ARDUINOJSON_USE_8_BYTE_POOL 0
|
# define ARDUINOJSON_USE_EXTENSIONS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(nullptr)
|
#if defined(nullptr)
|
||||||
|
@ -34,11 +34,6 @@ class Slot {
|
|||||||
return ptr_;
|
return ptr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator*() const {
|
|
||||||
ARDUINOJSON_ASSERT(ptr_ != nullptr);
|
|
||||||
return *ptr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator->() const {
|
T* operator->() const {
|
||||||
ARDUINOJSON_ASSERT(ptr_ != nullptr);
|
ARDUINOJSON_ASSERT(ptr_ != nullptr);
|
||||||
return ptr_;
|
return ptr_;
|
||||||
@ -81,14 +76,6 @@ class MemoryPool {
|
|||||||
return slots_ + id;
|
return slots_ + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotId find(const T& value) const {
|
|
||||||
for (SlotId i = 0; i < usage_; i++) {
|
|
||||||
if (slots_[i] == value)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return NULL_SLOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
usage_ = 0;
|
usage_ = 0;
|
||||||
}
|
}
|
||||||
|
@ -114,15 +114,6 @@ class MemoryPoolList {
|
|||||||
return pools_[poolIndex].getSlot(indexInPool);
|
return pools_[poolIndex].getSlot(indexInPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotId find(const T& value) const {
|
|
||||||
for (PoolCount i = 0; i < count_; i++) {
|
|
||||||
SlotId id = pools_[i].find(value);
|
|
||||||
if (id != NULL_SLOT)
|
|
||||||
return SlotId(i * ARDUINOJSON_POOL_CAPACITY + id);
|
|
||||||
}
|
|
||||||
return NULL_SLOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear(Allocator* allocator) {
|
void clear(Allocator* allocator) {
|
||||||
for (PoolCount i = 0; i < count_; i++)
|
for (PoolCount i = 0; i < count_; i++)
|
||||||
pools_[i].destroy(allocator);
|
pools_[i].destroy(allocator);
|
||||||
|
@ -18,17 +18,22 @@ class VariantData;
|
|||||||
class VariantWithId;
|
class VariantWithId;
|
||||||
|
|
||||||
class ResourceManager {
|
class ResourceManager {
|
||||||
|
union SlotData {
|
||||||
|
VariantData variant;
|
||||||
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
|
VariantExtension extension;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
constexpr static size_t slotSize = sizeof(SlotData);
|
||||||
|
|
||||||
ResourceManager(Allocator* allocator = DefaultAllocator::instance())
|
ResourceManager(Allocator* allocator = DefaultAllocator::instance())
|
||||||
: allocator_(allocator), overflowed_(false) {}
|
: allocator_(allocator), overflowed_(false) {}
|
||||||
|
|
||||||
~ResourceManager() {
|
~ResourceManager() {
|
||||||
stringPool_.clear(allocator_);
|
stringPool_.clear(allocator_);
|
||||||
variantPools_.clear(allocator_);
|
variantPools_.clear(allocator_);
|
||||||
staticStringsPools_.clear(allocator_);
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
|
||||||
eightBytePools_.clear(allocator_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceManager(const ResourceManager&) = delete;
|
ResourceManager(const ResourceManager&) = delete;
|
||||||
@ -37,10 +42,6 @@ class ResourceManager {
|
|||||||
friend void swap(ResourceManager& a, ResourceManager& b) {
|
friend void swap(ResourceManager& a, ResourceManager& b) {
|
||||||
swap(a.stringPool_, b.stringPool_);
|
swap(a.stringPool_, b.stringPool_);
|
||||||
swap(a.variantPools_, b.variantPools_);
|
swap(a.variantPools_, b.variantPools_);
|
||||||
swap(a.staticStringsPools_, b.staticStringsPools_);
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
|
||||||
swap(a.eightBytePools_, b.eightBytePools_);
|
|
||||||
#endif
|
|
||||||
swap_(a.allocator_, b.allocator_);
|
swap_(a.allocator_, b.allocator_);
|
||||||
swap_(a.overflowed_, b.overflowed_);
|
swap_(a.overflowed_, b.overflowed_);
|
||||||
}
|
}
|
||||||
@ -61,10 +62,10 @@ class ResourceManager {
|
|||||||
void freeVariant(Slot<VariantData> slot);
|
void freeVariant(Slot<VariantData> slot);
|
||||||
VariantData* getVariant(SlotId id) const;
|
VariantData* getVariant(SlotId id) const;
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
Slot<EightByteValue> allocEightByte();
|
Slot<VariantExtension> allocExtension();
|
||||||
void freeEightByte(SlotId slot);
|
void freeExtension(SlotId slot);
|
||||||
EightByteValue* getEightByte(SlotId id) const;
|
VariantExtension* getExtension(SlotId id) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
@ -110,51 +111,21 @@ class ResourceManager {
|
|||||||
stringPool_.dereference(s, allocator_);
|
stringPool_.dereference(s, allocator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotId saveStaticString(const char* s) {
|
|
||||||
auto existingSlotId = staticStringsPools_.find(s);
|
|
||||||
if (existingSlotId != NULL_SLOT)
|
|
||||||
return existingSlotId;
|
|
||||||
|
|
||||||
auto slot = staticStringsPools_.allocSlot(allocator_);
|
|
||||||
if (slot)
|
|
||||||
*slot = s;
|
|
||||||
else
|
|
||||||
overflowed_ = true;
|
|
||||||
|
|
||||||
return slot.id();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* getStaticString(SlotId id) const {
|
|
||||||
return *staticStringsPools_.getSlot(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
overflowed_ = false;
|
|
||||||
variantPools_.clear(allocator_);
|
variantPools_.clear(allocator_);
|
||||||
|
overflowed_ = false;
|
||||||
stringPool_.clear(allocator_);
|
stringPool_.clear(allocator_);
|
||||||
staticStringsPools_.clear(allocator_);
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
|
||||||
eightBytePools_.clear(allocator_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void shrinkToFit() {
|
void shrinkToFit() {
|
||||||
variantPools_.shrinkToFit(allocator_);
|
variantPools_.shrinkToFit(allocator_);
|
||||||
staticStringsPools_.shrinkToFit(allocator_);
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
|
||||||
eightBytePools_.shrinkToFit(allocator_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Allocator* allocator_;
|
Allocator* allocator_;
|
||||||
bool overflowed_;
|
bool overflowed_;
|
||||||
StringPool stringPool_;
|
StringPool stringPool_;
|
||||||
MemoryPoolList<VariantData> variantPools_;
|
MemoryPoolList<SlotData> variantPools_;
|
||||||
MemoryPoolList<const char*> staticStringsPools_;
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
|
||||||
MemoryPoolList<EightByteValue> eightBytePools_;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -12,41 +12,40 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
inline Slot<VariantData> ResourceManager::allocVariant() {
|
inline Slot<VariantData> ResourceManager::allocVariant() {
|
||||||
auto slot = variantPools_.allocSlot(allocator_);
|
auto p = variantPools_.allocSlot(allocator_);
|
||||||
if (!slot) {
|
if (!p) {
|
||||||
overflowed_ = true;
|
overflowed_ = true;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
new (slot.ptr()) VariantData();
|
return {new (&p->variant) VariantData, p.id()};
|
||||||
return slot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ResourceManager::freeVariant(Slot<VariantData> slot) {
|
inline void ResourceManager::freeVariant(Slot<VariantData> variant) {
|
||||||
slot->clear(this);
|
variant->clear(this);
|
||||||
variantPools_.freeSlot(slot);
|
variantPools_.freeSlot({alias_cast<SlotData*>(variant.ptr()), variant.id()});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VariantData* ResourceManager::getVariant(SlotId id) const {
|
inline VariantData* ResourceManager::getVariant(SlotId id) const {
|
||||||
return reinterpret_cast<VariantData*>(variantPools_.getSlot(id));
|
return reinterpret_cast<VariantData*>(variantPools_.getSlot(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
inline Slot<EightByteValue> ResourceManager::allocEightByte() {
|
inline Slot<VariantExtension> ResourceManager::allocExtension() {
|
||||||
auto slot = eightBytePools_.allocSlot(allocator_);
|
auto p = variantPools_.allocSlot(allocator_);
|
||||||
if (!slot) {
|
if (!p) {
|
||||||
overflowed_ = true;
|
overflowed_ = true;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return slot;
|
return {&p->extension, p.id()};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ResourceManager::freeEightByte(SlotId id) {
|
inline void ResourceManager::freeExtension(SlotId id) {
|
||||||
auto p = getEightByte(id);
|
auto p = getExtension(id);
|
||||||
eightBytePools_.freeSlot({p, id});
|
variantPools_.freeSlot({reinterpret_cast<SlotData*>(p), id});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline EightByteValue* ResourceManager::getEightByte(SlotId id) const {
|
inline VariantExtension* ResourceManager::getExtension(SlotId id) const {
|
||||||
return eightBytePools_.getSlot(id);
|
return &variantPools_.getSlot(id)->extension;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class JsonPair {
|
|||||||
JsonPair(detail::ObjectData::iterator iterator,
|
JsonPair(detail::ObjectData::iterator iterator,
|
||||||
detail::ResourceManager* resources) {
|
detail::ResourceManager* resources) {
|
||||||
if (!iterator.done()) {
|
if (!iterator.done()) {
|
||||||
key_ = iterator->asString(resources);
|
key_ = iterator->asString();
|
||||||
iterator.next(resources);
|
iterator.next(resources);
|
||||||
value_ = JsonVariant(iterator.data(), resources);
|
value_ = JsonVariant(iterator.data(), resources);
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ class JsonPairConst {
|
|||||||
JsonPairConst(detail::ObjectData::iterator iterator,
|
JsonPairConst(detail::ObjectData::iterator iterator,
|
||||||
const detail::ResourceManager* resources) {
|
const detail::ResourceManager* resources) {
|
||||||
if (!iterator.done()) {
|
if (!iterator.done()) {
|
||||||
key_ = iterator->asString(resources);
|
key_ = iterator->asString();
|
||||||
iterator.next(resources);
|
iterator.next(resources);
|
||||||
value_ = JsonVariantConst(iterator.data(), resources);
|
value_ = JsonVariantConst(iterator.data(), resources);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ inline ObjectData::iterator ObjectData::findKey(
|
|||||||
return iterator();
|
return iterator();
|
||||||
bool isKey = true;
|
bool isKey = true;
|
||||||
for (auto it = createIterator(resources); !it.done(); it.next(resources)) {
|
for (auto it = createIterator(resources); !it.done(); it.next(resources)) {
|
||||||
if (isKey && stringEquals(key, adaptString(it->asString(resources))))
|
if (isKey && stringEquals(key, adaptString(it->asString())))
|
||||||
return it;
|
return it;
|
||||||
isKey = !isKey;
|
isKey = !isKey;
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ inline VariantData* ObjectData::addPair(VariantData** value,
|
|||||||
|
|
||||||
// Returns the size (in bytes) of an object with n members.
|
// Returns the size (in bytes) of an object with n members.
|
||||||
constexpr size_t sizeofObject(size_t n) {
|
constexpr size_t sizeofObject(size_t n) {
|
||||||
return 2 * n * sizeof(VariantData);
|
return 2 * n * ResourceManager::slotSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -90,9 +90,8 @@ template <size_t N>
|
|||||||
struct StringAdapter<const char (&)[N]> {
|
struct StringAdapter<const char (&)[N]> {
|
||||||
using AdaptedString = RamString;
|
using AdaptedString = RamString;
|
||||||
|
|
||||||
static AdaptedString adapt(const char* p) {
|
static AdaptedString adapt(const char (&p)[N]) {
|
||||||
ARDUINOJSON_ASSERT(p);
|
return RamString(p, N - 1, true);
|
||||||
return RamString(p, ::strlen(p), true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,7 +28,8 @@ class JsonString {
|
|||||||
detail::enable_if_t<detail::is_integral<TSize>::value &&
|
detail::enable_if_t<detail::is_integral<TSize>::value &&
|
||||||
!detail::is_same<TSize, bool>::value,
|
!detail::is_same<TSize, bool>::value,
|
||||||
int> = 0>
|
int> = 0>
|
||||||
JsonString(const char* data, TSize sz) : str_(data, size_t(sz), false) {}
|
JsonString(const char* data, TSize sz, bool isStatic = false)
|
||||||
|
: str_(data, size_t(sz), isStatic) {}
|
||||||
|
|
||||||
// Returns a pointer to the characters.
|
// Returns a pointer to the characters.
|
||||||
const char* c_str() const {
|
const char* c_str() const {
|
||||||
|
@ -160,7 +160,7 @@ struct Converter<const char*> : private detail::VariantAttorney {
|
|||||||
|
|
||||||
static const char* fromJson(JsonVariantConst src) {
|
static const char* fromJson(JsonVariantConst src) {
|
||||||
auto data = getData(src);
|
auto data = getData(src);
|
||||||
return data ? data->asString(getResourceManager(src)).c_str() : 0;
|
return data ? data->asString().c_str() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool checkJson(JsonVariantConst src) {
|
static bool checkJson(JsonVariantConst src) {
|
||||||
@ -178,7 +178,7 @@ struct Converter<JsonString> : private detail::VariantAttorney {
|
|||||||
|
|
||||||
static JsonString fromJson(JsonVariantConst src) {
|
static JsonString fromJson(JsonVariantConst src) {
|
||||||
auto data = getData(src);
|
auto data = getData(src);
|
||||||
return data ? data->asString(getResourceManager(src)) : JsonString();
|
return data ? data->asString() : JsonString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool checkJson(JsonVariantConst src) {
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
@ -16,7 +16,9 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
enum class VariantTypeBits : uint8_t {
|
enum class VariantTypeBits : uint8_t {
|
||||||
OwnedStringBit = 0x01, // 0000 0001
|
OwnedStringBit = 0x01, // 0000 0001
|
||||||
NumberBit = 0x08, // 0000 1000
|
NumberBit = 0x08, // 0000 1000
|
||||||
EightByteBit = 0x10, // 0001 0000
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
|
ExtensionBit = 0x10, // 0001 0000
|
||||||
|
#endif
|
||||||
CollectionMask = 0x60,
|
CollectionMask = 0x60,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,16 +56,19 @@ union VariantContent {
|
|||||||
bool asBoolean;
|
bool asBoolean;
|
||||||
uint32_t asUint32;
|
uint32_t asUint32;
|
||||||
int32_t asInt32;
|
int32_t asInt32;
|
||||||
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
SlotId asSlotId;
|
SlotId asSlotId;
|
||||||
|
#endif
|
||||||
ArrayData asArray;
|
ArrayData asArray;
|
||||||
ObjectData asObject;
|
ObjectData asObject;
|
||||||
CollectionData asCollection;
|
CollectionData asCollection;
|
||||||
|
const char* asLinkedString;
|
||||||
struct StringNode* asOwnedString;
|
struct StringNode* asOwnedString;
|
||||||
char asTinyString[tinyStringMaxLength + 1];
|
char asTinyString[tinyStringMaxLength + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
union EightByteValue {
|
union VariantExtension {
|
||||||
# if ARDUINOJSON_USE_LONG_LONG
|
# if ARDUINOJSON_USE_LONG_LONG
|
||||||
uint64_t asUint64;
|
uint64_t asUint64;
|
||||||
int64_t asInt64;
|
int64_t asInt64;
|
||||||
@ -72,9 +77,6 @@ union EightByteValue {
|
|||||||
double asDouble;
|
double asDouble;
|
||||||
# endif
|
# endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(EightByteValue) == 8,
|
|
||||||
"sizeof(EightByteValue) must be 8 bytes");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -53,8 +53,8 @@ class VariantData {
|
|||||||
template <typename TVisitor>
|
template <typename TVisitor>
|
||||||
typename TVisitor::result_type accept(
|
typename TVisitor::result_type accept(
|
||||||
TVisitor& visit, const ResourceManager* resources) const {
|
TVisitor& visit, const ResourceManager* resources) const {
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
auto eightByteValue = getEightByte(resources);
|
auto extension = getExtension(resources);
|
||||||
#else
|
#else
|
||||||
(void)resources; // silence warning
|
(void)resources; // silence warning
|
||||||
#endif
|
#endif
|
||||||
@ -64,7 +64,7 @@ class VariantData {
|
|||||||
|
|
||||||
#if ARDUINOJSON_USE_DOUBLE
|
#if ARDUINOJSON_USE_DOUBLE
|
||||||
case VariantType::Double:
|
case VariantType::Double:
|
||||||
return visit.visit(eightByteValue->asDouble);
|
return visit.visit(extension->asDouble);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case VariantType::Array:
|
case VariantType::Array:
|
||||||
@ -77,7 +77,7 @@ class VariantData {
|
|||||||
return visit.visit(JsonString(content_.asTinyString));
|
return visit.visit(JsonString(content_.asTinyString));
|
||||||
|
|
||||||
case VariantType::LinkedString:
|
case VariantType::LinkedString:
|
||||||
return visit.visit(JsonString(asLinkedString(resources), true));
|
return visit.visit(JsonString(content_.asLinkedString, true));
|
||||||
|
|
||||||
case VariantType::OwnedString:
|
case VariantType::OwnedString:
|
||||||
return visit.visit(JsonString(content_.asOwnedString->data,
|
return visit.visit(JsonString(content_.asOwnedString->data,
|
||||||
@ -95,10 +95,10 @@ class VariantData {
|
|||||||
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
case VariantType::Int64:
|
case VariantType::Int64:
|
||||||
return visit.visit(eightByteValue->asInt64);
|
return visit.visit(extension->asInt64);
|
||||||
|
|
||||||
case VariantType::Uint64:
|
case VariantType::Uint64:
|
||||||
return visit.visit(eightByteValue->asUint64);
|
return visit.visit(extension->asUint64);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case VariantType::Boolean:
|
case VariantType::Boolean:
|
||||||
@ -145,8 +145,8 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool asBoolean(const ResourceManager* resources) const {
|
bool asBoolean(const ResourceManager* resources) const {
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
auto eightByteValue = getEightByte(resources);
|
auto extension = getExtension(resources);
|
||||||
#else
|
#else
|
||||||
(void)resources; // silence warning
|
(void)resources; // silence warning
|
||||||
#endif
|
#endif
|
||||||
@ -160,14 +160,14 @@ class VariantData {
|
|||||||
return content_.asFloat != 0;
|
return content_.asFloat != 0;
|
||||||
#if ARDUINOJSON_USE_DOUBLE
|
#if ARDUINOJSON_USE_DOUBLE
|
||||||
case VariantType::Double:
|
case VariantType::Double:
|
||||||
return eightByteValue->asDouble != 0;
|
return extension->asDouble != 0;
|
||||||
#endif
|
#endif
|
||||||
case VariantType::Null:
|
case VariantType::Null:
|
||||||
return false;
|
return false;
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
case VariantType::Uint64:
|
case VariantType::Uint64:
|
||||||
case VariantType::Int64:
|
case VariantType::Int64:
|
||||||
return eightByteValue->asUint64 != 0;
|
return extension->asUint64 != 0;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
@ -193,8 +193,8 @@ class VariantData {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T asFloat(const ResourceManager* resources) const {
|
T asFloat(const ResourceManager* resources) const {
|
||||||
static_assert(is_floating_point<T>::value, "T must be a floating point");
|
static_assert(is_floating_point<T>::value, "T must be a floating point");
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
auto eightByteValue = getEightByte(resources);
|
auto extension = getExtension(resources);
|
||||||
#else
|
#else
|
||||||
(void)resources; // silence warning
|
(void)resources; // silence warning
|
||||||
#endif
|
#endif
|
||||||
@ -208,15 +208,15 @@ class VariantData {
|
|||||||
return static_cast<T>(content_.asInt32);
|
return static_cast<T>(content_.asInt32);
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
case VariantType::Uint64:
|
case VariantType::Uint64:
|
||||||
return static_cast<T>(eightByteValue->asUint64);
|
return static_cast<T>(extension->asUint64);
|
||||||
case VariantType::Int64:
|
case VariantType::Int64:
|
||||||
return static_cast<T>(eightByteValue->asInt64);
|
return static_cast<T>(extension->asInt64);
|
||||||
#endif
|
#endif
|
||||||
case VariantType::TinyString:
|
case VariantType::TinyString:
|
||||||
str = content_.asTinyString;
|
str = content_.asTinyString;
|
||||||
break;
|
break;
|
||||||
case VariantType::LinkedString:
|
case VariantType::LinkedString:
|
||||||
str = asLinkedString(resources);
|
str = content_.asLinkedString;
|
||||||
break;
|
break;
|
||||||
case VariantType::OwnedString:
|
case VariantType::OwnedString:
|
||||||
str = content_.asOwnedString->data;
|
str = content_.asOwnedString->data;
|
||||||
@ -225,7 +225,7 @@ class VariantData {
|
|||||||
return static_cast<T>(content_.asFloat);
|
return static_cast<T>(content_.asFloat);
|
||||||
#if ARDUINOJSON_USE_DOUBLE
|
#if ARDUINOJSON_USE_DOUBLE
|
||||||
case VariantType::Double:
|
case VariantType::Double:
|
||||||
return static_cast<T>(eightByteValue->asDouble);
|
return static_cast<T>(extension->asDouble);
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return 0.0;
|
return 0.0;
|
||||||
@ -238,8 +238,8 @@ class VariantData {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T asIntegral(const ResourceManager* resources) const {
|
T asIntegral(const ResourceManager* resources) const {
|
||||||
static_assert(is_integral<T>::value, "T must be an integral type");
|
static_assert(is_integral<T>::value, "T must be an integral type");
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
auto eightByteValue = getEightByte(resources);
|
auto extension = getExtension(resources);
|
||||||
#else
|
#else
|
||||||
(void)resources; // silence warning
|
(void)resources; // silence warning
|
||||||
#endif
|
#endif
|
||||||
@ -253,15 +253,15 @@ class VariantData {
|
|||||||
return convertNumber<T>(content_.asInt32);
|
return convertNumber<T>(content_.asInt32);
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
case VariantType::Uint64:
|
case VariantType::Uint64:
|
||||||
return convertNumber<T>(eightByteValue->asUint64);
|
return convertNumber<T>(extension->asUint64);
|
||||||
case VariantType::Int64:
|
case VariantType::Int64:
|
||||||
return convertNumber<T>(eightByteValue->asInt64);
|
return convertNumber<T>(extension->asInt64);
|
||||||
#endif
|
#endif
|
||||||
case VariantType::TinyString:
|
case VariantType::TinyString:
|
||||||
str = content_.asTinyString;
|
str = content_.asTinyString;
|
||||||
break;
|
break;
|
||||||
case VariantType::LinkedString:
|
case VariantType::LinkedString:
|
||||||
str = asLinkedString(resources);
|
str = content_.asLinkedString;
|
||||||
break;
|
break;
|
||||||
case VariantType::OwnedString:
|
case VariantType::OwnedString:
|
||||||
str = content_.asOwnedString->data;
|
str = content_.asOwnedString->data;
|
||||||
@ -270,7 +270,7 @@ class VariantData {
|
|||||||
return convertNumber<T>(content_.asFloat);
|
return convertNumber<T>(content_.asFloat);
|
||||||
#if ARDUINOJSON_USE_DOUBLE
|
#if ARDUINOJSON_USE_DOUBLE
|
||||||
case VariantType::Double:
|
case VariantType::Double:
|
||||||
return convertNumber<T>(eightByteValue->asDouble);
|
return convertNumber<T>(extension->asDouble);
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@ -298,14 +298,12 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* asLinkedString(const ResourceManager* resources) const;
|
JsonString asString() const {
|
||||||
|
|
||||||
JsonString asString(const ResourceManager* resources) const {
|
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case VariantType::TinyString:
|
case VariantType::TinyString:
|
||||||
return JsonString(content_.asTinyString);
|
return JsonString(content_.asTinyString);
|
||||||
case VariantType::LinkedString:
|
case VariantType::LinkedString:
|
||||||
return JsonString(asLinkedString(resources), true);
|
return JsonString(content_.asLinkedString, true);
|
||||||
case VariantType::OwnedString:
|
case VariantType::OwnedString:
|
||||||
return JsonString(content_.asOwnedString->data,
|
return JsonString(content_.asOwnedString->data,
|
||||||
content_.asOwnedString->length);
|
content_.asOwnedString->length);
|
||||||
@ -314,8 +312,8 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
const EightByteValue* getEightByte(const ResourceManager* resources) const;
|
const VariantExtension* getExtension(const ResourceManager* resources) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VariantData* getElement(size_t index,
|
VariantData* getElement(size_t index,
|
||||||
@ -378,7 +376,7 @@ class VariantData {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
bool isInteger(const ResourceManager* resources) const {
|
bool isInteger(const ResourceManager* resources) const {
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
auto eightByteValue = getEightByte(resources);
|
auto extension = getExtension(resources);
|
||||||
#else
|
#else
|
||||||
(void)resources; // silence warning
|
(void)resources; // silence warning
|
||||||
#endif
|
#endif
|
||||||
@ -391,10 +389,10 @@ class VariantData {
|
|||||||
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
case VariantType::Uint64:
|
case VariantType::Uint64:
|
||||||
return canConvertNumber<T>(eightByteValue->asUint64);
|
return canConvertNumber<T>(extension->asUint64);
|
||||||
|
|
||||||
case VariantType::Int64:
|
case VariantType::Int64:
|
||||||
return canConvertNumber<T>(eightByteValue->asInt64);
|
return canConvertNumber<T>(extension->asInt64);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -521,7 +519,12 @@ class VariantData {
|
|||||||
var->setString(value, resources);
|
var->setString(value, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setLinkedString(const char* s, ResourceManager* resources);
|
void setLinkedString(const char* s) {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
|
||||||
|
ARDUINOJSON_ASSERT(s);
|
||||||
|
type_ = VariantType::LinkedString;
|
||||||
|
content_.asLinkedString = s;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
void setTinyString(const TAdaptedString& s) {
|
void setTinyString(const TAdaptedString& s) {
|
||||||
|
@ -18,20 +18,6 @@ inline void VariantData::setRawString(SerializedValue<T> value,
|
|||||||
setRawString(dup);
|
setRawString(dup);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool VariantData::setLinkedString(const char* s,
|
|
||||||
ResourceManager* resources) {
|
|
||||||
ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
|
|
||||||
ARDUINOJSON_ASSERT(s);
|
|
||||||
|
|
||||||
auto slotId = resources->saveStaticString(s);
|
|
||||||
if (slotId == NULL_SLOT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
type_ = VariantType::LinkedString;
|
|
||||||
content_.asSlotId = slotId;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline bool VariantData::setString(TAdaptedString value,
|
inline bool VariantData::setString(TAdaptedString value,
|
||||||
ResourceManager* resources) {
|
ResourceManager* resources) {
|
||||||
@ -40,8 +26,10 @@ inline bool VariantData::setString(TAdaptedString value,
|
|||||||
if (value.isNull())
|
if (value.isNull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (value.isStatic())
|
if (value.isStatic()) {
|
||||||
return setLinkedString(value.data(), resources);
|
setLinkedString(value.data());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (isTinyString(value, value.size())) {
|
if (isTinyString(value, value.size())) {
|
||||||
setTinyString(value);
|
setTinyString(value);
|
||||||
@ -61,9 +49,9 @@ inline void VariantData::clear(ResourceManager* resources) {
|
|||||||
if (type_ & VariantTypeBits::OwnedStringBit)
|
if (type_ & VariantTypeBits::OwnedStringBit)
|
||||||
resources->dereferenceString(content_.asOwnedString->data);
|
resources->dereferenceString(content_.asOwnedString->data);
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
if (type_ & VariantTypeBits::EightByteBit)
|
if (type_ & VariantTypeBits::ExtensionBit)
|
||||||
resources->freeEightByte(content_.asSlotId);
|
resources->freeExtension(content_.asSlotId);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto collection = asCollection();
|
auto collection = asCollection();
|
||||||
@ -73,21 +61,15 @@ inline void VariantData::clear(ResourceManager* resources) {
|
|||||||
type_ = VariantType::Null;
|
type_ = VariantType::Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
#if ARDUINOJSON_USE_EXTENSIONS
|
||||||
inline const EightByteValue* VariantData::getEightByte(
|
inline const VariantExtension* VariantData::getExtension(
|
||||||
const ResourceManager* resources) const {
|
const ResourceManager* resources) const {
|
||||||
return type_ & VariantTypeBits::EightByteBit
|
return type_ & VariantTypeBits::ExtensionBit
|
||||||
? resources->getEightByte(content_.asSlotId)
|
? resources->getExtension(content_.asSlotId)
|
||||||
: 0;
|
: nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline const char* VariantData::asLinkedString(
|
|
||||||
const ResourceManager* resources) const {
|
|
||||||
ARDUINOJSON_ASSERT(type_ == VariantType::LinkedString);
|
|
||||||
return resources->getStaticString(content_.asSlotId);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
enable_if_t<sizeof(T) == 8, bool> VariantData::setFloat(
|
enable_if_t<sizeof(T) == 8, bool> VariantData::setFloat(
|
||||||
T value, ResourceManager* resources) {
|
T value, ResourceManager* resources) {
|
||||||
@ -101,12 +83,12 @@ enable_if_t<sizeof(T) == 8, bool> VariantData::setFloat(
|
|||||||
type_ = VariantType::Float;
|
type_ = VariantType::Float;
|
||||||
content_.asFloat = valueAsFloat;
|
content_.asFloat = valueAsFloat;
|
||||||
} else {
|
} else {
|
||||||
auto slot = resources->allocEightByte();
|
auto extension = resources->allocExtension();
|
||||||
if (!slot)
|
if (!extension)
|
||||||
return false;
|
return false;
|
||||||
type_ = VariantType::Double;
|
type_ = VariantType::Double;
|
||||||
content_.asSlotId = slot.id();
|
content_.asSlotId = extension.id();
|
||||||
slot->asDouble = value;
|
extension->asDouble = value;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
type_ = VariantType::Float;
|
type_ = VariantType::Float;
|
||||||
@ -127,12 +109,12 @@ enable_if_t<is_signed<T>::value, bool> VariantData::setInteger(
|
|||||||
}
|
}
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
else {
|
else {
|
||||||
auto slot = resources->allocEightByte();
|
auto extension = resources->allocExtension();
|
||||||
if (!slot)
|
if (!extension)
|
||||||
return false;
|
return false;
|
||||||
type_ = VariantType::Int64;
|
type_ = VariantType::Int64;
|
||||||
content_.asSlotId = slot.id();
|
content_.asSlotId = extension.id();
|
||||||
slot->asInt64 = value;
|
extension->asInt64 = value;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
@ -150,12 +132,12 @@ enable_if_t<is_unsigned<T>::value, bool> VariantData::setInteger(
|
|||||||
}
|
}
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
else {
|
else {
|
||||||
auto slot = resources->allocEightByte();
|
auto extension = resources->allocExtension();
|
||||||
if (!slot)
|
if (!extension)
|
||||||
return false;
|
return false;
|
||||||
type_ = VariantType::Uint64;
|
type_ = VariantType::Uint64;
|
||||||
content_.asSlotId = slot.id();
|
content_.asSlotId = extension.id();
|
||||||
slot->asUint64 = value;
|
extension->asUint64 = value;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ARDUINOJSON_VERSION "7.4.1"
|
#define ARDUINOJSON_VERSION "7.4.2"
|
||||||
#define ARDUINOJSON_VERSION_MAJOR 7
|
#define ARDUINOJSON_VERSION_MAJOR 7
|
||||||
#define ARDUINOJSON_VERSION_MINOR 4
|
#define ARDUINOJSON_VERSION_MINOR 4
|
||||||
#define ARDUINOJSON_VERSION_REVISION 1
|
#define ARDUINOJSON_VERSION_REVISION 2
|
||||||
#define ARDUINOJSON_VERSION_MACRO V741
|
#define ARDUINOJSON_VERSION_MACRO V742
|
||||||
|
Reference in New Issue
Block a user