mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-06-28 19:01:01 +02:00
Compare commits
10 Commits
variant-im
...
7.5
Author | SHA1 | Date | |
---|---|---|---|
5bc6a3077a | |||
31a729d35c | |||
48dec78781 | |||
8cc190b7bf | |||
b1a58f3c0c | |||
fe6de3a82b | |||
e27439f3cd | |||
7e093ffc25 | |||
8e3286aac8 | |||
c07744dc0d |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -179,19 +179,19 @@ jobs:
|
||||
|
||||
conf_test_windows:
|
||||
name: Test configuration on Windows
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2022
|
||||
needs: [gcc, clang]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: 32-bit
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
|
||||
cl /Isrc extras/conf_test/x86.cpp
|
||||
shell: cmd
|
||||
- name: 64-bit
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cl /Isrc extras/conf_test/x64.cpp
|
||||
shell: cmd
|
||||
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include "ArduinoJson/Variant/ConverterImpl.hpp"
|
||||
#include "ArduinoJson/Variant/JsonVariantCopier.hpp"
|
||||
#include "ArduinoJson/Variant/VariantCompare.hpp"
|
||||
#include "ArduinoJson/Variant/VariantImpl.hpp"
|
||||
#include "ArduinoJson/Variant/VariantRefBaseImpl.hpp"
|
||||
|
||||
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
||||
|
@ -308,8 +308,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||
template <typename TString,
|
||||
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
|
||||
void remove(const TString& key) {
|
||||
detail::VariantImpl(getData(), getResourceManager())
|
||||
.removeMember(detail::adaptString(key));
|
||||
getVariantImpl().removeMember(detail::adaptString(key));
|
||||
}
|
||||
|
||||
// Removes a member of the root object or an element of the root array.
|
||||
|
@ -4,10 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Collection/CollectionData.hpp>
|
||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||
#include <ArduinoJson/Polyfills/alias_cast.hpp>
|
||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||
#include <ArduinoJson/Variant/VariantImpl.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
|
@ -56,9 +56,7 @@ class MemberProxy
|
||||
}
|
||||
|
||||
VariantData* getData() const {
|
||||
VariantImpl variant(VariantAttorney::getData(upstream_),
|
||||
VariantAttorney::getResourceManager(upstream_));
|
||||
return variant.getMember(key_);
|
||||
return VariantAttorney::getVariantImpl(upstream_).getMember(key_);
|
||||
}
|
||||
|
||||
VariantData* getOrCreateData() const {
|
||||
|
@ -14,8 +14,7 @@ size_t measure(ArduinoJson::JsonVariantConst source) {
|
||||
auto data = VariantAttorney::getData(source);
|
||||
auto resources = VariantAttorney::getResourceManager(source);
|
||||
TSerializer<DummyWriter> serializer(dp, resources);
|
||||
VariantImpl variant(data, resources);
|
||||
return variant.accept(serializer);
|
||||
return VariantImpl(data, resources).accept(serializer);
|
||||
}
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
@ -13,8 +13,7 @@ size_t doSerialize(ArduinoJson::JsonVariantConst source, TWriter writer) {
|
||||
auto data = VariantAttorney::getData(source);
|
||||
auto resources = VariantAttorney::getResourceManager(source);
|
||||
TSerializer<TWriter> serializer(writer, resources);
|
||||
VariantImpl variant(data, resources);
|
||||
return variant.accept(serializer);
|
||||
return VariantImpl(data, resources).accept(serializer);
|
||||
}
|
||||
|
||||
template <template <typename> class TSerializer, typename TDestination>
|
||||
|
@ -240,8 +240,7 @@ inline void convertToJson(const ::Printable& src, JsonVariant dst) {
|
||||
auto data = detail::VariantAttorney::getData(dst);
|
||||
if (!resources || !data)
|
||||
return;
|
||||
detail::VariantImpl impl(data, resources);
|
||||
impl.clear();
|
||||
detail::VariantImpl(data, resources).clear();
|
||||
detail::StringBuilderPrint print(resources);
|
||||
src.printTo(print);
|
||||
if (print.overflowed())
|
||||
|
@ -50,9 +50,8 @@ typename TVisitor::result_type accept(JsonVariantConst variant,
|
||||
TVisitor& visit) {
|
||||
auto data = VariantAttorney::getData(variant);
|
||||
auto resources = VariantAttorney::getResourceManager(variant);
|
||||
VariantImpl impl(data, resources);
|
||||
VisitorAdapter<TVisitor> adapter(visit);
|
||||
return impl.accept(adapter);
|
||||
return VariantImpl(data, resources).accept(adapter);
|
||||
}
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||
#include <ArduinoJson/Variant/VariantImpl.hpp>
|
||||
#include <ArduinoJson/Variant/VariantTo.hpp>
|
||||
#include "JsonVariantConst.hpp"
|
||||
|
||||
|
@ -4,12 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Memory/StringNode.hpp>
|
||||
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
@ -86,422 +81,4 @@ struct VariantData {
|
||||
}
|
||||
};
|
||||
|
||||
class VariantImpl {
|
||||
public:
|
||||
VariantImpl() : data_(nullptr), resources_(nullptr) {}
|
||||
|
||||
VariantImpl(VariantData* data, ResourceManager* resources)
|
||||
: data_(data), resources_(resources) {}
|
||||
|
||||
VariantData* getData() const {
|
||||
return data_;
|
||||
}
|
||||
|
||||
ResourceManager* getResourceManager() const {
|
||||
return resources_;
|
||||
}
|
||||
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor& visit) {
|
||||
if (!data_)
|
||||
return visit.visit(nullptr);
|
||||
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
switch (data_->type) {
|
||||
case VariantType::Float:
|
||||
return visit.visit(data_->content.asFloat);
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
case VariantType::Double:
|
||||
return visit.visit(eightByteValue->asDouble);
|
||||
#endif
|
||||
|
||||
case VariantType::Array:
|
||||
return visit.visit(asArray());
|
||||
|
||||
case VariantType::Object:
|
||||
return visit.visit(asObject());
|
||||
|
||||
case VariantType::TinyString:
|
||||
return visit.visit(JsonString(data_->content.asTinyString));
|
||||
|
||||
case VariantType::LinkedString:
|
||||
return visit.visit(JsonString(asLinkedString(), true));
|
||||
|
||||
case VariantType::OwnedString:
|
||||
return visit.visit(JsonString(data_->content.asOwnedString->data,
|
||||
data_->content.asOwnedString->length));
|
||||
|
||||
case VariantType::RawString:
|
||||
return visit.visit(RawString(data_->content.asOwnedString->data,
|
||||
data_->content.asOwnedString->length));
|
||||
|
||||
case VariantType::Int32:
|
||||
return visit.visit(static_cast<JsonInteger>(data_->content.asInt32));
|
||||
|
||||
case VariantType::Uint32:
|
||||
return visit.visit(static_cast<JsonUInt>(data_->content.asUint32));
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Int64:
|
||||
return visit.visit(eightByteValue->asInt64);
|
||||
|
||||
case VariantType::Uint64:
|
||||
return visit.visit(eightByteValue->asUint64);
|
||||
#endif
|
||||
|
||||
case VariantType::Boolean:
|
||||
return visit.visit(data_->content.asBoolean != 0);
|
||||
|
||||
default:
|
||||
return visit.visit(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
VariantData* addElement() {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.addElement();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool addValue(const T& value) {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.addValue(value);
|
||||
}
|
||||
|
||||
bool asBoolean() const {
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
switch (data_->type) {
|
||||
case VariantType::Boolean:
|
||||
return data_->content.asBoolean;
|
||||
case VariantType::Uint32:
|
||||
case VariantType::Int32:
|
||||
return data_->content.asUint32 != 0;
|
||||
case VariantType::Float:
|
||||
return data_->content.asFloat != 0;
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
case VariantType::Double:
|
||||
return eightByteValue->asDouble != 0;
|
||||
#endif
|
||||
case VariantType::Null:
|
||||
return false;
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Uint64:
|
||||
case VariantType::Int64:
|
||||
return eightByteValue->asUint64 != 0;
|
||||
#endif
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayImpl asArray() {
|
||||
return ArrayImpl(isArray() ? &data_->content.asCollection : nullptr,
|
||||
resources_);
|
||||
}
|
||||
|
||||
CollectionImpl asCollection() {
|
||||
return CollectionImpl(
|
||||
isCollection() ? &data_->content.asCollection : nullptr, resources_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T asFloat() const {
|
||||
if (!data_)
|
||||
return 0.0;
|
||||
|
||||
static_assert(is_floating_point<T>::value, "T must be a floating point");
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
const char* str = nullptr;
|
||||
switch (data_->type) {
|
||||
case VariantType::Boolean:
|
||||
return static_cast<T>(data_->content.asBoolean);
|
||||
case VariantType::Uint32:
|
||||
return static_cast<T>(data_->content.asUint32);
|
||||
case VariantType::Int32:
|
||||
return static_cast<T>(data_->content.asInt32);
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Uint64:
|
||||
return static_cast<T>(eightByteValue->asUint64);
|
||||
case VariantType::Int64:
|
||||
return static_cast<T>(eightByteValue->asInt64);
|
||||
#endif
|
||||
case VariantType::TinyString:
|
||||
str = data_->content.asTinyString;
|
||||
break;
|
||||
case VariantType::LinkedString:
|
||||
str = asLinkedString();
|
||||
break;
|
||||
case VariantType::OwnedString:
|
||||
str = data_->content.asOwnedString->data;
|
||||
break;
|
||||
case VariantType::Float:
|
||||
return static_cast<T>(data_->content.asFloat);
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
case VariantType::Double:
|
||||
return static_cast<T>(eightByteValue->asDouble);
|
||||
#endif
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
ARDUINOJSON_ASSERT(str != nullptr);
|
||||
return parseNumber<T>(str);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T asIntegral() const {
|
||||
if (!data_)
|
||||
return 0;
|
||||
|
||||
static_assert(is_integral<T>::value, "T must be an integral type");
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
const char* str = nullptr;
|
||||
switch (data_->type) {
|
||||
case VariantType::Boolean:
|
||||
return data_->content.asBoolean;
|
||||
case VariantType::Uint32:
|
||||
return convertNumber<T>(data_->content.asUint32);
|
||||
case VariantType::Int32:
|
||||
return convertNumber<T>(data_->content.asInt32);
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Uint64:
|
||||
return convertNumber<T>(eightByteValue->asUint64);
|
||||
case VariantType::Int64:
|
||||
return convertNumber<T>(eightByteValue->asInt64);
|
||||
#endif
|
||||
case VariantType::TinyString:
|
||||
str = data_->content.asTinyString;
|
||||
break;
|
||||
case VariantType::LinkedString:
|
||||
str = asLinkedString();
|
||||
break;
|
||||
case VariantType::OwnedString:
|
||||
str = data_->content.asOwnedString->data;
|
||||
break;
|
||||
case VariantType::Float:
|
||||
return convertNumber<T>(data_->content.asFloat);
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
case VariantType::Double:
|
||||
return convertNumber<T>(eightByteValue->asDouble);
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
ARDUINOJSON_ASSERT(str != nullptr);
|
||||
return parseNumber<T>(str);
|
||||
}
|
||||
|
||||
ObjectImpl asObject() {
|
||||
return ObjectImpl(isObject() ? &data_->content.asCollection : nullptr,
|
||||
resources_);
|
||||
}
|
||||
|
||||
JsonString asRawString() const {
|
||||
switch (type()) {
|
||||
case VariantType::RawString:
|
||||
return JsonString(data_->content.asOwnedString->data,
|
||||
data_->content.asOwnedString->length);
|
||||
default:
|
||||
return JsonString();
|
||||
}
|
||||
}
|
||||
|
||||
const char* asLinkedString() const;
|
||||
|
||||
JsonString asString() const {
|
||||
switch (type()) {
|
||||
case VariantType::TinyString:
|
||||
return JsonString(data_->content.asTinyString);
|
||||
case VariantType::LinkedString:
|
||||
return JsonString(asLinkedString(), true);
|
||||
case VariantType::OwnedString:
|
||||
return JsonString(data_->content.asOwnedString->data,
|
||||
data_->content.asOwnedString->length);
|
||||
default:
|
||||
return JsonString();
|
||||
}
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
const EightByteValue* getEightByte() const;
|
||||
#endif
|
||||
|
||||
VariantData* getElement(size_t index) {
|
||||
return asArray().getElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData* getMember(TAdaptedString key) {
|
||||
return asObject().getMember(key);
|
||||
}
|
||||
|
||||
VariantData* getOrAddElement(size_t index) {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.getOrAddElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData* getOrAddMember(TAdaptedString key) {
|
||||
if (key.isNull())
|
||||
return nullptr;
|
||||
auto obj = isNull() ? toObject() : asObject();
|
||||
return obj.getOrAddMember(key);
|
||||
}
|
||||
|
||||
bool isArray() const {
|
||||
return type() == VariantType::Array;
|
||||
}
|
||||
|
||||
bool isBoolean() const {
|
||||
return type() == VariantType::Boolean;
|
||||
}
|
||||
|
||||
bool isCollection() const {
|
||||
return type() & VariantTypeBits::CollectionMask;
|
||||
}
|
||||
|
||||
bool isFloat() const {
|
||||
return data_ && data_->isFloat();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool isInteger() const {
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
switch (data_->type) {
|
||||
case VariantType::Uint32:
|
||||
return canConvertNumber<T>(data_->content.asUint32);
|
||||
|
||||
case VariantType::Int32:
|
||||
return canConvertNumber<T>(data_->content.asInt32);
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Uint64:
|
||||
return canConvertNumber<T>(eightByteValue->asUint64);
|
||||
|
||||
case VariantType::Int64:
|
||||
return canConvertNumber<T>(eightByteValue->asInt64);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return type() == VariantType::Null;
|
||||
}
|
||||
|
||||
bool isObject() const {
|
||||
return type() == VariantType::Object;
|
||||
}
|
||||
|
||||
bool isString() const {
|
||||
return data_ && data_->isString();
|
||||
}
|
||||
|
||||
size_t nesting() {
|
||||
return asCollection().nesting();
|
||||
}
|
||||
|
||||
void removeElement(size_t index) {
|
||||
asArray().removeElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void removeMember(TAdaptedString key) {
|
||||
asObject().removeMember(key);
|
||||
}
|
||||
|
||||
bool setBoolean(bool value) {
|
||||
if (!data_)
|
||||
return false;
|
||||
data_->setBoolean(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<sizeof(T) == 4, bool> setFloat(T value) {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
|
||||
if (!data_)
|
||||
return false;
|
||||
data_->type = VariantType::Float;
|
||||
data_->content.asFloat = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<sizeof(T) == 8, bool> setFloat(T value);
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<is_signed<T>::value, bool> setInteger(T value);
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<is_unsigned<T>::value, bool> setInteger(T value);
|
||||
|
||||
template <typename T>
|
||||
void setRawString(SerializedValue<T> value);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
bool setString(TAdaptedString value);
|
||||
|
||||
bool setLinkedString(const char* s);
|
||||
|
||||
size_t size() {
|
||||
if (isObject())
|
||||
return asObject().size();
|
||||
|
||||
if (isArray())
|
||||
return asArray().size();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ArrayImpl toArray() {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
|
||||
if (!data_)
|
||||
return ArrayImpl();
|
||||
data_->type = VariantType::Array;
|
||||
return ArrayImpl(new (&data_->content.asCollection) CollectionData(),
|
||||
resources_);
|
||||
}
|
||||
|
||||
ObjectImpl toObject() {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
|
||||
if (!data_)
|
||||
return ObjectImpl();
|
||||
data_->type = VariantType::Object;
|
||||
return ObjectImpl(new (&data_->content.asCollection) CollectionData(),
|
||||
resources_);
|
||||
}
|
||||
|
||||
VariantType type() const {
|
||||
return data_ ? data_->type : VariantType::Null;
|
||||
}
|
||||
|
||||
// Release the resources used by this variant and set it to null.
|
||||
void clear();
|
||||
|
||||
private:
|
||||
VariantData* data_;
|
||||
ResourceManager* resources_;
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
@ -5,10 +5,506 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
class VariantImpl {
|
||||
public:
|
||||
VariantImpl() : data_(nullptr), resources_(nullptr) {}
|
||||
|
||||
VariantImpl(VariantData* data, ResourceManager* resources)
|
||||
: data_(data), resources_(resources) {}
|
||||
|
||||
VariantData* getData() const {
|
||||
return data_;
|
||||
}
|
||||
|
||||
ResourceManager* getResourceManager() const {
|
||||
return resources_;
|
||||
}
|
||||
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor& visit) {
|
||||
if (!data_)
|
||||
return visit.visit(nullptr);
|
||||
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
switch (data_->type) {
|
||||
case VariantType::Float:
|
||||
return visit.visit(data_->content.asFloat);
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
case VariantType::Double:
|
||||
return visit.visit(eightByteValue->asDouble);
|
||||
#endif
|
||||
|
||||
case VariantType::Array:
|
||||
return visit.visit(asArray());
|
||||
|
||||
case VariantType::Object:
|
||||
return visit.visit(asObject());
|
||||
|
||||
case VariantType::TinyString:
|
||||
return visit.visit(JsonString(data_->content.asTinyString));
|
||||
|
||||
case VariantType::LinkedString:
|
||||
return visit.visit(JsonString(asLinkedString(), true));
|
||||
|
||||
case VariantType::OwnedString:
|
||||
return visit.visit(JsonString(data_->content.asOwnedString->data,
|
||||
data_->content.asOwnedString->length));
|
||||
|
||||
case VariantType::RawString:
|
||||
return visit.visit(RawString(data_->content.asOwnedString->data,
|
||||
data_->content.asOwnedString->length));
|
||||
|
||||
case VariantType::Int32:
|
||||
return visit.visit(static_cast<JsonInteger>(data_->content.asInt32));
|
||||
|
||||
case VariantType::Uint32:
|
||||
return visit.visit(static_cast<JsonUInt>(data_->content.asUint32));
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Int64:
|
||||
return visit.visit(eightByteValue->asInt64);
|
||||
|
||||
case VariantType::Uint64:
|
||||
return visit.visit(eightByteValue->asUint64);
|
||||
#endif
|
||||
|
||||
case VariantType::Boolean:
|
||||
return visit.visit(data_->content.asBoolean != 0);
|
||||
|
||||
default:
|
||||
return visit.visit(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
VariantData* addElement() {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.addElement();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool addValue(const T& value) {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.addValue(value);
|
||||
}
|
||||
|
||||
bool asBoolean() const {
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
switch (data_->type) {
|
||||
case VariantType::Boolean:
|
||||
return data_->content.asBoolean;
|
||||
case VariantType::Uint32:
|
||||
case VariantType::Int32:
|
||||
return data_->content.asUint32 != 0;
|
||||
case VariantType::Float:
|
||||
return data_->content.asFloat != 0;
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
case VariantType::Double:
|
||||
return eightByteValue->asDouble != 0;
|
||||
#endif
|
||||
case VariantType::Null:
|
||||
return false;
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Uint64:
|
||||
case VariantType::Int64:
|
||||
return eightByteValue->asUint64 != 0;
|
||||
#endif
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayImpl asArray() {
|
||||
return ArrayImpl(isArray() ? &data_->content.asCollection : nullptr,
|
||||
resources_);
|
||||
}
|
||||
|
||||
CollectionImpl asCollection() {
|
||||
return CollectionImpl(
|
||||
isCollection() ? &data_->content.asCollection : nullptr, resources_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T asFloat() const {
|
||||
if (!data_)
|
||||
return 0.0;
|
||||
|
||||
static_assert(is_floating_point<T>::value, "T must be a floating point");
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
const char* str = nullptr;
|
||||
switch (data_->type) {
|
||||
case VariantType::Boolean:
|
||||
return static_cast<T>(data_->content.asBoolean);
|
||||
case VariantType::Uint32:
|
||||
return static_cast<T>(data_->content.asUint32);
|
||||
case VariantType::Int32:
|
||||
return static_cast<T>(data_->content.asInt32);
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Uint64:
|
||||
return static_cast<T>(eightByteValue->asUint64);
|
||||
case VariantType::Int64:
|
||||
return static_cast<T>(eightByteValue->asInt64);
|
||||
#endif
|
||||
case VariantType::TinyString:
|
||||
str = data_->content.asTinyString;
|
||||
break;
|
||||
case VariantType::LinkedString:
|
||||
str = asLinkedString();
|
||||
break;
|
||||
case VariantType::OwnedString:
|
||||
str = data_->content.asOwnedString->data;
|
||||
break;
|
||||
case VariantType::Float:
|
||||
return static_cast<T>(data_->content.asFloat);
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
case VariantType::Double:
|
||||
return static_cast<T>(eightByteValue->asDouble);
|
||||
#endif
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
ARDUINOJSON_ASSERT(str != nullptr);
|
||||
return parseNumber<T>(str);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T asIntegral() const {
|
||||
if (!data_)
|
||||
return 0;
|
||||
|
||||
static_assert(is_integral<T>::value, "T must be an integral type");
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
const char* str = nullptr;
|
||||
switch (data_->type) {
|
||||
case VariantType::Boolean:
|
||||
return data_->content.asBoolean;
|
||||
case VariantType::Uint32:
|
||||
return convertNumber<T>(data_->content.asUint32);
|
||||
case VariantType::Int32:
|
||||
return convertNumber<T>(data_->content.asInt32);
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Uint64:
|
||||
return convertNumber<T>(eightByteValue->asUint64);
|
||||
case VariantType::Int64:
|
||||
return convertNumber<T>(eightByteValue->asInt64);
|
||||
#endif
|
||||
case VariantType::TinyString:
|
||||
str = data_->content.asTinyString;
|
||||
break;
|
||||
case VariantType::LinkedString:
|
||||
str = asLinkedString();
|
||||
break;
|
||||
case VariantType::OwnedString:
|
||||
str = data_->content.asOwnedString->data;
|
||||
break;
|
||||
case VariantType::Float:
|
||||
return convertNumber<T>(data_->content.asFloat);
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
case VariantType::Double:
|
||||
return convertNumber<T>(eightByteValue->asDouble);
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
ARDUINOJSON_ASSERT(str != nullptr);
|
||||
return parseNumber<T>(str);
|
||||
}
|
||||
|
||||
ObjectImpl asObject() {
|
||||
return ObjectImpl(isObject() ? &data_->content.asCollection : nullptr,
|
||||
resources_);
|
||||
}
|
||||
|
||||
JsonString asRawString() const {
|
||||
switch (type()) {
|
||||
case VariantType::RawString:
|
||||
return JsonString(data_->content.asOwnedString->data,
|
||||
data_->content.asOwnedString->length);
|
||||
default:
|
||||
return JsonString();
|
||||
}
|
||||
}
|
||||
|
||||
const char* asLinkedString() const {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::LinkedString);
|
||||
return resources_->getStaticString(data_->content.asSlotId);
|
||||
}
|
||||
|
||||
JsonString asString() const {
|
||||
switch (type()) {
|
||||
case VariantType::TinyString:
|
||||
return JsonString(data_->content.asTinyString);
|
||||
case VariantType::LinkedString:
|
||||
return JsonString(asLinkedString(), true);
|
||||
case VariantType::OwnedString:
|
||||
return JsonString(data_->content.asOwnedString->data,
|
||||
data_->content.asOwnedString->length);
|
||||
default:
|
||||
return JsonString();
|
||||
}
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
const EightByteValue* getEightByte() const {
|
||||
return type() & VariantTypeBits::EightByteBit
|
||||
? resources_->getEightByte(data_->content.asSlotId)
|
||||
: 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
VariantData* getElement(size_t index) {
|
||||
return asArray().getElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData* getMember(TAdaptedString key) {
|
||||
return asObject().getMember(key);
|
||||
}
|
||||
|
||||
VariantData* getOrAddElement(size_t index) {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.getOrAddElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData* getOrAddMember(TAdaptedString key) {
|
||||
if (key.isNull())
|
||||
return nullptr;
|
||||
auto obj = isNull() ? toObject() : asObject();
|
||||
return obj.getOrAddMember(key);
|
||||
}
|
||||
|
||||
bool isArray() const {
|
||||
return type() == VariantType::Array;
|
||||
}
|
||||
|
||||
bool isBoolean() const {
|
||||
return type() == VariantType::Boolean;
|
||||
}
|
||||
|
||||
bool isCollection() const {
|
||||
return type() & VariantTypeBits::CollectionMask;
|
||||
}
|
||||
|
||||
bool isFloat() const {
|
||||
return data_ && data_->isFloat();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool isInteger() const {
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
auto eightByteValue = getEightByte();
|
||||
#endif
|
||||
switch (data_->type) {
|
||||
case VariantType::Uint32:
|
||||
return canConvertNumber<T>(data_->content.asUint32);
|
||||
|
||||
case VariantType::Int32:
|
||||
return canConvertNumber<T>(data_->content.asInt32);
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case VariantType::Uint64:
|
||||
return canConvertNumber<T>(eightByteValue->asUint64);
|
||||
|
||||
case VariantType::Int64:
|
||||
return canConvertNumber<T>(eightByteValue->asInt64);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return type() == VariantType::Null;
|
||||
}
|
||||
|
||||
bool isObject() const {
|
||||
return type() == VariantType::Object;
|
||||
}
|
||||
|
||||
bool isString() const {
|
||||
return data_ && data_->isString();
|
||||
}
|
||||
|
||||
size_t nesting() {
|
||||
return asCollection().nesting();
|
||||
}
|
||||
|
||||
void removeElement(size_t index) {
|
||||
asArray().removeElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void removeMember(TAdaptedString key) {
|
||||
asObject().removeMember(key);
|
||||
}
|
||||
|
||||
bool setBoolean(bool value) {
|
||||
if (!data_)
|
||||
return false;
|
||||
data_->setBoolean(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<sizeof(T) == 4, bool> setFloat(T value) {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
|
||||
if (!data_)
|
||||
return false;
|
||||
data_->type = VariantType::Float;
|
||||
data_->content.asFloat = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<sizeof(T) == 8, bool> setFloat(T value) {
|
||||
ARDUINOJSON_ASSERT(isNull()); // must call clear() first
|
||||
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
float valueAsFloat = static_cast<float>(value);
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
if (value == valueAsFloat) {
|
||||
data_->type = VariantType::Float;
|
||||
data_->content.asFloat = valueAsFloat;
|
||||
} else {
|
||||
auto slot = resources_->allocEightByte();
|
||||
if (!slot)
|
||||
return false;
|
||||
data_->type = VariantType::Double;
|
||||
data_->content.asSlotId = slot.id();
|
||||
slot->asDouble = value;
|
||||
}
|
||||
#else
|
||||
data_->type = VariantType::Float;
|
||||
data_->content.asFloat = valueAsFloat;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<is_signed<T>::value, bool> setInteger(T value) {
|
||||
ARDUINOJSON_ASSERT(isNull()); // must call clear() first
|
||||
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
if (canConvertNumber<int32_t>(value)) {
|
||||
data_->type = VariantType::Int32;
|
||||
data_->content.asInt32 = static_cast<int32_t>(value);
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
else {
|
||||
auto slot = resources_->allocEightByte();
|
||||
if (!slot)
|
||||
return false;
|
||||
data_->type = VariantType::Int64;
|
||||
data_->content.asSlotId = slot.id();
|
||||
slot->asInt64 = value;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<is_unsigned<T>::value, bool> setInteger(T value) {
|
||||
ARDUINOJSON_ASSERT(isNull()); // must call clear() first
|
||||
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
if (canConvertNumber<uint32_t>(value)) {
|
||||
data_->type = VariantType::Uint32;
|
||||
data_->content.asUint32 = static_cast<uint32_t>(value);
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
else {
|
||||
auto slot = resources_->allocEightByte();
|
||||
if (!slot)
|
||||
return false;
|
||||
data_->type = VariantType::Uint64;
|
||||
data_->content.asSlotId = slot.id();
|
||||
slot->asUint64 = value;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void setRawString(SerializedValue<T> value);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
bool setString(TAdaptedString value);
|
||||
|
||||
bool setLinkedString(const char* s);
|
||||
|
||||
size_t size() {
|
||||
if (isObject())
|
||||
return asObject().size();
|
||||
|
||||
if (isArray())
|
||||
return asArray().size();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ArrayImpl toArray() {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
|
||||
if (!data_)
|
||||
return ArrayImpl();
|
||||
data_->type = VariantType::Array;
|
||||
return ArrayImpl(new (&data_->content.asCollection) CollectionData(),
|
||||
resources_);
|
||||
}
|
||||
|
||||
ObjectImpl toObject() {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
|
||||
if (!data_)
|
||||
return ObjectImpl();
|
||||
data_->type = VariantType::Object;
|
||||
return ObjectImpl(new (&data_->content.asCollection) CollectionData(),
|
||||
resources_);
|
||||
}
|
||||
|
||||
VariantType type() const {
|
||||
return data_ ? data_->type : VariantType::Null;
|
||||
}
|
||||
|
||||
// Release the resources used by this variant and set it to null.
|
||||
void clear();
|
||||
|
||||
private:
|
||||
VariantData* data_;
|
||||
ResourceManager* resources_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline void VariantImpl::setRawString(SerializedValue<T> value) {
|
||||
if (!data_)
|
||||
@ -75,93 +571,4 @@ inline void VariantImpl::clear() {
|
||||
data_->type = VariantType::Null;
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_USE_8_BYTE_POOL
|
||||
inline const EightByteValue* VariantImpl::getEightByte() const {
|
||||
return type() & VariantTypeBits::EightByteBit
|
||||
? resources_->getEightByte(data_->content.asSlotId)
|
||||
: 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline const char* VariantImpl::asLinkedString() const {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::LinkedString);
|
||||
return resources_->getStaticString(data_->content.asSlotId);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<sizeof(T) == 8, bool> VariantImpl::setFloat(T value) {
|
||||
ARDUINOJSON_ASSERT(isNull()); // must call clear() first
|
||||
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
float valueAsFloat = static_cast<float>(value);
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
if (value == valueAsFloat) {
|
||||
data_->type = VariantType::Float;
|
||||
data_->content.asFloat = valueAsFloat;
|
||||
} else {
|
||||
auto slot = resources_->allocEightByte();
|
||||
if (!slot)
|
||||
return false;
|
||||
data_->type = VariantType::Double;
|
||||
data_->content.asSlotId = slot.id();
|
||||
slot->asDouble = value;
|
||||
}
|
||||
#else
|
||||
data_->type = VariantType::Float;
|
||||
data_->content.asFloat = valueAsFloat;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<is_signed<T>::value, bool> VariantImpl::setInteger(T value) {
|
||||
ARDUINOJSON_ASSERT(isNull()); // must call clear() first
|
||||
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
if (canConvertNumber<int32_t>(value)) {
|
||||
data_->type = VariantType::Int32;
|
||||
data_->content.asInt32 = static_cast<int32_t>(value);
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
else {
|
||||
auto slot = resources_->allocEightByte();
|
||||
if (!slot)
|
||||
return false;
|
||||
data_->type = VariantType::Int64;
|
||||
data_->content.asSlotId = slot.id();
|
||||
slot->asInt64 = value;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<is_unsigned<T>::value, bool> VariantImpl::setInteger(T value) {
|
||||
ARDUINOJSON_ASSERT(isNull()); // must call clear() first
|
||||
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
if (canConvertNumber<uint32_t>(value)) {
|
||||
data_->type = VariantType::Uint32;
|
||||
data_->content.asUint32 = static_cast<uint32_t>(value);
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
else {
|
||||
auto slot = resources_->allocEightByte();
|
||||
if (!slot)
|
||||
return false;
|
||||
data_->type = VariantType::Uint64;
|
||||
data_->content.asSlotId = slot.id();
|
||||
slot->asUint64 = value;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
@ -69,22 +69,20 @@ inline void convertToJson(const VariantRefBase<TDerived>& src,
|
||||
template <typename TDerived>
|
||||
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int>>
|
||||
inline T VariantRefBase<TDerived>::add() const {
|
||||
detail::VariantImpl variant(getOrCreateData(), getResourceManager());
|
||||
return JsonVariant(variant.addElement(), getResourceManager());
|
||||
return JsonVariant(getOrCreateVariantImpl().addElement(),
|
||||
getResourceManager());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString, enable_if_t<IsString<TString>::value, int>>
|
||||
inline bool VariantRefBase<TDerived>::containsKey(const TString& key) const {
|
||||
detail::VariantImpl variant(getData(), getResourceManager());
|
||||
return variant.getMember(adaptString(key)) != 0;
|
||||
return getVariantImpl().getMember(adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TChar, enable_if_t<IsString<TChar*>::value, int>>
|
||||
inline bool VariantRefBase<TDerived>::containsKey(TChar* key) const {
|
||||
detail::VariantImpl variant(getData(), getResourceManager());
|
||||
return variant.getMember(adaptString(key)) != 0;
|
||||
return getVariantImpl().getMember(adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
|
Reference in New Issue
Block a user