From 249fc4f137b41782998dc19961c985c0abfb7adf Mon Sep 17 00:00:00 2001 From: Leonid Stryzhevskyi Date: Mon, 29 Apr 2024 02:48:51 +0300 Subject: [PATCH] mapping::Tree: introduce attributes. Add PAIRS type --- src/oatpp/data/mapping/ObjectToTreeMapper.cpp | 4 +- src/oatpp/data/mapping/ObjectToTreeMapper.hpp | 4 +- src/oatpp/data/mapping/Tree.cpp | 140 +++++++++++++++++- src/oatpp/data/mapping/Tree.hpp | 48 ++++-- src/oatpp/data/mapping/TreeToObjectMapper.cpp | 4 +- src/oatpp/data/mapping/TreeToObjectMapper.hpp | 4 +- test/oatpp/AllTestsMain.cpp | 2 + 7 files changed, 182 insertions(+), 24 deletions(-) diff --git a/src/oatpp/data/mapping/ObjectToTreeMapper.cpp b/src/oatpp/data/mapping/ObjectToTreeMapper.cpp index 71222aeb..6db3b653 100644 --- a/src/oatpp/data/mapping/ObjectToTreeMapper.cpp +++ b/src/oatpp/data/mapping/ObjectToTreeMapper.cpp @@ -27,7 +27,7 @@ #include "oatpp/data/stream/BufferStream.hpp" #include "oatpp/utils/Conversion.hpp" -namespace oatpp { namespace data { +namespace oatpp { namespace data { namespace mapping { oatpp::String ObjectToTreeMapper::MappingState::errorStacktrace() const { stream::BufferOutputStream ss; @@ -298,4 +298,4 @@ void ObjectToTreeMapper::mapObject(ObjectToTreeMapper* mapper, MappingState& sta } -}} +}}} diff --git a/src/oatpp/data/mapping/ObjectToTreeMapper.hpp b/src/oatpp/data/mapping/ObjectToTreeMapper.hpp index 7b1fe8aa..0abd13dd 100644 --- a/src/oatpp/data/mapping/ObjectToTreeMapper.hpp +++ b/src/oatpp/data/mapping/ObjectToTreeMapper.hpp @@ -27,7 +27,7 @@ #include "./Tree.hpp" -namespace oatpp { namespace data { +namespace oatpp { namespace data { namespace mapping { class ObjectToTreeMapper : public base::Countable { public: @@ -86,6 +86,6 @@ public: }; -}} +}}} #endif //oatpp_data_mapping_ObjectToTreeMapper_hpp diff --git a/src/oatpp/data/mapping/Tree.cpp b/src/oatpp/data/mapping/Tree.cpp index ec40e9e2..2320ed3f 100644 --- a/src/oatpp/data/mapping/Tree.cpp +++ b/src/oatpp/data/mapping/Tree.cpp @@ -26,7 +26,7 @@ #include "oatpp/data/stream/BufferStream.hpp" -namespace oatpp { namespace data { +namespace oatpp { namespace data { namespace mapping { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Tree::Map @@ -63,6 +63,59 @@ v_uint64 Tree::Map::size() const { return m_map.size(); } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Tree::Attributes + +Tree::Attributes::Attributes() + : m_attributes(nullptr) +{} + +Tree::Attributes::Attributes(const Attributes& other) + : m_attributes(other.m_attributes != nullptr ? new std::unordered_map(*other.m_attributes) : nullptr) +{} + +Tree::Attributes::Attributes(Attributes&& other) noexcept + : m_attributes(other.m_attributes) +{ + other.m_attributes = nullptr; +} + +Tree::Attributes& Tree::Attributes::operator = (const Attributes& other) { + if(other.m_attributes) { + if(m_attributes) { + *m_attributes = *other.m_attributes; + } else { + m_attributes = new std::unordered_map(*other.m_attributes); + } + } else { + delete m_attributes; + m_attributes = nullptr; + } + return *this; +} + +Tree::Attributes& Tree::Attributes::operator = (Attributes&& other) noexcept { + delete m_attributes; + m_attributes = other.m_attributes; + other.m_attributes = nullptr; + return *this; +} + +Tree::Attributes::~Attributes() { + delete m_attributes; +} + +bool Tree::Attributes::empty() const { + return m_attributes == nullptr || m_attributes->empty(); +} + +v_uint64 Tree::Attributes::size() const { + if(m_attributes) { + return m_attributes->size(); + } + return 0; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Tree @@ -80,11 +133,18 @@ Tree::Tree(const Tree& other) Tree::Tree(Tree&& other) noexcept : m_type(other.m_type) , m_data(other.m_data) + , m_attributes(std::move(other.m_attributes)) { other.m_type = Type::UNDEFINED; other.m_data = 0; } +Tree::Tree(const oatpp::String& value) + : Tree() +{ + setString(value); +} + Tree::~Tree() { deleteValueObject(); } @@ -99,6 +159,11 @@ Tree& Tree::operator = (Tree&& other) noexcept { return *this; } +Tree& Tree::operator = (const oatpp::String& value) { + setString(value); + return *this; +} + void Tree::deleteValueObject() { switch (m_type) { @@ -140,6 +205,11 @@ void Tree::deleteValueObject() { delete data; break; } + case Type::PAIRS: { + auto data = reinterpret_cast> *>(m_data); + delete data; + break; + } default: // DO-NOTHING @@ -176,6 +246,7 @@ void Tree::setCopy(const Tree& other) { deleteValueObject(); m_type = other.m_type; + m_attributes = other.m_attributes; switch (other.m_type) { @@ -229,6 +300,15 @@ void Tree::setCopy(const Tree& other) { m_data = reinterpret_cast(ptr); break; } + case Type::PAIRS: { + auto otherData = reinterpret_cast> *>(other.m_data); + if(otherData == nullptr) { + throw std::runtime_error("[oatpp::data::Tree::setCopy()]: other.data is null, other.type is 'PAIRS'"); + } + auto ptr = new std::vector>(*otherData); + m_data = reinterpret_cast(ptr); + break; + } default: m_data = other.m_data; @@ -239,11 +319,16 @@ void Tree::setCopy(const Tree& other) { } void Tree::setMove(Tree&& other) { + deleteValueObject(); + m_type = other.m_type; m_data = other.m_data; + m_attributes = std::move(other.m_attributes); + other.m_type = Type::NULL_VALUE; other.m_data = 0; + } void Tree::setNull() { @@ -298,6 +383,13 @@ void Tree::setMap(const Map& value) { m_data = reinterpret_cast(data); } +void Tree::setPairs(const std::vector>& value) { + deleteValueObject(); + m_type = Type::PAIRS; + auto data = new std::vector>(value); + m_data = reinterpret_cast(data); +} + bool Tree::isNull() const { return m_type == Type::NULL_VALUE; } @@ -332,6 +424,7 @@ bool Tree::isPrimitive() const { case Type::STRING: case Type::VECTOR: case Type::MAP: + case Type::PAIRS: default: return false; } @@ -367,6 +460,7 @@ v_int32 Tree::primitiveDataSize() const { case Type::STRING: case Type::VECTOR: case Type::MAP: + case Type::PAIRS: default: return -1; } @@ -397,6 +491,7 @@ bool Tree::isFloatPrimitive() const { case Type::STRING: case Type::VECTOR: case Type::MAP: + case Type::PAIRS: default: return false; } @@ -428,6 +523,7 @@ bool Tree::isIntPrimitive() const { case Type::STRING: case Type::VECTOR: case Type::MAP: + case Type::PAIRS: default: return false; } @@ -475,6 +571,14 @@ const Tree::Map& Tree::getMap() const { return *data; } +const std::vector>& Tree::getPairs() const { + if(m_type != Type::PAIRS) { + throw std::runtime_error("[oatpp::data::Tree::getPairs()]: NOT a PAIRS."); + } + auto data = reinterpret_cast>*>(m_data); + return *data; +} + std::vector& Tree::getVector() { if(m_type == Type::UNDEFINED) { setVector({}); @@ -497,6 +601,25 @@ Tree::Map& Tree::getMap() { return *data; } +std::vector>& Tree::getPairs() { + if(m_type == Type::UNDEFINED) { + setPairs({}); + } + if(m_type != Type::MAP) { + throw std::runtime_error("[oatpp::data::Tree::getMap()]: NOT a MAP."); + } + auto data = reinterpret_cast>*>(m_data); + return *data; +} + +Tree::Attributes& Tree::attributes() { + return m_attributes; +} + +const Tree::Attributes& Tree::attributes() const { + return m_attributes; +} + oatpp::String Tree::debugPrint(v_uint32 indent0, v_uint32 indentDelta, bool firstLineIndent) const { stream::BufferOutputStream ss; @@ -588,7 +711,7 @@ oatpp::String Tree::debugPrint(v_uint32 indent0, v_uint32 indentDelta, bool firs } case Type::VECTOR: { - ss << "[\n"; + ss << "VECTOR [\n"; auto& vector = getVector(); for(auto& v : vector) { ss << v.debugPrint(indent0 + indentDelta, indentDelta) << "\n"; @@ -597,7 +720,7 @@ oatpp::String Tree::debugPrint(v_uint32 indent0, v_uint32 indentDelta, bool firs break; } case Type::MAP: { - ss << "{\n"; + ss << "MAP {\n"; auto& map = getMap(); for(v_uint32 i = 0; i < map.size(); i ++) { const auto& node = map[i]; @@ -606,6 +729,15 @@ oatpp::String Tree::debugPrint(v_uint32 indent0, v_uint32 indentDelta, bool firs ss << indentStr0 << "}"; break; } + case Type::PAIRS: { + ss << "PAIRS {\n"; + auto& pairs = getPairs(); + for(auto& node : pairs) { + ss << indentStr0 << indentDeltaStr << node.first << ": " << node.second.debugPrint(indent0 + indentDelta, indentDelta, false) << "\n"; + } + ss << indentStr0 << "}"; + break; + } default: break; @@ -615,4 +747,4 @@ oatpp::String Tree::debugPrint(v_uint32 indent0, v_uint32 indentDelta, bool firs } -}} +}}} diff --git a/src/oatpp/data/mapping/Tree.hpp b/src/oatpp/data/mapping/Tree.hpp index 533c259c..0ec0b511 100644 --- a/src/oatpp/data/mapping/Tree.hpp +++ b/src/oatpp/data/mapping/Tree.hpp @@ -27,7 +27,7 @@ #include "oatpp/Types.hpp" -namespace oatpp { namespace data { +namespace oatpp { namespace data { namespace mapping { class Tree { public: @@ -58,7 +58,8 @@ public: STRING = 14, VECTOR = 15, - MAP = 16 + MAP = 16, + PAIRS = 17 }; @@ -84,6 +85,28 @@ public: }; +public: + + class Attributes { + private: + std::unordered_map* m_attributes; + public: + + Attributes(); + Attributes(const Attributes& other); + Attributes(Attributes&& other) noexcept; + + Attributes& operator = (const Attributes& other); + Attributes& operator = (Attributes&& other) noexcept; + + ~Attributes(); + + bool empty() const; + + v_uint64 size() const; + + }; + private: typedef v_uint64 LARGEST_TYPE; private: @@ -91,6 +114,7 @@ private: private: Type m_type; LARGEST_TYPE m_data; + Attributes m_attributes; public: Tree(); @@ -104,11 +128,7 @@ public: setValue(value); } - explicit Tree(const oatpp::String& value) - : Tree() - { - setString(value); - } + explicit Tree(const oatpp::String& value); ~Tree(); @@ -121,10 +141,7 @@ public: return *this; } - Tree& operator = (const oatpp::String& value) { - setString(value); - return *this; - } + Tree& operator = (const oatpp::String& value); template ::value_type> operator T () const { @@ -154,6 +171,7 @@ public: case Type::STRING: case Type::VECTOR: case Type::MAP: + case Type::PAIRS: default: break; @@ -205,6 +223,7 @@ public: void setVector(const std::vector& value); void setVector(v_uint64 size); void setMap(const Map& value); + void setPairs(const std::vector>& value); bool isNull() const; bool isUndefined() const; @@ -221,9 +240,14 @@ public: const std::vector& getVector() const; const Map& getMap() const; + const std::vector>& getPairs() const; std::vector& getVector(); Map& getMap(); + std::vector>& getPairs(); + + Attributes& attributes(); + const Attributes& attributes() const; oatpp::String debugPrint(v_uint32 indent0 = 0, v_uint32 indentDelta = 2, bool firstLineIndent = true) const; @@ -309,6 +333,6 @@ struct Tree::NodePrimitiveType { typedef v_float64 value_type; }; -}} +}}} #endif //oatpp_data_mapping_Tree_hpp diff --git a/src/oatpp/data/mapping/TreeToObjectMapper.cpp b/src/oatpp/data/mapping/TreeToObjectMapper.cpp index 52c61f8c..f60868f3 100644 --- a/src/oatpp/data/mapping/TreeToObjectMapper.cpp +++ b/src/oatpp/data/mapping/TreeToObjectMapper.cpp @@ -27,7 +27,7 @@ #include "oatpp/data/stream/BufferStream.hpp" #include "oatpp/utils/Conversion.hpp" -namespace oatpp { namespace data { +namespace oatpp { namespace data { namespace mapping { oatpp::String TreeToObjectMapper::MappingState::errorStacktrace() const { stream::BufferOutputStream ss; @@ -382,4 +382,4 @@ oatpp::Void TreeToObjectMapper::mapObject(TreeToObjectMapper* mapper, MappingSta } -}} +}}} diff --git a/src/oatpp/data/mapping/TreeToObjectMapper.hpp b/src/oatpp/data/mapping/TreeToObjectMapper.hpp index 62d1732f..3b9fa340 100644 --- a/src/oatpp/data/mapping/TreeToObjectMapper.hpp +++ b/src/oatpp/data/mapping/TreeToObjectMapper.hpp @@ -27,7 +27,7 @@ #include "./Tree.hpp" -namespace oatpp { namespace data { +namespace oatpp { namespace data { namespace mapping { class TreeToObjectMapper : public base::Countable { public: @@ -90,6 +90,6 @@ public: }; -}} +}}} #endif //oatpp_data_mapping_TreeToObjectMapper_hpp diff --git a/test/oatpp/AllTestsMain.cpp b/test/oatpp/AllTestsMain.cpp index d681d0a9..25dcd751 100644 --- a/test/oatpp/AllTestsMain.cpp +++ b/test/oatpp/AllTestsMain.cpp @@ -68,6 +68,8 @@ #include "oatpp/async/Coroutine.hpp" #include "oatpp/Types.hpp" +#include "oatpp/data/mapping/Tree.hpp" + #include "oatpp/Environment.hpp" #include