Update ArduinoJSON
This commit is contained in:
@@ -19,10 +19,10 @@ class ArrayData : public CollectionData {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool addValue(T&& value, ResourceManager* resources);
|
||||
bool addValue(const T& value, ResourceManager* resources);
|
||||
|
||||
template <typename T>
|
||||
static bool addValue(ArrayData* array, T&& value,
|
||||
static bool addValue(ArrayData* array, const T& value,
|
||||
ResourceManager* resources) {
|
||||
if (!array)
|
||||
return false;
|
||||
|
||||
@@ -57,13 +57,13 @@ inline void ArrayData::removeElement(size_t index, ResourceManager* resources) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
|
||||
inline bool ArrayData::addValue(const T& value, ResourceManager* resources) {
|
||||
ARDUINOJSON_ASSERT(resources != nullptr);
|
||||
auto slot = resources->allocVariant();
|
||||
if (!slot)
|
||||
return false;
|
||||
JsonVariant variant(slot.ptr(), resources);
|
||||
if (!variant.set(detail::forward<T>(value))) {
|
||||
if (!variant.set(value)) {
|
||||
resources->freeVariant(slot);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,18 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
|
||||
public VariantOperators<ElementProxy<TUpstream>> {
|
||||
friend class VariantAttorney;
|
||||
|
||||
friend class VariantRefBase<ElementProxy<TUpstream>>;
|
||||
|
||||
template <typename, typename>
|
||||
friend class MemberProxy;
|
||||
|
||||
template <typename>
|
||||
friend class ElementProxy;
|
||||
|
||||
public:
|
||||
ElementProxy(TUpstream upstream, size_t index)
|
||||
: upstream_(upstream), index_(index) {}
|
||||
|
||||
ElementProxy(const ElementProxy& src)
|
||||
: upstream_(src.upstream_), index_(src.index_) {}
|
||||
|
||||
ElementProxy& operator=(const ElementProxy& src) {
|
||||
this->set(src);
|
||||
return *this;
|
||||
@@ -40,6 +45,11 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
|
||||
}
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
ElementProxy(const ElementProxy& src) // Error here? See https://arduinojson.org/v7/proxy-non-copyable/
|
||||
: upstream_(src.upstream_), index_(src.index_) {}
|
||||
// clang-format on
|
||||
|
||||
ResourceManager* getResourceManager() const {
|
||||
return VariantAttorney::getResourceManager(upstream_);
|
||||
}
|
||||
|
||||
@@ -43,16 +43,18 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
||||
// Appends a new (empty) element to the array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
||||
template <typename T>
|
||||
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() const {
|
||||
template <typename T, detail::enable_if_t<
|
||||
!detail::is_same<T, JsonVariant>::value, int> = 0>
|
||||
T add() const {
|
||||
return add<JsonVariant>().to<T>();
|
||||
}
|
||||
|
||||
// Appends a new (null) element to the array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
||||
template <typename T>
|
||||
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() const {
|
||||
template <typename T, detail::enable_if_t<
|
||||
detail::is_same<T, JsonVariant>::value, int> = 0>
|
||||
JsonVariant add() const {
|
||||
return JsonVariant(detail::ArrayData::addElement(data_, resources_),
|
||||
resources_);
|
||||
}
|
||||
@@ -66,7 +68,8 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
||||
|
||||
// Appends a value to the array.
|
||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
||||
template <typename T>
|
||||
template <typename T,
|
||||
detail::enable_if_t<!detail::is_const<T>::value, int> = 0>
|
||||
bool add(T* value) const {
|
||||
return detail::ArrayData::addValue(data_, value, resources_);
|
||||
}
|
||||
@@ -114,9 +117,9 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
||||
|
||||
// Removes the element at the specified index.
|
||||
// https://arduinojson.org/v7/api/jsonarray/remove/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove(
|
||||
TVariant variant) const {
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
void remove(const TVariant& variant) const {
|
||||
if (variant.template is<size_t>())
|
||||
remove(variant.template as<size_t>());
|
||||
}
|
||||
@@ -129,21 +132,19 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
||||
|
||||
// Gets or sets the element at the specified index.
|
||||
// https://arduinojson.org/v7/api/jsonarray/subscript/
|
||||
template <typename T>
|
||||
detail::enable_if_t<detail::is_integral<T>::value,
|
||||
detail::ElementProxy<JsonArray>>
|
||||
operator[](T index) const {
|
||||
template <typename T,
|
||||
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
|
||||
detail::ElementProxy<JsonArray> operator[](T index) const {
|
||||
return {*this, size_t(index)};
|
||||
}
|
||||
|
||||
// Gets or sets the element at the specified index.
|
||||
// https://arduinojson.org/v7/api/jsonarray/subscript/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value,
|
||||
detail::ElementProxy<JsonArray>>
|
||||
operator[](const TVariant& variant) const {
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
detail::ElementProxy<JsonArray> operator[](const TVariant& variant) const {
|
||||
if (variant.template is<size_t>())
|
||||
return operator[](variant.template as<size_t>());
|
||||
return {*this, variant.template as<size_t>()};
|
||||
else
|
||||
return {*this, size_t(-1)};
|
||||
}
|
||||
|
||||
@@ -45,9 +45,9 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
||||
|
||||
// Returns the element at the specified index.
|
||||
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
|
||||
template <typename T>
|
||||
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
|
||||
operator[](T index) const {
|
||||
template <typename T,
|
||||
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
|
||||
JsonVariantConst operator[](T index) const {
|
||||
return JsonVariantConst(
|
||||
detail::ArrayData::getElement(data_, size_t(index), resources_),
|
||||
resources_);
|
||||
@@ -55,9 +55,9 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
||||
|
||||
// Returns the element at the specified index.
|
||||
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
|
||||
operator[](const TVariant& variant) const {
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
JsonVariantConst operator[](const TVariant& variant) const {
|
||||
if (variant.template is<size_t>())
|
||||
return operator[](variant.template as<size_t>());
|
||||
else
|
||||
|
||||
@@ -11,27 +11,26 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||
|
||||
// Copies a value to a JsonVariant.
|
||||
// This is a degenerated form of copyArray() to stop the recursion.
|
||||
template <typename T>
|
||||
inline detail::enable_if_t<!detail::is_array<T>::value, bool> copyArray(
|
||||
const T& src, JsonVariant dst) {
|
||||
template <typename T, detail::enable_if_t<!detail::is_array<T>::value, int> = 0>
|
||||
inline bool copyArray(const T& src, JsonVariant dst) {
|
||||
return dst.set(src);
|
||||
}
|
||||
|
||||
// Copies values from an array to a JsonArray or a JsonVariant.
|
||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
||||
template <typename T, size_t N, typename TDestination>
|
||||
inline detail::enable_if_t<
|
||||
!detail::is_base_of<JsonDocument, TDestination>::value, bool>
|
||||
copyArray(T (&src)[N], const TDestination& dst) {
|
||||
template <typename T, size_t N, typename TDestination,
|
||||
detail::enable_if_t<
|
||||
!detail::is_base_of<JsonDocument, TDestination>::value, int> = 0>
|
||||
inline bool copyArray(T (&src)[N], const TDestination& dst) {
|
||||
return copyArray(src, N, dst);
|
||||
}
|
||||
|
||||
// Copies values from an array to a JsonArray or a JsonVariant.
|
||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
||||
template <typename T, typename TDestination>
|
||||
inline detail::enable_if_t<
|
||||
!detail::is_base_of<JsonDocument, TDestination>::value, bool>
|
||||
copyArray(const T* src, size_t len, const TDestination& dst) {
|
||||
template <typename T, typename TDestination,
|
||||
detail::enable_if_t<
|
||||
!detail::is_base_of<JsonDocument, TDestination>::value, int> = 0>
|
||||
inline bool copyArray(const T* src, size_t len, const TDestination& dst) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ok &= copyArray(src[i], dst.template add<JsonVariant>());
|
||||
@@ -62,9 +61,8 @@ inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
|
||||
|
||||
// Copies a value from a JsonVariant.
|
||||
// This is a degenerated form of copyArray() to stop the recursion.
|
||||
template <typename T>
|
||||
inline detail::enable_if_t<!detail::is_array<T>::value, size_t> copyArray(
|
||||
JsonVariantConst src, T& dst) {
|
||||
template <typename T, detail::enable_if_t<!detail::is_array<T>::value, int> = 0>
|
||||
inline size_t copyArray(JsonVariantConst src, T& dst) {
|
||||
dst = src.as<T>();
|
||||
return 1;
|
||||
}
|
||||
@@ -102,11 +100,12 @@ inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) {
|
||||
|
||||
// Copies values from a JsonDocument to an array.
|
||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
||||
template <typename TSource, typename T>
|
||||
inline detail::enable_if_t<detail::is_array<T>::value &&
|
||||
detail::is_base_of<JsonDocument, TSource>::value,
|
||||
size_t>
|
||||
copyArray(const TSource& src, T& dst) {
|
||||
template <
|
||||
typename TSource, typename T,
|
||||
detail::enable_if_t<detail::is_array<T>::value &&
|
||||
detail::is_base_of<JsonDocument, TSource>::value,
|
||||
int> = 0>
|
||||
inline size_t copyArray(const TSource& src, T& dst) {
|
||||
return copyArray(src.template as<JsonArrayConst>(), dst);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
// The default reader is a simple wrapper for Readers that are not copiable
|
||||
// The default reader is a simple wrapper for Readers that are not copyable
|
||||
template <typename TSource, typename Enable = void>
|
||||
struct Reader {
|
||||
public:
|
||||
|
||||
@@ -55,10 +55,11 @@ DeserializationError doDeserialize(TDestination&& dst, TReader reader,
|
||||
return err;
|
||||
}
|
||||
|
||||
template <template <typename> class TDeserializer, typename TDestination,
|
||||
typename TStream, typename... Args,
|
||||
typename = enable_if_t< // issue #1897
|
||||
!is_integral<typename first_or_void<Args...>::type>::value>>
|
||||
template <
|
||||
template <typename> class TDeserializer, typename TDestination,
|
||||
typename TStream, typename... Args,
|
||||
enable_if_t< // issue #1897
|
||||
!is_integral<typename first_or_void<Args...>::type>::value, int> = 0>
|
||||
DeserializationError deserialize(TDestination&& dst, TStream&& input,
|
||||
Args... args) {
|
||||
return doDeserialize<TDeserializer>(
|
||||
@@ -68,7 +69,7 @@ DeserializationError deserialize(TDestination&& dst, TStream&& input,
|
||||
|
||||
template <template <typename> class TDeserializer, typename TDestination,
|
||||
typename TChar, typename Size, typename... Args,
|
||||
typename = enable_if_t<is_integral<Size>::value>>
|
||||
enable_if_t<is_integral<Size>::value, int> = 0>
|
||||
DeserializationError deserialize(TDestination&& dst, TChar* input,
|
||||
Size inputSize, Args... args) {
|
||||
return doDeserialize<TDeserializer>(dst, makeReader(input, size_t(inputSize)),
|
||||
|
||||
@@ -36,14 +36,15 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||
}
|
||||
|
||||
// Construct from variant, array, or object
|
||||
template <typename T>
|
||||
JsonDocument(
|
||||
const T& src, Allocator* alloc = detail::DefaultAllocator::instance(),
|
||||
detail::enable_if_t<detail::IsVariant<T>::value ||
|
||||
detail::is_same<T, JsonArray>::value ||
|
||||
detail::is_same<T, JsonArrayConst>::value ||
|
||||
detail::is_same<T, JsonObject>::value ||
|
||||
detail::is_same<T, JsonObjectConst>::value>* = 0)
|
||||
template <typename T,
|
||||
detail::enable_if_t<detail::IsVariant<T>::value ||
|
||||
detail::is_same<T, JsonArray>::value ||
|
||||
detail::is_same<T, JsonArrayConst>::value ||
|
||||
detail::is_same<T, JsonObject>::value ||
|
||||
detail::is_same<T, JsonObjectConst>::value,
|
||||
int> = 0>
|
||||
JsonDocument(const T& src,
|
||||
Allocator* alloc = detail::DefaultAllocator::instance())
|
||||
: JsonDocument(alloc) {
|
||||
set(src);
|
||||
}
|
||||
@@ -136,15 +137,17 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||
|
||||
// Replaces the root with the specified value.
|
||||
// https://arduinojson.org/v7/api/jsondocument/set/
|
||||
template <typename T>
|
||||
detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, bool> set(
|
||||
const T& src) {
|
||||
template <
|
||||
typename T,
|
||||
detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, int> = 0>
|
||||
bool set(const T& src) {
|
||||
return to<JsonVariant>().set(src);
|
||||
}
|
||||
|
||||
// Replaces the root with the specified value.
|
||||
// https://arduinojson.org/v7/api/jsondocument/set/
|
||||
template <typename TChar>
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<!detail::is_const<TChar>::value, int> = 0>
|
||||
bool set(TChar* src) {
|
||||
return to<JsonVariant>().set(src);
|
||||
}
|
||||
@@ -167,64 +170,67 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsondocument/containskey/
|
||||
template <typename TString>
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
|
||||
const TString& key) const {
|
||||
bool containsKey(const TString& key) const {
|
||||
return data_.getMember(detail::adaptString(key), &resources_) != 0;
|
||||
}
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsondocument/containskey/
|
||||
template <typename TVariant>
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
|
||||
const TVariant& key) const {
|
||||
bool containsKey(const TVariant& key) const {
|
||||
return containsKey(key.template as<const char*>());
|
||||
}
|
||||
|
||||
// Gets or sets a root object's member.
|
||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||
template <typename TString>
|
||||
detail::enable_if_t<detail::IsString<TString>::value,
|
||||
detail::MemberProxy<JsonDocument&, TString>>
|
||||
operator[](const TString& key) {
|
||||
return {*this, key};
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
detail::MemberProxy<JsonDocument&, detail::AdaptedString<TString>> operator[](
|
||||
const TString& key) {
|
||||
return {*this, detail::adaptString(key)};
|
||||
}
|
||||
|
||||
// Gets or sets a root object's member.
|
||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||
template <typename TChar>
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value,
|
||||
detail::MemberProxy<JsonDocument&, TChar*>>
|
||||
operator[](TChar* key) {
|
||||
return {*this, key};
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value &&
|
||||
!detail::is_const<TChar>::value,
|
||||
int> = 0>
|
||||
detail::MemberProxy<JsonDocument&, detail::AdaptedString<TChar*>> operator[](
|
||||
TChar* key) {
|
||||
return {*this, detail::adaptString(key)};
|
||||
}
|
||||
|
||||
// Gets a root object's member.
|
||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||
template <typename TString>
|
||||
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
|
||||
operator[](const TString& key) const {
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
JsonVariantConst operator[](const TString& key) const {
|
||||
return JsonVariantConst(
|
||||
data_.getMember(detail::adaptString(key), &resources_), &resources_);
|
||||
}
|
||||
|
||||
// Gets a root object's member.
|
||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||
template <typename TChar>
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
|
||||
operator[](TChar* key) const {
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value &&
|
||||
!detail::is_const<TChar>::value,
|
||||
int> = 0>
|
||||
JsonVariantConst operator[](TChar* key) const {
|
||||
return JsonVariantConst(
|
||||
data_.getMember(detail::adaptString(key), &resources_), &resources_);
|
||||
}
|
||||
|
||||
// Gets or sets a root array's element.
|
||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||
template <typename T>
|
||||
detail::enable_if_t<detail::is_integral<T>::value,
|
||||
detail::ElementProxy<JsonDocument&>>
|
||||
operator[](T index) {
|
||||
template <typename T,
|
||||
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
|
||||
detail::ElementProxy<JsonDocument&> operator[](T index) {
|
||||
return {*this, size_t(index)};
|
||||
}
|
||||
|
||||
@@ -236,9 +242,9 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||
|
||||
// Gets or sets a root object's member.
|
||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
|
||||
operator[](const TVariant& key) const {
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
JsonVariantConst operator[](const TVariant& key) const {
|
||||
if (key.template is<JsonString>())
|
||||
return operator[](key.template as<JsonString>());
|
||||
if (key.template is<size_t>())
|
||||
@@ -249,16 +255,18 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||
// Appends a new (empty) element to the root array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
||||
template <typename T>
|
||||
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() {
|
||||
template <typename T, detail::enable_if_t<
|
||||
!detail::is_same<T, JsonVariant>::value, int> = 0>
|
||||
T add() {
|
||||
return add<JsonVariant>().to<T>();
|
||||
}
|
||||
|
||||
// Appends a new (null) element to the root array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
||||
template <typename T>
|
||||
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() {
|
||||
template <typename T, detail::enable_if_t<
|
||||
detail::is_same<T, JsonVariant>::value, int> = 0>
|
||||
JsonVariant add() {
|
||||
return JsonVariant(data_.addElement(&resources_), &resources_);
|
||||
}
|
||||
|
||||
@@ -271,41 +279,46 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||
|
||||
// Appends a value to the root array.
|
||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
||||
template <typename TChar>
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<!detail::is_const<TChar>::value, int> = 0>
|
||||
bool add(TChar* value) {
|
||||
return data_.addValue(value, &resources_);
|
||||
}
|
||||
|
||||
// Removes an element of the root array.
|
||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
||||
template <typename T>
|
||||
detail::enable_if_t<detail::is_integral<T>::value> remove(T index) {
|
||||
template <typename T,
|
||||
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
|
||||
void remove(T index) {
|
||||
detail::VariantData::removeElement(getData(), size_t(index),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
// Removes a member of the root object.
|
||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
||||
template <typename TChar>
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value> remove(TChar* key) {
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value &&
|
||||
!detail::is_const<TChar>::value,
|
||||
int> = 0>
|
||||
void remove(TChar* key) {
|
||||
detail::VariantData::removeMember(getData(), detail::adaptString(key),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
// Removes a member of the root object.
|
||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
||||
template <typename TString>
|
||||
detail::enable_if_t<detail::IsString<TString>::value> remove(
|
||||
const TString& key) {
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
void remove(const TString& key) {
|
||||
detail::VariantData::removeMember(getData(), detail::adaptString(key),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
// Removes a member of the root object or an element of the root array.
|
||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove(
|
||||
const TVariant& key) {
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
void remove(const TVariant& key) {
|
||||
if (key.template is<const char*>())
|
||||
remove(key.template as<const char*>());
|
||||
if (key.template is<size_t>())
|
||||
|
||||
@@ -270,10 +270,10 @@ class JsonDeserializer {
|
||||
|
||||
JsonString key = stringBuilder_.str();
|
||||
|
||||
TFilter memberFilter = filter[key.c_str()];
|
||||
TFilter memberFilter = filter[key];
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
auto member = object.getMember(adaptString(key.c_str()), resources_);
|
||||
auto member = object.getMember(adaptString(key), resources_);
|
||||
if (!member) {
|
||||
// Save key in memory pool.
|
||||
auto savedKey = stringBuilder_.save();
|
||||
@@ -697,10 +697,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v7/api/json/deserializejson/
|
||||
template <typename TDestination, typename... Args>
|
||||
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
|
||||
DeserializationError>
|
||||
deserializeJson(TDestination&& dst, Args&&... args) {
|
||||
template <typename TDestination, typename... Args,
|
||||
detail::enable_if_t<
|
||||
detail::is_deserialize_destination<TDestination>::value, int> = 0>
|
||||
inline DeserializationError deserializeJson(TDestination&& dst,
|
||||
Args&&... args) {
|
||||
using namespace detail;
|
||||
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
|
||||
detail::forward<Args>(args)...);
|
||||
@@ -708,10 +709,11 @@ deserializeJson(TDestination&& dst, Args&&... args) {
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v7/api/json/deserializejson/
|
||||
template <typename TDestination, typename TChar, typename... Args>
|
||||
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
|
||||
DeserializationError>
|
||||
deserializeJson(TDestination&& dst, TChar* input, Args&&... args) {
|
||||
template <typename TDestination, typename TChar, typename... Args,
|
||||
detail::enable_if_t<
|
||||
detail::is_deserialize_destination<TDestination>::value, int> = 0>
|
||||
inline DeserializationError deserializeJson(TDestination&& dst, TChar* input,
|
||||
Args&&... args) {
|
||||
using namespace detail;
|
||||
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
|
||||
input, detail::forward<Args>(args)...);
|
||||
|
||||
@@ -129,9 +129,10 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||
|
||||
// Produces a minified JSON document.
|
||||
// https://arduinojson.org/v7/api/json/serializejson/
|
||||
template <typename TDestination>
|
||||
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t>
|
||||
serializeJson(JsonVariantConst source, TDestination& destination) {
|
||||
template <
|
||||
typename TDestination,
|
||||
detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
|
||||
size_t serializeJson(JsonVariantConst source, TDestination& destination) {
|
||||
using namespace detail;
|
||||
return serialize<JsonSerializer>(source, destination);
|
||||
}
|
||||
@@ -152,10 +153,10 @@ inline size_t measureJson(JsonVariantConst source) {
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
template <typename T>
|
||||
inline detail::enable_if_t<detail::is_convertible<T, JsonVariantConst>::value,
|
||||
std::ostream&>
|
||||
operator<<(std::ostream& os, const T& source) {
|
||||
template <typename T,
|
||||
detail::enable_if_t<
|
||||
detail::is_convertible<T, JsonVariantConst>::value, int> = 0>
|
||||
inline std::ostream& operator<<(std::ostream& os, const T& source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -83,9 +83,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||
|
||||
// Produces JsonDocument to create a prettified JSON document.
|
||||
// https://arduinojson.org/v7/api/json/serializejsonpretty/
|
||||
template <typename TDestination>
|
||||
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t>
|
||||
serializeJsonPretty(JsonVariantConst source, TDestination& destination) {
|
||||
template <
|
||||
typename TDestination,
|
||||
detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
|
||||
inline size_t serializeJsonPretty(JsonVariantConst source,
|
||||
TDestination& destination) {
|
||||
using namespace ArduinoJson::detail;
|
||||
return serialize<PrettyJsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class StringBuffer {
|
||||
JsonString str() const {
|
||||
ARDUINOJSON_ASSERT(node_ != nullptr);
|
||||
|
||||
return JsonString(node_->data, node_->length, JsonString::Copied);
|
||||
return JsonString(node_->data, node_->length);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -68,7 +68,7 @@ class StringBuilder {
|
||||
JsonString str() const {
|
||||
ARDUINOJSON_ASSERT(node_ != nullptr);
|
||||
node_->data[size_] = 0;
|
||||
return JsonString(node_->data, size_, JsonString::Copied);
|
||||
return JsonString(node_->data, size_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2024, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
#include <ArduinoJson/Polyfills/integer.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
class VariantSlot;
|
||||
using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
|
||||
using SlotCount = SlotId;
|
||||
const SlotId NULL_SLOT = SlotId(-1);
|
||||
|
||||
class SlotWithId {
|
||||
public:
|
||||
SlotWithId() : slot_(nullptr), id_(NULL_SLOT) {}
|
||||
SlotWithId(VariantSlot* slot, SlotId id) : slot_(slot), id_(id) {
|
||||
ARDUINOJSON_ASSERT((slot == nullptr) == (id == NULL_SLOT));
|
||||
}
|
||||
|
||||
SlotId id() const {
|
||||
return id_;
|
||||
}
|
||||
|
||||
operator VariantSlot*() {
|
||||
return slot_;
|
||||
}
|
||||
|
||||
VariantSlot* operator->() {
|
||||
ARDUINOJSON_ASSERT(slot_ != nullptr);
|
||||
return slot_;
|
||||
}
|
||||
|
||||
private:
|
||||
VariantSlot* slot_;
|
||||
SlotId id_;
|
||||
};
|
||||
|
||||
class VariantPool {
|
||||
public:
|
||||
void create(SlotCount cap, Allocator* allocator);
|
||||
void destroy(Allocator* allocator);
|
||||
|
||||
SlotWithId allocSlot();
|
||||
VariantSlot* getSlot(SlotId id) const;
|
||||
void clear();
|
||||
void shrinkToFit(Allocator*);
|
||||
SlotCount usage() const;
|
||||
|
||||
static SlotCount bytesToSlots(size_t);
|
||||
static size_t slotsToBytes(SlotCount);
|
||||
|
||||
private:
|
||||
SlotCount capacity_;
|
||||
SlotCount usage_;
|
||||
VariantSlot* slots_;
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
@@ -1,81 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2024, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/VariantPool.hpp>
|
||||
#include <ArduinoJson/Variant/VariantSlot.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
inline void VariantPool::create(SlotCount cap, Allocator* allocator) {
|
||||
ARDUINOJSON_ASSERT(cap > 0);
|
||||
slots_ =
|
||||
reinterpret_cast<VariantSlot*>(allocator->allocate(slotsToBytes(cap)));
|
||||
capacity_ = slots_ ? cap : 0;
|
||||
usage_ = 0;
|
||||
}
|
||||
|
||||
inline void VariantPool::destroy(Allocator* allocator) {
|
||||
if (slots_)
|
||||
allocator->deallocate(slots_);
|
||||
slots_ = nullptr;
|
||||
capacity_ = 0;
|
||||
usage_ = 0;
|
||||
}
|
||||
|
||||
inline void VariantPool::shrinkToFit(Allocator* allocator) {
|
||||
auto newSlots = reinterpret_cast<VariantSlot*>(
|
||||
allocator->reallocate(slots_, slotsToBytes(usage_)));
|
||||
if (newSlots) {
|
||||
slots_ = newSlots;
|
||||
capacity_ = usage_;
|
||||
}
|
||||
}
|
||||
|
||||
inline SlotWithId VariantPool::allocSlot() {
|
||||
if (!slots_)
|
||||
return {};
|
||||
if (usage_ >= capacity_)
|
||||
return {};
|
||||
auto index = usage_++;
|
||||
auto slot = &slots_[index];
|
||||
return {new (slot) VariantSlot, SlotId(index)};
|
||||
}
|
||||
|
||||
inline VariantSlot* VariantPool::getSlot(SlotId id) const {
|
||||
ARDUINOJSON_ASSERT(id < usage_);
|
||||
return &slots_[id];
|
||||
}
|
||||
|
||||
inline SlotCount VariantPool::usage() const {
|
||||
return usage_;
|
||||
}
|
||||
|
||||
inline void VariantPool::clear() {
|
||||
usage_ = 0;
|
||||
}
|
||||
|
||||
inline SlotCount VariantPool::bytesToSlots(size_t n) {
|
||||
return static_cast<SlotCount>(n / sizeof(VariantSlot));
|
||||
}
|
||||
|
||||
inline size_t VariantPool::slotsToBytes(SlotCount n) {
|
||||
return n * sizeof(VariantSlot);
|
||||
}
|
||||
|
||||
inline SlotWithId VariantPoolList::allocFromFreeList() {
|
||||
ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
|
||||
auto id = freeList_;
|
||||
auto slot = getSlot(freeList_);
|
||||
freeList_ = slot->next();
|
||||
return {new (slot) VariantSlot, id};
|
||||
}
|
||||
|
||||
inline void VariantPoolList::freeSlot(SlotWithId slot) {
|
||||
slot->setNext(freeList_);
|
||||
freeList_ = slot.id();
|
||||
}
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
@@ -1,189 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2024, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/VariantPool.hpp>
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
using PoolCount = SlotId;
|
||||
|
||||
class VariantPoolList {
|
||||
public:
|
||||
VariantPoolList() = default;
|
||||
|
||||
~VariantPoolList() {
|
||||
ARDUINOJSON_ASSERT(count_ == 0);
|
||||
}
|
||||
|
||||
friend void swap(VariantPoolList& a, VariantPoolList& b) {
|
||||
bool aUsedPreallocated = a.pools_ == a.preallocatedPools_;
|
||||
bool bUsedPreallocated = b.pools_ == b.preallocatedPools_;
|
||||
|
||||
// Who is using preallocated pools?
|
||||
if (aUsedPreallocated && bUsedPreallocated) {
|
||||
// both of us => swap preallocated pools
|
||||
for (PoolCount i = 0; i < ARDUINOJSON_INITIAL_POOL_COUNT; i++)
|
||||
swap_(a.preallocatedPools_[i], b.preallocatedPools_[i]);
|
||||
} else if (bUsedPreallocated) {
|
||||
// only b => copy b's preallocated pools and give him a's pointer
|
||||
for (PoolCount i = 0; i < b.count_; i++)
|
||||
a.preallocatedPools_[i] = b.preallocatedPools_[i];
|
||||
b.pools_ = a.pools_;
|
||||
a.pools_ = a.preallocatedPools_;
|
||||
} else if (aUsedPreallocated) {
|
||||
// only a => copy a's preallocated pools and give him b's pointer
|
||||
for (PoolCount i = 0; i < a.count_; i++)
|
||||
b.preallocatedPools_[i] = a.preallocatedPools_[i];
|
||||
a.pools_ = b.pools_;
|
||||
b.pools_ = b.preallocatedPools_;
|
||||
} else {
|
||||
// neither => swap pointers
|
||||
swap_(a.pools_, b.pools_);
|
||||
}
|
||||
|
||||
swap_(a.count_, b.count_);
|
||||
swap_(a.capacity_, b.capacity_);
|
||||
swap_(a.freeList_, b.freeList_);
|
||||
}
|
||||
|
||||
VariantPoolList& operator=(VariantPoolList&& src) {
|
||||
ARDUINOJSON_ASSERT(count_ == 0);
|
||||
if (src.pools_ == src.preallocatedPools_) {
|
||||
memcpy(preallocatedPools_, src.preallocatedPools_,
|
||||
sizeof(preallocatedPools_));
|
||||
pools_ = preallocatedPools_;
|
||||
} else {
|
||||
pools_ = src.pools_;
|
||||
src.pools_ = nullptr;
|
||||
}
|
||||
count_ = src.count_;
|
||||
capacity_ = src.capacity_;
|
||||
src.count_ = 0;
|
||||
src.capacity_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SlotWithId allocSlot(Allocator* allocator) {
|
||||
// try to allocate from free list
|
||||
if (freeList_ != NULL_SLOT) {
|
||||
return allocFromFreeList();
|
||||
}
|
||||
|
||||
// try to allocate from last pool (other pools are full)
|
||||
if (count_) {
|
||||
auto slot = allocFromLastPool();
|
||||
if (slot)
|
||||
return slot;
|
||||
}
|
||||
|
||||
// create a new pool and try again
|
||||
auto pool = addPool(allocator);
|
||||
if (!pool)
|
||||
return {};
|
||||
|
||||
return allocFromLastPool();
|
||||
}
|
||||
|
||||
void freeSlot(SlotWithId slot);
|
||||
|
||||
VariantSlot* getSlot(SlotId id) const {
|
||||
if (id == NULL_SLOT)
|
||||
return nullptr;
|
||||
auto poolIndex = SlotId(id / ARDUINOJSON_POOL_CAPACITY);
|
||||
auto indexInPool = SlotId(id % ARDUINOJSON_POOL_CAPACITY);
|
||||
ARDUINOJSON_ASSERT(poolIndex < count_);
|
||||
return pools_[poolIndex].getSlot(indexInPool);
|
||||
}
|
||||
|
||||
void clear(Allocator* allocator) {
|
||||
for (PoolCount i = 0; i < count_; i++)
|
||||
pools_[i].destroy(allocator);
|
||||
count_ = 0;
|
||||
freeList_ = NULL_SLOT;
|
||||
if (pools_ != preallocatedPools_) {
|
||||
allocator->deallocate(pools_);
|
||||
pools_ = preallocatedPools_;
|
||||
capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
SlotCount usage() const {
|
||||
SlotCount total = 0;
|
||||
for (PoolCount i = 0; i < count_; i++)
|
||||
total = SlotCount(total + pools_[i].usage());
|
||||
return total;
|
||||
}
|
||||
|
||||
void shrinkToFit(Allocator* allocator) {
|
||||
if (count_ > 0)
|
||||
pools_[count_ - 1].shrinkToFit(allocator);
|
||||
if (pools_ != preallocatedPools_ && count_ != capacity_) {
|
||||
pools_ = static_cast<VariantPool*>(
|
||||
allocator->reallocate(pools_, count_ * sizeof(VariantPool)));
|
||||
ARDUINOJSON_ASSERT(pools_ != nullptr); // realloc to smaller can't fail
|
||||
capacity_ = count_;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SlotWithId allocFromFreeList();
|
||||
|
||||
SlotWithId allocFromLastPool() {
|
||||
ARDUINOJSON_ASSERT(count_ > 0);
|
||||
auto poolIndex = SlotId(count_ - 1);
|
||||
auto slot = pools_[poolIndex].allocSlot();
|
||||
if (!slot)
|
||||
return {};
|
||||
return {slot, SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
|
||||
}
|
||||
|
||||
VariantPool* addPool(Allocator* allocator) {
|
||||
if (count_ == capacity_ && !increaseCapacity(allocator))
|
||||
return nullptr;
|
||||
auto pool = &pools_[count_++];
|
||||
SlotCount poolCapacity = ARDUINOJSON_POOL_CAPACITY;
|
||||
if (count_ == maxPools) // last pool is smaller because of NULL_SLOT
|
||||
poolCapacity--;
|
||||
pool->create(poolCapacity, allocator);
|
||||
return pool;
|
||||
}
|
||||
|
||||
bool increaseCapacity(Allocator* allocator) {
|
||||
if (capacity_ == maxPools)
|
||||
return false;
|
||||
void* newPools;
|
||||
auto newCapacity = PoolCount(capacity_ * 2);
|
||||
|
||||
if (pools_ == preallocatedPools_) {
|
||||
newPools = allocator->allocate(newCapacity * sizeof(VariantPool));
|
||||
if (!newPools)
|
||||
return false;
|
||||
memcpy(newPools, preallocatedPools_, sizeof(preallocatedPools_));
|
||||
} else {
|
||||
newPools =
|
||||
allocator->reallocate(pools_, newCapacity * sizeof(VariantPool));
|
||||
if (!newPools)
|
||||
return false;
|
||||
}
|
||||
|
||||
pools_ = static_cast<VariantPool*>(newPools);
|
||||
capacity_ = newCapacity;
|
||||
return true;
|
||||
}
|
||||
|
||||
VariantPool preallocatedPools_[ARDUINOJSON_INITIAL_POOL_COUNT];
|
||||
VariantPool* pools_ = preallocatedPools_;
|
||||
PoolCount count_ = 0;
|
||||
PoolCount capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
|
||||
SlotId freeList_ = NULL_SLOT;
|
||||
|
||||
public:
|
||||
static const PoolCount maxPools =
|
||||
PoolCount(NULL_SLOT / ARDUINOJSON_POOL_CAPACITY + 1);
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
@@ -464,10 +464,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||
|
||||
// Parses a MessagePack input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
|
||||
template <typename TDestination, typename... Args>
|
||||
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
|
||||
DeserializationError>
|
||||
deserializeMsgPack(TDestination&& dst, Args&&... args) {
|
||||
template <typename TDestination, typename... Args,
|
||||
detail::enable_if_t<
|
||||
detail::is_deserialize_destination<TDestination>::value, int> = 0>
|
||||
inline DeserializationError deserializeMsgPack(TDestination&& dst,
|
||||
Args&&... args) {
|
||||
using namespace detail;
|
||||
return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
|
||||
detail::forward<Args>(args)...);
|
||||
@@ -475,10 +476,11 @@ deserializeMsgPack(TDestination&& dst, Args&&... args) {
|
||||
|
||||
// Parses a MessagePack input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
|
||||
template <typename TDestination, typename TChar, typename... Args>
|
||||
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
|
||||
DeserializationError>
|
||||
deserializeMsgPack(TDestination&& dst, TChar* input, Args&&... args) {
|
||||
template <typename TDestination, typename TChar, typename... Args,
|
||||
detail::enable_if_t<
|
||||
detail::is_deserialize_destination<TDestination>::value, int> = 0>
|
||||
inline DeserializationError deserializeMsgPack(TDestination&& dst, TChar* input,
|
||||
Args&&... args) {
|
||||
using namespace detail;
|
||||
return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
|
||||
input,
|
||||
|
||||
@@ -96,7 +96,7 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
||||
}
|
||||
|
||||
size_t visit(JsonString value) {
|
||||
ARDUINOJSON_ASSERT(value != NULL);
|
||||
ARDUINOJSON_ASSERT(!value.isNull());
|
||||
|
||||
auto n = value.size();
|
||||
|
||||
@@ -218,9 +218,10 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||
|
||||
// Produces a MessagePack document.
|
||||
// https://arduinojson.org/v7/api/msgpack/serializemsgpack/
|
||||
template <typename TDestination>
|
||||
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t>
|
||||
serializeMsgPack(JsonVariantConst source, TDestination& output) {
|
||||
template <
|
||||
typename TDestination,
|
||||
detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
|
||||
inline size_t serializeMsgPack(JsonVariantConst source, TDestination& output) {
|
||||
using namespace ArduinoJson::detail;
|
||||
return serialize<MsgPackSerializer>(source, output);
|
||||
}
|
||||
|
||||
@@ -101,32 +101,31 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
||||
|
||||
// Gets or sets the member with specified key.
|
||||
// https://arduinojson.org/v7/api/jsonobject/subscript/
|
||||
template <typename TString>
|
||||
detail::enable_if_t<detail::IsString<TString>::value,
|
||||
detail::MemberProxy<JsonObject, TString>>
|
||||
operator[](const TString& key) const {
|
||||
return {*this, key};
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
detail::MemberProxy<JsonObject, detail::AdaptedString<TString>> operator[](
|
||||
const TString& key) const {
|
||||
return {*this, detail::adaptString(key)};
|
||||
}
|
||||
|
||||
// Gets or sets the member with specified key.
|
||||
// https://arduinojson.org/v7/api/jsonobject/subscript/
|
||||
template <typename TChar>
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value,
|
||||
detail::MemberProxy<JsonObject, TChar*>>
|
||||
operator[](TChar* key) const {
|
||||
return {*this, key};
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value &&
|
||||
!detail::is_const<TChar>::value,
|
||||
int> = 0>
|
||||
detail::MemberProxy<JsonObject, detail::AdaptedString<TChar*>> operator[](
|
||||
TChar* key) const {
|
||||
return {*this, detail::adaptString(key)};
|
||||
}
|
||||
|
||||
// Gets or sets the member with specified key.
|
||||
// https://arduinojson.org/v7/api/jsonobject/subscript/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value,
|
||||
detail::MemberProxy<JsonObject, JsonString>>
|
||||
operator[](const TVariant& key) const {
|
||||
if (key.template is<JsonString>())
|
||||
return {*this, key.template as<JsonString>()};
|
||||
else
|
||||
return {*this, nullptr};
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
detail::MemberProxy<JsonObject, detail::AdaptedString<JsonString>> operator[](
|
||||
const TVariant& key) const {
|
||||
return {*this, detail::adaptString(key.template as<JsonString>())};
|
||||
}
|
||||
|
||||
// Removes the member at the specified iterator.
|
||||
@@ -137,18 +136,18 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
||||
|
||||
// Removes the member with the specified key.
|
||||
// https://arduinojson.org/v7/api/jsonobject/remove/
|
||||
template <typename TString>
|
||||
detail::enable_if_t<detail::IsString<TString>::value> remove(
|
||||
const TString& key) const {
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
void remove(const TString& key) const {
|
||||
detail::ObjectData::removeMember(data_, detail::adaptString(key),
|
||||
resources_);
|
||||
}
|
||||
|
||||
// Removes the member with the specified key.
|
||||
// https://arduinojson.org/v7/api/jsonobject/remove/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove(
|
||||
const TVariant& key) const {
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
void remove(const TVariant& key) const {
|
||||
if (key.template is<const char*>())
|
||||
remove(key.template as<const char*>());
|
||||
}
|
||||
@@ -163,30 +162,32 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonobject/containskey/
|
||||
template <typename TString>
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
|
||||
const TString& key) const {
|
||||
bool containsKey(const TString& key) const {
|
||||
return detail::ObjectData::getMember(data_, detail::adaptString(key),
|
||||
resources_) != 0;
|
||||
}
|
||||
|
||||
// DEPRECATED: use obj["key"].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonobject/containskey/
|
||||
template <typename TChar>
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value &&
|
||||
!detail::is_const<TChar>::value,
|
||||
int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value, bool> containsKey(
|
||||
TChar* key) const {
|
||||
bool containsKey(TChar* key) const {
|
||||
return detail::ObjectData::getMember(data_, detail::adaptString(key),
|
||||
resources_) != 0;
|
||||
}
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonobject/containskey/
|
||||
template <typename TVariant>
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
|
||||
const TVariant& key) const {
|
||||
bool containsKey(const TVariant& key) const {
|
||||
return containsKey(key.template as<const char*>());
|
||||
}
|
||||
|
||||
|
||||
@@ -70,10 +70,10 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonobjectconst/containskey/
|
||||
template <typename TString>
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
|
||||
const TString& key) const {
|
||||
bool containsKey(const TString& key) const {
|
||||
return detail::ObjectData::getMember(data_, detail::adaptString(key),
|
||||
resources_) != 0;
|
||||
}
|
||||
@@ -89,18 +89,18 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonobjectconst/containskey/
|
||||
template <typename TVariant>
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
|
||||
const TVariant& key) const {
|
||||
bool containsKey(const TVariant& key) const {
|
||||
return containsKey(key.template as<const char*>());
|
||||
}
|
||||
|
||||
// Gets the member with specified key.
|
||||
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/
|
||||
template <typename TString>
|
||||
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
|
||||
operator[](const TString& key) const {
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
JsonVariantConst operator[](const TString& key) const {
|
||||
return JsonVariantConst(detail::ObjectData::getMember(
|
||||
data_, detail::adaptString(key), resources_),
|
||||
resources_);
|
||||
@@ -108,9 +108,11 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
||||
|
||||
// Gets the member with specified key.
|
||||
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/
|
||||
template <typename TChar>
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
|
||||
operator[](TChar* key) const {
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value &&
|
||||
!detail::is_const<TChar>::value,
|
||||
int> = 0>
|
||||
JsonVariantConst operator[](TChar* key) const {
|
||||
return JsonVariantConst(detail::ObjectData::getMember(
|
||||
data_, detail::adaptString(key), resources_),
|
||||
resources_);
|
||||
@@ -118,9 +120,9 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
||||
|
||||
// Gets the member with specified key.
|
||||
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
|
||||
operator[](const TVariant& key) const {
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
JsonVariantConst operator[](const TVariant& key) const {
|
||||
if (key.template is<JsonString>())
|
||||
return operator[](key.template as<JsonString>());
|
||||
else
|
||||
|
||||
@@ -10,18 +10,23 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
// A proxy class to get or set a member of an object.
|
||||
// https://arduinojson.org/v7/api/jsonobject/subscript/
|
||||
template <typename TUpstream, typename TStringRef>
|
||||
template <typename TUpstream, typename AdaptedString>
|
||||
class MemberProxy
|
||||
: public VariantRefBase<MemberProxy<TUpstream, TStringRef>>,
|
||||
public VariantOperators<MemberProxy<TUpstream, TStringRef>> {
|
||||
: public VariantRefBase<MemberProxy<TUpstream, AdaptedString>>,
|
||||
public VariantOperators<MemberProxy<TUpstream, AdaptedString>> {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
MemberProxy(TUpstream upstream, TStringRef key)
|
||||
: upstream_(upstream), key_(key) {}
|
||||
friend class VariantRefBase<MemberProxy<TUpstream, AdaptedString>>;
|
||||
|
||||
MemberProxy(const MemberProxy& src)
|
||||
: upstream_(src.upstream_), key_(src.key_) {}
|
||||
template <typename, typename>
|
||||
friend class MemberProxy;
|
||||
|
||||
template <typename>
|
||||
friend class ElementProxy;
|
||||
|
||||
public:
|
||||
MemberProxy(TUpstream upstream, AdaptedString key)
|
||||
: upstream_(upstream), key_(key) {}
|
||||
|
||||
MemberProxy& operator=(const MemberProxy& src) {
|
||||
this->set(src);
|
||||
@@ -34,20 +39,25 @@ class MemberProxy
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename T, enable_if_t<!is_const<T>::value, int> = 0>
|
||||
MemberProxy& operator=(T* src) {
|
||||
this->set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
MemberProxy(const MemberProxy& src) // Error here? See https://arduinojson.org/v7/proxy-non-copyable/
|
||||
: upstream_(src.upstream_), key_(src.key_) {}
|
||||
// clang-format on
|
||||
|
||||
ResourceManager* getResourceManager() const {
|
||||
return VariantAttorney::getResourceManager(upstream_);
|
||||
}
|
||||
|
||||
VariantData* getData() const {
|
||||
return VariantData::getMember(
|
||||
VariantAttorney::getData(upstream_), adaptString(key_),
|
||||
VariantAttorney::getData(upstream_), key_,
|
||||
VariantAttorney::getResourceManager(upstream_));
|
||||
}
|
||||
|
||||
@@ -55,13 +65,13 @@ class MemberProxy
|
||||
auto data = VariantAttorney::getOrCreateData(upstream_);
|
||||
if (!data)
|
||||
return nullptr;
|
||||
return data->getOrAddMember(adaptString(key_),
|
||||
return data->getOrAddMember(key_,
|
||||
VariantAttorney::getResourceManager(upstream_));
|
||||
}
|
||||
|
||||
private:
|
||||
TUpstream upstream_;
|
||||
TStringRef key_;
|
||||
AdaptedString key_;
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "type_traits/conditional.hpp"
|
||||
#include "type_traits/decay.hpp"
|
||||
#include "type_traits/enable_if.hpp"
|
||||
#include "type_traits/function_traits.hpp"
|
||||
#include "type_traits/integral_constant.hpp"
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2024, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include <ArduinoJson/Namespace.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
template <typename T>
|
||||
struct decay {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct decay<T&> : decay<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct decay<T&&> : decay<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct decay<T[]> : decay<T*> {};
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct decay<T[N]> : decay<T*> {};
|
||||
|
||||
template <typename T>
|
||||
using decay_t = typename decay<T>::type;
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
// The default writer is a simple wrapper for Writers that are not copiable
|
||||
// The default writer is a simple wrapper for Writers that are not copyable
|
||||
template <typename TDestination, typename Enable = void>
|
||||
class Writer {
|
||||
public:
|
||||
|
||||
@@ -34,7 +34,7 @@ class FlashString {
|
||||
return size_;
|
||||
}
|
||||
|
||||
friend bool stringEquals(FlashString a, SizedRamString b) {
|
||||
friend bool stringEquals(FlashString a, RamString b) {
|
||||
ARDUINOJSON_ASSERT(a.typeSortKey < b.typeSortKey);
|
||||
ARDUINOJSON_ASSERT(!a.isNull());
|
||||
ARDUINOJSON_ASSERT(!b.isNull());
|
||||
@@ -43,7 +43,7 @@ class FlashString {
|
||||
return ::memcmp_P(b.data(), a.str_, a.size_) == 0;
|
||||
}
|
||||
|
||||
friend int stringCompare(FlashString a, SizedRamString b) {
|
||||
friend int stringCompare(FlashString a, RamString b) {
|
||||
ARDUINOJSON_ASSERT(a.typeSortKey < b.typeSortKey);
|
||||
ARDUINOJSON_ASSERT(!a.isNull());
|
||||
ARDUINOJSON_ASSERT(!b.isNull());
|
||||
@@ -63,7 +63,7 @@ class FlashString {
|
||||
::memcpy_P(p, s.str_, n);
|
||||
}
|
||||
|
||||
bool isLinked() const {
|
||||
bool isStatic() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2024, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
class JsonStringAdapter : public SizedRamString {
|
||||
public:
|
||||
JsonStringAdapter(const JsonString& s)
|
||||
: SizedRamString(s.c_str(), s.size()), linked_(s.isLinked()) {}
|
||||
|
||||
bool isLinked() const {
|
||||
return linked_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool linked_;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringAdapter<JsonString> {
|
||||
using AdaptedString = JsonStringAdapter;
|
||||
|
||||
static AdaptedString adapt(const JsonString& s) {
|
||||
return AdaptedString(s);
|
||||
}
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
@@ -17,79 +17,19 @@ template <typename T>
|
||||
struct IsChar
|
||||
: integral_constant<bool, is_integral<T>::value && sizeof(T) == 1> {};
|
||||
|
||||
class ZeroTerminatedRamString {
|
||||
public:
|
||||
static const size_t typeSortKey = 3;
|
||||
|
||||
ZeroTerminatedRamString(const char* str) : str_(str) {}
|
||||
|
||||
bool isNull() const {
|
||||
return !str_;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return str_ ? ::strlen(str_) : 0;
|
||||
}
|
||||
|
||||
char operator[](size_t i) const {
|
||||
ARDUINOJSON_ASSERT(str_ != 0);
|
||||
ARDUINOJSON_ASSERT(i <= size());
|
||||
return str_[i];
|
||||
}
|
||||
|
||||
const char* data() const {
|
||||
return str_;
|
||||
}
|
||||
|
||||
bool isLinked() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* str_;
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
struct StringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
|
||||
using AdaptedString = ZeroTerminatedRamString;
|
||||
|
||||
static AdaptedString adapt(const TChar* p) {
|
||||
return AdaptedString(reinterpret_cast<const char*>(p));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar, size_t N>
|
||||
struct StringAdapter<TChar[N], enable_if_t<IsChar<TChar>::value>> {
|
||||
using AdaptedString = ZeroTerminatedRamString;
|
||||
|
||||
static AdaptedString adapt(const TChar* p) {
|
||||
return AdaptedString(reinterpret_cast<const char*>(p));
|
||||
}
|
||||
};
|
||||
|
||||
class StaticStringAdapter : public ZeroTerminatedRamString {
|
||||
public:
|
||||
StaticStringAdapter(const char* str) : ZeroTerminatedRamString(str) {}
|
||||
|
||||
bool isLinked() const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringAdapter<const char*, void> {
|
||||
using AdaptedString = StaticStringAdapter;
|
||||
|
||||
static AdaptedString adapt(const char* p) {
|
||||
return AdaptedString(p);
|
||||
}
|
||||
};
|
||||
|
||||
class SizedRamString {
|
||||
class RamString {
|
||||
public:
|
||||
static const size_t typeSortKey = 2;
|
||||
#if ARDUINOJSON_SIZEOF_POINTER <= 2
|
||||
static constexpr size_t sizeMask = size_t(-1) >> 1;
|
||||
#else
|
||||
static constexpr size_t sizeMask = size_t(-1);
|
||||
#endif
|
||||
|
||||
SizedRamString(const char* str, size_t sz) : str_(str), size_(sz) {}
|
||||
RamString(const char* str, size_t sz, bool isStatic = false)
|
||||
: str_(str), size_(sz & sizeMask), static_(isStatic) {
|
||||
ARDUINOJSON_ASSERT(size_ == sz);
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return !str_;
|
||||
@@ -109,18 +49,55 @@ class SizedRamString {
|
||||
return str_;
|
||||
}
|
||||
|
||||
bool isLinked() const {
|
||||
return false;
|
||||
bool isStatic() const {
|
||||
return static_;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* str_;
|
||||
|
||||
#if ARDUINOJSON_SIZEOF_POINTER <= 2
|
||||
// Use a bitfield only on 8-bit microcontrollers
|
||||
size_t size_ : sizeof(size_t) * 8 - 1;
|
||||
bool static_ : 1;
|
||||
#else
|
||||
size_t size_;
|
||||
bool static_;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
struct StringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
|
||||
using AdaptedString = RamString;
|
||||
|
||||
static AdaptedString adapt(const TChar* p) {
|
||||
auto str = reinterpret_cast<const char*>(p);
|
||||
return AdaptedString(str, str ? ::strlen(str) : 0);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct StringAdapter<const char (&)[N]> {
|
||||
using AdaptedString = RamString;
|
||||
|
||||
static AdaptedString adapt(const char (&p)[N]) {
|
||||
return RamString(p, N - 1, true);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar, size_t N>
|
||||
struct StringAdapter<TChar[N], enable_if_t<IsChar<TChar>::value>> {
|
||||
using AdaptedString = RamString;
|
||||
|
||||
static AdaptedString adapt(const TChar* p) {
|
||||
auto str = reinterpret_cast<const char*>(p);
|
||||
return AdaptedString(str, str ? ::strlen(str) : 0);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
struct SizedStringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
|
||||
using AdaptedString = SizedRamString;
|
||||
using AdaptedString = RamString;
|
||||
|
||||
static AdaptedString adapt(const TChar* p, size_t n) {
|
||||
return AdaptedString(reinterpret_cast<const char*>(p), n);
|
||||
|
||||
@@ -15,7 +15,7 @@ struct StringAdapter<
|
||||
T,
|
||||
enable_if_t<(string_traits<T>::has_cstr || string_traits<T>::has_data) &&
|
||||
(string_traits<T>::has_length || string_traits<T>::has_size)>> {
|
||||
using AdaptedString = SizedRamString;
|
||||
using AdaptedString = RamString;
|
||||
|
||||
static AdaptedString adapt(const T& s) {
|
||||
return AdaptedString(get_data(s), get_size(s));
|
||||
|
||||
@@ -13,7 +13,7 @@ template <typename T, typename Enable = void>
|
||||
struct IsString : false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct IsString<T, void_t<typename StringAdapter<T>::AdaptedString>>
|
||||
struct IsString<T, void_t<typename StringAdapterFor<T>::AdaptedString>>
|
||||
: true_type {};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
# include <ostream>
|
||||
#endif
|
||||
@@ -13,54 +16,58 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||
// A string.
|
||||
// https://arduinojson.org/v7/api/jsonstring/
|
||||
class JsonString {
|
||||
friend struct detail::StringAdapter<JsonString>;
|
||||
|
||||
public:
|
||||
enum Ownership { Copied, Linked };
|
||||
JsonString() : str_(nullptr, 0, true) {}
|
||||
|
||||
JsonString() : data_(0), size_(0), ownership_(Linked) {}
|
||||
JsonString(const char* data, bool isStatic = false)
|
||||
: str_(data, data ? ::strlen(data) : 0, isStatic) {}
|
||||
|
||||
JsonString(const char* data, Ownership ownership = Linked)
|
||||
: data_(data), size_(data ? ::strlen(data) : 0), ownership_(ownership) {}
|
||||
|
||||
JsonString(const char* data, size_t sz, Ownership ownership = Linked)
|
||||
: data_(data), size_(sz), ownership_(ownership) {}
|
||||
template <typename TSize,
|
||||
detail::enable_if_t<detail::is_integral<TSize>::value &&
|
||||
!detail::is_same<TSize, bool>::value,
|
||||
int> = 0>
|
||||
JsonString(const char* data, TSize sz, bool isStatic = false)
|
||||
: str_(data, size_t(sz), isStatic) {}
|
||||
|
||||
// Returns a pointer to the characters.
|
||||
const char* c_str() const {
|
||||
return data_;
|
||||
return str_.data();
|
||||
}
|
||||
|
||||
// Returns true if the string is null.
|
||||
bool isNull() const {
|
||||
return !data_;
|
||||
return str_.isNull();
|
||||
}
|
||||
|
||||
// Returns true if the string is stored by address.
|
||||
// Returns false if the string is stored by copy.
|
||||
bool isLinked() const {
|
||||
return ownership_ == Linked;
|
||||
bool isStatic() const {
|
||||
return str_.isStatic();
|
||||
}
|
||||
|
||||
// Returns length of the string.
|
||||
size_t size() const {
|
||||
return size_;
|
||||
return str_.size();
|
||||
}
|
||||
|
||||
// Returns true if the string is non-null
|
||||
explicit operator bool() const {
|
||||
return data_ != 0;
|
||||
return str_.data() != 0;
|
||||
}
|
||||
|
||||
// Returns true if strings are equal.
|
||||
friend bool operator==(JsonString lhs, JsonString rhs) {
|
||||
if (lhs.size_ != rhs.size_)
|
||||
if (lhs.size() != rhs.size())
|
||||
return false;
|
||||
if (lhs.data_ == rhs.data_)
|
||||
if (lhs.c_str() == rhs.c_str())
|
||||
return true;
|
||||
if (!lhs.data_)
|
||||
if (!lhs.c_str())
|
||||
return false;
|
||||
if (!rhs.data_)
|
||||
if (!rhs.c_str())
|
||||
return false;
|
||||
return memcmp(lhs.data_, rhs.data_, lhs.size_) == 0;
|
||||
return memcmp(lhs.c_str(), rhs.c_str(), lhs.size()) == 0;
|
||||
}
|
||||
|
||||
// Returns true if strings differs.
|
||||
@@ -76,9 +83,18 @@ class JsonString {
|
||||
#endif
|
||||
|
||||
private:
|
||||
const char* data_;
|
||||
size_t size_;
|
||||
Ownership ownership_;
|
||||
detail::RamString str_;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <>
|
||||
struct StringAdapter<JsonString> {
|
||||
using AdaptedString = RamString;
|
||||
|
||||
static const AdaptedString& adapt(const JsonString& s) {
|
||||
return s.str_;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||
|
||||
@@ -4,8 +4,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Polyfills/utility.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
// a meta function that tells if the type is a string literal (const char[N])
|
||||
template <typename T>
|
||||
struct IsStringLiteral : false_type {};
|
||||
|
||||
template <size_t N>
|
||||
struct IsStringLiteral<const char (&)[N]> : true_type {};
|
||||
|
||||
template <typename TString, typename Enable = void>
|
||||
struct StringAdapter;
|
||||
|
||||
@@ -13,18 +22,25 @@ template <typename TString, typename Enable = void>
|
||||
struct SizedStringAdapter;
|
||||
|
||||
template <typename TString>
|
||||
typename StringAdapter<TString>::AdaptedString adaptString(const TString& s) {
|
||||
return StringAdapter<TString>::adapt(s);
|
||||
using StringAdapterFor =
|
||||
StringAdapter<conditional_t<IsStringLiteral<TString>::value, TString,
|
||||
remove_cv_t<remove_reference_t<TString>>>>;
|
||||
|
||||
template <typename T>
|
||||
using AdaptedString = typename StringAdapterFor<T>::AdaptedString;
|
||||
|
||||
template <typename TString>
|
||||
AdaptedString<TString> adaptString(TString&& s) {
|
||||
return StringAdapterFor<TString>::adapt(detail::forward<TString>(s));
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
typename StringAdapter<TChar*>::AdaptedString adaptString(TChar* p) {
|
||||
template <typename TChar, enable_if_t<!is_const<TChar>::value, int> = 0>
|
||||
AdaptedString<TChar*> adaptString(TChar* p) {
|
||||
return StringAdapter<TChar*>::adapt(p);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
typename SizedStringAdapter<TChar*>::AdaptedString adaptString(TChar* p,
|
||||
size_t n) {
|
||||
AdaptedString<TChar*> adaptString(TChar* p, size_t n) {
|
||||
return SizedStringAdapter<TChar*>::adapt(p, n);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Strings/Adapters/JsonString.hpp>
|
||||
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||
#include <ArduinoJson/Strings/Adapters/StringObject.hpp>
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ struct Converter {
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
static T fromJson(JsonVariantConst src) {
|
||||
static detail::decay_t<T> fromJson(JsonVariantConst src) {
|
||||
static_assert(!detail::is_same<T, char*>::value,
|
||||
"type 'char*' is not supported, use 'const char*' instead");
|
||||
|
||||
@@ -178,7 +178,7 @@ struct Converter<JsonString> : private detail::VariantAttorney {
|
||||
|
||||
static JsonString fromJson(JsonVariantConst src) {
|
||||
auto data = getData(src);
|
||||
return data ? data->asString() : 0;
|
||||
return data ? data->asString() : JsonString();
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
|
||||
@@ -68,27 +68,29 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
// Casts the value to the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/as/
|
||||
template <typename T,
|
||||
detail::enable_if_t<ConversionSupported<T>::value, bool> = true>
|
||||
detail::enable_if_t<ConversionSupported<T>::value, int> = 0>
|
||||
T as() const {
|
||||
return Converter<T>::fromJson(*this);
|
||||
}
|
||||
|
||||
// Invalid conversion. Will not compile.
|
||||
template <typename T,
|
||||
detail::enable_if_t<!ConversionSupported<T>::value, bool> = true>
|
||||
detail::enable_if_t<!ConversionSupported<T>::value, int> = 0>
|
||||
detail::InvalidConversion<JsonVariantConst, T> as() const;
|
||||
|
||||
// Returns true if the value is of the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/is/
|
||||
template <typename T>
|
||||
detail::enable_if_t<ConversionSupported<T>::value, bool> is() const {
|
||||
template <typename T,
|
||||
detail::enable_if_t<ConversionSupported<T>::value, int> = 0>
|
||||
bool is() const {
|
||||
return Converter<T>::checkJson(*this);
|
||||
}
|
||||
|
||||
// Always returns false for the unsupported types.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/is/
|
||||
template <typename T>
|
||||
detail::enable_if_t<!ConversionSupported<T>::value, bool> is() const {
|
||||
template <typename T,
|
||||
detail::enable_if_t<!ConversionSupported<T>::value, int> = 0>
|
||||
bool is() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -99,9 +101,9 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
|
||||
// Gets array's element at specified index.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
|
||||
template <typename T>
|
||||
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
|
||||
operator[](T index) const {
|
||||
template <typename T,
|
||||
detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
|
||||
JsonVariantConst operator[](T index) const {
|
||||
return JsonVariantConst(
|
||||
detail::VariantData::getElement(data_, size_t(index), resources_),
|
||||
resources_);
|
||||
@@ -109,9 +111,9 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
|
||||
// Gets object's member with specified key.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
|
||||
template <typename TString>
|
||||
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
|
||||
operator[](const TString& key) const {
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
JsonVariantConst operator[](const TString& key) const {
|
||||
return JsonVariantConst(detail::VariantData::getMember(
|
||||
data_, detail::adaptString(key), resources_),
|
||||
resources_);
|
||||
@@ -119,9 +121,11 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
|
||||
// Gets object's member with specified key.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
|
||||
template <typename TChar>
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
|
||||
operator[](TChar* key) const {
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value &&
|
||||
!detail::is_const<TChar>::value,
|
||||
int> = 0>
|
||||
JsonVariantConst operator[](TChar* key) const {
|
||||
return JsonVariantConst(detail::VariantData::getMember(
|
||||
data_, detail::adaptString(key), resources_),
|
||||
resources_);
|
||||
@@ -130,9 +134,9 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
// Gets object's member with specified key or the array's element at the
|
||||
// specified index.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
|
||||
operator[](const TVariant& key) const {
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
JsonVariantConst operator[](const TVariant& key) const {
|
||||
if (key.template is<size_t>())
|
||||
return operator[](key.template as<size_t>());
|
||||
else
|
||||
@@ -141,30 +145,32 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/
|
||||
template <typename TString>
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use var[key].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
|
||||
const TString& key) const {
|
||||
bool containsKey(const TString& key) const {
|
||||
return detail::VariantData::getMember(getData(), detail::adaptString(key),
|
||||
resources_) != 0;
|
||||
}
|
||||
|
||||
// DEPRECATED: use obj["key"].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/
|
||||
template <typename TChar>
|
||||
template <typename TChar,
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value &&
|
||||
!detail::is_const<TChar>::value,
|
||||
int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsString<TChar*>::value, bool> containsKey(
|
||||
TChar* key) const {
|
||||
bool containsKey(TChar* key) const {
|
||||
return detail::VariantData::getMember(getData(), detail::adaptString(key),
|
||||
resources_) != 0;
|
||||
}
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/
|
||||
template <typename TVariant>
|
||||
template <typename TVariant,
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use var[key].is<T>() instead")
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
|
||||
const TVariant& key) const {
|
||||
bool containsKey(const TVariant& key) const {
|
||||
return containsKey(key.template as<const char*>());
|
||||
}
|
||||
|
||||
|
||||
@@ -64,12 +64,11 @@ class VariantData {
|
||||
return visit.visit(content_.asObject);
|
||||
|
||||
case VariantType::LinkedString:
|
||||
return visit.visit(JsonString(content_.asLinkedString));
|
||||
return visit.visit(JsonString(content_.asLinkedString, true));
|
||||
|
||||
case VariantType::OwnedString:
|
||||
return visit.visit(JsonString(content_.asOwnedString->data,
|
||||
content_.asOwnedString->length,
|
||||
JsonString::Copied));
|
||||
content_.asOwnedString->length));
|
||||
|
||||
case VariantType::RawString:
|
||||
return visit.visit(RawString(content_.asOwnedString->data,
|
||||
@@ -119,14 +118,13 @@ class VariantData {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool addValue(T&& value, ResourceManager* resources) {
|
||||
bool addValue(const T& value, ResourceManager* resources) {
|
||||
auto array = isNull() ? &toArray() : asArray();
|
||||
return detail::ArrayData::addValue(array, detail::forward<T>(value),
|
||||
resources);
|
||||
return detail::ArrayData::addValue(array, value, resources);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool addValue(VariantData* var, T&& value,
|
||||
static bool addValue(VariantData* var, const T& value,
|
||||
ResourceManager* resources) {
|
||||
if (!var)
|
||||
return false;
|
||||
@@ -262,7 +260,7 @@ class VariantData {
|
||||
switch (type_) {
|
||||
case VariantType::RawString:
|
||||
return JsonString(content_.asOwnedString->data,
|
||||
content_.asOwnedString->length, JsonString::Copied);
|
||||
content_.asOwnedString->length);
|
||||
default:
|
||||
return JsonString();
|
||||
}
|
||||
@@ -271,10 +269,10 @@ class VariantData {
|
||||
JsonString asString() const {
|
||||
switch (type_) {
|
||||
case VariantType::LinkedString:
|
||||
return JsonString(content_.asLinkedString, JsonString::Linked);
|
||||
return JsonString(content_.asLinkedString, true);
|
||||
case VariantType::OwnedString:
|
||||
return JsonString(content_.asOwnedString->data,
|
||||
content_.asOwnedString->length, JsonString::Copied);
|
||||
content_.asOwnedString->length);
|
||||
default:
|
||||
return JsonString();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ inline bool VariantData::setString(TAdaptedString value,
|
||||
if (value.isNull())
|
||||
return false;
|
||||
|
||||
if (value.isLinked()) {
|
||||
if (value.isStatic()) {
|
||||
setLinkedString(value.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ struct VariantOperators : VariantOperatorTag {
|
||||
// int operator|(JsonVariant, int)
|
||||
// float operator|(JsonVariant, float)
|
||||
// bool operator|(JsonVariant, bool)
|
||||
template <typename T>
|
||||
friend enable_if_t<!IsVariant<T>::value && !is_array<T>::value, T> operator|(
|
||||
const TVariant& variant, const T& defaultValue) {
|
||||
template <typename T,
|
||||
enable_if_t<!IsVariant<T>::value && !is_array<T>::value, int> = 0>
|
||||
friend T operator|(const TVariant& variant, const T& defaultValue) {
|
||||
if (variant.template is<T>())
|
||||
return variant.template as<T>();
|
||||
else
|
||||
@@ -51,7 +51,7 @@ struct VariantOperators : VariantOperatorTag {
|
||||
// JsonVariant operator|(JsonVariant, JsonVariant)
|
||||
template <typename T>
|
||||
friend enable_if_t<IsVariant<T>::value, JsonVariantConst> operator|(
|
||||
const TVariant& variant, T defaultValue) {
|
||||
const TVariant& variant, const T& defaultValue) {
|
||||
if (variant)
|
||||
return variant;
|
||||
else
|
||||
@@ -60,127 +60,127 @@ struct VariantOperators : VariantOperatorTag {
|
||||
|
||||
// value == TVariant
|
||||
template <typename T>
|
||||
friend bool operator==(T* lhs, TVariant rhs) {
|
||||
friend bool operator==(T* lhs, const TVariant& rhs) {
|
||||
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
template <typename T>
|
||||
friend bool operator==(const T& lhs, TVariant rhs) {
|
||||
friend bool operator==(const T& lhs, const TVariant& rhs) {
|
||||
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
|
||||
// TVariant == value
|
||||
template <typename T>
|
||||
friend bool operator==(TVariant lhs, T* rhs) {
|
||||
friend bool operator==(const TVariant& lhs, T* rhs) {
|
||||
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
template <typename T>
|
||||
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
|
||||
operator==(TVariant lhs, const T& rhs) {
|
||||
template <typename T,
|
||||
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
|
||||
friend bool operator==(const TVariant& lhs, const T& rhs) {
|
||||
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
|
||||
// value != TVariant
|
||||
template <typename T>
|
||||
friend bool operator!=(T* lhs, TVariant rhs) {
|
||||
friend bool operator!=(T* lhs, const TVariant& rhs) {
|
||||
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
template <typename T>
|
||||
friend bool operator!=(const T& lhs, TVariant rhs) {
|
||||
friend bool operator!=(const T& lhs, const TVariant& rhs) {
|
||||
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
|
||||
// TVariant != value
|
||||
template <typename T>
|
||||
friend bool operator!=(TVariant lhs, T* rhs) {
|
||||
friend bool operator!=(const TVariant& lhs, T* rhs) {
|
||||
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
template <typename T>
|
||||
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
|
||||
operator!=(TVariant lhs, const T& rhs) {
|
||||
template <typename T,
|
||||
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
|
||||
friend bool operator!=(TVariant lhs, const T& rhs) {
|
||||
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
|
||||
// value < TVariant
|
||||
template <typename T>
|
||||
friend bool operator<(T* lhs, TVariant rhs) {
|
||||
friend bool operator<(T* lhs, const TVariant& rhs) {
|
||||
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
|
||||
}
|
||||
template <typename T>
|
||||
friend bool operator<(const T& lhs, TVariant rhs) {
|
||||
friend bool operator<(const T& lhs, const TVariant& rhs) {
|
||||
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
|
||||
}
|
||||
|
||||
// TVariant < value
|
||||
template <typename T>
|
||||
friend bool operator<(TVariant lhs, T* rhs) {
|
||||
friend bool operator<(const TVariant& lhs, T* rhs) {
|
||||
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
|
||||
}
|
||||
template <typename T>
|
||||
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> operator<(
|
||||
TVariant lhs, const T& rhs) {
|
||||
template <typename T,
|
||||
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
|
||||
friend bool operator<(TVariant lhs, const T& rhs) {
|
||||
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
|
||||
}
|
||||
|
||||
// value <= TVariant
|
||||
template <typename T>
|
||||
friend bool operator<=(T* lhs, TVariant rhs) {
|
||||
friend bool operator<=(T* lhs, const TVariant& rhs) {
|
||||
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
|
||||
}
|
||||
template <typename T>
|
||||
friend bool operator<=(const T& lhs, TVariant rhs) {
|
||||
friend bool operator<=(const T& lhs, const TVariant& rhs) {
|
||||
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
|
||||
}
|
||||
|
||||
// TVariant <= value
|
||||
template <typename T>
|
||||
friend bool operator<=(TVariant lhs, T* rhs) {
|
||||
friend bool operator<=(const TVariant& lhs, T* rhs) {
|
||||
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
|
||||
}
|
||||
template <typename T>
|
||||
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
|
||||
operator<=(TVariant lhs, const T& rhs) {
|
||||
template <typename T,
|
||||
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
|
||||
friend bool operator<=(TVariant lhs, const T& rhs) {
|
||||
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
|
||||
}
|
||||
|
||||
// value > TVariant
|
||||
template <typename T>
|
||||
friend bool operator>(T* lhs, TVariant rhs) {
|
||||
friend bool operator>(T* lhs, const TVariant& rhs) {
|
||||
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
|
||||
}
|
||||
template <typename T>
|
||||
friend bool operator>(const T& lhs, TVariant rhs) {
|
||||
friend bool operator>(const T& lhs, const TVariant& rhs) {
|
||||
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
|
||||
}
|
||||
|
||||
// TVariant > value
|
||||
template <typename T>
|
||||
friend bool operator>(TVariant lhs, T* rhs) {
|
||||
friend bool operator>(const TVariant& lhs, T* rhs) {
|
||||
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
|
||||
}
|
||||
template <typename T>
|
||||
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> operator>(
|
||||
TVariant lhs, const T& rhs) {
|
||||
template <typename T,
|
||||
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
|
||||
friend bool operator>(TVariant lhs, const T& rhs) {
|
||||
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
|
||||
}
|
||||
|
||||
// value >= TVariant
|
||||
template <typename T>
|
||||
friend bool operator>=(T* lhs, TVariant rhs) {
|
||||
friend bool operator>=(T* lhs, const TVariant& rhs) {
|
||||
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
|
||||
}
|
||||
template <typename T>
|
||||
friend bool operator>=(const T& lhs, TVariant rhs) {
|
||||
friend bool operator>=(const T& lhs, const TVariant& rhs) {
|
||||
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
|
||||
}
|
||||
|
||||
// TVariant >= value
|
||||
template <typename T>
|
||||
friend bool operator>=(TVariant lhs, T* rhs) {
|
||||
friend bool operator>=(const TVariant& lhs, T* rhs) {
|
||||
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
|
||||
}
|
||||
template <typename T>
|
||||
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
|
||||
operator>=(TVariant lhs, const T& rhs) {
|
||||
template <typename T,
|
||||
enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
|
||||
friend bool operator>=(const TVariant& lhs, const T& rhs) {
|
||||
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,25 +48,25 @@ class VariantRefBase : public VariantTag {
|
||||
template <typename T>
|
||||
T as() const;
|
||||
|
||||
template <typename T, typename = enable_if_t<!is_same<T, TDerived>::value>>
|
||||
template <typename T, enable_if_t<!is_same<T, TDerived>::value, int> = 0>
|
||||
operator T() const {
|
||||
return as<T>();
|
||||
}
|
||||
|
||||
// Sets the value to an empty array.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/to/
|
||||
template <typename T>
|
||||
enable_if_t<is_same<T, JsonArray>::value, JsonArray> to() const;
|
||||
template <typename T, enable_if_t<is_same<T, JsonArray>::value, int> = 0>
|
||||
JsonArray to() const;
|
||||
|
||||
// Sets the value to an empty object.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/to/
|
||||
template <typename T>
|
||||
enable_if_t<is_same<T, JsonObject>::value, JsonObject> to() const;
|
||||
template <typename T, enable_if_t<is_same<T, JsonObject>::value, int> = 0>
|
||||
JsonObject to() const;
|
||||
|
||||
// Sets the value to null.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/to/
|
||||
template <typename T>
|
||||
enable_if_t<is_same<T, JsonVariant>::value, JsonVariant> to() const;
|
||||
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int> = 0>
|
||||
JsonVariant to() const;
|
||||
|
||||
// Returns true if the value is of the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/is/
|
||||
@@ -77,12 +77,15 @@ class VariantRefBase : public VariantTag {
|
||||
// https://arduinojson.org/v7/api/jsonvariant/set/
|
||||
template <typename T>
|
||||
bool set(const T& value) const {
|
||||
return doSet<Converter<remove_cv_t<T>>>(value);
|
||||
using TypeForConverter = conditional_t<IsStringLiteral<T>::value, T,
|
||||
remove_cv_t<remove_reference_t<T>>>;
|
||||
return doSet<Converter<TypeForConverter>>(value);
|
||||
}
|
||||
|
||||
// Copies the specified value.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/set/
|
||||
template <typename T>
|
||||
template <typename T,
|
||||
detail::enable_if_t<!detail::is_const<T>::value, int> = 0>
|
||||
bool set(T* value) const {
|
||||
return doSet<Converter<T*>>(value);
|
||||
}
|
||||
@@ -102,16 +105,16 @@ class VariantRefBase : public VariantTag {
|
||||
// Appends a new (empty) element to the array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/add/
|
||||
template <typename T>
|
||||
enable_if_t<!is_same<T, JsonVariant>::value, T> add() const {
|
||||
template <typename T, enable_if_t<!is_same<T, JsonVariant>::value, int> = 0>
|
||||
T add() const {
|
||||
return add<JsonVariant>().template to<T>();
|
||||
}
|
||||
|
||||
// Appends a new (null) element to the array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/add/
|
||||
template <typename T>
|
||||
enable_if_t<is_same<T, JsonVariant>::value, T> add() const;
|
||||
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int> = 0>
|
||||
T add() const;
|
||||
|
||||
// Appends a value to the array.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/add/
|
||||
@@ -123,7 +126,7 @@ class VariantRefBase : public VariantTag {
|
||||
|
||||
// Appends a value to the array.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/add/
|
||||
template <typename T>
|
||||
template <typename T, enable_if_t<!is_const<T>::value, int> = 0>
|
||||
bool add(T* value) const {
|
||||
return detail::VariantData::addValue(getOrCreateData(), value,
|
||||
getResourceManager());
|
||||
@@ -137,24 +140,24 @@ class VariantRefBase : public VariantTag {
|
||||
|
||||
// Removes a member of the object.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/remove/
|
||||
template <typename TChar>
|
||||
enable_if_t<IsString<TChar*>::value> remove(TChar* key) const {
|
||||
template <typename TChar, enable_if_t<IsString<TChar*>::value, int> = 0>
|
||||
void remove(TChar* key) const {
|
||||
VariantData::removeMember(getData(), adaptString(key),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
// Removes a member of the object.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/remove/
|
||||
template <typename TString>
|
||||
enable_if_t<IsString<TString>::value> remove(const TString& key) const {
|
||||
template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
|
||||
void remove(const TString& key) const {
|
||||
VariantData::removeMember(getData(), adaptString(key),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
// Removes a member of the object or an element of the array.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/remove/
|
||||
template <typename TVariant>
|
||||
enable_if_t<IsVariant<TVariant>::value> remove(const TVariant& key) const {
|
||||
template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
|
||||
void remove(const TVariant& key) const {
|
||||
if (key.template is<size_t>())
|
||||
remove(key.template as<size_t>());
|
||||
else
|
||||
@@ -167,43 +170,40 @@ class VariantRefBase : public VariantTag {
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonvariant/containskey/
|
||||
template <typename TString>
|
||||
template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
|
||||
enable_if_t<IsString<TString>::value, bool> containsKey(
|
||||
const TString& key) const;
|
||||
bool containsKey(const TString& key) const;
|
||||
|
||||
// DEPRECATED: use obj["key"].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonvariant/containskey/
|
||||
template <typename TChar>
|
||||
template <typename TChar, enable_if_t<IsString<TChar*>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
|
||||
enable_if_t<IsString<TChar*>::value, bool> containsKey(TChar* key) const;
|
||||
bool containsKey(TChar* key) const;
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
// https://arduinojson.org/v7/api/jsonvariant/containskey/
|
||||
template <typename TVariant>
|
||||
template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
|
||||
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
|
||||
enable_if_t<IsVariant<TVariant>::value, bool> containsKey(
|
||||
const TVariant& key) const;
|
||||
bool containsKey(const TVariant& key) const;
|
||||
|
||||
// Gets or sets an object member.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/subscript/
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
|
||||
operator[](const TString& key) const;
|
||||
template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
|
||||
FORCE_INLINE MemberProxy<TDerived, AdaptedString<TString>> operator[](
|
||||
const TString& key) const;
|
||||
|
||||
// Gets or sets an object member.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/subscript/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE
|
||||
enable_if_t<IsString<TChar*>::value, MemberProxy<TDerived, TChar*>>
|
||||
operator[](TChar* key) const;
|
||||
template <
|
||||
typename TChar,
|
||||
enable_if_t<IsString<TChar*>::value && !is_const<TChar>::value, int> = 0>
|
||||
FORCE_INLINE MemberProxy<TDerived, AdaptedString<TChar*>> operator[](
|
||||
TChar* key) const;
|
||||
|
||||
// Gets an object member or an array element.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/subscript/
|
||||
template <typename TVariant>
|
||||
enable_if_t<IsVariant<TVariant>::value, JsonVariantConst> operator[](
|
||||
const TVariant& key) const {
|
||||
template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
|
||||
JsonVariantConst operator[](const TVariant& key) const {
|
||||
if (key.template is<size_t>())
|
||||
return operator[](key.template as<size_t>());
|
||||
else
|
||||
@@ -294,19 +294,18 @@ class VariantRefBase : public VariantTag {
|
||||
}
|
||||
|
||||
template <typename TConverter, typename T>
|
||||
bool doSet(T&& value) const {
|
||||
bool doSet(const T& value) const {
|
||||
return doSet<TConverter>(
|
||||
detail::forward<T>(value),
|
||||
is_same<typename function_traits<
|
||||
decltype(&TConverter::toJson)>::return_type,
|
||||
bool>{});
|
||||
value, is_same<typename function_traits<
|
||||
decltype(&TConverter::toJson)>::return_type,
|
||||
bool>{});
|
||||
}
|
||||
|
||||
template <typename TConverter, typename T>
|
||||
bool doSet(T&& value, false_type) const;
|
||||
bool doSet(const T& value, false_type) const;
|
||||
|
||||
template <typename TConverter, typename T>
|
||||
bool doSet(T&& value, true_type) const;
|
||||
bool doSet(const T& value, true_type) const;
|
||||
|
||||
ArduinoJson::JsonVariant getOrCreateVariant() const;
|
||||
};
|
||||
|
||||
@@ -67,34 +67,30 @@ inline void convertToJson(const VariantRefBase<TDerived>& src,
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
inline enable_if_t<is_same<T, JsonVariant>::value, T>
|
||||
VariantRefBase<TDerived>::add() const {
|
||||
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int>>
|
||||
inline T VariantRefBase<TDerived>::add() const {
|
||||
return JsonVariant(
|
||||
detail::VariantData::addElement(getOrCreateData(), getResourceManager()),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString>
|
||||
inline enable_if_t<IsString<TString>::value, bool>
|
||||
VariantRefBase<TDerived>::containsKey(const TString& key) const {
|
||||
template <typename TString, enable_if_t<IsString<TString>::value, int>>
|
||||
inline bool VariantRefBase<TDerived>::containsKey(const TString& key) const {
|
||||
return VariantData::getMember(getData(), adaptString(key),
|
||||
getResourceManager()) != 0;
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TChar>
|
||||
inline enable_if_t<IsString<TChar*>::value, bool>
|
||||
VariantRefBase<TDerived>::containsKey(TChar* key) const {
|
||||
template <typename TChar, enable_if_t<IsString<TChar*>::value, int>>
|
||||
inline bool VariantRefBase<TDerived>::containsKey(TChar* key) const {
|
||||
return VariantData::getMember(getData(), adaptString(key),
|
||||
getResourceManager()) != 0;
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TVariant>
|
||||
inline enable_if_t<IsVariant<TVariant>::value, bool>
|
||||
VariantRefBase<TDerived>::containsKey(const TVariant& key) const {
|
||||
template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int>>
|
||||
inline bool VariantRefBase<TDerived>::containsKey(const TVariant& key) const {
|
||||
return containsKey(key.template as<const char*>());
|
||||
}
|
||||
|
||||
@@ -119,26 +115,27 @@ inline bool VariantRefBase<TDerived>::is() const {
|
||||
template <typename TDerived>
|
||||
inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
|
||||
size_t index) const {
|
||||
return ElementProxy<TDerived>(derived(), index);
|
||||
return {derived(), index};
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString>
|
||||
inline enable_if_t<IsString<TString*>::value, MemberProxy<TDerived, TString*>>
|
||||
VariantRefBase<TDerived>::operator[](TString* key) const {
|
||||
return MemberProxy<TDerived, TString*>(derived(), key);
|
||||
template <typename TChar,
|
||||
enable_if_t<IsString<TChar*>::value && !is_const<TChar>::value, int>>
|
||||
inline MemberProxy<TDerived, AdaptedString<TChar*>>
|
||||
VariantRefBase<TDerived>::operator[](TChar* key) const {
|
||||
return {derived(), adaptString(key)};
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString>
|
||||
inline enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
|
||||
template <typename TString, enable_if_t<IsString<TString>::value, int>>
|
||||
inline MemberProxy<TDerived, AdaptedString<TString>>
|
||||
VariantRefBase<TDerived>::operator[](const TString& key) const {
|
||||
return MemberProxy<TDerived, TString>(derived(), key);
|
||||
return {derived(), adaptString(key)};
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TConverter, typename T>
|
||||
inline bool VariantRefBase<TDerived>::doSet(T&& value, false_type) const {
|
||||
inline bool VariantRefBase<TDerived>::doSet(const T& value, false_type) const {
|
||||
TConverter::toJson(value, getOrCreateVariant());
|
||||
auto resources = getResourceManager();
|
||||
return resources && !resources->overflowed();
|
||||
@@ -146,32 +143,29 @@ inline bool VariantRefBase<TDerived>::doSet(T&& value, false_type) const {
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TConverter, typename T>
|
||||
inline bool VariantRefBase<TDerived>::doSet(T&& value, true_type) const {
|
||||
inline bool VariantRefBase<TDerived>::doSet(const T& value, true_type) const {
|
||||
return TConverter::toJson(value, getOrCreateVariant());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
inline enable_if_t<is_same<T, JsonArray>::value, JsonArray>
|
||||
VariantRefBase<TDerived>::to() const {
|
||||
template <typename T, enable_if_t<is_same<T, JsonArray>::value, int>>
|
||||
inline JsonArray VariantRefBase<TDerived>::to() const {
|
||||
return JsonArray(
|
||||
VariantData::toArray(getOrCreateData(), getResourceManager()),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
enable_if_t<is_same<T, JsonObject>::value, JsonObject>
|
||||
VariantRefBase<TDerived>::to() const {
|
||||
template <typename T, enable_if_t<is_same<T, JsonObject>::value, int>>
|
||||
JsonObject VariantRefBase<TDerived>::to() const {
|
||||
return JsonObject(
|
||||
VariantData::toObject(getOrCreateData(), getResourceManager()),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
enable_if_t<is_same<T, JsonVariant>::value, JsonVariant>
|
||||
VariantRefBase<TDerived>::to() const {
|
||||
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int>>
|
||||
JsonVariant VariantRefBase<TDerived>::to() const {
|
||||
auto data = getOrCreateData();
|
||||
auto resources = getResourceManager();
|
||||
detail::VariantData::clear(data, resources);
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2024, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||
#include <ArduinoJson/Polyfills/limits.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
struct StringNode;
|
||||
|
||||
class VariantSlot {
|
||||
// CAUTION: same layout as VariantData
|
||||
// we cannot use composition because it adds padding
|
||||
// (+20% on ESP8266 for example)
|
||||
VariantContent content_;
|
||||
uint8_t flags_;
|
||||
SlotId next_;
|
||||
const char* key_;
|
||||
|
||||
public:
|
||||
// Placement new
|
||||
static void* operator new(size_t, void* p) noexcept {
|
||||
return p;
|
||||
}
|
||||
|
||||
static void operator delete(void*, void*) noexcept {}
|
||||
|
||||
VariantSlot() : flags_(0), next_(NULL_SLOT), key_(0) {}
|
||||
|
||||
VariantData* data() {
|
||||
return reinterpret_cast<VariantData*>(&content_);
|
||||
}
|
||||
|
||||
const VariantData* data() const {
|
||||
return reinterpret_cast<const VariantData*>(&content_);
|
||||
}
|
||||
|
||||
SlotId next() const {
|
||||
return next_;
|
||||
}
|
||||
|
||||
void setNext(SlotId slot) {
|
||||
next_ = slot;
|
||||
}
|
||||
|
||||
void setKey(const char* k) {
|
||||
ARDUINOJSON_ASSERT(k);
|
||||
flags_ &= VALUE_MASK;
|
||||
key_ = k;
|
||||
}
|
||||
|
||||
void setKey(StringNode* k) {
|
||||
ARDUINOJSON_ASSERT(k);
|
||||
flags_ |= OWNED_KEY_BIT;
|
||||
key_ = k->data;
|
||||
}
|
||||
|
||||
const char* key() const {
|
||||
return key_;
|
||||
}
|
||||
|
||||
bool ownsKey() const {
|
||||
return (flags_ & OWNED_KEY_BIT) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
inline VariantData* slotData(VariantSlot* slot) {
|
||||
return reinterpret_cast<VariantData*>(slot);
|
||||
}
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
constexpr size_t sizeofArray(size_t n) {
|
||||
return n * sizeof(VariantSlot);
|
||||
}
|
||||
|
||||
// Returns the size (in bytes) of an object with n members.
|
||||
constexpr size_t sizeofObject(size_t n) {
|
||||
return n * sizeof(VariantSlot);
|
||||
}
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ARDUINOJSON_VERSION "7.2.1"
|
||||
#define ARDUINOJSON_VERSION "7.3.0"
|
||||
#define ARDUINOJSON_VERSION_MAJOR 7
|
||||
#define ARDUINOJSON_VERSION_MINOR 2
|
||||
#define ARDUINOJSON_VERSION_REVISION 1
|
||||
#define ARDUINOJSON_VERSION_MACRO V721
|
||||
#define ARDUINOJSON_VERSION_MINOR 3
|
||||
#define ARDUINOJSON_VERSION_REVISION 0
|
||||
#define ARDUINOJSON_VERSION_MACRO V730
|
||||
|
||||
Reference in New Issue
Block a user