Update ArduinoJSON

This commit is contained in:
iranl
2025-01-06 22:27:44 +01:00
parent 565a887c95
commit a379b30c11
82 changed files with 1098 additions and 1500 deletions

View File

@@ -19,10 +19,10 @@ class ArrayData : public CollectionData {
}
template <typename T>
bool addValue(T&& value, ResourceManager* resources);
bool addValue(const T& value, ResourceManager* resources);
template <typename T>
static bool addValue(ArrayData* array, T&& value,
static bool addValue(ArrayData* array, const T& value,
ResourceManager* resources) {
if (!array)
return false;

View File

@@ -57,13 +57,13 @@ inline void ArrayData::removeElement(size_t index, ResourceManager* resources) {
}
template <typename T>
inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
inline bool ArrayData::addValue(const T& value, ResourceManager* resources) {
ARDUINOJSON_ASSERT(resources != nullptr);
auto slot = resources->allocVariant();
if (!slot)
return false;
JsonVariant variant(slot.ptr(), resources);
if (!variant.set(detail::forward<T>(value))) {
if (!variant.set(value)) {
resources->freeVariant(slot);
return false;
}

View File

@@ -15,13 +15,18 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
public VariantOperators<ElementProxy<TUpstream>> {
friend class VariantAttorney;
friend class VariantRefBase<ElementProxy<TUpstream>>;
template <typename, typename>
friend class MemberProxy;
template <typename>
friend class ElementProxy;
public:
ElementProxy(TUpstream upstream, size_t index)
: upstream_(upstream), index_(index) {}
ElementProxy(const ElementProxy& src)
: upstream_(src.upstream_), index_(src.index_) {}
ElementProxy& operator=(const ElementProxy& src) {
this->set(src);
return *this;
@@ -40,6 +45,11 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
}
private:
// clang-format off
ElementProxy(const ElementProxy& src) // Error here? See https://arduinojson.org/v7/proxy-non-copyable/
: upstream_(src.upstream_), index_(src.index_) {}
// clang-format on
ResourceManager* getResourceManager() const {
return VariantAttorney::getResourceManager(upstream_);
}

View File

@@ -43,16 +43,18 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Appends a new (empty) element to the array.
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonarray/add/
template <typename T>
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() const {
template <typename T, detail::enable_if_t<
!detail::is_same<T, JsonVariant>::value, int> = 0>
T add() const {
return add<JsonVariant>().to<T>();
}
// Appends a new (null) element to the array.
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonarray/add/
template <typename T>
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() const {
template <typename T, detail::enable_if_t<
detail::is_same<T, JsonVariant>::value, int> = 0>
JsonVariant add() const {
return JsonVariant(detail::ArrayData::addElement(data_, resources_),
resources_);
}
@@ -66,7 +68,8 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Appends a value to the array.
// https://arduinojson.org/v7/api/jsonarray/add/
template <typename T>
template <typename T,
detail::enable_if_t<!detail::is_const<T>::value, int> = 0>
bool add(T* value) const {
return detail::ArrayData::addValue(data_, value, resources_);
}
@@ -114,9 +117,9 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// 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 {
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
void remove(const TVariant& variant) const {
if (variant.template is<size_t>())
remove(variant.template as<size_t>());
}
@@ -129,21 +132,19 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Gets or sets the element at the specified index.
// https://arduinojson.org/v7/api/jsonarray/subscript/
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value,
detail::ElementProxy<JsonArray>>
operator[](T index) const {
template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
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 {
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
detail::ElementProxy<JsonArray> operator[](const TVariant& variant) const {
if (variant.template is<size_t>())
return operator[](variant.template as<size_t>());
return {*this, variant.template as<size_t>()};
else
return {*this, size_t(-1)};
}

View File

@@ -45,9 +45,9 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
// Returns the element at the specified index.
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
operator[](T index) const {
template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
JsonVariantConst operator[](T index) const {
return JsonVariantConst(
detail::ArrayData::getElement(data_, size_t(index), resources_),
resources_);
@@ -55,9 +55,9 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
// 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 {
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
JsonVariantConst operator[](const TVariant& variant) const {
if (variant.template is<size_t>())
return operator[](variant.template as<size_t>());
else

View File

@@ -11,27 +11,26 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Copies a value to a JsonVariant.
// This is a degenerated form of copyArray() to stop the recursion.
template <typename T>
inline detail::enable_if_t<!detail::is_array<T>::value, bool> copyArray(
const T& src, JsonVariant dst) {
template <typename T, detail::enable_if_t<!detail::is_array<T>::value, int> = 0>
inline bool copyArray(const T& src, JsonVariant dst) {
return dst.set(src);
}
// Copies values from an array to a JsonArray or a JsonVariant.
// https://arduinojson.org/v7/api/misc/copyarray/
template <typename T, size_t N, typename TDestination>
inline detail::enable_if_t<
!detail::is_base_of<JsonDocument, TDestination>::value, bool>
copyArray(T (&src)[N], const TDestination& dst) {
template <typename T, size_t N, typename TDestination,
detail::enable_if_t<
!detail::is_base_of<JsonDocument, TDestination>::value, int> = 0>
inline bool copyArray(T (&src)[N], const TDestination& dst) {
return copyArray(src, N, dst);
}
// Copies values from an array to a JsonArray or a JsonVariant.
// https://arduinojson.org/v7/api/misc/copyarray/
template <typename T, typename TDestination>
inline detail::enable_if_t<
!detail::is_base_of<JsonDocument, TDestination>::value, bool>
copyArray(const T* src, size_t len, const TDestination& dst) {
template <typename T, typename TDestination,
detail::enable_if_t<
!detail::is_base_of<JsonDocument, TDestination>::value, int> = 0>
inline bool copyArray(const T* src, size_t len, const TDestination& dst) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= copyArray(src[i], dst.template add<JsonVariant>());
@@ -62,9 +61,8 @@ inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
// Copies a value from a JsonVariant.
// This is a degenerated form of copyArray() to stop the recursion.
template <typename T>
inline detail::enable_if_t<!detail::is_array<T>::value, size_t> copyArray(
JsonVariantConst src, T& dst) {
template <typename T, detail::enable_if_t<!detail::is_array<T>::value, int> = 0>
inline size_t copyArray(JsonVariantConst src, T& dst) {
dst = src.as<T>();
return 1;
}
@@ -102,11 +100,12 @@ inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) {
// Copies values from a JsonDocument to an array.
// https://arduinojson.org/v7/api/misc/copyarray/
template <typename TSource, typename T>
inline detail::enable_if_t<detail::is_array<T>::value &&
detail::is_base_of<JsonDocument, TSource>::value,
size_t>
copyArray(const TSource& src, T& dst) {
template <
typename TSource, typename T,
detail::enable_if_t<detail::is_array<T>::value &&
detail::is_base_of<JsonDocument, TSource>::value,
int> = 0>
inline size_t copyArray(const TSource& src, T& dst) {
return copyArray(src.template as<JsonArrayConst>(), dst);
}

View File

@@ -11,7 +11,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// The default reader is a simple wrapper for Readers that are not copiable
// The default reader is a simple wrapper for Readers that are not copyable
template <typename TSource, typename Enable = void>
struct Reader {
public:

View File

@@ -55,10 +55,11 @@ DeserializationError doDeserialize(TDestination&& dst, TReader reader,
return err;
}
template <template <typename> class TDeserializer, typename TDestination,
typename TStream, typename... Args,
typename = enable_if_t< // issue #1897
!is_integral<typename first_or_void<Args...>::type>::value>>
template <
template <typename> class TDeserializer, typename TDestination,
typename TStream, typename... Args,
enable_if_t< // issue #1897
!is_integral<typename first_or_void<Args...>::type>::value, int> = 0>
DeserializationError deserialize(TDestination&& dst, TStream&& input,
Args... args) {
return doDeserialize<TDeserializer>(
@@ -68,7 +69,7 @@ DeserializationError deserialize(TDestination&& dst, TStream&& input,
template <template <typename> class TDeserializer, typename TDestination,
typename TChar, typename Size, typename... Args,
typename = enable_if_t<is_integral<Size>::value>>
enable_if_t<is_integral<Size>::value, int> = 0>
DeserializationError deserialize(TDestination&& dst, TChar* input,
Size inputSize, Args... args) {
return doDeserialize<TDeserializer>(dst, makeReader(input, size_t(inputSize)),

View File

@@ -36,14 +36,15 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
}
// Construct from variant, array, or object
template <typename T>
JsonDocument(
const T& src, Allocator* alloc = detail::DefaultAllocator::instance(),
detail::enable_if_t<detail::IsVariant<T>::value ||
detail::is_same<T, JsonArray>::value ||
detail::is_same<T, JsonArrayConst>::value ||
detail::is_same<T, JsonObject>::value ||
detail::is_same<T, JsonObjectConst>::value>* = 0)
template <typename T,
detail::enable_if_t<detail::IsVariant<T>::value ||
detail::is_same<T, JsonArray>::value ||
detail::is_same<T, JsonArrayConst>::value ||
detail::is_same<T, JsonObject>::value ||
detail::is_same<T, JsonObjectConst>::value,
int> = 0>
JsonDocument(const T& src,
Allocator* alloc = detail::DefaultAllocator::instance())
: JsonDocument(alloc) {
set(src);
}
@@ -136,15 +137,17 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Replaces the root with the specified value.
// https://arduinojson.org/v7/api/jsondocument/set/
template <typename T>
detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, bool> set(
const T& src) {
template <
typename T,
detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, int> = 0>
bool set(const T& src) {
return to<JsonVariant>().set(src);
}
// Replaces the root with the specified value.
// https://arduinojson.org/v7/api/jsondocument/set/
template <typename TChar>
template <typename TChar,
detail::enable_if_t<!detail::is_const<TChar>::value, int> = 0>
bool set(TChar* src) {
return to<JsonVariant>().set(src);
}
@@ -167,64 +170,67 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsondocument/containskey/
template <typename TString>
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead")
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
const TString& key) const {
bool containsKey(const TString& key) const {
return data_.getMember(detail::adaptString(key), &resources_) != 0;
}
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsondocument/containskey/
template <typename TVariant>
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead")
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const {
bool containsKey(const TVariant& key) const {
return containsKey(key.template as<const char*>());
}
// Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value,
detail::MemberProxy<JsonDocument&, TString>>
operator[](const TString& key) {
return {*this, key};
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
detail::MemberProxy<JsonDocument&, detail::AdaptedString<TString>> operator[](
const TString& key) {
return {*this, detail::adaptString(key)};
}
// Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TChar>
detail::enable_if_t<detail::IsString<TChar*>::value,
detail::MemberProxy<JsonDocument&, TChar*>>
operator[](TChar* key) {
return {*this, key};
template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
detail::MemberProxy<JsonDocument&, detail::AdaptedString<TChar*>> operator[](
TChar* key) {
return {*this, detail::adaptString(key)};
}
// Gets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
operator[](const TString& key) const {
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
JsonVariantConst operator[](const TString& key) const {
return JsonVariantConst(
data_.getMember(detail::adaptString(key), &resources_), &resources_);
}
// Gets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TChar>
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
operator[](TChar* key) const {
template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
JsonVariantConst operator[](TChar* key) const {
return JsonVariantConst(
data_.getMember(detail::adaptString(key), &resources_), &resources_);
}
// Gets or sets a root array's element.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value,
detail::ElementProxy<JsonDocument&>>
operator[](T index) {
template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
detail::ElementProxy<JsonDocument&> operator[](T index) {
return {*this, size_t(index)};
}
@@ -236,9 +242,9 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// 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 {
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
JsonVariantConst operator[](const TVariant& key) const {
if (key.template is<JsonString>())
return operator[](key.template as<JsonString>());
if (key.template is<size_t>())
@@ -249,16 +255,18 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Appends a new (empty) element to the root array.
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsondocument/add/
template <typename T>
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() {
template <typename T, detail::enable_if_t<
!detail::is_same<T, JsonVariant>::value, int> = 0>
T add() {
return add<JsonVariant>().to<T>();
}
// Appends a new (null) element to the root array.
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsondocument/add/
template <typename T>
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() {
template <typename T, detail::enable_if_t<
detail::is_same<T, JsonVariant>::value, int> = 0>
JsonVariant add() {
return JsonVariant(data_.addElement(&resources_), &resources_);
}
@@ -271,41 +279,46 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Appends a value to the root array.
// https://arduinojson.org/v7/api/jsondocument/add/
template <typename TChar>
template <typename TChar,
detail::enable_if_t<!detail::is_const<TChar>::value, int> = 0>
bool add(TChar* value) {
return data_.addValue(value, &resources_);
}
// Removes an element of the root array.
// https://arduinojson.org/v7/api/jsondocument/remove/
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value> remove(T index) {
template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
void remove(T index) {
detail::VariantData::removeElement(getData(), size_t(index),
getResourceManager());
}
// Removes a member of the root object.
// https://arduinojson.org/v7/api/jsondocument/remove/
template <typename TChar>
detail::enable_if_t<detail::IsString<TChar*>::value> remove(TChar* key) {
template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
void remove(TChar* key) {
detail::VariantData::removeMember(getData(), detail::adaptString(key),
getResourceManager());
}
// Removes a member of the root object.
// https://arduinojson.org/v7/api/jsondocument/remove/
template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value> remove(
const TString& key) {
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
void remove(const TString& key) {
detail::VariantData::removeMember(getData(), detail::adaptString(key),
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) {
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
void remove(const TVariant& key) {
if (key.template is<const char*>())
remove(key.template as<const char*>());
if (key.template is<size_t>())

View File

@@ -270,10 +270,10 @@ class JsonDeserializer {
JsonString key = stringBuilder_.str();
TFilter memberFilter = filter[key.c_str()];
TFilter memberFilter = filter[key];
if (memberFilter.allow()) {
auto member = object.getMember(adaptString(key.c_str()), resources_);
auto member = object.getMember(adaptString(key), resources_);
if (!member) {
// Save key in memory pool.
auto savedKey = stringBuilder_.save();
@@ -697,10 +697,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/json/deserializejson/
template <typename TDestination, typename... Args>
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
DeserializationError>
deserializeJson(TDestination&& dst, Args&&... args) {
template <typename TDestination, typename... Args,
detail::enable_if_t<
detail::is_deserialize_destination<TDestination>::value, int> = 0>
inline DeserializationError deserializeJson(TDestination&& dst,
Args&&... args) {
using namespace detail;
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
detail::forward<Args>(args)...);
@@ -708,10 +709,11 @@ deserializeJson(TDestination&& dst, Args&&... args) {
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/json/deserializejson/
template <typename TDestination, typename TChar, typename... Args>
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
DeserializationError>
deserializeJson(TDestination&& dst, TChar* input, Args&&... args) {
template <typename TDestination, typename TChar, typename... Args,
detail::enable_if_t<
detail::is_deserialize_destination<TDestination>::value, int> = 0>
inline DeserializationError deserializeJson(TDestination&& dst, TChar* input,
Args&&... args) {
using namespace detail;
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
input, detail::forward<Args>(args)...);

View File

@@ -129,9 +129,10 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Produces a minified JSON document.
// https://arduinojson.org/v7/api/json/serializejson/
template <typename TDestination>
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t>
serializeJson(JsonVariantConst source, TDestination& destination) {
template <
typename TDestination,
detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
size_t serializeJson(JsonVariantConst source, TDestination& destination) {
using namespace detail;
return serialize<JsonSerializer>(source, destination);
}
@@ -152,10 +153,10 @@ inline size_t measureJson(JsonVariantConst source) {
}
#if ARDUINOJSON_ENABLE_STD_STREAM
template <typename T>
inline detail::enable_if_t<detail::is_convertible<T, JsonVariantConst>::value,
std::ostream&>
operator<<(std::ostream& os, const T& source) {
template <typename T,
detail::enable_if_t<
detail::is_convertible<T, JsonVariantConst>::value, int> = 0>
inline std::ostream& operator<<(std::ostream& os, const T& source) {
serializeJson(source, os);
return os;
}

View File

@@ -83,9 +83,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Produces JsonDocument to create a prettified JSON document.
// https://arduinojson.org/v7/api/json/serializejsonpretty/
template <typename TDestination>
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t>
serializeJsonPretty(JsonVariantConst source, TDestination& destination) {
template <
typename TDestination,
detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
inline size_t serializeJsonPretty(JsonVariantConst source,
TDestination& destination) {
using namespace ArduinoJson::detail;
return serialize<PrettyJsonSerializer>(source, destination);
}

View File

@@ -55,7 +55,7 @@ class StringBuffer {
JsonString str() const {
ARDUINOJSON_ASSERT(node_ != nullptr);
return JsonString(node_->data, node_->length, JsonString::Copied);
return JsonString(node_->data, node_->length);
}
private:

View File

@@ -68,7 +68,7 @@ class StringBuilder {
JsonString str() const {
ARDUINOJSON_ASSERT(node_ != nullptr);
node_->data[size_] = 0;
return JsonString(node_->data, size_, JsonString::Copied);
return JsonString(node_->data, size_);
}
private:

View File

@@ -1,63 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/integer.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class VariantSlot;
using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
using SlotCount = SlotId;
const SlotId NULL_SLOT = SlotId(-1);
class SlotWithId {
public:
SlotWithId() : slot_(nullptr), id_(NULL_SLOT) {}
SlotWithId(VariantSlot* slot, SlotId id) : slot_(slot), id_(id) {
ARDUINOJSON_ASSERT((slot == nullptr) == (id == NULL_SLOT));
}
SlotId id() const {
return id_;
}
operator VariantSlot*() {
return slot_;
}
VariantSlot* operator->() {
ARDUINOJSON_ASSERT(slot_ != nullptr);
return slot_;
}
private:
VariantSlot* slot_;
SlotId id_;
};
class VariantPool {
public:
void create(SlotCount cap, Allocator* allocator);
void destroy(Allocator* allocator);
SlotWithId allocSlot();
VariantSlot* getSlot(SlotId id) const;
void clear();
void shrinkToFit(Allocator*);
SlotCount usage() const;
static SlotCount bytesToSlots(size_t);
static size_t slotsToBytes(SlotCount);
private:
SlotCount capacity_;
SlotCount usage_;
VariantSlot* slots_;
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -1,81 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/VariantPool.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
inline void VariantPool::create(SlotCount cap, Allocator* allocator) {
ARDUINOJSON_ASSERT(cap > 0);
slots_ =
reinterpret_cast<VariantSlot*>(allocator->allocate(slotsToBytes(cap)));
capacity_ = slots_ ? cap : 0;
usage_ = 0;
}
inline void VariantPool::destroy(Allocator* allocator) {
if (slots_)
allocator->deallocate(slots_);
slots_ = nullptr;
capacity_ = 0;
usage_ = 0;
}
inline void VariantPool::shrinkToFit(Allocator* allocator) {
auto newSlots = reinterpret_cast<VariantSlot*>(
allocator->reallocate(slots_, slotsToBytes(usage_)));
if (newSlots) {
slots_ = newSlots;
capacity_ = usage_;
}
}
inline SlotWithId VariantPool::allocSlot() {
if (!slots_)
return {};
if (usage_ >= capacity_)
return {};
auto index = usage_++;
auto slot = &slots_[index];
return {new (slot) VariantSlot, SlotId(index)};
}
inline VariantSlot* VariantPool::getSlot(SlotId id) const {
ARDUINOJSON_ASSERT(id < usage_);
return &slots_[id];
}
inline SlotCount VariantPool::usage() const {
return usage_;
}
inline void VariantPool::clear() {
usage_ = 0;
}
inline SlotCount VariantPool::bytesToSlots(size_t n) {
return static_cast<SlotCount>(n / sizeof(VariantSlot));
}
inline size_t VariantPool::slotsToBytes(SlotCount n) {
return n * sizeof(VariantSlot);
}
inline SlotWithId VariantPoolList::allocFromFreeList() {
ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
auto id = freeList_;
auto slot = getSlot(freeList_);
freeList_ = slot->next();
return {new (slot) VariantSlot, id};
}
inline void VariantPoolList::freeSlot(SlotWithId slot) {
slot->setNext(freeList_);
freeList_ = slot.id();
}
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -1,189 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/VariantPool.hpp>
#include <ArduinoJson/Polyfills/assert.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
using PoolCount = SlotId;
class VariantPoolList {
public:
VariantPoolList() = default;
~VariantPoolList() {
ARDUINOJSON_ASSERT(count_ == 0);
}
friend void swap(VariantPoolList& a, VariantPoolList& b) {
bool aUsedPreallocated = a.pools_ == a.preallocatedPools_;
bool bUsedPreallocated = b.pools_ == b.preallocatedPools_;
// Who is using preallocated pools?
if (aUsedPreallocated && bUsedPreallocated) {
// both of us => swap preallocated pools
for (PoolCount i = 0; i < ARDUINOJSON_INITIAL_POOL_COUNT; i++)
swap_(a.preallocatedPools_[i], b.preallocatedPools_[i]);
} else if (bUsedPreallocated) {
// only b => copy b's preallocated pools and give him a's pointer
for (PoolCount i = 0; i < b.count_; i++)
a.preallocatedPools_[i] = b.preallocatedPools_[i];
b.pools_ = a.pools_;
a.pools_ = a.preallocatedPools_;
} else if (aUsedPreallocated) {
// only a => copy a's preallocated pools and give him b's pointer
for (PoolCount i = 0; i < a.count_; i++)
b.preallocatedPools_[i] = a.preallocatedPools_[i];
a.pools_ = b.pools_;
b.pools_ = b.preallocatedPools_;
} else {
// neither => swap pointers
swap_(a.pools_, b.pools_);
}
swap_(a.count_, b.count_);
swap_(a.capacity_, b.capacity_);
swap_(a.freeList_, b.freeList_);
}
VariantPoolList& operator=(VariantPoolList&& src) {
ARDUINOJSON_ASSERT(count_ == 0);
if (src.pools_ == src.preallocatedPools_) {
memcpy(preallocatedPools_, src.preallocatedPools_,
sizeof(preallocatedPools_));
pools_ = preallocatedPools_;
} else {
pools_ = src.pools_;
src.pools_ = nullptr;
}
count_ = src.count_;
capacity_ = src.capacity_;
src.count_ = 0;
src.capacity_ = 0;
return *this;
}
SlotWithId allocSlot(Allocator* allocator) {
// try to allocate from free list
if (freeList_ != NULL_SLOT) {
return allocFromFreeList();
}
// try to allocate from last pool (other pools are full)
if (count_) {
auto slot = allocFromLastPool();
if (slot)
return slot;
}
// create a new pool and try again
auto pool = addPool(allocator);
if (!pool)
return {};
return allocFromLastPool();
}
void freeSlot(SlotWithId slot);
VariantSlot* getSlot(SlotId id) const {
if (id == NULL_SLOT)
return nullptr;
auto poolIndex = SlotId(id / ARDUINOJSON_POOL_CAPACITY);
auto indexInPool = SlotId(id % ARDUINOJSON_POOL_CAPACITY);
ARDUINOJSON_ASSERT(poolIndex < count_);
return pools_[poolIndex].getSlot(indexInPool);
}
void clear(Allocator* allocator) {
for (PoolCount i = 0; i < count_; i++)
pools_[i].destroy(allocator);
count_ = 0;
freeList_ = NULL_SLOT;
if (pools_ != preallocatedPools_) {
allocator->deallocate(pools_);
pools_ = preallocatedPools_;
capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
}
}
SlotCount usage() const {
SlotCount total = 0;
for (PoolCount i = 0; i < count_; i++)
total = SlotCount(total + pools_[i].usage());
return total;
}
void shrinkToFit(Allocator* allocator) {
if (count_ > 0)
pools_[count_ - 1].shrinkToFit(allocator);
if (pools_ != preallocatedPools_ && count_ != capacity_) {
pools_ = static_cast<VariantPool*>(
allocator->reallocate(pools_, count_ * sizeof(VariantPool)));
ARDUINOJSON_ASSERT(pools_ != nullptr); // realloc to smaller can't fail
capacity_ = count_;
}
}
private:
SlotWithId allocFromFreeList();
SlotWithId allocFromLastPool() {
ARDUINOJSON_ASSERT(count_ > 0);
auto poolIndex = SlotId(count_ - 1);
auto slot = pools_[poolIndex].allocSlot();
if (!slot)
return {};
return {slot, SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
}
VariantPool* addPool(Allocator* allocator) {
if (count_ == capacity_ && !increaseCapacity(allocator))
return nullptr;
auto pool = &pools_[count_++];
SlotCount poolCapacity = ARDUINOJSON_POOL_CAPACITY;
if (count_ == maxPools) // last pool is smaller because of NULL_SLOT
poolCapacity--;
pool->create(poolCapacity, allocator);
return pool;
}
bool increaseCapacity(Allocator* allocator) {
if (capacity_ == maxPools)
return false;
void* newPools;
auto newCapacity = PoolCount(capacity_ * 2);
if (pools_ == preallocatedPools_) {
newPools = allocator->allocate(newCapacity * sizeof(VariantPool));
if (!newPools)
return false;
memcpy(newPools, preallocatedPools_, sizeof(preallocatedPools_));
} else {
newPools =
allocator->reallocate(pools_, newCapacity * sizeof(VariantPool));
if (!newPools)
return false;
}
pools_ = static_cast<VariantPool*>(newPools);
capacity_ = newCapacity;
return true;
}
VariantPool preallocatedPools_[ARDUINOJSON_INITIAL_POOL_COUNT];
VariantPool* pools_ = preallocatedPools_;
PoolCount count_ = 0;
PoolCount capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
SlotId freeList_ = NULL_SLOT;
public:
static const PoolCount maxPools =
PoolCount(NULL_SLOT / ARDUINOJSON_POOL_CAPACITY + 1);
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -464,10 +464,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Parses a MessagePack input and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
template <typename TDestination, typename... Args>
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
DeserializationError>
deserializeMsgPack(TDestination&& dst, Args&&... args) {
template <typename TDestination, typename... Args,
detail::enable_if_t<
detail::is_deserialize_destination<TDestination>::value, int> = 0>
inline DeserializationError deserializeMsgPack(TDestination&& dst,
Args&&... args) {
using namespace detail;
return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
detail::forward<Args>(args)...);
@@ -475,10 +476,11 @@ deserializeMsgPack(TDestination&& dst, Args&&... args) {
// Parses a MessagePack input and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
template <typename TDestination, typename TChar, typename... Args>
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
DeserializationError>
deserializeMsgPack(TDestination&& dst, TChar* input, Args&&... args) {
template <typename TDestination, typename TChar, typename... Args,
detail::enable_if_t<
detail::is_deserialize_destination<TDestination>::value, int> = 0>
inline DeserializationError deserializeMsgPack(TDestination&& dst, TChar* input,
Args&&... args) {
using namespace detail;
return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
input,

View File

@@ -96,7 +96,7 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
}
size_t visit(JsonString value) {
ARDUINOJSON_ASSERT(value != NULL);
ARDUINOJSON_ASSERT(!value.isNull());
auto n = value.size();
@@ -218,9 +218,10 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Produces a MessagePack document.
// https://arduinojson.org/v7/api/msgpack/serializemsgpack/
template <typename TDestination>
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t>
serializeMsgPack(JsonVariantConst source, TDestination& output) {
template <
typename TDestination,
detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
inline size_t serializeMsgPack(JsonVariantConst source, TDestination& output) {
using namespace ArduinoJson::detail;
return serialize<MsgPackSerializer>(source, output);
}

View File

@@ -101,32 +101,31 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value,
detail::MemberProxy<JsonObject, TString>>
operator[](const TString& key) const {
return {*this, key};
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
detail::MemberProxy<JsonObject, detail::AdaptedString<TString>> operator[](
const TString& key) const {
return {*this, detail::adaptString(key)};
}
// Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TChar>
detail::enable_if_t<detail::IsString<TChar*>::value,
detail::MemberProxy<JsonObject, TChar*>>
operator[](TChar* key) const {
return {*this, key};
template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
detail::MemberProxy<JsonObject, detail::AdaptedString<TChar*>> operator[](
TChar* key) const {
return {*this, detail::adaptString(key)};
}
// Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value,
detail::MemberProxy<JsonObject, JsonString>>
operator[](const TVariant& key) const {
if (key.template is<JsonString>())
return {*this, key.template as<JsonString>()};
else
return {*this, nullptr};
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
detail::MemberProxy<JsonObject, detail::AdaptedString<JsonString>> operator[](
const TVariant& key) const {
return {*this, detail::adaptString(key.template as<JsonString>())};
}
// Removes the member at the specified iterator.
@@ -137,18 +136,18 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Removes the member with the specified key.
// https://arduinojson.org/v7/api/jsonobject/remove/
template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value> remove(
const TString& key) const {
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
void remove(const TString& key) const {
detail::ObjectData::removeMember(data_, detail::adaptString(key),
resources_);
}
// Removes the member with the specified key.
// https://arduinojson.org/v7/api/jsonobject/remove/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove(
const TVariant& key) const {
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
void remove(const TVariant& key) const {
if (key.template is<const char*>())
remove(key.template as<const char*>());
}
@@ -163,30 +162,32 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TString>
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
const TString& key) const {
bool containsKey(const TString& key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0;
}
// DEPRECATED: use obj["key"].is<T>() instead
// https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TChar>
template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
detail::enable_if_t<detail::IsString<TChar*>::value, bool> containsKey(
TChar* key) const {
bool containsKey(TChar* key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0;
}
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TVariant>
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const {
bool containsKey(const TVariant& key) const {
return containsKey(key.template as<const char*>());
}

View File

@@ -70,10 +70,10 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonobjectconst/containskey/
template <typename TString>
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
const TString& key) const {
bool containsKey(const TString& key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0;
}
@@ -89,18 +89,18 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonobjectconst/containskey/
template <typename TVariant>
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const {
bool containsKey(const TVariant& key) const {
return containsKey(key.template as<const char*>());
}
// Gets the member with specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/
template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
operator[](const TString& key) const {
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
JsonVariantConst operator[](const TString& key) const {
return JsonVariantConst(detail::ObjectData::getMember(
data_, detail::adaptString(key), resources_),
resources_);
@@ -108,9 +108,11 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// Gets the member with specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/
template <typename TChar>
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
operator[](TChar* key) const {
template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
JsonVariantConst operator[](TChar* key) const {
return JsonVariantConst(detail::ObjectData::getMember(
data_, detail::adaptString(key), resources_),
resources_);
@@ -118,9 +120,9 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// Gets the member with specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
operator[](const TVariant& key) const {
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
JsonVariantConst operator[](const TVariant& key) const {
if (key.template is<JsonString>())
return operator[](key.template as<JsonString>());
else

View File

@@ -10,18 +10,23 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// A proxy class to get or set a member of an object.
// https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TUpstream, typename TStringRef>
template <typename TUpstream, typename AdaptedString>
class MemberProxy
: public VariantRefBase<MemberProxy<TUpstream, TStringRef>>,
public VariantOperators<MemberProxy<TUpstream, TStringRef>> {
: public VariantRefBase<MemberProxy<TUpstream, AdaptedString>>,
public VariantOperators<MemberProxy<TUpstream, AdaptedString>> {
friend class VariantAttorney;
public:
MemberProxy(TUpstream upstream, TStringRef key)
: upstream_(upstream), key_(key) {}
friend class VariantRefBase<MemberProxy<TUpstream, AdaptedString>>;
MemberProxy(const MemberProxy& src)
: upstream_(src.upstream_), key_(src.key_) {}
template <typename, typename>
friend class MemberProxy;
template <typename>
friend class ElementProxy;
public:
MemberProxy(TUpstream upstream, AdaptedString key)
: upstream_(upstream), key_(key) {}
MemberProxy& operator=(const MemberProxy& src) {
this->set(src);
@@ -34,20 +39,25 @@ class MemberProxy
return *this;
}
template <typename T>
template <typename T, enable_if_t<!is_const<T>::value, int> = 0>
MemberProxy& operator=(T* src) {
this->set(src);
return *this;
}
private:
// clang-format off
MemberProxy(const MemberProxy& src) // Error here? See https://arduinojson.org/v7/proxy-non-copyable/
: upstream_(src.upstream_), key_(src.key_) {}
// clang-format on
ResourceManager* getResourceManager() const {
return VariantAttorney::getResourceManager(upstream_);
}
VariantData* getData() const {
return VariantData::getMember(
VariantAttorney::getData(upstream_), adaptString(key_),
VariantAttorney::getData(upstream_), key_,
VariantAttorney::getResourceManager(upstream_));
}
@@ -55,13 +65,13 @@ class MemberProxy
auto data = VariantAttorney::getOrCreateData(upstream_);
if (!data)
return nullptr;
return data->getOrAddMember(adaptString(key_),
return data->getOrAddMember(key_,
VariantAttorney::getResourceManager(upstream_));
}
private:
TUpstream upstream_;
TStringRef key_;
AdaptedString key_;
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -5,6 +5,7 @@
#pragma once
#include "type_traits/conditional.hpp"
#include "type_traits/decay.hpp"
#include "type_traits/enable_if.hpp"
#include "type_traits/function_traits.hpp"
#include "type_traits/integral_constant.hpp"

View File

@@ -0,0 +1,33 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <stddef.h> // size_t
#include <ArduinoJson/Namespace.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename T>
struct decay {
using type = T;
};
template <typename T>
struct decay<T&> : decay<T> {};
template <typename T>
struct decay<T&&> : decay<T> {};
template <typename T>
struct decay<T[]> : decay<T*> {};
template <typename T, size_t N>
struct decay<T[N]> : decay<T*> {};
template <typename T>
using decay_t = typename decay<T>::type;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -8,7 +8,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// The default writer is a simple wrapper for Writers that are not copiable
// The default writer is a simple wrapper for Writers that are not copyable
template <typename TDestination, typename Enable = void>
class Writer {
public:

View File

@@ -34,7 +34,7 @@ class FlashString {
return size_;
}
friend bool stringEquals(FlashString a, SizedRamString b) {
friend bool stringEquals(FlashString a, RamString b) {
ARDUINOJSON_ASSERT(a.typeSortKey < b.typeSortKey);
ARDUINOJSON_ASSERT(!a.isNull());
ARDUINOJSON_ASSERT(!b.isNull());
@@ -43,7 +43,7 @@ class FlashString {
return ::memcmp_P(b.data(), a.str_, a.size_) == 0;
}
friend int stringCompare(FlashString a, SizedRamString b) {
friend int stringCompare(FlashString a, RamString b) {
ARDUINOJSON_ASSERT(a.typeSortKey < b.typeSortKey);
ARDUINOJSON_ASSERT(!a.isNull());
ARDUINOJSON_ASSERT(!b.isNull());
@@ -63,7 +63,7 @@ class FlashString {
::memcpy_P(p, s.str_, n);
}
bool isLinked() const {
bool isStatic() const {
return false;
}

View File

@@ -1,35 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
#include <ArduinoJson/Strings/JsonString.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class JsonStringAdapter : public SizedRamString {
public:
JsonStringAdapter(const JsonString& s)
: SizedRamString(s.c_str(), s.size()), linked_(s.isLinked()) {}
bool isLinked() const {
return linked_;
}
private:
bool linked_;
};
template <>
struct StringAdapter<JsonString> {
using AdaptedString = JsonStringAdapter;
static AdaptedString adapt(const JsonString& s) {
return AdaptedString(s);
}
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -17,79 +17,19 @@ template <typename T>
struct IsChar
: integral_constant<bool, is_integral<T>::value && sizeof(T) == 1> {};
class ZeroTerminatedRamString {
public:
static const size_t typeSortKey = 3;
ZeroTerminatedRamString(const char* str) : str_(str) {}
bool isNull() const {
return !str_;
}
FORCE_INLINE size_t size() const {
return str_ ? ::strlen(str_) : 0;
}
char operator[](size_t i) const {
ARDUINOJSON_ASSERT(str_ != 0);
ARDUINOJSON_ASSERT(i <= size());
return str_[i];
}
const char* data() const {
return str_;
}
bool isLinked() const {
return false;
}
protected:
const char* str_;
};
template <typename TChar>
struct StringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
using AdaptedString = ZeroTerminatedRamString;
static AdaptedString adapt(const TChar* p) {
return AdaptedString(reinterpret_cast<const char*>(p));
}
};
template <typename TChar, size_t N>
struct StringAdapter<TChar[N], enable_if_t<IsChar<TChar>::value>> {
using AdaptedString = ZeroTerminatedRamString;
static AdaptedString adapt(const TChar* p) {
return AdaptedString(reinterpret_cast<const char*>(p));
}
};
class StaticStringAdapter : public ZeroTerminatedRamString {
public:
StaticStringAdapter(const char* str) : ZeroTerminatedRamString(str) {}
bool isLinked() const {
return true;
}
};
template <>
struct StringAdapter<const char*, void> {
using AdaptedString = StaticStringAdapter;
static AdaptedString adapt(const char* p) {
return AdaptedString(p);
}
};
class SizedRamString {
class RamString {
public:
static const size_t typeSortKey = 2;
#if ARDUINOJSON_SIZEOF_POINTER <= 2
static constexpr size_t sizeMask = size_t(-1) >> 1;
#else
static constexpr size_t sizeMask = size_t(-1);
#endif
SizedRamString(const char* str, size_t sz) : str_(str), size_(sz) {}
RamString(const char* str, size_t sz, bool isStatic = false)
: str_(str), size_(sz & sizeMask), static_(isStatic) {
ARDUINOJSON_ASSERT(size_ == sz);
}
bool isNull() const {
return !str_;
@@ -109,18 +49,55 @@ class SizedRamString {
return str_;
}
bool isLinked() const {
return false;
bool isStatic() const {
return static_;
}
protected:
const char* str_;
#if ARDUINOJSON_SIZEOF_POINTER <= 2
// Use a bitfield only on 8-bit microcontrollers
size_t size_ : sizeof(size_t) * 8 - 1;
bool static_ : 1;
#else
size_t size_;
bool static_;
#endif
};
template <typename TChar>
struct StringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
using AdaptedString = RamString;
static AdaptedString adapt(const TChar* p) {
auto str = reinterpret_cast<const char*>(p);
return AdaptedString(str, str ? ::strlen(str) : 0);
}
};
template <size_t N>
struct StringAdapter<const char (&)[N]> {
using AdaptedString = RamString;
static AdaptedString adapt(const char (&p)[N]) {
return RamString(p, N - 1, true);
}
};
template <typename TChar, size_t N>
struct StringAdapter<TChar[N], enable_if_t<IsChar<TChar>::value>> {
using AdaptedString = RamString;
static AdaptedString adapt(const TChar* p) {
auto str = reinterpret_cast<const char*>(p);
return AdaptedString(str, str ? ::strlen(str) : 0);
}
};
template <typename TChar>
struct SizedStringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
using AdaptedString = SizedRamString;
using AdaptedString = RamString;
static AdaptedString adapt(const TChar* p, size_t n) {
return AdaptedString(reinterpret_cast<const char*>(p), n);

View File

@@ -15,7 +15,7 @@ struct StringAdapter<
T,
enable_if_t<(string_traits<T>::has_cstr || string_traits<T>::has_data) &&
(string_traits<T>::has_length || string_traits<T>::has_size)>> {
using AdaptedString = SizedRamString;
using AdaptedString = RamString;
static AdaptedString adapt(const T& s) {
return AdaptedString(get_data(s), get_size(s));

View File

@@ -13,7 +13,7 @@ template <typename T, typename Enable = void>
struct IsString : false_type {};
template <typename T>
struct IsString<T, void_t<typename StringAdapter<T>::AdaptedString>>
struct IsString<T, void_t<typename StringAdapterFor<T>::AdaptedString>>
: true_type {};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -4,6 +4,9 @@
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
#if ARDUINOJSON_ENABLE_STD_STREAM
# include <ostream>
#endif
@@ -13,54 +16,58 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// A string.
// https://arduinojson.org/v7/api/jsonstring/
class JsonString {
friend struct detail::StringAdapter<JsonString>;
public:
enum Ownership { Copied, Linked };
JsonString() : str_(nullptr, 0, true) {}
JsonString() : data_(0), size_(0), ownership_(Linked) {}
JsonString(const char* data, bool isStatic = false)
: str_(data, data ? ::strlen(data) : 0, isStatic) {}
JsonString(const char* data, Ownership ownership = Linked)
: data_(data), size_(data ? ::strlen(data) : 0), ownership_(ownership) {}
JsonString(const char* data, size_t sz, Ownership ownership = Linked)
: data_(data), size_(sz), ownership_(ownership) {}
template <typename TSize,
detail::enable_if_t<detail::is_integral<TSize>::value &&
!detail::is_same<TSize, bool>::value,
int> = 0>
JsonString(const char* data, TSize sz, bool isStatic = false)
: str_(data, size_t(sz), isStatic) {}
// Returns a pointer to the characters.
const char* c_str() const {
return data_;
return str_.data();
}
// Returns true if the string is null.
bool isNull() const {
return !data_;
return str_.isNull();
}
// Returns true if the string is stored by address.
// Returns false if the string is stored by copy.
bool isLinked() const {
return ownership_ == Linked;
bool isStatic() const {
return str_.isStatic();
}
// Returns length of the string.
size_t size() const {
return size_;
return str_.size();
}
// Returns true if the string is non-null
explicit operator bool() const {
return data_ != 0;
return str_.data() != 0;
}
// Returns true if strings are equal.
friend bool operator==(JsonString lhs, JsonString rhs) {
if (lhs.size_ != rhs.size_)
if (lhs.size() != rhs.size())
return false;
if (lhs.data_ == rhs.data_)
if (lhs.c_str() == rhs.c_str())
return true;
if (!lhs.data_)
if (!lhs.c_str())
return false;
if (!rhs.data_)
if (!rhs.c_str())
return false;
return memcmp(lhs.data_, rhs.data_, lhs.size_) == 0;
return memcmp(lhs.c_str(), rhs.c_str(), lhs.size()) == 0;
}
// Returns true if strings differs.
@@ -76,9 +83,18 @@ class JsonString {
#endif
private:
const char* data_;
size_t size_;
Ownership ownership_;
detail::RamString str_;
};
namespace detail {
template <>
struct StringAdapter<JsonString> {
using AdaptedString = RamString;
static const AdaptedString& adapt(const JsonString& s) {
return s.str_;
}
};
} // namespace detail
ARDUINOJSON_END_PUBLIC_NAMESPACE

View File

@@ -4,8 +4,17 @@
#pragma once
#include <ArduinoJson/Polyfills/utility.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// a meta function that tells if the type is a string literal (const char[N])
template <typename T>
struct IsStringLiteral : false_type {};
template <size_t N>
struct IsStringLiteral<const char (&)[N]> : true_type {};
template <typename TString, typename Enable = void>
struct StringAdapter;
@@ -13,18 +22,25 @@ template <typename TString, typename Enable = void>
struct SizedStringAdapter;
template <typename TString>
typename StringAdapter<TString>::AdaptedString adaptString(const TString& s) {
return StringAdapter<TString>::adapt(s);
using StringAdapterFor =
StringAdapter<conditional_t<IsStringLiteral<TString>::value, TString,
remove_cv_t<remove_reference_t<TString>>>>;
template <typename T>
using AdaptedString = typename StringAdapterFor<T>::AdaptedString;
template <typename TString>
AdaptedString<TString> adaptString(TString&& s) {
return StringAdapterFor<TString>::adapt(detail::forward<TString>(s));
}
template <typename TChar>
typename StringAdapter<TChar*>::AdaptedString adaptString(TChar* p) {
template <typename TChar, enable_if_t<!is_const<TChar>::value, int> = 0>
AdaptedString<TChar*> adaptString(TChar* p) {
return StringAdapter<TChar*>::adapt(p);
}
template <typename TChar>
typename SizedStringAdapter<TChar*>::AdaptedString adaptString(TChar* p,
size_t n) {
AdaptedString<TChar*> adaptString(TChar* p, size_t n) {
return SizedStringAdapter<TChar*>::adapt(p, n);
}

View File

@@ -5,7 +5,6 @@
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/Adapters/JsonString.hpp>
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
#include <ArduinoJson/Strings/Adapters/StringObject.hpp>

View File

@@ -31,7 +31,7 @@ struct Converter {
// clang-format on
}
static T fromJson(JsonVariantConst src) {
static detail::decay_t<T> fromJson(JsonVariantConst src) {
static_assert(!detail::is_same<T, char*>::value,
"type 'char*' is not supported, use 'const char*' instead");
@@ -178,7 +178,7 @@ struct Converter<JsonString> : private detail::VariantAttorney {
static JsonString fromJson(JsonVariantConst src) {
auto data = getData(src);
return data ? data->asString() : 0;
return data ? data->asString() : JsonString();
}
static bool checkJson(JsonVariantConst src) {

View File

@@ -68,27 +68,29 @@ class JsonVariantConst : public detail::VariantTag,
// Casts the value to the specified type.
// https://arduinojson.org/v7/api/jsonvariantconst/as/
template <typename T,
detail::enable_if_t<ConversionSupported<T>::value, bool> = true>
detail::enable_if_t<ConversionSupported<T>::value, int> = 0>
T as() const {
return Converter<T>::fromJson(*this);
}
// Invalid conversion. Will not compile.
template <typename T,
detail::enable_if_t<!ConversionSupported<T>::value, bool> = true>
detail::enable_if_t<!ConversionSupported<T>::value, int> = 0>
detail::InvalidConversion<JsonVariantConst, T> as() const;
// Returns true if the value is of the specified type.
// https://arduinojson.org/v7/api/jsonvariantconst/is/
template <typename T>
detail::enable_if_t<ConversionSupported<T>::value, bool> is() const {
template <typename T,
detail::enable_if_t<ConversionSupported<T>::value, int> = 0>
bool is() const {
return Converter<T>::checkJson(*this);
}
// Always returns false for the unsupported types.
// https://arduinojson.org/v7/api/jsonvariantconst/is/
template <typename T>
detail::enable_if_t<!ConversionSupported<T>::value, bool> is() const {
template <typename T,
detail::enable_if_t<!ConversionSupported<T>::value, int> = 0>
bool is() const {
return false;
}
@@ -99,9 +101,9 @@ class JsonVariantConst : public detail::VariantTag,
// Gets array's element at specified index.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
operator[](T index) const {
template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
JsonVariantConst operator[](T index) const {
return JsonVariantConst(
detail::VariantData::getElement(data_, size_t(index), resources_),
resources_);
@@ -109,9 +111,9 @@ class JsonVariantConst : public detail::VariantTag,
// Gets object's member with specified key.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
operator[](const TString& key) const {
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
JsonVariantConst operator[](const TString& key) const {
return JsonVariantConst(detail::VariantData::getMember(
data_, detail::adaptString(key), resources_),
resources_);
@@ -119,9 +121,11 @@ class JsonVariantConst : public detail::VariantTag,
// Gets object's member with specified key.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename TChar>
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
operator[](TChar* key) const {
template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
JsonVariantConst operator[](TChar* key) const {
return JsonVariantConst(detail::VariantData::getMember(
data_, detail::adaptString(key), resources_),
resources_);
@@ -130,9 +134,9 @@ class JsonVariantConst : public detail::VariantTag,
// Gets object's member with specified key or the array's element at the
// specified index.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
operator[](const TVariant& key) const {
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
JsonVariantConst operator[](const TVariant& key) const {
if (key.template is<size_t>())
return operator[](key.template as<size_t>());
else
@@ -141,30 +145,32 @@ class JsonVariantConst : public detail::VariantTag,
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/
template <typename TString>
template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use var[key].is<T>() instead")
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
const TString& key) const {
bool containsKey(const TString& key) const {
return detail::VariantData::getMember(getData(), detail::adaptString(key),
resources_) != 0;
}
// DEPRECATED: use obj["key"].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/
template <typename TChar>
template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
detail::enable_if_t<detail::IsString<TChar*>::value, bool> containsKey(
TChar* key) const {
bool containsKey(TChar* key) const {
return detail::VariantData::getMember(getData(), detail::adaptString(key),
resources_) != 0;
}
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/
template <typename TVariant>
template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use var[key].is<T>() instead")
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const {
bool containsKey(const TVariant& key) const {
return containsKey(key.template as<const char*>());
}

View File

@@ -64,12 +64,11 @@ class VariantData {
return visit.visit(content_.asObject);
case VariantType::LinkedString:
return visit.visit(JsonString(content_.asLinkedString));
return visit.visit(JsonString(content_.asLinkedString, true));
case VariantType::OwnedString:
return visit.visit(JsonString(content_.asOwnedString->data,
content_.asOwnedString->length,
JsonString::Copied));
content_.asOwnedString->length));
case VariantType::RawString:
return visit.visit(RawString(content_.asOwnedString->data,
@@ -119,14 +118,13 @@ class VariantData {
}
template <typename T>
bool addValue(T&& value, ResourceManager* resources) {
bool addValue(const T& value, ResourceManager* resources) {
auto array = isNull() ? &toArray() : asArray();
return detail::ArrayData::addValue(array, detail::forward<T>(value),
resources);
return detail::ArrayData::addValue(array, value, resources);
}
template <typename T>
static bool addValue(VariantData* var, T&& value,
static bool addValue(VariantData* var, const T& value,
ResourceManager* resources) {
if (!var)
return false;
@@ -262,7 +260,7 @@ class VariantData {
switch (type_) {
case VariantType::RawString:
return JsonString(content_.asOwnedString->data,
content_.asOwnedString->length, JsonString::Copied);
content_.asOwnedString->length);
default:
return JsonString();
}
@@ -271,10 +269,10 @@ class VariantData {
JsonString asString() const {
switch (type_) {
case VariantType::LinkedString:
return JsonString(content_.asLinkedString, JsonString::Linked);
return JsonString(content_.asLinkedString, true);
case VariantType::OwnedString:
return JsonString(content_.asOwnedString->data,
content_.asOwnedString->length, JsonString::Copied);
content_.asOwnedString->length);
default:
return JsonString();
}

View File

@@ -26,7 +26,7 @@ inline bool VariantData::setString(TAdaptedString value,
if (value.isNull())
return false;
if (value.isLinked()) {
if (value.isStatic()) {
setLinkedString(value.data());
return true;
}

View File

@@ -30,9 +30,9 @@ struct VariantOperators : VariantOperatorTag {
// int operator|(JsonVariant, int)
// float operator|(JsonVariant, float)
// bool operator|(JsonVariant, bool)
template <typename T>
friend enable_if_t<!IsVariant<T>::value && !is_array<T>::value, T> operator|(
const TVariant& variant, const T& defaultValue) {
template <typename T,
enable_if_t<!IsVariant<T>::value && !is_array<T>::value, int> = 0>
friend T operator|(const TVariant& variant, const T& defaultValue) {
if (variant.template is<T>())
return variant.template as<T>();
else
@@ -51,7 +51,7 @@ struct VariantOperators : VariantOperatorTag {
// JsonVariant operator|(JsonVariant, JsonVariant)
template <typename T>
friend enable_if_t<IsVariant<T>::value, JsonVariantConst> operator|(
const TVariant& variant, T defaultValue) {
const TVariant& variant, const T& defaultValue) {
if (variant)
return variant;
else
@@ -60,127 +60,127 @@ struct VariantOperators : VariantOperatorTag {
// value == TVariant
template <typename T>
friend bool operator==(T* lhs, TVariant rhs) {
friend bool operator==(T* lhs, const TVariant& rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend bool operator==(const T& lhs, TVariant rhs) {
friend bool operator==(const T& lhs, const TVariant& rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
}
// TVariant == value
template <typename T>
friend bool operator==(TVariant lhs, T* rhs) {
friend bool operator==(const TVariant& lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
operator==(TVariant lhs, const T& rhs) {
template <typename T,
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
friend bool operator==(const TVariant& lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
// value != TVariant
template <typename T>
friend bool operator!=(T* lhs, TVariant rhs) {
friend bool operator!=(T* lhs, const TVariant& rhs) {
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend bool operator!=(const T& lhs, TVariant rhs) {
friend bool operator!=(const T& lhs, const TVariant& rhs) {
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
}
// TVariant != value
template <typename T>
friend bool operator!=(TVariant lhs, T* rhs) {
friend bool operator!=(const TVariant& lhs, T* rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
operator!=(TVariant lhs, const T& rhs) {
template <typename T,
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
friend bool operator!=(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
// value < TVariant
template <typename T>
friend bool operator<(T* lhs, TVariant rhs) {
friend bool operator<(T* lhs, const TVariant& rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend bool operator<(const T& lhs, TVariant rhs) {
friend bool operator<(const T& lhs, const TVariant& rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
}
// TVariant < value
template <typename T>
friend bool operator<(TVariant lhs, T* rhs) {
friend bool operator<(const TVariant& lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> operator<(
TVariant lhs, const T& rhs) {
template <typename T,
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
friend bool operator<(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
// value <= TVariant
template <typename T>
friend bool operator<=(T* lhs, TVariant rhs) {
friend bool operator<=(T* lhs, const TVariant& rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator<=(const T& lhs, TVariant rhs) {
friend bool operator<=(const T& lhs, const TVariant& rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
// TVariant <= value
template <typename T>
friend bool operator<=(TVariant lhs, T* rhs) {
friend bool operator<=(const TVariant& lhs, T* rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
operator<=(TVariant lhs, const T& rhs) {
template <typename T,
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
friend bool operator<=(TVariant lhs, const T& rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
// value > TVariant
template <typename T>
friend bool operator>(T* lhs, TVariant rhs) {
friend bool operator>(T* lhs, const TVariant& rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend bool operator>(const T& lhs, TVariant rhs) {
friend bool operator>(const T& lhs, const TVariant& rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
}
// TVariant > value
template <typename T>
friend bool operator>(TVariant lhs, T* rhs) {
friend bool operator>(const TVariant& lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> operator>(
TVariant lhs, const T& rhs) {
template <typename T,
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
friend bool operator>(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
// value >= TVariant
template <typename T>
friend bool operator>=(T* lhs, TVariant rhs) {
friend bool operator>=(T* lhs, const TVariant& rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator>=(const T& lhs, TVariant rhs) {
friend bool operator>=(const T& lhs, const TVariant& rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
// TVariant >= value
template <typename T>
friend bool operator>=(TVariant lhs, T* rhs) {
friend bool operator>=(const TVariant& lhs, T* rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
operator>=(TVariant lhs, const T& rhs) {
template <typename T,
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
friend bool operator>=(const TVariant& lhs, const T& rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
};

View File

@@ -48,25 +48,25 @@ class VariantRefBase : public VariantTag {
template <typename T>
T as() const;
template <typename T, typename = enable_if_t<!is_same<T, TDerived>::value>>
template <typename T, enable_if_t<!is_same<T, TDerived>::value, int> = 0>
operator T() const {
return as<T>();
}
// Sets the value to an empty array.
// https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T>
enable_if_t<is_same<T, JsonArray>::value, JsonArray> to() const;
template <typename T, enable_if_t<is_same<T, JsonArray>::value, int> = 0>
JsonArray to() const;
// Sets the value to an empty object.
// https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T>
enable_if_t<is_same<T, JsonObject>::value, JsonObject> to() const;
template <typename T, enable_if_t<is_same<T, JsonObject>::value, int> = 0>
JsonObject to() const;
// Sets the value to null.
// https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T>
enable_if_t<is_same<T, JsonVariant>::value, JsonVariant> to() const;
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int> = 0>
JsonVariant to() const;
// Returns true if the value is of the specified type.
// https://arduinojson.org/v7/api/jsonvariant/is/
@@ -77,12 +77,15 @@ class VariantRefBase : public VariantTag {
// https://arduinojson.org/v7/api/jsonvariant/set/
template <typename T>
bool set(const T& value) const {
return doSet<Converter<remove_cv_t<T>>>(value);
using TypeForConverter = conditional_t<IsStringLiteral<T>::value, T,
remove_cv_t<remove_reference_t<T>>>;
return doSet<Converter<TypeForConverter>>(value);
}
// Copies the specified value.
// https://arduinojson.org/v7/api/jsonvariant/set/
template <typename T>
template <typename T,
detail::enable_if_t<!detail::is_const<T>::value, int> = 0>
bool set(T* value) const {
return doSet<Converter<T*>>(value);
}
@@ -102,16 +105,16 @@ class VariantRefBase : public VariantTag {
// Appends a new (empty) element to the array.
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T>
enable_if_t<!is_same<T, JsonVariant>::value, T> add() const {
template <typename T, enable_if_t<!is_same<T, JsonVariant>::value, int> = 0>
T add() const {
return add<JsonVariant>().template to<T>();
}
// Appends a new (null) element to the array.
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T>
enable_if_t<is_same<T, JsonVariant>::value, T> add() const;
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int> = 0>
T add() const;
// Appends a value to the array.
// https://arduinojson.org/v7/api/jsonvariant/add/
@@ -123,7 +126,7 @@ class VariantRefBase : public VariantTag {
// Appends a value to the array.
// https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T>
template <typename T, enable_if_t<!is_const<T>::value, int> = 0>
bool add(T* value) const {
return detail::VariantData::addValue(getOrCreateData(), value,
getResourceManager());
@@ -137,24 +140,24 @@ class VariantRefBase : public VariantTag {
// Removes a member of the object.
// https://arduinojson.org/v7/api/jsonvariant/remove/
template <typename TChar>
enable_if_t<IsString<TChar*>::value> remove(TChar* key) const {
template <typename TChar, enable_if_t<IsString<TChar*>::value, int> = 0>
void remove(TChar* key) const {
VariantData::removeMember(getData(), adaptString(key),
getResourceManager());
}
// Removes a member of the object.
// https://arduinojson.org/v7/api/jsonvariant/remove/
template <typename TString>
enable_if_t<IsString<TString>::value> remove(const TString& key) const {
template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
void remove(const TString& key) const {
VariantData::removeMember(getData(), adaptString(key),
getResourceManager());
}
// Removes a member of the object or an element of the array.
// https://arduinojson.org/v7/api/jsonvariant/remove/
template <typename TVariant>
enable_if_t<IsVariant<TVariant>::value> remove(const TVariant& key) const {
template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
void remove(const TVariant& key) const {
if (key.template is<size_t>())
remove(key.template as<size_t>());
else
@@ -167,43 +170,40 @@ class VariantRefBase : public VariantTag {
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TString>
template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
enable_if_t<IsString<TString>::value, bool> containsKey(
const TString& key) const;
bool containsKey(const TString& key) const;
// DEPRECATED: use obj["key"].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TChar>
template <typename TChar, enable_if_t<IsString<TChar*>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
enable_if_t<IsString<TChar*>::value, bool> containsKey(TChar* key) const;
bool containsKey(TChar* key) const;
// DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TVariant>
template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
enable_if_t<IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const;
bool containsKey(const TVariant& key) const;
// Gets or sets an object member.
// https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TString>
FORCE_INLINE
enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
operator[](const TString& key) const;
template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
FORCE_INLINE MemberProxy<TDerived, AdaptedString<TString>> operator[](
const TString& key) const;
// Gets or sets an object member.
// https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TChar>
FORCE_INLINE
enable_if_t<IsString<TChar*>::value, MemberProxy<TDerived, TChar*>>
operator[](TChar* key) const;
template <
typename TChar,
enable_if_t<IsString<TChar*>::value && !is_const<TChar>::value, int> = 0>
FORCE_INLINE MemberProxy<TDerived, AdaptedString<TChar*>> operator[](
TChar* key) const;
// Gets an object member or an array element.
// https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TVariant>
enable_if_t<IsVariant<TVariant>::value, JsonVariantConst> operator[](
const TVariant& key) const {
template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
JsonVariantConst operator[](const TVariant& key) const {
if (key.template is<size_t>())
return operator[](key.template as<size_t>());
else
@@ -294,19 +294,18 @@ class VariantRefBase : public VariantTag {
}
template <typename TConverter, typename T>
bool doSet(T&& value) const {
bool doSet(const T& value) const {
return doSet<TConverter>(
detail::forward<T>(value),
is_same<typename function_traits<
decltype(&TConverter::toJson)>::return_type,
bool>{});
value, is_same<typename function_traits<
decltype(&TConverter::toJson)>::return_type,
bool>{});
}
template <typename TConverter, typename T>
bool doSet(T&& value, false_type) const;
bool doSet(const T& value, false_type) const;
template <typename TConverter, typename T>
bool doSet(T&& value, true_type) const;
bool doSet(const T& value, true_type) const;
ArduinoJson::JsonVariant getOrCreateVariant() const;
};

View File

@@ -67,34 +67,30 @@ inline void convertToJson(const VariantRefBase<TDerived>& src,
}
template <typename TDerived>
template <typename T>
inline enable_if_t<is_same<T, JsonVariant>::value, T>
VariantRefBase<TDerived>::add() const {
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int>>
inline T VariantRefBase<TDerived>::add() const {
return JsonVariant(
detail::VariantData::addElement(getOrCreateData(), getResourceManager()),
getResourceManager());
}
template <typename TDerived>
template <typename TString>
inline enable_if_t<IsString<TString>::value, bool>
VariantRefBase<TDerived>::containsKey(const TString& key) const {
template <typename TString, enable_if_t<IsString<TString>::value, int>>
inline bool VariantRefBase<TDerived>::containsKey(const TString& key) const {
return VariantData::getMember(getData(), adaptString(key),
getResourceManager()) != 0;
}
template <typename TDerived>
template <typename TChar>
inline enable_if_t<IsString<TChar*>::value, bool>
VariantRefBase<TDerived>::containsKey(TChar* key) const {
template <typename TChar, enable_if_t<IsString<TChar*>::value, int>>
inline bool VariantRefBase<TDerived>::containsKey(TChar* key) const {
return VariantData::getMember(getData(), adaptString(key),
getResourceManager()) != 0;
}
template <typename TDerived>
template <typename TVariant>
inline enable_if_t<IsVariant<TVariant>::value, bool>
VariantRefBase<TDerived>::containsKey(const TVariant& key) const {
template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int>>
inline bool VariantRefBase<TDerived>::containsKey(const TVariant& key) const {
return containsKey(key.template as<const char*>());
}
@@ -119,26 +115,27 @@ inline bool VariantRefBase<TDerived>::is() const {
template <typename TDerived>
inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
size_t index) const {
return ElementProxy<TDerived>(derived(), index);
return {derived(), index};
}
template <typename TDerived>
template <typename TString>
inline enable_if_t<IsString<TString*>::value, MemberProxy<TDerived, TString*>>
VariantRefBase<TDerived>::operator[](TString* key) const {
return MemberProxy<TDerived, TString*>(derived(), key);
template <typename TChar,
enable_if_t<IsString<TChar*>::value && !is_const<TChar>::value, int>>
inline MemberProxy<TDerived, AdaptedString<TChar*>>
VariantRefBase<TDerived>::operator[](TChar* key) const {
return {derived(), adaptString(key)};
}
template <typename TDerived>
template <typename TString>
inline enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
template <typename TString, enable_if_t<IsString<TString>::value, int>>
inline MemberProxy<TDerived, AdaptedString<TString>>
VariantRefBase<TDerived>::operator[](const TString& key) const {
return MemberProxy<TDerived, TString>(derived(), key);
return {derived(), adaptString(key)};
}
template <typename TDerived>
template <typename TConverter, typename T>
inline bool VariantRefBase<TDerived>::doSet(T&& value, false_type) const {
inline bool VariantRefBase<TDerived>::doSet(const T& value, false_type) const {
TConverter::toJson(value, getOrCreateVariant());
auto resources = getResourceManager();
return resources && !resources->overflowed();
@@ -146,32 +143,29 @@ inline bool VariantRefBase<TDerived>::doSet(T&& value, false_type) const {
template <typename TDerived>
template <typename TConverter, typename T>
inline bool VariantRefBase<TDerived>::doSet(T&& value, true_type) const {
inline bool VariantRefBase<TDerived>::doSet(const T& value, true_type) const {
return TConverter::toJson(value, getOrCreateVariant());
}
template <typename TDerived>
template <typename T>
inline enable_if_t<is_same<T, JsonArray>::value, JsonArray>
VariantRefBase<TDerived>::to() const {
template <typename T, enable_if_t<is_same<T, JsonArray>::value, int>>
inline JsonArray VariantRefBase<TDerived>::to() const {
return JsonArray(
VariantData::toArray(getOrCreateData(), getResourceManager()),
getResourceManager());
}
template <typename TDerived>
template <typename T>
enable_if_t<is_same<T, JsonObject>::value, JsonObject>
VariantRefBase<TDerived>::to() const {
template <typename T, enable_if_t<is_same<T, JsonObject>::value, int>>
JsonObject VariantRefBase<TDerived>::to() const {
return JsonObject(
VariantData::toObject(getOrCreateData(), getResourceManager()),
getResourceManager());
}
template <typename TDerived>
template <typename T>
enable_if_t<is_same<T, JsonVariant>::value, JsonVariant>
VariantRefBase<TDerived>::to() const {
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int>>
JsonVariant VariantRefBase<TDerived>::to() const {
auto data = getOrCreateData();
auto resources = getResourceManager();
detail::VariantData::clear(data, resources);

View File

@@ -1,86 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Polyfills/limits.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantContent.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
struct StringNode;
class VariantSlot {
// CAUTION: same layout as VariantData
// we cannot use composition because it adds padding
// (+20% on ESP8266 for example)
VariantContent content_;
uint8_t flags_;
SlotId next_;
const char* key_;
public:
// Placement new
static void* operator new(size_t, void* p) noexcept {
return p;
}
static void operator delete(void*, void*) noexcept {}
VariantSlot() : flags_(0), next_(NULL_SLOT), key_(0) {}
VariantData* data() {
return reinterpret_cast<VariantData*>(&content_);
}
const VariantData* data() const {
return reinterpret_cast<const VariantData*>(&content_);
}
SlotId next() const {
return next_;
}
void setNext(SlotId slot) {
next_ = slot;
}
void setKey(const char* k) {
ARDUINOJSON_ASSERT(k);
flags_ &= VALUE_MASK;
key_ = k;
}
void setKey(StringNode* k) {
ARDUINOJSON_ASSERT(k);
flags_ |= OWNED_KEY_BIT;
key_ = k->data;
}
const char* key() const {
return key_;
}
bool ownsKey() const {
return (flags_ & OWNED_KEY_BIT) != 0;
}
};
inline VariantData* slotData(VariantSlot* slot) {
return reinterpret_cast<VariantData*>(slot);
}
// Returns the size (in bytes) of an array with n elements.
constexpr size_t sizeofArray(size_t n) {
return n * sizeof(VariantSlot);
}
// Returns the size (in bytes) of an object with n members.
constexpr size_t sizeofObject(size_t n) {
return n * sizeof(VariantSlot);
}
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -4,8 +4,8 @@
#pragma once
#define ARDUINOJSON_VERSION "7.2.1"
#define ARDUINOJSON_VERSION "7.3.0"
#define ARDUINOJSON_VERSION_MAJOR 7
#define ARDUINOJSON_VERSION_MINOR 2
#define ARDUINOJSON_VERSION_REVISION 1
#define ARDUINOJSON_VERSION_MACRO V721
#define ARDUINOJSON_VERSION_MINOR 3
#define ARDUINOJSON_VERSION_REVISION 0
#define ARDUINOJSON_VERSION_MACRO V730