From 65ba36622c0e32cd1936abf10a51035ce5db7fc9 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Mon, 2 Sep 2024 17:56:19 +0200 Subject: [PATCH] Add `VariantType` --- src/ArduinoJson/Variant/VariantContent.hpp | 49 +++---- src/ArduinoJson/Variant/VariantData.hpp | 141 +++++++++++---------- src/ArduinoJson/Variant/VariantImpl.hpp | 38 +++--- 3 files changed, 115 insertions(+), 113 deletions(-) diff --git a/src/ArduinoJson/Variant/VariantContent.hpp b/src/ArduinoJson/Variant/VariantContent.hpp index b1a6a5f7..cae3f207 100644 --- a/src/ArduinoJson/Variant/VariantContent.hpp +++ b/src/ArduinoJson/Variant/VariantContent.hpp @@ -13,38 +13,39 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE -enum { - OWNED_VALUE_BIT = 0x01, - VALUE_IS_NULL = 0, - VALUE_IS_RAW_STRING = 0x03, - VALUE_IS_LINKED_STRING = 0x04, - VALUE_IS_OWNED_STRING = 0x05, - - // CAUTION: no OWNED_VALUE_BIT below - - VALUE_IS_BOOLEAN = 0x06, - - NUMBER_BIT = 0x08, // 0000 1000 - VALUE_IS_UINT32 = 0x0A, // 0000 1010 - VALUE_IS_INT32 = 0x0C, // 0000 1100 - VALUE_IS_FLOAT = 0x0E, // 0000 1110 - +enum class VariantTypeBits : uint8_t { + OwnedStringBit = 0x01, // 0000 0001 + NumberBit = 0x08, // 0000 1000 #if ARDUINOJSON_USE_EXTENSIONS - EXTENSION_BIT = 0x10, // 0001 0000 + ExtensionBit = 0x10, // 0001 0000 #endif + CollectionMask = 0x60, +}; + +enum class VariantType : uint8_t { + Null = 0, // 0000 0000 + RawString = 0x03, // 0000 0011 + LinkedString = 0x04, // 0000 0100 + OwnedString = 0x05, // 0000 0101 + Boolean = 0x06, // 0000 0110 + Uint32 = 0x0A, // 0000 1010 + Int32 = 0x0C, // 0000 1100 + Float = 0x0E, // 0000 1110 #if ARDUINOJSON_USE_LONG_LONG - VALUE_IS_UINT64 = 0x1A, // 0001 1010 - VALUE_IS_INT64 = 0x1C, // 0001 1100 + Uint64 = 0x1A, // 0001 1010 + Int64 = 0x1C, // 0001 1100 #endif #if ARDUINOJSON_USE_DOUBLE - VALUE_IS_DOUBLE = 0x1E, // 0001 1110 + Double = 0x1E, // 0001 1110 #endif - - COLLECTION_MASK = 0x60, - VALUE_IS_OBJECT = 0x20, - VALUE_IS_ARRAY = 0x40, + Object = 0x20, + Array = 0x40, }; +inline bool operator&(VariantType type, VariantTypeBits bit) { + return (uint8_t(type) & uint8_t(bit)) != 0; +} + union VariantContent { VariantContent() {} diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index 30c5ba0a..b31c6668 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -19,7 +19,7 @@ T parseNumber(const char* s); class VariantData { VariantContent content_; // must be first to allow cast from array to variant - uint8_t type_; + VariantType type_; SlotId next_; public: @@ -30,7 +30,7 @@ class VariantData { static void operator delete(void*, void*) noexcept {} - VariantData() : type_(VALUE_IS_NULL), next_(NULL_SLOT) {} + VariantData() : type_(VariantType::Null), next_(NULL_SLOT) {} SlotId next() const { return next_; @@ -45,47 +45,47 @@ class VariantData { TVisitor& visit, const ResourceManager* resources) const { (void)resources; // silence warning switch (type_) { - case VALUE_IS_FLOAT: + case VariantType::Float: return visit.visit(static_cast(content_.asFloat)); #if ARDUINOJSON_USE_DOUBLE - case VALUE_IS_DOUBLE: + case VariantType::Double: return visit.visit(getExtension(resources)->asDouble); #endif - case VALUE_IS_ARRAY: + case VariantType::Array: return visit.visit(content_.asArray); - case VALUE_IS_OBJECT: + case VariantType::Object: return visit.visit(content_.asObject); - case VALUE_IS_LINKED_STRING: + case VariantType::LinkedString: return visit.visit(JsonString(content_.asLinkedString)); - case VALUE_IS_OWNED_STRING: + case VariantType::OwnedString: return visit.visit(JsonString(content_.asOwnedString->data, content_.asOwnedString->length, JsonString::Copied)); - case VALUE_IS_RAW_STRING: + case VariantType::RawString: return visit.visit(RawString(content_.asOwnedString->data, content_.asOwnedString->length)); - case VALUE_IS_INT32: + case VariantType::Int32: return visit.visit(static_cast(content_.asInt32)); - case VALUE_IS_UINT32: + case VariantType::Uint32: return visit.visit(static_cast(content_.asUint32)); #if ARDUINOJSON_USE_LONG_LONG - case VALUE_IS_INT64: + case VariantType::Int64: return visit.visit(getExtension(resources)->asInt64); - case VALUE_IS_UINT64: + case VariantType::Uint64: return visit.visit(getExtension(resources)->asUint64); #endif - case VALUE_IS_BOOLEAN: + case VariantType::Boolean: return visit.visit(content_.asBoolean != 0); default: @@ -132,22 +132,22 @@ class VariantData { bool asBoolean(const ResourceManager* resources) const { (void)resources; // silence warning switch (type_) { - case VALUE_IS_BOOLEAN: + case VariantType::Boolean: return content_.asBoolean; - case VALUE_IS_UINT32: - case VALUE_IS_INT32: + case VariantType::Uint32: + case VariantType::Int32: return content_.asUint32 != 0; - case VALUE_IS_FLOAT: + case VariantType::Float: return content_.asFloat != 0; #if ARDUINOJSON_USE_DOUBLE - case VALUE_IS_DOUBLE: + case VariantType::Double: return getExtension(resources)->asDouble != 0; #endif - case VALUE_IS_NULL: + case VariantType::Null: return false; #if ARDUINOJSON_USE_LONG_LONG - case VALUE_IS_UINT64: - case VALUE_IS_INT64: + case VariantType::Uint64: + case VariantType::Int64: return getExtension(resources)->asUint64 != 0; #endif default: @@ -176,25 +176,25 @@ class VariantData { static_assert(is_floating_point::value, "T must be a floating point"); (void)resources; // silence warning switch (type_) { - case VALUE_IS_BOOLEAN: + case VariantType::Boolean: return static_cast(content_.asBoolean); - case VALUE_IS_UINT32: + case VariantType::Uint32: return static_cast(content_.asUint32); - case VALUE_IS_INT32: + case VariantType::Int32: return static_cast(content_.asInt32); #if ARDUINOJSON_USE_LONG_LONG - case VALUE_IS_UINT64: + case VariantType::Uint64: return static_cast(getExtension(resources)->asUint64); - case VALUE_IS_INT64: + case VariantType::Int64: return static_cast(getExtension(resources)->asInt64); #endif - case VALUE_IS_LINKED_STRING: - case VALUE_IS_OWNED_STRING: + case VariantType::LinkedString: + case VariantType::OwnedString: return parseNumber(content_.asOwnedString->data); - case VALUE_IS_FLOAT: + case VariantType::Float: return static_cast(content_.asFloat); #if ARDUINOJSON_USE_DOUBLE - case VALUE_IS_DOUBLE: + case VariantType::Double: return static_cast(getExtension(resources)->asDouble); #endif default: @@ -207,26 +207,26 @@ class VariantData { static_assert(is_integral::value, "T must be an integral type"); (void)resources; // silence warning switch (type_) { - case VALUE_IS_BOOLEAN: + case VariantType::Boolean: return content_.asBoolean; - case VALUE_IS_UINT32: + case VariantType::Uint32: return convertNumber(content_.asUint32); - case VALUE_IS_INT32: + case VariantType::Int32: return convertNumber(content_.asInt32); #if ARDUINOJSON_USE_LONG_LONG - case VALUE_IS_UINT64: + case VariantType::Uint64: return convertNumber(getExtension(resources)->asUint64); - case VALUE_IS_INT64: + case VariantType::Int64: return convertNumber(getExtension(resources)->asInt64); #endif - case VALUE_IS_LINKED_STRING: + case VariantType::LinkedString: return parseNumber(content_.asLinkedString); - case VALUE_IS_OWNED_STRING: + case VariantType::OwnedString: return parseNumber(content_.asOwnedString->data); - case VALUE_IS_FLOAT: + case VariantType::Float: return convertNumber(content_.asFloat); #if ARDUINOJSON_USE_DOUBLE - case VALUE_IS_DOUBLE: + case VariantType::Double: return convertNumber(getExtension(resources)->asDouble); #endif default: @@ -244,7 +244,7 @@ class VariantData { JsonString asRawString() const { switch (type_) { - case VALUE_IS_RAW_STRING: + case VariantType::RawString: return JsonString(content_.asOwnedString->data, content_.asOwnedString->length, JsonString::Copied); default: @@ -254,9 +254,9 @@ class VariantData { JsonString asString() const { switch (type_) { - case VALUE_IS_LINKED_STRING: + case VariantType::LinkedString: return JsonString(content_.asLinkedString, JsonString::Linked); - case VALUE_IS_OWNED_STRING: + case VariantType::OwnedString: return JsonString(content_.asOwnedString->data, content_.asOwnedString->length, JsonString::Copied); default: @@ -310,36 +310,36 @@ class VariantData { } bool isArray() const { - return type_ == VALUE_IS_ARRAY; + return type_ == VariantType::Array; } bool isBoolean() const { - return type_ == VALUE_IS_BOOLEAN; + return type_ == VariantType::Boolean; } bool isCollection() const { - return (type_ & COLLECTION_MASK) != 0; + return type_ & VariantTypeBits::CollectionMask; } bool isFloat() const { - return (type_ & NUMBER_BIT) != 0; + return type_ & VariantTypeBits::NumberBit; } template bool isInteger(const ResourceManager* resources) const { (void)resources; // silence warning switch (type_) { - case VALUE_IS_UINT32: + case VariantType::Uint32: return canConvertNumber(content_.asUint32); - case VALUE_IS_INT32: + case VariantType::Int32: return canConvertNumber(content_.asInt32); #if ARDUINOJSON_USE_LONG_LONG - case VALUE_IS_UINT64: + case VariantType::Uint64: return canConvertNumber(getExtension(resources)->asUint64); - case VALUE_IS_INT64: + case VariantType::Int64: return canConvertNumber(getExtension(resources)->asInt64); #endif @@ -349,7 +349,7 @@ class VariantData { } bool isNull() const { - return type_ == VALUE_IS_NULL; + return type_ == VariantType::Null; } static bool isNull(const VariantData* var) { @@ -359,11 +359,12 @@ class VariantData { } bool isObject() const { - return type_ == VALUE_IS_OBJECT; + return type_ == VariantType::Object; } bool isString() const { - return type_ == VALUE_IS_LINKED_STRING || type_ == VALUE_IS_OWNED_STRING; + return type_ == VariantType::LinkedString || + type_ == VariantType::OwnedString; } size_t nesting(const ResourceManager* resources) const { @@ -406,19 +407,19 @@ class VariantData { } void reset() { // TODO: remove - type_ = VALUE_IS_NULL; + type_ = VariantType::Null; } void setBoolean(bool value) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first - type_ = VALUE_IS_BOOLEAN; + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first + type_ = VariantType::Boolean; content_.asBoolean = value; } template enable_if_t setFloat(T value, ResourceManager*) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first - type_ = VALUE_IS_FLOAT; + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first + type_ = VariantType::Float; content_.asFloat = value; return true; } @@ -435,9 +436,9 @@ class VariantData { T value, ResourceManager* resources); void setRawString(StringNode* s) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first ARDUINOJSON_ASSERT(s); - type_ = VALUE_IS_RAW_STRING; + type_ = VariantType::RawString; content_.asOwnedString = s; } @@ -471,16 +472,16 @@ class VariantData { } void setLinkedString(const char* s) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first ARDUINOJSON_ASSERT(s); - type_ = VALUE_IS_LINKED_STRING; + type_ = VariantType::LinkedString; content_.asLinkedString = s; } void setOwnedString(StringNode* s) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first ARDUINOJSON_ASSERT(s); - type_ = VALUE_IS_OWNED_STRING; + type_ = VariantType::OwnedString; content_.asOwnedString = s; } @@ -499,8 +500,8 @@ class VariantData { } ArrayData& toArray() { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first - type_ = VALUE_IS_ARRAY; + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first + type_ = VariantType::Array; new (&content_.asArray) ArrayData(); return content_.asArray; } @@ -513,8 +514,8 @@ class VariantData { } ObjectData& toObject() { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first - type_ = VALUE_IS_OBJECT; + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first + type_ = VariantType::Object; new (&content_.asObject) ObjectData(); return content_.asObject; } @@ -526,7 +527,7 @@ class VariantData { return &var->toObject(); } - uint8_t type() const { + VariantType type() const { return type_; } diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index 11534673..32513de3 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -12,7 +12,7 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template inline void VariantData::setRawString(SerializedValue value, ResourceManager* resources) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first auto dup = resources->saveString(adaptString(value.data(), value.size())); if (dup) setRawString(dup); @@ -21,7 +21,7 @@ inline void VariantData::setRawString(SerializedValue value, template inline bool VariantData::setString(TAdaptedString value, ResourceManager* resources) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first if (value.isNull()) return false; @@ -41,11 +41,11 @@ inline bool VariantData::setString(TAdaptedString value, } inline void VariantData::clear(ResourceManager* resources) { - if (type_ & OWNED_VALUE_BIT) + if (type_ & VariantTypeBits::OwnedStringBit) resources->dereferenceString(content_.asOwnedString->data); #if ARDUINOJSON_USE_EXTENSIONS - if (type_ & EXTENSION_BIT) + if (type_ & VariantTypeBits::ExtensionBit) resources->freeExtension(content_.asSlotId); #endif @@ -53,13 +53,13 @@ inline void VariantData::clear(ResourceManager* resources) { if (collection) collection->clear(resources); - type_ = VALUE_IS_NULL; + type_ = VariantType::Null; } #if ARDUINOJSON_USE_EXTENSIONS inline const VariantExtension* VariantData::getExtension( const ResourceManager* resources) const { - ARDUINOJSON_ASSERT(type_ & EXTENSION_BIT); + ARDUINOJSON_ASSERT(type_ & VariantTypeBits::ExtensionBit); return resources->getExtension(content_.asSlotId); } #endif @@ -67,25 +67,25 @@ inline const VariantExtension* VariantData::getExtension( template enable_if_t VariantData::setFloat( T value, ResourceManager* resources) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first - (void)resources; // silence warning + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first + (void)resources; // silence warning float valueAsFloat = static_cast(value); #if ARDUINOJSON_USE_DOUBLE if (value == valueAsFloat) { - type_ = VALUE_IS_FLOAT; + type_ = VariantType::Float; content_.asFloat = valueAsFloat; } else { auto extension = resources->allocExtension(); if (!extension) return false; - type_ = VALUE_IS_DOUBLE; + type_ = VariantType::Double; content_.asSlotId = extension.id(); extension->asDouble = value; } #else - type_ = VALUE_IS_FLOAT; + type_ = VariantType::Float; content_.asFloat = valueAsFloat; #endif return true; @@ -94,11 +94,11 @@ enable_if_t VariantData::setFloat( template enable_if_t::value, bool> VariantData::setInteger( T value, ResourceManager* resources) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first - (void)resources; // silence warning + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first + (void)resources; // silence warning if (canConvertNumber(value)) { - type_ = VALUE_IS_INT32; + type_ = VariantType::Int32; content_.asInt32 = static_cast(value); } #if ARDUINOJSON_USE_LONG_LONG @@ -106,7 +106,7 @@ enable_if_t::value, bool> VariantData::setInteger( auto extension = resources->allocExtension(); if (!extension) return false; - type_ = VALUE_IS_INT64; + type_ = VariantType::Int64; content_.asSlotId = extension.id(); extension->asInt64 = value; } @@ -117,11 +117,11 @@ enable_if_t::value, bool> VariantData::setInteger( template enable_if_t::value, bool> VariantData::setInteger( T value, ResourceManager* resources) { - ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first - (void)resources; // silence warning + ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first + (void)resources; // silence warning if (canConvertNumber(value)) { - type_ = VALUE_IS_UINT32; + type_ = VariantType::Uint32; content_.asUint32 = static_cast(value); } #if ARDUINOJSON_USE_LONG_LONG @@ -129,7 +129,7 @@ enable_if_t::value, bool> VariantData::setInteger( auto extension = resources->allocExtension(); if (!extension) return false; - type_ = VALUE_IS_UINT64; + type_ = VariantType::Uint64; content_.asSlotId = extension.id(); extension->asUint64 = value; }