Update ArduinoJSON, esp-nimble-cpp, Arduino Core, ESP-IDF (#448)

* ArduinoJSON 7.1.0

* Update nimble and arduino core

* Update nuki_ble
This commit is contained in:
iranl
2024-08-11 11:20:31 +02:00
committed by GitHub
parent 4af90cbc79
commit 9d55c2173d
216 changed files with 6437 additions and 5705 deletions

View File

@@ -36,6 +36,7 @@
#include "ArduinoJson/Array/ElementProxy.hpp"
#include "ArduinoJson/Array/Utilities.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Memory/ResourceManagerImpl.hpp"
#include "ArduinoJson/Memory/VariantPoolImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp"
@@ -47,7 +48,9 @@
#include "ArduinoJson/Json/JsonDeserializer.hpp"
#include "ArduinoJson/Json/JsonSerializer.hpp"
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackBinary.hpp"
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackExtension.hpp"
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
#include "ArduinoJson/compatibility.hpp"

View File

@@ -20,6 +20,17 @@ class ArrayData : public CollectionData {
return array->addElement(resources);
}
template <typename T>
bool addValue(T&& value, ResourceManager* resources);
template <typename T>
static bool addValue(ArrayData* array, T&& value,
ResourceManager* resources) {
if (!array)
return false;
return array->addValue(value, resources);
}
VariantData* getOrAddElement(size_t index, ResourceManager* resources);
VariantData* getElement(size_t index, const ResourceManager* resources) const;

View File

@@ -47,4 +47,19 @@ inline void ArrayData::removeElement(size_t index, ResourceManager* resources) {
remove(at(index, resources), resources);
}
template <typename T>
inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
ARDUINOJSON_ASSERT(resources != nullptr);
auto slot = resources->allocSlot();
if (!slot)
return false;
JsonVariant variant(slot->data(), resources);
if (!variant.set(detail::forward<T>(value))) {
resources->freeSlot(slot);
return false;
}
addSlot(slot, resources);
return true;
}
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -44,8 +44,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonarray/add/
template <typename T>
typename detail::enable_if<!detail::is_same<T, JsonVariant>::value, T>::type
add() const {
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() const {
return add<JsonVariant>().to<T>();
}
@@ -53,8 +52,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonarray/add/
template <typename T>
typename detail::enable_if<detail::is_same<T, JsonVariant>::value, T>::type
add() const {
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() const {
return JsonVariant(detail::ArrayData::addElement(data_, resources_),
resources_);
}
@@ -63,14 +61,14 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// https://arduinojson.org/v7/api/jsonarray/add/
template <typename T>
bool add(const T& value) const {
return add<JsonVariant>().set(value);
return detail::ArrayData::addValue(data_, value, resources_);
}
// Appends a value to the array.
// https://arduinojson.org/v7/api/jsonarray/add/
template <typename T>
bool add(T* value) const {
return add<JsonVariant>().set(value);
return detail::ArrayData::addValue(data_, value, resources_);
}
// Returns an iterator to the first element of the array.
@@ -114,6 +112,15 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
detail::ArrayData::removeElement(data_, index, resources_);
}
// Removes the element at the specified index.
// https://arduinojson.org/v7/api/jsonarray/remove/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove(
TVariant variant) const {
if (variant.template is<size_t>())
remove(variant.template as<size_t>());
}
// Removes all the elements of the array.
// https://arduinojson.org/v7/api/jsonarray/clear/
void clear() const {
@@ -122,8 +129,23 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Gets or sets the element at the specified index.
// https://arduinojson.org/v7/api/jsonarray/subscript/
detail::ElementProxy<JsonArray> operator[](size_t index) const {
return {*this, index};
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value,
detail::ElementProxy<JsonArray>>
operator[](T index) const {
return {*this, size_t(index)};
}
// Gets or sets the element at the specified index.
// https://arduinojson.org/v7/api/jsonarray/subscript/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value,
detail::ElementProxy<JsonArray>>
operator[](const TVariant& variant) const {
if (variant.template is<size_t>())
return operator[](variant.template as<size_t>());
else
return {*this, size_t(-1)};
}
operator JsonVariantConst() const {

View File

@@ -36,7 +36,7 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
}
// Creates an unbound reference.
JsonArrayConst() : data_(0) {}
JsonArrayConst() : data_(0), resources_(0) {}
// INTERNAL USE ONLY
JsonArrayConst(const detail::ArrayData* data,
@@ -45,9 +45,23 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
// Returns the element at the specified index.
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
JsonVariantConst operator[](size_t index) const {
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
operator[](T index) const {
return JsonVariantConst(
detail::ArrayData::getElement(data_, index, resources_), resources_);
detail::ArrayData::getElement(data_, size_t(index), resources_),
resources_);
}
// Returns the element at the specified index.
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
operator[](const TVariant& variant) const {
if (variant.template is<size_t>())
return operator[](variant.template as<size_t>());
else
return JsonVariantConst();
}
operator JsonVariantConst() const {

View File

@@ -12,16 +12,16 @@ 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 typename detail::enable_if<!detail::is_array<T>::value, bool>::type
copyArray(const T& src, JsonVariant dst) {
inline detail::enable_if_t<!detail::is_array<T>::value, 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 typename detail::enable_if<
!detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
inline detail::enable_if_t<
!detail::is_base_of<JsonDocument, TDestination>::value, bool>
copyArray(T (&src)[N], const TDestination& dst) {
return copyArray(src, N, dst);
}
@@ -29,8 +29,8 @@ copyArray(T (&src)[N], const TDestination& dst) {
// Copies values from an array to a JsonArray or a JsonVariant.
// https://arduinojson.org/v7/api/misc/copyarray/
template <typename T, typename TDestination>
inline typename detail::enable_if<
!detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
inline detail::enable_if_t<
!detail::is_base_of<JsonDocument, TDestination>::value, bool>
copyArray(const T* src, size_t len, const TDestination& dst) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
@@ -63,8 +63,8 @@ inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
// Copies a value from a JsonVariant.
// This is a degenerated form of copyArray() to stop the recursion.
template <typename T>
inline typename detail::enable_if<!detail::is_array<T>::value, size_t>::type
copyArray(JsonVariantConst src, T& dst) {
inline detail::enable_if_t<!detail::is_array<T>::value, size_t> copyArray(
JsonVariantConst src, T& dst) {
dst = src.as<T>();
return 1;
}
@@ -103,10 +103,9 @@ 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 typename detail::enable_if<
detail::is_array<T>::value &&
detail::is_base_of<JsonDocument, TSource>::value,
size_t>::type
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) {
return copyArray(src.template as<JsonArrayConst>(), dst);
}

View File

@@ -111,12 +111,13 @@ class CollectionData {
return head_;
}
void addSlot(SlotWithId slot, ResourceManager* resources);
protected:
iterator addSlot(ResourceManager*);
private:
SlotWithId getPreviousSlot(VariantSlot*, const ResourceManager*) const;
void releaseSlot(SlotWithId, ResourceManager*);
};
inline const VariantData* collectionToVariant(

View File

@@ -63,13 +63,25 @@ inline CollectionData::iterator CollectionData::addSlot(
return iterator(slot, slot.id());
}
inline void CollectionData::addSlot(SlotWithId slot,
ResourceManager* resources) {
if (tail_ != NULL_SLOT) {
auto tail = resources->getSlot(tail_);
tail->setNext(slot.id());
tail_ = slot.id();
} else {
head_ = slot.id();
tail_ = slot.id();
}
}
inline void CollectionData::clear(ResourceManager* resources) {
auto next = head_;
while (next != NULL_SLOT) {
auto currId = next;
auto slot = resources->getSlot(next);
next = slot->next();
releaseSlot(SlotWithId(slot, currId), resources);
resources->freeSlot(SlotWithId(slot, currId));
}
head_ = NULL_SLOT;
@@ -102,7 +114,7 @@ inline void CollectionData::remove(iterator it, ResourceManager* resources) {
head_ = next;
if (next == NULL_SLOT)
tail_ = prev.id();
releaseSlot({it.slot_, it.currentId_}, resources);
resources->freeSlot({it.slot_, it.currentId_});
}
inline size_t CollectionData::nesting(const ResourceManager* resources) const {
@@ -122,12 +134,4 @@ inline size_t CollectionData::size(const ResourceManager* resources) const {
return count;
}
inline void CollectionData::releaseSlot(SlotWithId slot,
ResourceManager* resources) {
if (slot->ownsKey())
resources->dereferenceString(slot->key());
slot->data()->setNull(resources);
resources->freeSlot(slot);
}
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -93,11 +93,14 @@
// https://arduinojson.org/v7/config/slot_id_size/
#ifndef ARDUINOJSON_SLOT_ID_SIZE
# if ARDUINOJSON_SIZEOF_POINTER <= 2
# define ARDUINOJSON_SLOT_ID_SIZE 1 // up to 255 slots
// 8-bit and 16-bit archs => up to 255 slots
# define ARDUINOJSON_SLOT_ID_SIZE 1
# elif ARDUINOJSON_SIZEOF_POINTER == 4
# define ARDUINOJSON_SLOT_ID_SIZE 2 // up to 65535 slots
// 32-bit arch => up to 65535 slots
# define ARDUINOJSON_SLOT_ID_SIZE 2
# else
# define ARDUINOJSON_SLOT_ID_SIZE 4 // up to 4294967295 slots
// 64-bit arch => up to 4294967295 slots
# define ARDUINOJSON_SLOT_ID_SIZE 4
# endif
#endif

View File

@@ -62,9 +62,8 @@ ARDUINOJSON_END_PRIVATE_NAMESPACE
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TInput>
Reader<typename remove_reference<TInput>::type> makeReader(TInput&& input) {
return Reader<typename remove_reference<TInput>::type>{
detail::forward<TInput>(input)};
Reader<remove_reference_t<TInput>> makeReader(TInput&& input) {
return Reader<remove_reference_t<TInput>>{detail::forward<TInput>(input)};
}
template <typename TChar>

View File

@@ -9,8 +9,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TSource>
struct Reader<TSource,
typename enable_if<is_base_of<Stream, TSource>::value>::type> {
struct Reader<TSource, enable_if_t<is_base_of<Stream, TSource>::value>> {
public:
explicit Reader(Stream& stream) : stream_(&stream) {}

View File

@@ -9,8 +9,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TSource>
struct Reader<TSource,
typename enable_if<is_base_of<::String, TSource>::value>::type>
struct Reader<TSource, enable_if_t<is_base_of<::String, TSource>::value>>
: BoundedReader<const char*> {
explicit Reader(const ::String& s)
: BoundedReader<const char*>(s.c_str(), s.length()) {}

View File

@@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TIterator>
@@ -29,13 +31,8 @@ class IteratorReader {
}
};
template <typename T>
struct void_ {
typedef void type;
};
template <typename TSource>
struct Reader<TSource, typename void_<typename TSource::const_iterator>::type>
struct Reader<TSource, void_t<typename TSource::const_iterator>>
: IteratorReader<typename TSource::const_iterator> {
explicit Reader(const TSource& source)
: IteratorReader<typename TSource::const_iterator>(source.begin(),

View File

@@ -19,8 +19,7 @@ template <typename T>
struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
template <typename TSource>
struct Reader<TSource*,
typename enable_if<IsCharOrVoid<TSource>::value>::type> {
struct Reader<TSource*, enable_if_t<IsCharOrVoid<TSource>::value>> {
const char* ptr_;
public:
@@ -39,8 +38,7 @@ struct Reader<TSource*,
};
template <typename TSource>
struct BoundedReader<TSource*,
typename enable_if<IsCharOrVoid<TSource>::value>::type>
struct BoundedReader<TSource*, enable_if_t<IsCharOrVoid<TSource>::value>>
: public IteratorReader<const char*> {
public:
explicit BoundedReader(const void* ptr, size_t len)

View File

@@ -9,8 +9,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TSource>
struct Reader<TSource, typename enable_if<
is_base_of<std::istream, TSource>::value>::type> {
struct Reader<TSource, enable_if_t<is_base_of<std::istream, TSource>::value>> {
public:
explicit Reader(std::istream& stream) : stream_(&stream) {}

View File

@@ -10,7 +10,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TVariant>
struct Reader<TVariant, typename enable_if<IsVariant<TVariant>::value>::type>
struct Reader<TVariant, enable_if_t<IsVariant<TVariant>::value>>
: Reader<char*, void> {
explicit Reader(const TVariant& x)
: Reader<char*, void>(x.template as<const char*>()) {}

View File

@@ -29,10 +29,9 @@ struct is_deserialize_destination : false_type {};
template <class T>
struct is_deserialize_destination<
T, typename enable_if<is_same<decltype(VariantAttorney::getResourceManager(
detail::declval<T&>())),
ResourceManager*>::value>::type> : true_type {
};
T, enable_if_t<is_same<decltype(VariantAttorney::getResourceManager(
detail::declval<T&>())),
ResourceManager*>::value>> : true_type {};
template <typename TDestination>
inline void shrinkJsonDocument(TDestination&) {
@@ -62,8 +61,8 @@ DeserializationError doDeserialize(TDestination&& dst, TReader reader,
template <template <typename> class TDeserializer, typename TDestination,
typename TStream, typename... Args,
typename = typename enable_if< // issue #1897
!is_integral<typename first_or_void<Args...>::type>::value>::type>
typename = enable_if_t< // issue #1897
!is_integral<typename first_or_void<Args...>::type>::value>>
DeserializationError deserialize(TDestination&& dst, TStream&& input,
Args... args) {
return doDeserialize<TDeserializer>(
@@ -73,7 +72,7 @@ DeserializationError deserialize(TDestination&& dst, TStream&& input,
template <template <typename> class TDeserializer, typename TDestination,
typename TChar, typename Size, typename... Args,
typename = typename enable_if<is_integral<Size>::value>::type>
typename = enable_if_t<is_integral<Size>::value>>
DeserializationError deserialize(TDestination&& dst, TChar* input,
Size inputSize, Args... args) {
return doDeserialize<TDeserializer>(dst, makeReader(input, size_t(inputSize)),

View File

@@ -37,15 +37,13 @@ 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(),
typename detail::enable_if<
detail::is_same<T, JsonVariant>::value ||
detail::is_same<T, JsonVariantConst>::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>::type* = 0)
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)
: JsonDocument(alloc) {
set(src);
}
@@ -139,9 +137,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Replaces the root with the specified value.
// https://arduinojson.org/v7/api/jsondocument/set/
template <typename T>
typename detail::enable_if<!detail::is_base_of<JsonDocument, T>::value,
bool>::type
set(const T& src) {
detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, bool> set(
const T& src) {
return to<JsonVariant>().set(src);
}
@@ -163,15 +160,24 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Returns true if the root object contains the specified key.
// https://arduinojson.org/v7/api/jsondocument/containskey/
template <typename TString>
bool containsKey(const TString& key) const {
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
const TString& key) const {
return data_.getMember(detail::adaptString(key), &resources_) != 0;
}
// Returns true if the root object contains the specified key.
// https://arduinojson.org/v7/api/jsondocument/containskey/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const {
return containsKey(key.template as<const char*>());
}
// Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TString>
typename detail::enable_if<detail::IsString<TString>::value,
detail::MemberProxy<JsonDocument&, TString>>::type
detail::enable_if_t<detail::IsString<TString>::value,
detail::MemberProxy<JsonDocument&, TString>>
operator[](const TString& key) {
return {*this, key};
}
@@ -179,8 +185,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TChar>
typename detail::enable_if<detail::IsString<TChar*>::value,
detail::MemberProxy<JsonDocument&, TChar*>>::type
detail::enable_if_t<detail::IsString<TChar*>::value,
detail::MemberProxy<JsonDocument&, TChar*>>
operator[](TChar* key) {
return {*this, key};
}
@@ -188,8 +194,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Gets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TString>
typename detail::enable_if<detail::IsString<TString>::value,
JsonVariantConst>::type
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
operator[](const TString& key) const {
return JsonVariantConst(
data_.getMember(detail::adaptString(key), &resources_), &resources_);
@@ -198,8 +203,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Gets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TChar>
typename detail::enable_if<detail::IsString<TChar*>::value,
JsonVariantConst>::type
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
operator[](TChar* key) const {
return JsonVariantConst(
data_.getMember(detail::adaptString(key), &resources_), &resources_);
@@ -207,8 +211,11 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Gets or sets a root array's element.
// https://arduinojson.org/v7/api/jsondocument/subscript/
detail::ElementProxy<JsonDocument&> operator[](size_t index) {
return {*this, index};
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value,
detail::ElementProxy<JsonDocument&>>
operator[](T index) {
return {*this, size_t(index)};
}
// Gets a root array's member.
@@ -217,12 +224,23 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
return JsonVariantConst(data_.getElement(index, &resources_), &resources_);
}
// Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
operator[](const TVariant& key) const {
if (key.template is<const char*>())
return operator[](key.template as<const char*>());
if (key.template is<size_t>())
return operator[](key.template as<size_t>());
return {};
}
// Appends a new (empty) element to the root array.
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsondocument/add/
template <typename T>
typename detail::enable_if<!detail::is_same<T, JsonVariant>::value, T>::type
add() {
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() {
return add<JsonVariant>().to<T>();
}
@@ -230,8 +248,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsondocument/add/
template <typename T>
typename detail::enable_if<detail::is_same<T, JsonVariant>::value, T>::type
add() {
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() {
return JsonVariant(data_.addElement(&resources_), &resources_);
}
@@ -239,27 +256,28 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// https://arduinojson.org/v7/api/jsondocument/add/
template <typename TValue>
bool add(const TValue& value) {
return add<JsonVariant>().set(value);
return data_.addValue(value, &resources_);
}
// Appends a value to the root array.
// https://arduinojson.org/v7/api/jsondocument/add/
template <typename TChar>
bool add(TChar* value) {
return add<JsonVariant>().set(value);
return data_.addValue(value, &resources_);
}
// Removes an element of the root array.
// https://arduinojson.org/v7/api/jsondocument/remove/
void remove(size_t index) {
detail::VariantData::removeElement(getData(), index, getResourceManager());
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value> remove(T index) {
detail::VariantData::removeElement(getData(), size_t(index),
getResourceManager());
}
// Removes a member of the root object.
// https://arduinojson.org/v7/api/jsondocument/remove/
template <typename TChar>
typename detail::enable_if<detail::IsString<TChar*>::value>::type remove(
TChar* key) {
detail::enable_if_t<detail::IsString<TChar*>::value> remove(TChar* key) {
detail::VariantData::removeMember(getData(), detail::adaptString(key),
getResourceManager());
}
@@ -267,13 +285,23 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Removes a member of the root object.
// https://arduinojson.org/v7/api/jsondocument/remove/
template <typename TString>
typename detail::enable_if<detail::IsString<TString>::value>::type remove(
detail::enable_if_t<detail::IsString<TString>::value> 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) {
if (key.template is<const char*>())
remove(key.template as<const char*>());
if (key.template is<size_t>())
remove(key.template as<size_t>());
}
operator JsonVariant() {
return getVariant();
}

View File

@@ -671,9 +671,8 @@ 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>
typename detail::enable_if<
detail::is_deserialize_destination<TDestination>::value,
DeserializationError>::type
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
DeserializationError>
deserializeJson(TDestination&& dst, Args&&... args) {
using namespace detail;
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
@@ -683,9 +682,8 @@ deserializeJson(TDestination&& dst, Args&&... args) {
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/json/deserializejson/
template <typename TDestination, typename TChar, typename... Args>
typename detail::enable_if<
detail::is_deserialize_destination<TDestination>::value,
DeserializationError>::type
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
DeserializationError>
deserializeJson(TDestination&& dst, TChar* input, Args&&... args) {
using namespace detail;
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),

View File

@@ -150,8 +150,8 @@ inline size_t measureJson(JsonVariantConst source) {
#if ARDUINOJSON_ENABLE_STD_STREAM
template <typename T>
inline typename detail::enable_if<
detail::is_convertible<T, JsonVariantConst>::value, std::ostream&>::type
inline detail::enable_if_t<detail::is_convertible<T, JsonVariantConst>::value,
std::ostream&>
operator<<(std::ostream& os, const T& source) {
serializeJson(source, os);
return os;

View File

@@ -100,8 +100,8 @@ class TextFormatter {
}
template <typename T>
typename enable_if<is_signed<T>::value>::type writeInteger(T value) {
typedef typename make_unsigned<T>::type unsigned_type;
enable_if_t<is_signed<T>::value> writeInteger(T value) {
typedef make_unsigned_t<T> unsigned_type;
unsigned_type unsigned_value;
if (value < 0) {
writeRaw('-');
@@ -113,7 +113,7 @@ class TextFormatter {
}
template <typename T>
typename enable_if<is_unsigned<T>::value>::type writeInteger(T value) {
enable_if_t<is_unsigned<T>::value> writeInteger(T value) {
char buffer[22];
char* end = buffer + sizeof(buffer);
char* begin = end;

View File

@@ -56,9 +56,7 @@ class ResourceManager {
return p;
}
void freeSlot(SlotWithId id) {
variantPools_.freeSlot(id);
}
void freeSlot(SlotWithId slot);
VariantSlot* getSlot(SlotId id) const {
return variantPools_.getSlot(id);

View File

@@ -0,0 +1,20 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Collection/CollectionData.hpp>
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
inline void ResourceManager::freeSlot(SlotWithId slot) {
if (slot->ownsKey())
dereferenceString(slot->key());
slot->data()->setNull(this);
variantPools_.freeSlot(slot);
}
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -0,0 +1,67 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/ResourceManager.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class StringBuffer {
public:
StringBuffer(ResourceManager* resources) : resources_(resources) {}
~StringBuffer() {
if (node_)
resources_->destroyString(node_);
}
char* reserve(size_t capacity) {
if (node_ && capacity > node_->length) {
// existing buffer is too small, we need to reallocate
resources_->destroyString(node_);
node_ = nullptr;
}
if (!node_)
node_ = resources_->createString(capacity);
if (!node_)
return nullptr;
size_ = capacity;
node_->data[capacity] = 0; // null-terminate the string
return node_->data;
}
StringNode* save() {
ARDUINOJSON_ASSERT(node_ != nullptr);
node_->data[size_] = 0;
auto node = resources_->getString(adaptString(node_->data, size_));
if (node) {
node->references++;
return node;
}
if (node_->length != size_) {
node = resources_->resizeString(node_, size_);
ARDUINOJSON_ASSERT(node != nullptr); // realloc to smaller can't fail
} else {
node = node_;
}
node_ = nullptr;
resources_->saveString(node);
return node;
}
JsonString str() const {
ARDUINOJSON_ASSERT(node_ != nullptr);
return JsonString(node_->data, node_->length, JsonString::Copied);
}
private:
ResourceManager* resources_;
StringNode* node_ = nullptr;
size_t size_ = 0;
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -17,9 +17,9 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
struct StringNode {
// Use the same type as SlotId to store the reference count
// (there can never be more references than slots)
using references_type = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>::type;
using references_type = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
using length_type = uint_t<ARDUINOJSON_STRING_LENGTH_SIZE * 8>::type;
using length_type = uint_t<ARDUINOJSON_STRING_LENGTH_SIZE * 8>;
struct StringNode* next;
references_type references;
@@ -35,8 +35,10 @@ struct StringNode {
static StringNode* create(size_t length, Allocator* allocator) {
if (length > maxLength)
return nullptr;
auto node = reinterpret_cast<StringNode*>(
allocator->allocate(sizeForLength(length)));
auto size = sizeForLength(length);
if (size < length) // integer overflow
return nullptr; // (not testable on 64-bit)
auto node = reinterpret_cast<StringNode*>(allocator->allocate(size));
if (node) {
node->length = length_type(length);
node->references = 1;

View File

@@ -11,7 +11,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class VariantSlot;
using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>::type;
using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
using SlotCount = SlotId;
const SlotId NULL_SLOT = SlotId(-1);

View File

@@ -0,0 +1,97 @@
#pragma once
#include <ArduinoJson/Variant/Converter.hpp>
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
class MsgPackBinary {
public:
MsgPackBinary() : data_(nullptr), size_(0) {}
explicit MsgPackBinary(const void* c, size_t size) : data_(c), size_(size) {}
const void* data() const {
return data_;
}
size_t size() const {
return size_;
}
private:
const void* data_;
size_t size_;
};
template <>
struct Converter<MsgPackBinary> : private detail::VariantAttorney {
static void toJson(MsgPackBinary src, JsonVariant dst) {
auto data = VariantAttorney::getData(dst);
if (!data)
return;
auto resources = getResourceManager(dst);
if (src.data()) {
size_t headerSize = src.size() >= 0x10000 ? 5
: src.size() >= 0x100 ? 3
: 2;
auto str = resources->createString(src.size() + headerSize);
if (str) {
resources->saveString(str);
auto ptr = reinterpret_cast<uint8_t*>(str->data);
switch (headerSize) {
case 2:
ptr[0] = uint8_t(0xc4);
ptr[1] = uint8_t(src.size() & 0xff);
break;
case 3:
ptr[0] = uint8_t(0xc5);
ptr[1] = uint8_t(src.size() >> 8 & 0xff);
ptr[2] = uint8_t(src.size() & 0xff);
break;
case 5:
ptr[0] = uint8_t(0xc6);
ptr[1] = uint8_t(src.size() >> 24 & 0xff);
ptr[2] = uint8_t(src.size() >> 16 & 0xff);
ptr[3] = uint8_t(src.size() >> 8 & 0xff);
ptr[4] = uint8_t(src.size() & 0xff);
break;
default:
ARDUINOJSON_ASSERT(false);
}
memcpy(ptr + headerSize, src.data(), src.size());
data->setRawString(str);
return;
}
}
data->setNull();
}
static MsgPackBinary fromJson(JsonVariantConst src) {
auto data = getData(src);
if (!data)
return {};
auto rawstr = data->asRawString();
auto p = reinterpret_cast<const uint8_t*>(rawstr.c_str());
auto n = rawstr.size();
if (n >= 2 && p[0] == 0xc4) { // bin 8
size_t size = p[1];
if (size + 2 == n)
return MsgPackBinary(p + 2, size);
} else if (n >= 3 && p[0] == 0xc5) { // bin 16
size_t size = size_t(p[1] << 8) | p[2];
if (size + 3 == n)
return MsgPackBinary(p + 3, size);
} else if (n >= 5 && p[0] == 0xc6) { // bin 32
size_t size =
size_t(p[1] << 24) | size_t(p[2] << 16) | size_t(p[3] << 8) | p[4];
if (size + 5 == n)
return MsgPackBinary(p + 5, size);
}
return {};
}
static bool checkJson(JsonVariantConst src) {
return fromJson(src).data() != nullptr;
}
};
ARDUINOJSON_END_PUBLIC_NAMESPACE

View File

@@ -6,7 +6,8 @@
#include <ArduinoJson/Deserialization/deserialize.hpp>
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/MsgPack/endianess.hpp>
#include <ArduinoJson/Memory/StringBuffer.hpp>
#include <ArduinoJson/MsgPack/endianness.hpp>
#include <ArduinoJson/MsgPack/ieee754.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
@@ -19,7 +20,7 @@ class MsgPackDeserializer {
MsgPackDeserializer(ResourceManager* resources, TReader reader)
: resources_(resources),
reader_(reader),
stringBuilder_(resources),
stringBuffer_(resources),
foundSomething_(false) {}
template <typename TFilter>
@@ -37,11 +38,13 @@ class MsgPackDeserializer {
DeserializationOption::NestingLimit nestingLimit) {
DeserializationError::Code err;
uint8_t code = 0; // TODO: why do we need to initialize this variable?
err = readByte(code);
uint8_t header[5];
err = readBytes(header, 1);
if (err)
return err;
const uint8_t& code = header[0];
foundSomething_ = true;
bool allowValue = filter.allowValue();
@@ -51,6 +54,14 @@ class MsgPackDeserializer {
ARDUINOJSON_ASSERT(variant != 0);
}
if (code >= 0xcc && code <= 0xd3) {
auto width = uint8_t(1U << ((code - 0xcc) % 4));
if (allowValue)
return readInteger(variant, width, code >= 0xd0);
else
return skipBytes(width);
}
switch (code) {
case 0xc0:
// already null
@@ -60,33 +71,11 @@ class MsgPackDeserializer {
return DeserializationError::InvalidInput;
case 0xc2:
if (allowValue)
variant->setBoolean(false);
return DeserializationError::Ok;
case 0xc3:
if (allowValue)
variant->setBoolean(true);
variant->setBoolean(code == 0xc3);
return DeserializationError::Ok;
case 0xc4: // bin 8 (not supported)
return skipString<uint8_t>();
case 0xc5: // bin 16 (not supported)
return skipString<uint16_t>();
case 0xc6: // bin 32 (not supported)
return skipString<uint32_t>();
case 0xc7: // ext 8 (not supported)
return skipExt<uint8_t>();
case 0xc8: // ext 16 (not supported)
return skipExt<uint16_t>();
case 0xc9: // ext 32 (not supported)
return skipExt<uint32_t>();
case 0xca:
if (allowValue)
return readFloat<float>(variant);
@@ -98,128 +87,97 @@ class MsgPackDeserializer {
return readDouble<double>(variant);
else
return skipBytes(8);
}
case 0xcc:
if (allowValue)
return readInteger<uint8_t>(variant);
else
return skipBytes(1);
if (code <= 0x7f || code >= 0xe0) { // fixint
if (allowValue)
variant->setInteger(static_cast<int8_t>(code));
return DeserializationError::Ok;
}
case 0xcd:
if (allowValue)
return readInteger<uint16_t>(variant);
else
return skipBytes(2);
uint8_t sizeBytes = 0;
size_t size = 0;
bool isExtension = code >= 0xc7 && code <= 0xc9;
case 0xce:
if (allowValue)
return readInteger<uint32_t>(variant);
else
return skipBytes(4);
switch (code) {
case 0xc4: // bin 8
case 0xc7: // ext 8
case 0xd9: // str 8
sizeBytes = 1;
break;
case 0xcf:
#if ARDUINOJSON_USE_LONG_LONG
if (allowValue)
return readInteger<uint64_t>(variant);
else
return skipBytes(8);
#else
return skipBytes(8); // not supported
#endif
case 0xc5: // bin 16
case 0xc8: // ext 16
case 0xda: // str 16
case 0xdc: // array 16
case 0xde: // map 16
sizeBytes = 2;
break;
case 0xd0:
if (allowValue)
return readInteger<int8_t>(variant);
else
return skipBytes(1);
case 0xc6: // bin 32
case 0xc9: // ext 32
case 0xdb: // str 32
case 0xdd: // array 32
case 0xdf: // map 32
sizeBytes = 4;
break;
}
case 0xd1:
if (allowValue)
return readInteger<int16_t>(variant);
else
return skipBytes(2);
case 0xd2:
if (allowValue)
return readInteger<int32_t>(variant);
else
return skipBytes(4);
case 0xd3:
#if ARDUINOJSON_USE_LONG_LONG
if (allowValue)
return readInteger<int64_t>(variant);
else
return skipBytes(8); // not supported
#else
return skipBytes(8);
#endif
case 0xd4: // fixext 1 (not supported)
return skipBytes(2);
case 0xd5: // fixext 2 (not supported)
return skipBytes(3);
case 0xd6: // fixext 4 (not supported)
return skipBytes(5);
case 0xd7: // fixext 8 (not supported)
return skipBytes(9);
case 0xd8: // fixext 16 (not supported)
return skipBytes(17);
case 0xd9:
if (allowValue)
return readString<uint8_t>(variant);
else
return skipString<uint8_t>();
case 0xda:
if (allowValue)
return readString<uint16_t>(variant);
else
return skipString<uint16_t>();
case 0xdb:
if (allowValue)
return readString<uint32_t>(variant);
else
return skipString<uint32_t>();
case 0xdc:
return readArray<uint16_t>(variant, filter, nestingLimit);
case 0xdd:
return readArray<uint32_t>(variant, filter, nestingLimit);
case 0xde:
return readObject<uint16_t>(variant, filter, nestingLimit);
case 0xdf:
return readObject<uint32_t>(variant, filter, nestingLimit);
if (code >= 0xd4 && code <= 0xd8) { // fixext
size = size_t(1) << (code - 0xd4);
isExtension = true;
}
switch (code & 0xf0) {
case 0x80:
return readObject(variant, code & 0x0F, filter, nestingLimit);
case 0x90:
return readArray(variant, code & 0x0F, filter, nestingLimit);
case 0x90: // fixarray
case 0x80: // fixmap
size = code & 0x0F;
break;
}
if ((code & 0xe0) == 0xa0) {
switch (code & 0xe0) {
case 0xa0: // fixstr
size = code & 0x1f;
break;
}
if (sizeBytes) {
err = readBytes(header + 1, sizeBytes);
if (err)
return err;
uint32_t size32 = 0;
for (uint8_t i = 0; i < sizeBytes; i++)
size32 = (size32 << 8) | header[i + 1];
size = size_t(size32);
if (size < size32) // integer overflow
return DeserializationError::NoMemory; // (not testable on 32/64-bit)
}
// array 16, 32 and fixarray
if (code == 0xdc || code == 0xdd || (code & 0xf0) == 0x90)
return readArray(variant, size, filter, nestingLimit);
// map 16, 32 and fixmap
if (code == 0xde || code == 0xdf || (code & 0xf0) == 0x80)
return readObject(variant, size, filter, nestingLimit);
// str 8, 16, 32 and fixstr
if (code == 0xd9 || code == 0xda || code == 0xdb || (code & 0xe0) == 0xa0) {
if (allowValue)
return readString(variant, code & 0x1f);
return readString(variant, size);
else
return skipBytes(code & 0x1f);
return skipBytes(size);
}
if (isExtension)
size++; // to include the type
if (allowValue)
variant->setInteger(static_cast<int8_t>(code));
return DeserializationError::Ok;
return readRawString(variant, header, uint8_t(1 + sizeBytes), size);
else
return skipBytes(size);
}
DeserializationError::Code readByte(uint8_t& value) {
@@ -230,7 +188,7 @@ class MsgPackDeserializer {
return DeserializationError::Ok;
}
DeserializationError::Code readBytes(uint8_t* p, size_t n) {
DeserializationError::Code readBytes(void* p, size_t n) {
if (reader_.readBytes(reinterpret_cast<char*>(p), n) == n)
return DeserializationError::Ok;
return DeserializationError::IncompleteInput;
@@ -238,7 +196,7 @@ class MsgPackDeserializer {
template <typename T>
DeserializationError::Code readBytes(T& value) {
return readBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
return readBytes(&value, sizeof(value));
}
DeserializationError::Code skipBytes(size_t n) {
@@ -249,36 +207,45 @@ class MsgPackDeserializer {
return DeserializationError::Ok;
}
template <typename T>
DeserializationError::Code readInteger(T& value) {
DeserializationError::Code err;
DeserializationError::Code readInteger(VariantData* variant, uint8_t width,
bool isSigned) {
uint8_t buffer[8];
err = readBytes(value);
auto err = readBytes(buffer, width);
if (err)
return err;
fixEndianess(value);
union {
int64_t signedValue;
uint64_t unsignedValue;
};
if (isSigned)
signedValue = static_cast<int8_t>(buffer[0]); // propagate sign bit
else
unsignedValue = static_cast<uint8_t>(buffer[0]);
for (uint8_t i = 1; i < width; i++)
unsignedValue = (unsignedValue << 8) | buffer[i];
if (isSigned) {
auto truncatedValue = static_cast<JsonInteger>(signedValue);
if (truncatedValue == signedValue)
variant->setInteger(truncatedValue);
// else set null on overflow
} else {
auto truncatedValue = static_cast<JsonUInt>(unsignedValue);
if (truncatedValue == unsignedValue)
variant->setInteger(truncatedValue);
// else set null on overflow
}
return DeserializationError::Ok;
}
template <typename T>
DeserializationError::Code readInteger(VariantData* variant) {
DeserializationError::Code err;
T value;
err = readInteger(value);
if (err)
return err;
variant->setInteger(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
readFloat(VariantData* variant) {
enable_if_t<sizeof(T) == 4, DeserializationError::Code> readFloat(
VariantData* variant) {
DeserializationError::Code err;
T value;
@@ -286,15 +253,15 @@ class MsgPackDeserializer {
if (err)
return err;
fixEndianess(value);
fixEndianness(value);
variant->setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 8, DeserializationError::Code>::type
readDouble(VariantData* variant) {
enable_if_t<sizeof(T) == 8, DeserializationError::Code> readDouble(
VariantData* variant) {
DeserializationError::Code err;
T value;
@@ -302,15 +269,15 @@ class MsgPackDeserializer {
if (err)
return err;
fixEndianess(value);
fixEndianness(value);
variant->setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
readDouble(VariantData* variant) {
enable_if_t<sizeof(T) == 4, DeserializationError::Code> readDouble(
VariantData* variant) {
DeserializationError::Code err;
uint8_t i[8]; // input is 8 bytes
T value; // output is 4 bytes
@@ -321,48 +288,12 @@ class MsgPackDeserializer {
return err;
doubleToFloat(i, o);
fixEndianess(value);
fixEndianness(value);
variant->setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
DeserializationError::Code readString(VariantData* variant) {
DeserializationError::Code err;
T size;
err = readInteger(size);
if (err)
return err;
return readString(variant, size);
}
template <typename T>
DeserializationError::Code readString() {
DeserializationError::Code err;
T size;
err = readInteger(size);
if (err)
return err;
return readString(size);
}
template <typename T>
DeserializationError::Code skipString() {
DeserializationError::Code err;
T size;
err = readInteger(size);
if (err)
return err;
return skipBytes(size);
}
DeserializationError::Code readString(VariantData* variant, size_t n) {
DeserializationError::Code err;
@@ -370,42 +301,37 @@ class MsgPackDeserializer {
if (err)
return err;
variant->setOwnedString(stringBuilder_.save());
variant->setOwnedString(stringBuffer_.save());
return DeserializationError::Ok;
}
DeserializationError::Code readString(size_t n) {
DeserializationError::Code err;
stringBuilder_.startString();
for (; n; --n) {
uint8_t c;
err = readBytes(c);
if (err)
return err;
stringBuilder_.append(static_cast<char>(c));
}
if (!stringBuilder_.isValid())
char* p = stringBuffer_.reserve(n);
if (!p)
return DeserializationError::NoMemory;
return DeserializationError::Ok;
return readBytes(p, n);
}
template <typename TSize, typename TFilter>
DeserializationError::Code readArray(
VariantData* variant, TFilter filter,
DeserializationOption::NestingLimit nestingLimit) {
DeserializationError::Code err;
TSize size;
DeserializationError::Code readRawString(VariantData* variant,
const void* header,
uint8_t headerSize, size_t n) {
auto totalSize = size_t(headerSize + n);
if (totalSize < n) // integer overflow
return DeserializationError::NoMemory; // (not testable on 64-bit)
err = readInteger(size);
char* p = stringBuffer_.reserve(totalSize);
if (!p)
return DeserializationError::NoMemory;
memcpy(p, header, headerSize);
auto err = readBytes(p + headerSize, n);
if (err)
return err;
return readArray(variant, size, filter, nestingLimit);
variant->setRawString(stringBuffer_.save());
return DeserializationError::Ok;
}
template <typename TFilter>
@@ -449,20 +375,6 @@ class MsgPackDeserializer {
return DeserializationError::Ok;
}
template <typename TSize, typename TFilter>
DeserializationError::Code readObject(
VariantData* variant, TFilter filter,
DeserializationOption::NestingLimit nestingLimit) {
DeserializationError::Code err;
TSize size;
err = readInteger(size);
if (err)
return err;
return readObject(variant, size, filter, nestingLimit);
}
template <typename TFilter>
DeserializationError::Code readObject(
VariantData* variant, size_t n, TFilter filter,
@@ -485,7 +397,7 @@ class MsgPackDeserializer {
if (err)
return err;
JsonString key = stringBuilder_.str();
JsonString key = stringBuffer_.str();
TFilter memberFilter = filter[key.c_str()];
VariantData* member;
@@ -493,7 +405,7 @@ class MsgPackDeserializer {
ARDUINOJSON_ASSERT(object != 0);
// Save key in memory pool.
auto savedKey = stringBuilder_.save();
auto savedKey = stringBuffer_.save();
member = object->addMember(savedKey, resources_);
if (!member)
@@ -521,36 +433,24 @@ class MsgPackDeserializer {
if ((code & 0xe0) == 0xa0)
return readString(code & 0x1f);
switch (code) {
case 0xd9:
return readString<uint8_t>();
case 0xda:
return readString<uint16_t>();
case 0xdb:
return readString<uint32_t>();
default:
return DeserializationError::InvalidInput;
if (code >= 0xd9 && code <= 0xdb) {
uint8_t sizeBytes = uint8_t(1U << (code - 0xd9));
uint32_t size = 0;
for (uint8_t i = 0; i < sizeBytes; i++) {
err = readByte(code);
if (err)
return err;
size = (size << 8) | code;
}
return readString(size);
}
}
template <typename T>
DeserializationError::Code skipExt() {
DeserializationError::Code err;
T size;
err = readInteger(size);
if (err)
return err;
return skipBytes(size + 1U);
return DeserializationError::InvalidInput;
}
ResourceManager* resources_;
TReader reader_;
StringBuilder stringBuilder_;
StringBuffer stringBuffer_;
bool foundSomething_;
};
@@ -561,9 +461,8 @@ 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>
typename detail::enable_if<
detail::is_deserialize_destination<TDestination>::value,
DeserializationError>::type
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
DeserializationError>
deserializeMsgPack(TDestination&& dst, Args&&... args) {
using namespace detail;
return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
@@ -573,9 +472,8 @@ 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>
typename detail::enable_if<
detail::is_deserialize_destination<TDestination>::value,
DeserializationError>::type
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
DeserializationError>
deserializeMsgPack(TDestination&& dst, TChar* input, Args&&... args) {
using namespace detail;
return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),

View File

@@ -0,0 +1,120 @@
#pragma once
#include <ArduinoJson/Variant/Converter.hpp>
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
class MsgPackExtension {
public:
MsgPackExtension() : data_(nullptr), size_(0), type_(0) {}
explicit MsgPackExtension(int8_t type, const void* data, size_t size)
: data_(data), size_(size), type_(type) {}
int8_t type() const {
return type_;
}
const void* data() const {
return data_;
}
size_t size() const {
return size_;
}
private:
const void* data_;
size_t size_;
int8_t type_;
};
template <>
struct Converter<MsgPackExtension> : private detail::VariantAttorney {
static void toJson(MsgPackExtension src, JsonVariant dst) {
auto data = VariantAttorney::getData(dst);
if (!data)
return;
auto resources = getResourceManager(dst);
if (src.data()) {
uint8_t format, sizeBytes;
if (src.size() >= 0x10000) {
format = 0xc9; // ext 32
sizeBytes = 4;
} else if (src.size() >= 0x100) {
format = 0xc8; // ext 16
sizeBytes = 2;
} else if (src.size() == 16) {
format = 0xd8; // fixext 16
sizeBytes = 0;
} else if (src.size() == 8) {
format = 0xd7; // fixext 8
sizeBytes = 0;
} else if (src.size() == 4) {
format = 0xd6; // fixext 4
sizeBytes = 0;
} else if (src.size() == 2) {
format = 0xd5; // fixext 2
sizeBytes = 0;
} else if (src.size() == 1) {
format = 0xd4; // fixext 1
sizeBytes = 0;
} else {
format = 0xc7; // ext 8
sizeBytes = 1;
}
auto str = resources->createString(src.size() + 2 + sizeBytes);
if (str) {
resources->saveString(str);
auto ptr = reinterpret_cast<uint8_t*>(str->data);
*ptr++ = uint8_t(format);
for (uint8_t i = 0; i < sizeBytes; i++)
*ptr++ = uint8_t(src.size() >> (sizeBytes - i - 1) * 8 & 0xff);
*ptr++ = uint8_t(src.type());
memcpy(ptr, src.data(), src.size());
data->setRawString(str);
return;
}
}
data->setNull();
}
static MsgPackExtension fromJson(JsonVariantConst src) {
auto data = getData(src);
if (!data)
return {};
auto rawstr = data->asRawString();
if (rawstr.size() == 0)
return {};
auto p = reinterpret_cast<const uint8_t*>(rawstr.c_str());
size_t payloadSize = 0;
uint8_t headerSize = 0;
const uint8_t& code = p[0];
if (code >= 0xd4 && code <= 0xd8) { // fixext 1
headerSize = 2;
payloadSize = size_t(1) << (code - 0xd4);
}
if (code >= 0xc7 && code <= 0xc9) {
uint8_t sizeBytes = uint8_t(1 << (code - 0xc7));
for (uint8_t i = 0; i < sizeBytes; i++)
payloadSize = (payloadSize << 8) | p[1 + i];
headerSize = uint8_t(2 + sizeBytes);
}
if (rawstr.size() == headerSize + payloadSize)
return MsgPackExtension(int8_t(p[headerSize - 1]), p + headerSize,
payloadSize);
return {};
}
static bool checkJson(JsonVariantConst src) {
return fromJson(src).data() != nullptr;
}
};
ARDUINOJSON_END_PUBLIC_NAMESPACE

View File

@@ -4,7 +4,7 @@
#pragma once
#include <ArduinoJson/MsgPack/endianess.hpp>
#include <ArduinoJson/MsgPack/endianness.hpp>
#include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Serialization/CountingDecorator.hpp>
@@ -23,9 +23,8 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
: writer_(writer), resources_(resources) {}
template <typename T>
typename enable_if<is_floating_point<T>::value && sizeof(T) == 4,
size_t>::type
visit(T value32) {
enable_if_t<is_floating_point<T>::value && sizeof(T) == 4, size_t> visit(
T value32) {
if (canConvertNumber<JsonInteger>(value32)) {
JsonInteger truncatedValue = JsonInteger(value32);
if (value32 == T(truncatedValue))
@@ -38,8 +37,8 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
template <typename T>
ARDUINOJSON_NO_SANITIZE("float-cast-overflow")
typename enable_if<is_floating_point<T>::value && sizeof(T) == 8,
size_t>::type visit(T value64) {
enable_if_t<is_floating_point<T>::value && sizeof(T) == 8, size_t> visit(
T value64) {
float value32 = float(value64);
if (value32 == value64)
return visit(value32);
@@ -206,7 +205,7 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
template <typename T>
void writeInteger(T value) {
fixEndianess(value);
fixEndianness(value);
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
}

View File

@@ -15,32 +15,32 @@ inline void swapBytes(uint8_t& a, uint8_t& b) {
b = t;
}
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 8>) {
inline void fixEndianness(uint8_t* p, integral_constant<size_t, 8>) {
swapBytes(p[0], p[7]);
swapBytes(p[1], p[6]);
swapBytes(p[2], p[5]);
swapBytes(p[3], p[4]);
}
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 4>) {
inline void fixEndianness(uint8_t* p, integral_constant<size_t, 4>) {
swapBytes(p[0], p[3]);
swapBytes(p[1], p[2]);
}
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 2>) {
inline void fixEndianness(uint8_t* p, integral_constant<size_t, 2>) {
swapBytes(p[0], p[1]);
}
inline void fixEndianess(uint8_t*, integral_constant<size_t, 1>) {}
inline void fixEndianness(uint8_t*, integral_constant<size_t, 1>) {}
template <typename T>
inline void fixEndianess(T& value) {
fixEndianess(reinterpret_cast<uint8_t*>(&value),
integral_constant<size_t, sizeof(T)>());
inline void fixEndianness(T& value) {
fixEndianness(reinterpret_cast<uint8_t*>(&value),
integral_constant<size_t, sizeof(T)>());
}
#else
template <typename T>
inline void fixEndianess(T&) {}
inline void fixEndianness(T&) {}
#endif
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -10,16 +10,16 @@
#ifndef ARDUINOJSON_VERSION_NAMESPACE
# define ARDUINOJSON_VERSION_NAMESPACE \
ARDUINOJSON_CONCAT4(ARDUINOJSON_VERSION_MACRO, \
ARDUINOJSON_BIN2ALPHA(ARDUINOJSON_ENABLE_PROGMEM, \
ARDUINOJSON_USE_LONG_LONG, \
ARDUINOJSON_USE_DOUBLE, 1), \
ARDUINOJSON_BIN2ALPHA(ARDUINOJSON_ENABLE_NAN, \
ARDUINOJSON_ENABLE_INFINITY, \
ARDUINOJSON_ENABLE_COMMENTS, \
ARDUINOJSON_DECODE_UNICODE), \
ARDUINOJSON_SLOT_ID_SIZE)
# define ARDUINOJSON_VERSION_NAMESPACE \
ARDUINOJSON_CONCAT5( \
ARDUINOJSON_VERSION_MACRO, \
ARDUINOJSON_BIN2ALPHA(ARDUINOJSON_ENABLE_PROGMEM, \
ARDUINOJSON_USE_LONG_LONG, \
ARDUINOJSON_USE_DOUBLE, 1), \
ARDUINOJSON_BIN2ALPHA( \
ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \
ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE), \
ARDUINOJSON_SLOT_ID_SIZE, ARDUINOJSON_STRING_LENGTH_SIZE)
#endif

View File

@@ -77,17 +77,17 @@ struct FloatTraits<T, 8 /*64bits*/> {
template <typename TOut> // int64_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 8,
signed>::type* = 0) {
enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 8,
signed>* = 0) {
return forge(0x43DFFFFFFFFFFFFF); // 9.2233720368547748e+18
}
template <typename TOut> // uint64_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 8,
unsigned>::type* = 0) {
enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 8,
unsigned>* = 0) {
return forge(0x43EFFFFFFFFFFFFF); // 1.8446744073709549568e+19
}
@@ -157,33 +157,33 @@ struct FloatTraits<T, 4 /*32bits*/> {
template <typename TOut> // int32_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 4,
signed>::type* = 0) {
enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 4,
signed>* = 0) {
return forge(0x4EFFFFFF); // 2.14748352E9
}
template <typename TOut> // uint32_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 4,
unsigned>::type* = 0) {
enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 4,
unsigned>* = 0) {
return forge(0x4F7FFFFF); // 4.29496704E9
}
template <typename TOut> // int64_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 8,
signed>::type* = 0) {
enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 8,
signed>* = 0) {
return forge(0x5EFFFFFF); // 9.22337148709896192E18
}
template <typename TOut> // uint64_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 8,
unsigned>::type* = 0) {
enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 8,
unsigned>* = 0) {
return forge(0x5F7FFFFF); // 1.844674297419792384E19
}

View File

@@ -32,34 +32,34 @@ CompareResult arithmeticCompare(const T& lhs, const T& rhs) {
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T1) < sizeof(T2)>::type* = 0) {
enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T1) < sizeof(T2)>* = 0) {
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T2) < sizeof(T1)>::type* = 0) {
enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T2) < sizeof(T1)>* = 0) {
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value == is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>::type* = 0) {
enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value == is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>* = 0) {
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_unsigned<T1>::value && is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>::type* = 0) {
enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
is_unsigned<T1>::value && is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>* = 0) {
if (rhs < 0)
return COMPARE_RESULT_GREATER;
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
@@ -68,9 +68,9 @@ CompareResult arithmeticCompare(
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value && is_unsigned<T2>::value &&
sizeof(T2) == sizeof(T1)>::type* = 0) {
enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value && is_unsigned<T2>::value &&
sizeof(T2) == sizeof(T1)>* = 0) {
if (lhs < 0)
return COMPARE_RESULT_LESS;
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
@@ -79,23 +79,21 @@ CompareResult arithmeticCompare(
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1& lhs, const T2& rhs,
typename enable_if<is_floating_point<T1>::value ||
is_floating_point<T2>::value>::type* = 0) {
enable_if_t<is_floating_point<T1>::value || is_floating_point<T2>::value>* =
0) {
return arithmeticCompare<double>(static_cast<double>(lhs),
static_cast<double>(rhs));
}
template <typename T2>
CompareResult arithmeticCompareNegateLeft(
JsonUInt, const T2&,
typename enable_if<is_unsigned<T2>::value>::type* = 0) {
JsonUInt, const T2&, enable_if_t<is_unsigned<T2>::value>* = 0) {
return COMPARE_RESULT_LESS;
}
template <typename T2>
CompareResult arithmeticCompareNegateLeft(
JsonUInt lhs, const T2& rhs,
typename enable_if<is_signed<T2>::value>::type* = 0) {
JsonUInt lhs, const T2& rhs, enable_if_t<is_signed<T2>::value>* = 0) {
if (rhs > 0)
return COMPARE_RESULT_LESS;
return arithmeticCompare(-rhs, static_cast<T2>(lhs));
@@ -103,15 +101,13 @@ CompareResult arithmeticCompareNegateLeft(
template <typename T1>
CompareResult arithmeticCompareNegateRight(
const T1&, JsonUInt,
typename enable_if<is_unsigned<T1>::value>::type* = 0) {
const T1&, JsonUInt, enable_if_t<is_unsigned<T1>::value>* = 0) {
return COMPARE_RESULT_GREATER;
}
template <typename T1>
CompareResult arithmeticCompareNegateRight(
const T1& lhs, JsonUInt rhs,
typename enable_if<is_signed<T1>::value>::type* = 0) {
const T1& lhs, JsonUInt rhs, enable_if_t<is_signed<T1>::value>* = 0) {
if (lhs > 0)
return COMPARE_RESULT_GREATER;
return arithmeticCompare(static_cast<T1>(rhs), -lhs);

View File

@@ -22,18 +22,18 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// uint32 -> int32
// uint64 -> int32
template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_unsigned<TIn>::value &&
is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn),
bool>::type
enable_if_t<is_integral<TIn>::value && is_unsigned<TIn>::value &&
is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn),
bool>
canConvertNumber(TIn value) {
return value <= TIn(numeric_limits<TOut>::highest());
}
// uint32 -> int64
template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_unsigned<TIn>::value &&
is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut),
bool>::type
enable_if_t<is_integral<TIn>::value && is_unsigned<TIn>::value &&
is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut),
bool>
canConvertNumber(TIn) {
return true;
}
@@ -41,18 +41,17 @@ canConvertNumber(TIn) {
// uint32 -> float
// int32 -> float
template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_floating_point<TOut>::value,
bool>::type
enable_if_t<is_integral<TIn>::value && is_floating_point<TOut>::value, bool>
canConvertNumber(TIn) {
return true;
}
// int64 -> int32
template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) < sizeof(TIn),
bool>::type
enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) < sizeof(TIn),
bool>
canConvertNumber(TIn value) {
return value >= TIn(numeric_limits<TOut>::lowest()) &&
value <= TIn(numeric_limits<TOut>::highest());
@@ -61,10 +60,10 @@ canConvertNumber(TIn value) {
// int32 -> int32
// int32 -> int64
template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TIn) <= sizeof(TOut),
bool>::type
enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TIn) <= sizeof(TOut),
bool>
canConvertNumber(TIn) {
return true;
}
@@ -72,10 +71,10 @@ canConvertNumber(TIn) {
// int32 -> uint32
// int32 -> uint64
template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) >= sizeof(TIn),
bool>::type
enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) >= sizeof(TIn),
bool>
canConvertNumber(TIn value) {
if (value < 0)
return false;
@@ -84,10 +83,10 @@ canConvertNumber(TIn value) {
// int32 -> uint16
template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) < sizeof(TIn),
bool>::type
enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) < sizeof(TIn),
bool>
canConvertNumber(TIn value) {
if (value < 0)
return false;
@@ -97,9 +96,9 @@ canConvertNumber(TIn value) {
// float32 -> int16
// float64 -> int32
template <typename TOut, typename TIn>
typename enable_if<is_floating_point<TIn>::value && is_integral<TOut>::value &&
sizeof(TOut) < sizeof(TIn),
bool>::type
enable_if_t<is_floating_point<TIn>::value && is_integral<TOut>::value &&
sizeof(TOut) < sizeof(TIn),
bool>
canConvertNumber(TIn value) {
return value >= numeric_limits<TOut>::lowest() &&
value <= numeric_limits<TOut>::highest();
@@ -112,9 +111,9 @@ canConvertNumber(TIn value) {
// float64 -> int64
// float64 -> uint64
template <typename TOut, typename TIn>
typename enable_if<is_floating_point<TIn>::value && is_integral<TOut>::value &&
sizeof(TOut) >= sizeof(TIn),
bool>::type
enable_if_t<is_floating_point<TIn>::value && is_integral<TOut>::value &&
sizeof(TOut) >= sizeof(TIn),
bool>
canConvertNumber(TIn value) {
// Avoid error "9.22337e+18 is outside the range of representable values of
// type 'long'"

View File

@@ -16,11 +16,11 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename A, typename B>
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
using largest_type = conditional_t<(sizeof(A) > sizeof(B)), A, B>;
inline bool parseNumber(const char* s, VariantData& result) {
typedef FloatTraits<JsonFloat> traits;
typedef choose_largest<traits::mantissa_type, JsonUInt>::type mantissa_t;
typedef largest_type<traits::mantissa_type, JsonUInt> mantissa_t;
typedef traits::exponent_type exponent_t;
ARDUINOJSON_ASSERT(s != 0);

View File

@@ -102,9 +102,8 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TString>
typename detail::enable_if<detail::IsString<TString>::value,
detail::MemberProxy<JsonObject, TString>>::type
detail::enable_if_t<detail::IsString<TString>::value,
detail::MemberProxy<JsonObject, TString>>
operator[](const TString& key) const {
return {*this, key};
}
@@ -112,13 +111,24 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TChar>
typename detail::enable_if<detail::IsString<TChar*>::value,
detail::MemberProxy<JsonObject, TChar*>>::type
detail::enable_if_t<detail::IsString<TChar*>::value,
detail::MemberProxy<JsonObject, TChar*>>
operator[](TChar* key) const {
return {*this, 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, const char*>>
operator[](const TVariant& key) const {
if (key.template is<const char*>())
return {*this, key.template as<const char*>()};
else
return {*this, nullptr};
}
// Removes the member at the specified iterator.
// https://arduinojson.org/v7/api/jsonobject/remove/
FORCE_INLINE void remove(iterator it) const {
@@ -128,11 +138,21 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Removes the member with the specified key.
// https://arduinojson.org/v7/api/jsonobject/remove/
template <typename TString>
FORCE_INLINE void remove(const TString& key) const {
detail::enable_if_t<detail::IsString<TString>::value> 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 {
if (key.template is<const char*>())
remove(key.template as<const char*>());
}
// Removes the member with the specified key.
// https://arduinojson.org/v7/api/jsonobject/remove/
template <typename TChar>
@@ -144,9 +164,8 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Returns true if the object contains the specified key.
// https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TString>
typename detail::enable_if<detail::IsString<TString>::value, bool>::type
containsKey(const TString& key) const {
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
const TString& key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0;
}
@@ -154,13 +173,20 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Returns true if the object contains the specified key.
// https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TChar>
typename detail::enable_if<detail::IsString<TChar*>::value, bool>::type
containsKey(TChar* key) const {
detail::enable_if_t<detail::IsString<TChar*>::value, bool> containsKey(
TChar* key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0;
}
// Returns true if the object contains the specified key.
// https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const {
return containsKey(key.template as<const char*>());
}
// DEPRECATED: use obj[key].to<JsonArray>() instead
template <typename TChar>
ARDUINOJSON_DEPRECATED("use obj[key].to<JsonArray>() instead")

View File

@@ -19,7 +19,7 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
typedef JsonObjectConstIterator iterator;
// Creates an unbound reference.
JsonObjectConst() : data_(0) {}
JsonObjectConst() : data_(0), resources_(0) {}
// INTERNAL USE ONLY
JsonObjectConst(const detail::ObjectData* data,
@@ -71,7 +71,8 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// Returns true if the object contains the specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/containskey/
template <typename TString>
bool containsKey(const TString& key) const {
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
const TString& key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0;
}
@@ -84,11 +85,18 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
resources_) != 0;
}
// Returns true if the object contains the specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/containskey/
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const {
return containsKey(key.template as<const char*>());
}
// Gets the member with specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/
template <typename TString>
typename detail::enable_if<detail::IsString<TString>::value,
JsonVariantConst>::type
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
operator[](const TString& key) const {
return JsonVariantConst(detail::ObjectData::getMember(
data_, detail::adaptString(key), resources_),
@@ -98,14 +106,24 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// Gets the member with specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/
template <typename TChar>
typename detail::enable_if<detail::IsString<TChar*>::value,
JsonVariantConst>::type
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
operator[](TChar* key) const {
return JsonVariantConst(detail::ObjectData::getMember(
data_, detail::adaptString(key), resources_),
resources_);
}
// 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 {
if (key.template is<const char*>())
return operator[](key.template as<const char*>());
else
return JsonVariantConst();
}
// DEPRECATED: always returns zero
ARDUINOJSON_DEPRECATED("always returns zero")
size_t memoryUsage() const {

View File

@@ -11,21 +11,24 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <int Bits>
struct uint_t;
struct uint_;
template <>
struct uint_t<8> {
struct uint_<8> {
typedef uint8_t type;
};
template <>
struct uint_t<16> {
struct uint_<16> {
typedef uint16_t type;
};
template <>
struct uint_t<32> {
struct uint_<32> {
typedef uint32_t type;
};
template <int Bits>
using uint_t = typename uint_<Bits>::type;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -18,7 +18,7 @@ template <typename T, typename Enable = void>
struct numeric_limits;
template <typename T>
struct numeric_limits<T, typename enable_if<is_unsigned<T>::value>::type> {
struct numeric_limits<T, enable_if_t<is_unsigned<T>::value>> {
static constexpr T lowest() {
return 0;
}
@@ -29,7 +29,7 @@ struct numeric_limits<T, typename enable_if<is_unsigned<T>::value>::type> {
template <typename T>
struct numeric_limits<
T, typename enable_if<is_integral<T>::value && is_signed<T>::value>::type> {
T, enable_if_t<is_integral<T>::value && is_signed<T>::value>> {
static constexpr T lowest() {
return T(T(1) << (sizeof(T) * 8 - 1));
}

View File

@@ -6,8 +6,12 @@
#define ARDUINOJSON_CONCAT_(A, B) A##B
#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B)
#define ARDUINOJSON_CONCAT3(A, B, C) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), C)
#define ARDUINOJSON_CONCAT4(A, B, C, D) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT3(A, B, C), D)
#define ARDUINOJSON_CONCAT5(A, B, C, D, E) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), E)
#define ARDUINOJSON_BIN2ALPHA_0000() A
#define ARDUINOJSON_BIN2ALPHA_0001() B

View File

@@ -6,6 +6,7 @@
#include "type_traits/conditional.hpp"
#include "type_traits/enable_if.hpp"
#include "type_traits/function_traits.hpp"
#include "type_traits/integral_constant.hpp"
#include "type_traits/is_array.hpp"
#include "type_traits/is_base_of.hpp"
@@ -20,6 +21,6 @@
#include "type_traits/is_signed.hpp"
#include "type_traits/is_unsigned.hpp"
#include "type_traits/make_unsigned.hpp"
#include "type_traits/make_void.hpp"
#include "type_traits/remove_const.hpp"
#include "type_traits/remove_reference.hpp"
#include "type_traits/void_t.hpp"

View File

@@ -18,4 +18,8 @@ struct conditional<false, TrueType, FalseType> {
typedef FalseType type;
};
template <bool Condition, class TrueType, class FalseType>
using conditional_t =
typename conditional<Condition, TrueType, FalseType>::type;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -17,4 +17,7 @@ struct enable_if<true, T> {
typedef T type;
};
template <bool Condition, typename T = void>
using enable_if_t = typename enable_if<Condition, T>::type;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -0,0 +1,27 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename Sig>
struct function_traits;
template <typename ReturnType, typename Arg1>
struct function_traits<ReturnType (*)(Arg1)> {
using return_type = ReturnType;
using arg1_type = Arg1;
};
template <typename ReturnType, typename Arg1, typename Arg2>
struct function_traits<ReturnType (*)(Arg1, Arg2)> {
using return_type = ReturnType;
using arg1_type = Arg1;
using arg2_type = Arg2;
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -20,8 +20,8 @@ class is_base_of {
public:
static const bool value =
sizeof(probe(reinterpret_cast<typename remove_reference<TDerived>::type*>(
0))) == sizeof(int);
sizeof(probe(reinterpret_cast<remove_reference_t<TDerived>*>(0))) ==
sizeof(int);
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -14,7 +14,7 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename T>
struct is_enum {
static const bool value = is_convertible<T, int>::value &&
static const bool value = is_convertible<T, long long>::value &&
!is_class<T>::value && !is_integral<T>::value &&
!is_floating_point<T>::value;
};

View File

@@ -12,9 +12,8 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <class T>
struct is_floating_point
: integral_constant<
bool, //
is_same<float, typename remove_cv<T>::type>::value ||
is_same<double, typename remove_cv<T>::type>::value> {};
: integral_constant<bool, //
is_same<float, remove_cv_t<T>>::value ||
is_same<double, remove_cv_t<T>>::value> {};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -15,18 +15,18 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// clang-format off
template <typename T>
struct is_integral : integral_constant<bool,
is_same<typename remove_cv<T>::type, signed char>::value ||
is_same<typename remove_cv<T>::type, unsigned char>::value ||
is_same<typename remove_cv<T>::type, signed short>::value ||
is_same<typename remove_cv<T>::type, unsigned short>::value ||
is_same<typename remove_cv<T>::type, signed int>::value ||
is_same<typename remove_cv<T>::type, unsigned int>::value ||
is_same<typename remove_cv<T>::type, signed long>::value ||
is_same<typename remove_cv<T>::type, unsigned long>::value ||
is_same<typename remove_cv<T>::type, signed long long>::value ||
is_same<typename remove_cv<T>::type, unsigned long long>::value ||
is_same<typename remove_cv<T>::type, char>::value ||
is_same<typename remove_cv<T>::type, bool>::value> {};
is_same<remove_cv_t<T>, signed char>::value ||
is_same<remove_cv_t<T>, unsigned char>::value ||
is_same<remove_cv_t<T>, signed short>::value ||
is_same<remove_cv_t<T>, unsigned short>::value ||
is_same<remove_cv_t<T>, signed int>::value ||
is_same<remove_cv_t<T>, unsigned int>::value ||
is_same<remove_cv_t<T>, signed long>::value ||
is_same<remove_cv_t<T>, unsigned long>::value ||
is_same<remove_cv_t<T>, signed long long>::value ||
is_same<remove_cv_t<T>, unsigned long long>::value ||
is_same<remove_cv_t<T>, char>::value ||
is_same<remove_cv_t<T>, bool>::value> {};
// clang-format on
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -13,14 +13,14 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// clang-format off
template <typename T>
struct is_signed : integral_constant<bool,
is_same<typename remove_cv<T>::type, char>::value ||
is_same<typename remove_cv<T>::type, signed char>::value ||
is_same<typename remove_cv<T>::type, signed short>::value ||
is_same<typename remove_cv<T>::type, signed int>::value ||
is_same<typename remove_cv<T>::type, signed long>::value ||
is_same<typename remove_cv<T>::type, signed long long>::value ||
is_same<typename remove_cv<T>::type, float>::value ||
is_same<typename remove_cv<T>::type, double>::value> {};
is_same<remove_cv_t<T>, char>::value ||
is_same<remove_cv_t<T>, signed char>::value ||
is_same<remove_cv_t<T>, signed short>::value ||
is_same<remove_cv_t<T>, signed int>::value ||
is_same<remove_cv_t<T>, signed long>::value ||
is_same<remove_cv_t<T>, signed long long>::value ||
is_same<remove_cv_t<T>, float>::value ||
is_same<remove_cv_t<T>, double>::value> {};
// clang-format on
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -13,12 +13,12 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// clang-format off
template <typename T>
struct is_unsigned : integral_constant<bool,
is_same<typename remove_cv<T>::type, unsigned char>::value ||
is_same<typename remove_cv<T>::type, unsigned short>::value ||
is_same<typename remove_cv<T>::type, unsigned int>::value ||
is_same<typename remove_cv<T>::type, unsigned long>::value ||
is_same<typename remove_cv<T>::type, unsigned long long>::value ||
is_same<typename remove_cv<T>::type, bool>::value> {};
is_same<remove_cv_t<T>, unsigned char>::value ||
is_same<remove_cv_t<T>, unsigned short>::value ||
is_same<remove_cv_t<T>, unsigned int>::value ||
is_same<remove_cv_t<T>, unsigned long>::value ||
is_same<remove_cv_t<T>, unsigned long long>::value ||
is_same<remove_cv_t<T>, bool>::value> {};
// clang-format on
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -38,4 +38,7 @@ struct make_unsigned<signed long long> : type_identity<unsigned long long> {};
template <>
struct make_unsigned<unsigned long long> : type_identity<unsigned long long> {};
template <typename T>
using make_unsigned_t = typename make_unsigned<T>::type;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -1,14 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <class = void>
struct make_void {
typedef void type;
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -18,4 +18,7 @@ struct remove_const<const T> {
typedef T type;
};
template <typename T>
using remove_const_t = typename remove_const<T>::type;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -25,4 +25,7 @@ struct remove_cv<const volatile T> {
typedef T type;
};
template <typename T>
using remove_cv_t = typename remove_cv<T>::type;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -18,4 +18,7 @@ struct remove_reference<T&> {
typedef T type;
};
template <typename T>
using remove_reference_t = typename remove_reference<T>::type;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -0,0 +1,20 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename...>
struct make_void {
using type = void;
};
template <typename... Args>
using void_t = typename make_void<Args...>::type;
// NOTE: using void_t = void; doesn't work on GCC 4.8
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -11,13 +11,13 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
using nullptr_t = decltype(nullptr);
template <class T>
T&& forward(typename remove_reference<T>::type& t) noexcept {
T&& forward(remove_reference_t<T>& t) noexcept {
return static_cast<T&&>(t);
}
template <class T>
typename remove_reference<T>::type&& move(T&& t) {
return static_cast<typename remove_reference<T>::type&&>(t);
remove_reference_t<T>&& move(T&& t) {
return static_cast<remove_reference_t<T>&&>(t);
}
// Polyfull for std::swap

View File

@@ -9,9 +9,8 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TDestination>
class Writer<
TDestination,
typename enable_if<is_base_of<::Print, TDestination>::value>::type> {
class Writer<TDestination,
enable_if_t<is_base_of<::Print, TDestination>::value>> {
public:
explicit Writer(::Print& print) : print_(&print) {}

View File

@@ -9,9 +9,8 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TDestination>
class Writer<
TDestination,
typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
class Writer<TDestination,
enable_if_t<is_base_of<std::ostream, TDestination>::value>> {
public:
explicit Writer(std::ostream& os) : os_(&os) {}

View File

@@ -14,13 +14,12 @@ struct is_std_string : false_type {};
template <class T>
struct is_std_string<
T, typename enable_if<is_same<void, decltype(T().push_back('a'))>::value &&
is_same<T&, decltype(T().append(""))>::value>::type>
: true_type {};
T, enable_if_t<is_same<void, decltype(T().push_back('a'))>::value &&
is_same<T&, decltype(T().append(""))>::value>> : true_type {
};
template <typename TDestination>
class Writer<TDestination,
typename enable_if<is_std_string<TDestination>::value>::type> {
class Writer<TDestination, enable_if_t<is_std_string<TDestination>::value>> {
public:
Writer(TDestination& str) : str_(&str) {
str.clear();

View File

@@ -23,17 +23,15 @@ size_t serialize(ArduinoJson::JsonVariantConst source,
}
template <template <typename> class TSerializer>
typename enable_if<!TSerializer<StaticStringWriter>::producesText, size_t>::type
serialize(ArduinoJson::JsonVariantConst source, void* buffer,
size_t bufferSize) {
enable_if_t<!TSerializer<StaticStringWriter>::producesText, size_t> serialize(
ArduinoJson::JsonVariantConst source, void* buffer, size_t bufferSize) {
StaticStringWriter writer(reinterpret_cast<char*>(buffer), bufferSize);
return doSerialize<TSerializer>(source, writer);
}
template <template <typename> class TSerializer>
typename enable_if<TSerializer<StaticStringWriter>::producesText, size_t>::type
serialize(ArduinoJson::JsonVariantConst source, void* buffer,
size_t bufferSize) {
enable_if_t<TSerializer<StaticStringWriter>::producesText, size_t> serialize(
ArduinoJson::JsonVariantConst source, void* buffer, size_t bufferSize) {
StaticStringWriter writer(reinterpret_cast<char*>(buffer), bufferSize);
size_t n = doSerialize<TSerializer>(source, writer);
// add null-terminator for text output (not counted in the size)
@@ -43,7 +41,7 @@ serialize(ArduinoJson::JsonVariantConst source, void* buffer,
}
template <template <typename> class TSerializer, typename TChar, size_t N>
typename enable_if<IsChar<TChar>::value, size_t>::type serialize(
enable_if_t<IsChar<TChar>::value, size_t> serialize(
ArduinoJson::JsonVariantConst source, TChar (&buffer)[N]) {
return serialize<TSerializer>(source, buffer, N);
}

View File

@@ -62,7 +62,7 @@ class ZeroTerminatedRamString {
};
template <typename TChar>
struct StringAdapter<TChar*, typename enable_if<IsChar<TChar>::value>::type> {
struct StringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
typedef ZeroTerminatedRamString AdaptedString;
static AdaptedString adapt(const TChar* p) {
@@ -71,7 +71,7 @@ struct StringAdapter<TChar*, typename enable_if<IsChar<TChar>::value>::type> {
};
template <typename TChar, size_t N>
struct StringAdapter<TChar[N], typename enable_if<IsChar<TChar>::value>::type> {
struct StringAdapter<TChar[N], enable_if_t<IsChar<TChar>::value>> {
typedef ZeroTerminatedRamString AdaptedString;
static AdaptedString adapt(const TChar* p) {
@@ -131,8 +131,7 @@ class SizedRamString {
};
template <typename TChar>
struct SizedStringAdapter<TChar*,
typename enable_if<IsChar<TChar>::value>::type> {
struct SizedStringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
typedef SizedRamString AdaptedString;
static AdaptedString adapt(const TChar* p, size_t n) {

View File

@@ -13,9 +13,8 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename T>
struct StringAdapter<
T,
typename enable_if<
(string_traits<T>::has_cstr || string_traits<T>::has_data) &&
(string_traits<T>::has_length || string_traits<T>::has_size)>::type> {
enable_if_t<(string_traits<T>::has_cstr || string_traits<T>::has_data) &&
(string_traits<T>::has_length || string_traits<T>::has_size)>> {
typedef SizedRamString AdaptedString;
static AdaptedString adapt(const T& s) {
@@ -24,26 +23,24 @@ struct StringAdapter<
private:
template <typename U>
static typename enable_if<string_traits<U>::has_size, size_t>::type get_size(
const U& s) {
static enable_if_t<string_traits<U>::has_size, size_t> get_size(const U& s) {
return s.size();
}
template <typename U>
static typename enable_if<!string_traits<U>::has_size, size_t>::type get_size(
const U& s) {
static enable_if_t<!string_traits<U>::has_size, size_t> get_size(const U& s) {
return s.length();
}
template <typename U>
static typename enable_if<string_traits<U>::has_data, const char*>::type
get_data(const U& s) {
static enable_if_t<string_traits<U>::has_data, const char*> get_data(
const U& s) {
return s.data();
}
template <typename U>
static typename enable_if<!string_traits<U>::has_data, const char*>::type
get_data(const U& s) {
static enable_if_t<!string_traits<U>::has_data, const char*> get_data(
const U& s) {
return s.c_str();
}
};

View File

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

View File

@@ -16,8 +16,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TAdaptedString1, typename TAdaptedString2>
typename enable_if<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey,
int>::type
enable_if_t<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey, int>
stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) {
ARDUINOJSON_ASSERT(!s1.isNull());
ARDUINOJSON_ASSERT(!s2.isNull());
@@ -36,15 +35,13 @@ stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) {
}
template <typename TAdaptedString1, typename TAdaptedString2>
typename enable_if<
(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), int>::type
enable_if_t<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), int>
stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) {
return -stringCompare(s2, s1);
}
template <typename TAdaptedString1, typename TAdaptedString2>
typename enable_if<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey,
bool>::type
enable_if_t<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey, bool>
stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) {
ARDUINOJSON_ASSERT(!s1.isNull());
ARDUINOJSON_ASSERT(!s2.isNull());
@@ -60,8 +57,7 @@ stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) {
}
template <typename TAdaptedString1, typename TAdaptedString2>
typename enable_if<
(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), bool>::type
enable_if_t<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), bool>
stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) {
return stringEquals(s2, s1);
}

View File

@@ -19,10 +19,8 @@ template <class T, class = void>
struct has_cstr : false_type {};
template <class T>
struct has_cstr<T,
typename enable_if<is_same<decltype(declval<const T>().c_str()),
const char*>::value>::type>
: true_type {};
struct has_cstr<T, enable_if_t<is_same<decltype(declval<const T>().c_str()),
const char*>::value>> : true_type {};
// const char* data() const
// - std::string
@@ -33,12 +31,10 @@ template <class T, class = void>
struct has_data : false_type {};
template <class T>
struct has_data<T,
typename enable_if<is_same<decltype(declval<const T>().data()),
const char*>::value>::type>
: true_type {};
struct has_data<T, enable_if_t<is_same<decltype(declval<const T>().data()),
const char*>::value>> : true_type {};
// size_t length() const
// unsigned int length() const
// - String
template <class T, class = void>
@@ -46,8 +42,7 @@ struct has_length : false_type {};
template <class T>
struct has_length<
T, typename enable_if<
is_same<decltype(declval<const T>().length()), size_t>::value>::type>
T, enable_if_t<is_unsigned<decltype(declval<const T>().length())>::value>>
: true_type {};
// size_t size() const
@@ -60,8 +55,7 @@ struct has_size : false_type {};
template <class T>
struct has_size<
T, typename enable_if<
is_same<decltype(declval<const T>().size()), size_t>::value>::type>
T, enable_if_t<is_same<decltype(declval<const T>().size()), size_t>::value>>
: true_type {};
} // namespace string_traits_impl

View File

@@ -20,7 +20,4 @@ template <typename T1, typename T2>
class InvalidConversion; // Error here? See https://arduinojson.org/v7/invalid-conversion/
// clang-format on
template <typename T>
struct ConverterNeedsWriteableRef;
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@@ -54,16 +54,17 @@ struct Converter {
};
template <typename T>
struct Converter<
T, typename detail::enable_if<detail::is_integral<T>::value &&
!detail::is_same<bool, T>::value &&
!detail::is_same<char, T>::value>::type>
struct Converter<T, detail::enable_if_t<detail::is_integral<T>::value &&
!detail::is_same<bool, T>::value &&
!detail::is_same<char, T>::value>>
: private detail::VariantAttorney {
static void toJson(T src, JsonVariant dst) {
static bool toJson(T src, JsonVariant dst) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
auto data = getData(dst);
if (data)
data->setInteger(src, getResourceManager(dst));
if (!data)
return false;
data->setInteger(src, getResourceManager(dst));
return true;
}
static T fromJson(JsonVariantConst src) {
@@ -79,10 +80,10 @@ struct Converter<
};
template <typename T>
struct Converter<T, typename detail::enable_if<detail::is_enum<T>::value>::type>
struct Converter<T, detail::enable_if_t<detail::is_enum<T>::value>>
: private detail::VariantAttorney {
static void toJson(T src, JsonVariant dst) {
dst.set(static_cast<JsonInteger>(src));
static bool toJson(T src, JsonVariant dst) {
return dst.set(static_cast<JsonInteger>(src));
}
static T fromJson(JsonVariantConst src) {
@@ -98,10 +99,12 @@ struct Converter<T, typename detail::enable_if<detail::is_enum<T>::value>::type>
template <>
struct Converter<bool> : private detail::VariantAttorney {
static void toJson(bool src, JsonVariant dst) {
static bool toJson(bool src, JsonVariant dst) {
auto data = getData(dst);
if (data)
data->setBoolean(src, getResourceManager(dst));
if (!data)
return false;
data->setBoolean(src, getResourceManager(dst));
return true;
}
static bool fromJson(JsonVariantConst src) {
@@ -116,13 +119,14 @@ struct Converter<bool> : private detail::VariantAttorney {
};
template <typename T>
struct Converter<
T, typename detail::enable_if<detail::is_floating_point<T>::value>::type>
struct Converter<T, detail::enable_if_t<detail::is_floating_point<T>::value>>
: private detail::VariantAttorney {
static void toJson(T src, JsonVariant dst) {
static bool toJson(T src, JsonVariant dst) {
auto data = getData(dst);
if (data)
data->setFloat(static_cast<JsonFloat>(src), getResourceManager(dst));
if (!data)
return false;
data->setFloat(static_cast<JsonFloat>(src), getResourceManager(dst));
return true;
}
static T fromJson(JsonVariantConst src) {
@@ -173,8 +177,8 @@ struct Converter<JsonString> : private detail::VariantAttorney {
};
template <typename T>
inline typename detail::enable_if<detail::IsString<T>::value>::type
convertToJson(const T& src, JsonVariant dst) {
inline detail::enable_if_t<detail::IsString<T>::value> convertToJson(
const T& src, JsonVariant dst) {
using namespace detail;
auto data = VariantAttorney::getData(dst);
auto resources = VariantAttorney::getResourceManager(dst);
@@ -305,19 +309,6 @@ inline bool canConvertFromJson(JsonVariantConst src, const std::string_view&) {
#endif
namespace detail {
template <typename T>
struct ConverterNeedsWriteableRef {
protected: // <- to avoid GCC's "all member functions in class are private"
static int probe(T (*f)(ArduinoJson::JsonVariant));
static char probe(T (*f)(ArduinoJson::JsonVariantConst));
public:
static const bool value =
sizeof(probe(Converter<T>::fromJson)) == sizeof(int);
};
} // namespace detail
template <>
struct Converter<JsonArrayConst> : private detail::VariantAttorney {
static void toJson(JsonArrayConst src, JsonVariant dst) {
@@ -354,13 +345,6 @@ struct Converter<JsonArray> : private detail::VariantAttorney {
return JsonArray(data != 0 ? data->asArray() : 0, resources);
}
static detail::InvalidConversion<JsonVariantConst, JsonArray> fromJson(
JsonVariantConst);
static bool checkJson(JsonVariantConst) {
return false;
}
static bool checkJson(JsonVariant src) {
auto data = getData(src);
return data && data->isArray();
@@ -403,13 +387,6 @@ struct Converter<JsonObject> : private detail::VariantAttorney {
return JsonObject(data != 0 ? data->asObject() : 0, resources);
}
static detail::InvalidConversion<JsonVariantConst, JsonObject> fromJson(
JsonVariantConst);
static bool checkJson(JsonVariantConst) {
return false;
}
static bool checkJson(JsonVariant src) {
auto data = getData(src);
return data && data->isObject();

View File

@@ -53,17 +53,10 @@ struct Converter<JsonVariant> : private detail::VariantAttorney {
return src;
}
static detail::InvalidConversion<JsonVariantConst, JsonVariant> fromJson(
JsonVariantConst);
static bool checkJson(JsonVariant src) {
auto data = getData(src);
return !!data;
}
static bool checkJson(JsonVariantConst) {
return false;
}
};
template <>

View File

@@ -27,6 +27,12 @@ class JsonVariantConst : public detail::VariantTag,
public detail::VariantOperators<JsonVariantConst> {
friend class detail::VariantAttorney;
template <typename T>
using ConversionSupported =
detail::is_same<typename detail::function_traits<
decltype(&Converter<T>::fromJson)>::arg1_type,
JsonVariantConst>;
public:
// Creates an unbound reference.
JsonVariantConst() : data_(nullptr), resources_(nullptr) {}
@@ -61,24 +67,31 @@ class JsonVariantConst : public detail::VariantTag,
// Casts the value to the specified type.
// https://arduinojson.org/v7/api/jsonvariantconst/as/
template <typename T>
typename detail::enable_if<!detail::is_same<T, char*>::value &&
!detail::is_same<T, char>::value,
T>::type
as() const {
template <typename T,
detail::enable_if_t<ConversionSupported<T>::value, bool> = true>
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::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>
typename detail::enable_if<!detail::is_same<T, char*>::value &&
!detail::is_same<T, char>::value,
bool>::type
is() const {
detail::enable_if_t<ConversionSupported<T>::value, 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 {
return false;
}
template <typename T>
operator T() const {
return as<T>();
@@ -86,16 +99,18 @@ class JsonVariantConst : public detail::VariantTag,
// Gets array's element at specified index.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
JsonVariantConst operator[](size_t index) const {
template <typename T>
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
operator[](T index) const {
return JsonVariantConst(
detail::VariantData::getElement(data_, index, resources_), resources_);
detail::VariantData::getElement(data_, size_t(index), resources_),
resources_);
}
// Gets object's member with specified key.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename TString>
typename detail::enable_if<detail::IsString<TString>::value,
JsonVariantConst>::type
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
operator[](const TString& key) const {
return JsonVariantConst(detail::VariantData::getMember(
data_, detail::adaptString(key), resources_),
@@ -105,20 +120,30 @@ class JsonVariantConst : public detail::VariantTag,
// Gets object's member with specified key.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename TChar>
typename detail::enable_if<detail::IsString<TChar*>::value,
JsonVariantConst>::type
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
operator[](TChar* key) const {
return JsonVariantConst(detail::VariantData::getMember(
data_, detail::adaptString(key), resources_),
resources_);
}
// 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 {
if (key.template is<size_t>())
return operator[](key.template as<size_t>());
else
return operator[](key.template as<const char*>());
}
// Returns true if tge object contains the specified key.
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/
template <typename TString>
typename detail::enable_if<detail::IsString<TString>::value, bool>::type
containsKey(const TString& key) const {
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
const TString& key) const {
return detail::VariantData::getMember(getData(), detail::adaptString(key),
resources_) != 0;
}
@@ -126,13 +151,18 @@ class JsonVariantConst : public detail::VariantTag,
// Returns true if tge object contains the specified key.
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/
template <typename TChar>
typename detail::enable_if<detail::IsString<TChar*>::value, bool>::type
containsKey(TChar* key) const {
detail::enable_if_t<detail::IsString<TChar*>::value, bool> containsKey(
TChar* key) const {
return detail::VariantData::getMember(getData(), detail::adaptString(key),
resources_) != 0;
}
template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const {
return containsKey(key.template as<const char*>());
}
// DEPRECATED: always returns zero
ARDUINOJSON_DEPRECATED("always returns zero")
size_t memoryUsage() const {

View File

@@ -19,8 +19,7 @@ template <typename T, typename Enable = void>
struct Comparer;
template <typename T>
struct Comparer<T, typename enable_if<IsString<T>::value>::type>
: ComparerBase {
struct Comparer<T, enable_if_t<IsString<T>::value>> : ComparerBase {
T rhs; // TODO: store adapted string?
explicit Comparer(T value) : rhs(value) {}
@@ -46,8 +45,8 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
};
template <typename T>
struct Comparer<T, typename enable_if<is_integral<T>::value ||
is_floating_point<T>::value>::type>
struct Comparer<
T, enable_if_t<is_integral<T>::value || is_floating_point<T>::value>>
: ComparerBase {
T rhs;
@@ -200,8 +199,8 @@ struct VariantComparer : ComparerBase {
};
template <typename T>
struct Comparer<T, typename enable_if<is_convertible<
T, ArduinoJson::JsonVariantConst>::value>::type>
struct Comparer<
T, enable_if_t<is_convertible<T, ArduinoJson::JsonVariantConst>::value>>
: VariantComparer {
explicit Comparer(const T& value)
: VariantComparer(static_cast<JsonVariantConst>(value)) {}

View File

@@ -82,6 +82,21 @@ class VariantData {
return var->addElement(resources);
}
template <typename T>
bool addValue(T&& value, ResourceManager* resources) {
auto array = isNull() ? &toArray() : asArray();
return detail::ArrayData::addValue(array, detail::forward<T>(value),
resources);
}
template <typename T>
static bool addValue(VariantData* var, T&& value,
ResourceManager* resources) {
if (!var)
return false;
return var->addValue(value, resources);
}
bool asBoolean() const {
switch (type()) {
case VALUE_IS_BOOLEAN:
@@ -338,13 +353,13 @@ class VariantData {
}
template <typename T>
typename enable_if<is_signed<T>::value>::type setInteger(T value) {
enable_if_t<is_signed<T>::value> setInteger(T value) {
setType(VALUE_IS_SIGNED_INTEGER);
content_.asSignedInteger = value;
}
template <typename T>
typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
enable_if_t<is_unsigned<T>::value> setInteger(T value) {
setType(VALUE_IS_UNSIGNED_INTEGER);
content_.asUnsignedInteger = static_cast<JsonUInt>(value);
}

View File

@@ -31,9 +31,8 @@ struct VariantOperators : VariantOperatorTag {
// float operator|(JsonVariant, float)
// bool operator|(JsonVariant, bool)
template <typename T>
friend
typename enable_if<!IsVariant<T>::value && !is_array<T>::value, T>::type
operator|(const TVariant& variant, const T& defaultValue) {
friend enable_if_t<!IsVariant<T>::value && !is_array<T>::value, T> operator|(
const TVariant& variant, const T& defaultValue) {
if (variant.template is<T>())
return variant.template as<T>();
else
@@ -51,8 +50,8 @@ struct VariantOperators : VariantOperatorTag {
//
// JsonVariant operator|(JsonVariant, JsonVariant)
template <typename T>
friend typename enable_if<IsVariant<T>::value, JsonVariantConst>::type
operator|(const TVariant& variant, T defaultValue) {
friend enable_if_t<IsVariant<T>::value, JsonVariantConst> operator|(
const TVariant& variant, T defaultValue) {
if (variant)
return variant;
else
@@ -75,9 +74,8 @@ struct VariantOperators : VariantOperatorTag {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator==(TVariant lhs, const T& rhs) {
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
operator==(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
@@ -97,9 +95,8 @@ struct VariantOperators : VariantOperatorTag {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator!=(TVariant lhs, const T& rhs) {
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
operator!=(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
@@ -119,9 +116,8 @@ struct VariantOperators : VariantOperatorTag {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator<(TVariant lhs, const T& rhs) {
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> operator<(
TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
@@ -141,9 +137,8 @@ struct VariantOperators : VariantOperatorTag {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator<=(TVariant lhs, const T& rhs) {
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
operator<=(TVariant lhs, const T& rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
@@ -163,9 +158,8 @@ struct VariantOperators : VariantOperatorTag {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator>(TVariant lhs, const T& rhs) {
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> operator>(
TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
@@ -185,9 +179,8 @@ struct VariantOperators : VariantOperatorTag {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator>=(TVariant lhs, const T& rhs) {
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
operator>=(TVariant lhs, const T& rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
};

View File

@@ -46,19 +46,9 @@ class VariantRefBase : public VariantTag {
// Casts the value to the specified type.
// https://arduinojson.org/v7/api/jsonvariant/as/
template <typename T>
T as() const;
typename enable_if<!ConverterNeedsWriteableRef<T>::value, T>::type as()
const {
return Converter<T>::fromJson(getVariantConst());
}
// Casts the value to the specified type.
// https://arduinojson.org/v7/api/jsonvariant/as/
template <typename T>
typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type as() const;
template <typename T,
typename = typename enable_if<!is_same<T, TDerived>::value>::type>
template <typename T, typename = enable_if_t<!is_same<T, TDerived>::value>>
operator T() const {
return as<T>();
}
@@ -66,45 +56,36 @@ class VariantRefBase : public VariantTag {
// Sets the value to an empty array.
// https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T>
typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type to() const;
enable_if_t<is_same<T, JsonArray>::value, JsonArray> to() const;
// Sets the value to an empty object.
// https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type to()
const;
enable_if_t<is_same<T, JsonObject>::value, JsonObject> to() const;
// Sets the value to null.
// https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type to()
const;
enable_if_t<is_same<T, JsonVariant>::value, JsonVariant> to() const;
// Returns true if the value is of the specified type.
// https://arduinojson.org/v7/api/jsonvariant/is/
template <typename T>
FORCE_INLINE
typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
is() const;
FORCE_INLINE bool is() const;
// Returns true if the value is of the specified type.
// https://arduinojson.org/v7/api/jsonvariant/is/
// Copies the specified value.
// https://arduinojson.org/v7/api/jsonvariant/set/
template <typename T>
FORCE_INLINE
typename enable_if<!ConverterNeedsWriteableRef<T>::value, bool>::type
is() const {
return Converter<T>::checkJson(getVariantConst());
bool set(const T& value) const {
return doSet<Converter<remove_cv_t<T>>>(value);
}
// Copies the specified value.
// https://arduinojson.org/v7/api/jsonvariant/set/
template <typename T>
bool set(const T& value) const;
// Copies the specified value.
// https://arduinojson.org/v7/api/jsonvariant/set/
template <typename T>
bool set(T* value) const;
bool set(T* value) const {
return doSet<Converter<T*>>(value);
}
// Returns the size of the array or object.
// https://arduinojson.org/v7/api/jsonvariant/size/
@@ -122,7 +103,7 @@ class VariantRefBase : public VariantTag {
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T>
typename enable_if<!is_same<T, JsonVariant>::value, T>::type add() const {
enable_if_t<!is_same<T, JsonVariant>::value, T> add() const {
return add<JsonVariant>().template to<T>();
}
@@ -130,20 +111,22 @@ class VariantRefBase : public VariantTag {
// Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, T>::type add() const;
enable_if_t<is_same<T, JsonVariant>::value, T> add() const;
// Appends a value to the array.
// https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T>
bool add(const T& value) const {
return add<JsonVariant>().set(value);
return detail::VariantData::addValue(getOrCreateData(), value,
getResourceManager());
}
// Appends a value to the array.
// https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T>
bool add(T* value) const {
return add<JsonVariant>().set(value);
return detail::VariantData::addValue(getOrCreateData(), value,
getResourceManager());
}
// Removes an element of the array.
@@ -155,7 +138,7 @@ class VariantRefBase : public VariantTag {
// Removes a member of the object.
// https://arduinojson.org/v7/api/jsonvariant/remove/
template <typename TChar>
typename enable_if<IsString<TChar*>::value>::type remove(TChar* key) const {
enable_if_t<IsString<TChar*>::value> remove(TChar* key) const {
VariantData::removeMember(getData(), adaptString(key),
getResourceManager());
}
@@ -163,12 +146,21 @@ class VariantRefBase : public VariantTag {
// Removes a member of the object.
// https://arduinojson.org/v7/api/jsonvariant/remove/
template <typename TString>
typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const {
enable_if_t<IsString<TString>::value> 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 {
if (key.template is<size_t>())
remove(key.template as<size_t>());
else
remove(key.template as<const char*>());
}
// Gets or sets an array element.
// https://arduinojson.org/v7/api/jsonvariant/subscript/
ElementProxy<TDerived> operator[](size_t index) const;
@@ -176,28 +168,44 @@ class VariantRefBase : public VariantTag {
// Returns true if the object contains the specified key.
// https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TString>
typename enable_if<IsString<TString>::value, bool>::type containsKey(
enable_if_t<IsString<TString>::value, bool> containsKey(
const TString& key) const;
// Returns true if the object contains the specified key.
// https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TChar>
typename enable_if<IsString<TChar*>::value, bool>::type containsKey(
TChar* key) const;
enable_if_t<IsString<TChar*>::value, bool> containsKey(TChar* key) const;
// Returns true if the object contains the specified key.
// https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TVariant>
enable_if_t<IsVariant<TVariant>::value, bool> containsKey(
const TVariant& key) const;
// Gets or sets an object member.
// https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<TDerived, TString>>::type
operator[](const TString& key) const;
FORCE_INLINE
enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
operator[](const TString& key) const;
// Gets or sets an object member.
// https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<TDerived, TChar*>>::type
operator[](TChar* key) const;
FORCE_INLINE
enable_if_t<IsString<TChar*>::value, MemberProxy<TDerived, 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 {
if (key.template is<size_t>())
return operator[](key.template as<size_t>());
else
return operator[](key.template as<const char*>());
}
// DEPRECATED: use add<JsonVariant>() instead
ARDUINOJSON_DEPRECATED("use add<JsonVariant>() instead")
@@ -270,6 +278,33 @@ class VariantRefBase : public VariantTag {
return ArduinoJson::JsonVariantConst(getData(), getResourceManager());
}
template <typename T>
FORCE_INLINE enable_if_t<is_same<T, JsonVariantConst>::value, T> getVariant()
const {
return getVariantConst();
}
template <typename T>
FORCE_INLINE enable_if_t<is_same<T, JsonVariant>::value, T> getVariant()
const {
return getVariant();
}
template <typename TConverter, typename T>
bool doSet(T&& value) const {
return doSet<TConverter>(
detail::forward<T>(value),
is_same<typename function_traits<
decltype(&TConverter::toJson)>::return_type,
bool>{});
}
template <typename TConverter, typename T>
bool doSet(T&& value, false_type) const;
template <typename TConverter, typename T>
bool doSet(T&& value, true_type) const;
ArduinoJson::JsonVariant getOrCreateVariant() const;
};

View File

@@ -17,9 +17,10 @@ inline JsonVariant VariantRefBase<TDerived>::add() const {
template <typename TDerived>
template <typename T>
inline typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
VariantRefBase<TDerived>::as() const {
return Converter<T>::fromJson(getVariant());
inline T VariantRefBase<TDerived>::as() const {
using variant_type = // JsonVariantConst or JsonVariant?
typename function_traits<decltype(&Converter<T>::fromJson)>::arg1_type;
return Converter<T>::fromJson(getVariant<variant_type>());
}
template <typename TDerived>
@@ -67,7 +68,7 @@ inline void convertToJson(const VariantRefBase<TDerived>& src,
template <typename TDerived>
template <typename T>
inline typename enable_if<is_same<T, JsonVariant>::value, T>::type
inline enable_if_t<is_same<T, JsonVariant>::value, T>
VariantRefBase<TDerived>::add() const {
return JsonVariant(
detail::VariantData::addElement(getOrCreateData(), getResourceManager()),
@@ -76,7 +77,7 @@ VariantRefBase<TDerived>::add() const {
template <typename TDerived>
template <typename TString>
inline typename enable_if<IsString<TString>::value, bool>::type
inline enable_if_t<IsString<TString>::value, bool>
VariantRefBase<TDerived>::containsKey(const TString& key) const {
return VariantData::getMember(getData(), adaptString(key),
getResourceManager()) != 0;
@@ -84,12 +85,19 @@ VariantRefBase<TDerived>::containsKey(const TString& key) const {
template <typename TDerived>
template <typename TChar>
inline typename enable_if<IsString<TChar*>::value, bool>::type
inline enable_if_t<IsString<TChar*>::value, 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 {
return containsKey(key.template as<const char*>());
}
template <typename TDerived>
inline JsonVariant VariantRefBase<TDerived>::getVariant() const {
return JsonVariant(getData(), getResourceManager());
@@ -102,9 +110,10 @@ inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant() const {
template <typename TDerived>
template <typename T>
inline typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
VariantRefBase<TDerived>::is() const {
return Converter<T>::checkJson(getVariant());
inline bool VariantRefBase<TDerived>::is() const {
using variant_type = // JsonVariantConst or JsonVariant?
typename function_traits<decltype(&Converter<T>::checkJson)>::arg1_type;
return Converter<T>::checkJson(getVariant<variant_type>());
}
template <typename TDerived>
@@ -115,40 +124,35 @@ inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
template <typename TDerived>
template <typename TString>
inline typename enable_if<IsString<TString*>::value,
MemberProxy<TDerived, TString*>>::type
inline enable_if_t<IsString<TString*>::value, MemberProxy<TDerived, TString*>>
VariantRefBase<TDerived>::operator[](TString* key) const {
return MemberProxy<TDerived, TString*>(derived(), key);
}
template <typename TDerived>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
MemberProxy<TDerived, TString>>::type
inline enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
VariantRefBase<TDerived>::operator[](const TString& key) const {
return MemberProxy<TDerived, TString>(derived(), key);
}
template <typename TDerived>
template <typename T>
inline bool VariantRefBase<TDerived>::set(const T& value) const {
Converter<typename detail::remove_cv<T>::type>::toJson(value,
getOrCreateVariant());
template <typename TConverter, typename T>
inline bool VariantRefBase<TDerived>::doSet(T&& value, false_type) const {
TConverter::toJson(value, getOrCreateVariant());
auto resources = getResourceManager();
return resources && !resources->overflowed();
}
template <typename TDerived>
template <typename T>
inline bool VariantRefBase<TDerived>::set(T* value) const {
Converter<T*>::toJson(value, getOrCreateVariant());
auto resources = getResourceManager();
return resources && !resources->overflowed();
template <typename TConverter, typename T>
inline bool VariantRefBase<TDerived>::doSet(T&& value, true_type) const {
return TConverter::toJson(value, getOrCreateVariant());
}
template <typename TDerived>
template <typename T>
inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type
inline enable_if_t<is_same<T, JsonArray>::value, JsonArray>
VariantRefBase<TDerived>::to() const {
return JsonArray(
VariantData::toArray(getOrCreateData(), getResourceManager()),
@@ -157,7 +161,7 @@ VariantRefBase<TDerived>::to() const {
template <typename TDerived>
template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
enable_if_t<is_same<T, JsonObject>::value, JsonObject>
VariantRefBase<TDerived>::to() const {
return JsonObject(
VariantData::toObject(getOrCreateData(), getResourceManager()),
@@ -166,7 +170,7 @@ VariantRefBase<TDerived>::to() const {
template <typename TDerived>
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
enable_if_t<is_same<T, JsonVariant>::value, JsonVariant>
VariantRefBase<TDerived>::to() const {
auto data = getOrCreateData();
auto resources = getResourceManager();

View File

@@ -4,8 +4,8 @@
#pragma once
#define ARDUINOJSON_VERSION "7.0.4"
#define ARDUINOJSON_VERSION "7.1.0"
#define ARDUINOJSON_VERSION_MAJOR 7
#define ARDUINOJSON_VERSION_MINOR 0
#define ARDUINOJSON_VERSION_REVISION 4
#define ARDUINOJSON_VERSION_MACRO V704
#define ARDUINOJSON_VERSION_MINOR 1
#define ARDUINOJSON_VERSION_REVISION 0
#define ARDUINOJSON_VERSION_MACRO V710