mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-21 16:15:13 +08:00
mapping::Tree: better tests, improved attributes, improved interface of oatpp::Tree
This commit is contained in:
parent
917dd454ce
commit
6765c3e591
@ -20,7 +20,9 @@
|
||||
|
||||
**News**
|
||||
|
||||
- ⚠️ Attention! Oat++ main repo is bumping it's version to 1.4.0. While 1.4.0 is **IN DEVELOPMENT** use `1.3.0-latest` tag.
|
||||
- ⚠️ Attention! Oat++ main repo is bumping its version to 1.4.0. While 1.4.0 is **IN DEVELOPMENT** use `1.3.0-latest` tag.
|
||||
- Follow the [changelog](https://github.com/oatpp/oatpp/blob/master/changelog/1.4.0.md) for news and features in version `1.4.0`.
|
||||
- Consider supporting Oat++ via the [GitHub sponsors](https://github.com/sponsors/oatpp) page.
|
||||
|
||||
---
|
||||
|
||||
|
@ -8,6 +8,8 @@ Contents:
|
||||
|
||||
- [URL Encoder And Decoder](#url-encoder-and-decoder)
|
||||
- [Introduce async::ConditionVariable](#async-condition-variable)
|
||||
- [oatpp::Tree](#oatpptree)
|
||||
- [Remapper](#remapper)
|
||||
- [Restructuring](#restructuring)
|
||||
|
||||
|
||||
@ -49,6 +51,61 @@ OATPP_ASSERT(decoded == data)
|
||||
...
|
||||
```
|
||||
|
||||
## oatpp::Tree
|
||||
|
||||
New mapping-enabled type `oatpp::Tree` for flexible data access.
|
||||
|
||||
```cpp
|
||||
ENDPOINT("POST", "users", createUser,
|
||||
BODY_DTO(oatpp::Tree, user))
|
||||
{
|
||||
oatpp::String name = user["name"];
|
||||
v_uint16 age = user["age"];
|
||||
|
||||
auto& subs = user["subscriptions"].getVector();
|
||||
for(auto& s : subs) {
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Any node of oatpp::Tree can be mapped to DTO or to any mapping-enabled oatpp type - see [Remapper](#remapper)
|
||||
|
||||
## Remapper
|
||||
|
||||
`oatpp::data::mapping::Remapper`.
|
||||
|
||||
Remapper can be user to remap any oatpp type to any oatpp type.
|
||||
UnorderedFields can be mapped to DTOs, DTOs to vectors of values, vector items to other DTOs, DTOs to Trees, etc...
|
||||
|
||||
```cpp
|
||||
class User : public oatpp::DTO {
|
||||
|
||||
DTO_INIT(User, DTO)
|
||||
|
||||
DTO_FIELD(String, name);
|
||||
DTO_FIELD(UInt32, age);
|
||||
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
oatpp::data::mapping::Remapper remapper;
|
||||
|
||||
auto user = User::createShared();
|
||||
user->name = "Jane";
|
||||
user->age = "25";
|
||||
|
||||
auto tree = remapper.remap<oatpp::Tree>(user); // remap to tree
|
||||
auto fields = remapper.remap<oatpp::Fields<oatpp::Tree>>(user); // remap to Fields
|
||||
auto otherDto = remapper.remap<oatpp::Object<OtherDto>>(user); // remap to OtherDto
|
||||
auto values = remapper.remap<oatpp::Vector<oatpp::Tree>>(user); // remap to Vector
|
||||
|
||||
oatpp::String name = values[0];
|
||||
v_uint32 age = values[1];
|
||||
```
|
||||
|
||||
## Restructuring
|
||||
|
||||
### Files
|
||||
|
@ -26,9 +26,9 @@
|
||||
|
||||
namespace oatpp { namespace data { namespace mapping {
|
||||
|
||||
oatpp::Void ObjectRemapper::mapTree(const Tree* tree, const oatpp::Type* toType, ErrorStack& errorStack) const {
|
||||
oatpp::Void ObjectRemapper::remap(const Tree& tree, const oatpp::Type* toType, ErrorStack& errorStack) const {
|
||||
TreeToObjectMapper::State state;
|
||||
state.tree = tree;
|
||||
state.tree = std::addressof(tree);
|
||||
state.config = &m_treeToObjectConfig;
|
||||
const auto & result = m_treeToObjectMapper.map(state, toType);
|
||||
if(!state.errorStack.empty()) {
|
||||
@ -40,10 +40,14 @@ oatpp::Void ObjectRemapper::mapTree(const Tree* tree, const oatpp::Type* toType,
|
||||
|
||||
oatpp::Void ObjectRemapper::remap(const oatpp::Void& polymorph, const oatpp::Type* toType, ErrorStack& errorStack) const {
|
||||
|
||||
if(polymorph == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* if polymorph is a Tree - we can map it right away */
|
||||
if(polymorph.getValueType() == oatpp::Tree::Class::getType()) {
|
||||
auto tree = static_cast<const Tree*>(polymorph.get());
|
||||
return mapTree(tree, toType, errorStack);
|
||||
return remap(*tree, toType, errorStack);
|
||||
}
|
||||
|
||||
Tree tree;
|
||||
@ -64,7 +68,7 @@ oatpp::Void ObjectRemapper::remap(const oatpp::Void& polymorph, const oatpp::Typ
|
||||
return oatpp::Tree(std::move(tree));
|
||||
}
|
||||
|
||||
return mapTree(&tree, toType, errorStack);
|
||||
return remap(tree, toType, errorStack);
|
||||
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,6 @@
|
||||
namespace oatpp { namespace data { namespace mapping {
|
||||
|
||||
class ObjectRemapper {
|
||||
protected:
|
||||
oatpp::Void mapTree(const Tree* tree, const oatpp::Type* toType, ErrorStack& errorStack) const;
|
||||
protected:
|
||||
ObjectToTreeMapper::Config m_objectToTreeConfig;
|
||||
TreeToObjectMapper::Config m_treeToObjectConfig;
|
||||
@ -45,6 +43,25 @@ public:
|
||||
ObjectRemapper() = default;
|
||||
virtual ~ObjectRemapper() = default;
|
||||
|
||||
oatpp::Void remap(const Tree& tree, const oatpp::Type* toType, ErrorStack& errorStack) const;
|
||||
|
||||
template<class Wrapper>
|
||||
Wrapper remap(const Tree& tree, ErrorStack& errorStack) const {
|
||||
auto toType = Wrapper::Class::getType();
|
||||
return remap(tree, toType, errorStack).template cast<Wrapper>();
|
||||
}
|
||||
|
||||
template<class Wrapper>
|
||||
Wrapper remap(const Tree& tree) const {
|
||||
auto toType = Wrapper::Class::getType();
|
||||
ErrorStack errorStack;
|
||||
const auto& result = remap(tree, toType, errorStack).template cast<Wrapper>();
|
||||
if(!errorStack.empty()) {
|
||||
throw MappingError(std::move(errorStack));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
oatpp::Void remap(const oatpp::Void& polymorph, const oatpp::Type* toType, ErrorStack& errorStack) const;
|
||||
|
||||
template<class Wrapper>
|
||||
|
@ -36,8 +36,10 @@ Tree::Attributes::Attributes()
|
||||
{}
|
||||
|
||||
Tree::Attributes::Attributes(const Attributes& other)
|
||||
: m_attributes(other.m_attributes != nullptr ? new std::unordered_map<type::String, type::String>(*other.m_attributes) : nullptr)
|
||||
{}
|
||||
: Attributes()
|
||||
{
|
||||
operator=(other);
|
||||
}
|
||||
|
||||
Tree::Attributes::Attributes(Attributes&& other) noexcept
|
||||
: m_attributes(other.m_attributes)
|
||||
@ -46,37 +48,101 @@ Tree::Attributes::Attributes(Attributes&& other) noexcept
|
||||
}
|
||||
|
||||
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<type::String, type::String>(*other.m_attributes);
|
||||
m_attributes = new Attrs(*other.m_attributes);
|
||||
}
|
||||
|
||||
for(auto & po : m_attributes->order){
|
||||
po.second = &m_attributes->map.at(po.first.lock());
|
||||
}
|
||||
|
||||
} 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;
|
||||
m_attributes = nullptr;
|
||||
}
|
||||
|
||||
void Tree::Attributes::initAttributes() {
|
||||
if(m_attributes == nullptr) {
|
||||
m_attributes = new Attrs();
|
||||
}
|
||||
}
|
||||
|
||||
type::String& Tree::Attributes::operator [] (const type::String& key) {
|
||||
initAttributes();
|
||||
auto it = m_attributes->map.find(key);
|
||||
if(it == m_attributes->map.end()) {
|
||||
auto& result = m_attributes->map[key];
|
||||
m_attributes->order.emplace_back(key.getPtr(), &result);
|
||||
return result;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const type::String& Tree::Attributes::operator [] (const type::String& key) const {
|
||||
if(m_attributes != nullptr) {
|
||||
auto it = m_attributes->map.find(key);
|
||||
if (it != m_attributes->map.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::Attributes::operator []]: const operator[] can't add items.");
|
||||
}
|
||||
|
||||
std::pair<type::String, std::reference_wrapper<type::String>> Tree::Attributes::operator [] (v_uint64 index) {
|
||||
if(m_attributes != nullptr) {
|
||||
auto &item = m_attributes->order.at(index);
|
||||
return {item.first.lock(), *item.second};
|
||||
}
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::Attributes::operator []]: const operator[] can't get item - empty attributes.");
|
||||
}
|
||||
|
||||
std::pair<type::String, std::reference_wrapper<const type::String>> Tree::Attributes::operator [] (v_uint64 index) const {
|
||||
if(m_attributes != nullptr) {
|
||||
auto &item = m_attributes->order.at(index);
|
||||
return {item.first.lock(), *item.second};
|
||||
}
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::Attributes::operator []]: const operator[] can't get item - empty attributes.");
|
||||
}
|
||||
|
||||
type::String Tree::Attributes::get(const type::String& key) const {
|
||||
if(m_attributes == nullptr) return nullptr;
|
||||
auto it = m_attributes->map.find(key);
|
||||
if(it != m_attributes->map.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Tree::Attributes::empty() const {
|
||||
return m_attributes == nullptr || m_attributes->empty();
|
||||
return m_attributes == nullptr || m_attributes->map.empty();
|
||||
}
|
||||
|
||||
v_uint64 Tree::Attributes::size() const {
|
||||
if(m_attributes) {
|
||||
return m_attributes->size();
|
||||
return m_attributes->map.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -725,13 +791,9 @@ TreeMap::TreeMap(TreeMap&& other) noexcept {
|
||||
|
||||
TreeMap& TreeMap::operator = (const TreeMap& other) {
|
||||
m_map = other.m_map;
|
||||
m_order.resize(other.m_order.size());
|
||||
for(v_uint64 i = 0; i < other.m_order.size(); i ++) {
|
||||
auto& po = other.m_order[i];
|
||||
auto& pt = m_order[i];
|
||||
pt.first = po.first;
|
||||
|
||||
pt.second = &m_map.at(po.first.lock());
|
||||
m_order = other.m_order;
|
||||
for(auto & po : m_order){
|
||||
po.second = &m_map.at(po.first.lock());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -72,7 +72,14 @@ public:
|
||||
|
||||
class Attributes {
|
||||
private:
|
||||
std::unordered_map<type::String, type::String>* m_attributes;
|
||||
struct Attrs {
|
||||
std::unordered_map<type::String, type::String> map;
|
||||
std::vector<std::pair<std::weak_ptr<std::string>, type::String*>> order;
|
||||
};
|
||||
private:
|
||||
void initAttributes();
|
||||
private:
|
||||
Attrs* m_attributes;
|
||||
public:
|
||||
|
||||
Attributes();
|
||||
@ -84,8 +91,15 @@ public:
|
||||
|
||||
~Attributes();
|
||||
|
||||
bool empty() const;
|
||||
type::String& operator [] (const type::String& key);
|
||||
const type::String& operator [] (const type::String& key) const;
|
||||
|
||||
std::pair<type::String, std::reference_wrapper<type::String>> operator [] (v_uint64 index);
|
||||
std::pair<type::String, std::reference_wrapper<const type::String>> operator [] (v_uint64 index) const;
|
||||
|
||||
type::String get(const type::String& key) const;
|
||||
|
||||
bool empty() const;
|
||||
v_uint64 size() const;
|
||||
|
||||
};
|
||||
|
@ -435,6 +435,7 @@ private:
|
||||
public:
|
||||
typedef oatpp::data::type::Void Void;
|
||||
typedef oatpp::data::type::Any Any;
|
||||
typedef oatpp::data::type::Tree Tree;
|
||||
typedef oatpp::data::type::String String;
|
||||
typedef oatpp::data::type::Int8 Int8;
|
||||
typedef oatpp::data::type::UInt8 UInt8;
|
||||
|
@ -123,6 +123,27 @@ bool Tree::operator != (const Tree& other) const {
|
||||
return !operator == (other);
|
||||
}
|
||||
|
||||
mapping::Tree* Tree::operator->() {
|
||||
if(!m_ptr) {
|
||||
m_ptr = std::make_shared<mapping::Tree>();
|
||||
}
|
||||
return m_ptr.get();
|
||||
}
|
||||
|
||||
mapping::Tree* Tree::operator->() const {
|
||||
if(!m_ptr) {
|
||||
throw std::runtime_error("[oatpp::data::type::Tree::operator ->()]: null-pointer exception");
|
||||
}
|
||||
return m_ptr.get();
|
||||
}
|
||||
|
||||
mapping::Tree& Tree::operator*() {
|
||||
if(!m_ptr) {
|
||||
m_ptr = std::make_shared<mapping::Tree>();
|
||||
}
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
const mapping::Tree& Tree::operator*() const {
|
||||
if(!m_ptr) {
|
||||
throw std::runtime_error("[oatpp::data::type::Tree::operator *()]: null-pointer exception");
|
||||
@ -130,12 +151,32 @@ const mapping::Tree& Tree::operator*() const {
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
mapping::Tree& Tree::operator*() {
|
||||
mapping::Tree& Tree::operator [] (const String& key) {
|
||||
if(!m_ptr) {
|
||||
throw std::runtime_error("[oatpp::data::type::Tree::operator *()]: null-pointer exception");
|
||||
m_ptr = std::make_shared<mapping::Tree>();
|
||||
}
|
||||
return *m_ptr;
|
||||
return (*m_ptr)[key];
|
||||
}
|
||||
|
||||
const mapping::Tree& Tree::operator [] (const String& key) const {
|
||||
if(!m_ptr) {
|
||||
throw std::runtime_error("[oatpp::data::type::Tree::operator []]: null-pointer exception");
|
||||
}
|
||||
return (*m_ptr)[key];
|
||||
}
|
||||
|
||||
mapping::Tree& Tree::operator [] (v_uint64 index) {
|
||||
if(!m_ptr) {
|
||||
m_ptr = std::make_shared<mapping::Tree>();
|
||||
}
|
||||
return (*m_ptr)[index];
|
||||
}
|
||||
|
||||
const mapping::Tree& Tree::operator [] (v_uint64 index) const {
|
||||
if(!m_ptr) {
|
||||
throw std::runtime_error("[oatpp::data::type::Tree::operator []]: null-pointer exception");
|
||||
}
|
||||
return (*m_ptr)[index];
|
||||
}
|
||||
|
||||
}}}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define oatpp_data_type_Tree_hpp
|
||||
|
||||
#include "./Type.hpp"
|
||||
#include "./Primitive.hpp"
|
||||
|
||||
namespace oatpp { namespace data { namespace mapping {
|
||||
|
||||
@ -108,8 +109,17 @@ public:
|
||||
bool operator == (const Tree& other) const;
|
||||
bool operator != (const Tree& other) const;
|
||||
|
||||
const mapping::Tree& operator*() const;
|
||||
mapping::Tree* operator->();
|
||||
mapping::Tree* operator->() const;
|
||||
|
||||
mapping::Tree& operator*();
|
||||
const mapping::Tree& operator*() const;
|
||||
|
||||
mapping::Tree& operator [] (const String& key);
|
||||
const mapping::Tree& operator [] (const String& key) const;
|
||||
|
||||
mapping::Tree& operator [] (v_uint64 index);
|
||||
const mapping::Tree& operator [] (v_uint64 index) const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -247,8 +247,6 @@ void runTests() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -168,6 +168,57 @@ void ObjectRemapperTest::onRun() {
|
||||
OATPP_ASSERT(vec[4] == nullptr)
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
OATPP_LOGD(TAG, "Remap tree fragments")
|
||||
|
||||
Tree tree;
|
||||
tree.setVector(3);
|
||||
|
||||
tree[0]["field_1"] = "val1";
|
||||
tree[0]["field_2"] = "val2";
|
||||
|
||||
tree[1]["field_1"] = "val1.2";
|
||||
tree[1]["field_2"] = "val2.2";
|
||||
|
||||
tree[2]["field_1"] = "val1.3";
|
||||
tree[2]["field_2"] = "val2.3";
|
||||
|
||||
{
|
||||
auto map = remapper.remap<oatpp::UnorderedFields<String>>(tree[0]);
|
||||
OATPP_ASSERT(map->size() == 2)
|
||||
OATPP_ASSERT(map["field_1"] == "val1")
|
||||
OATPP_ASSERT(map["field_2"] == "val2")
|
||||
}
|
||||
|
||||
{
|
||||
auto map = remapper.remap<oatpp::UnorderedFields<String>>(tree[1]);
|
||||
OATPP_ASSERT(map->size() == 2)
|
||||
OATPP_ASSERT(map["field_1"] == "val1.2")
|
||||
OATPP_ASSERT(map["field_2"] == "val2.2")
|
||||
}
|
||||
|
||||
{
|
||||
auto map = remapper.remap<oatpp::UnorderedFields<String>>(tree[2]);
|
||||
OATPP_ASSERT(map->size() == 2)
|
||||
OATPP_ASSERT(map["field_1"] == "val1.3")
|
||||
OATPP_ASSERT(map["field_2"] == "val2.3")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
oatpp::Tree tree;
|
||||
OATPP_ASSERT(tree == nullptr)
|
||||
|
||||
OATPP_ASSERT(tree->isUndefined()) // implicitly initialized
|
||||
OATPP_ASSERT(tree != nullptr)
|
||||
|
||||
tree["hello"] = "world";
|
||||
std::cout << *tree->debugPrint() << std::endl;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}}
|
||||
|
@ -36,6 +36,8 @@ namespace {
|
||||
template<typename T>
|
||||
void testTreeValue(T value) {
|
||||
|
||||
OATPP_LOGD("TEST", "Test value retrieval for '%s'", Tree::NodePrimitiveType<T>::name)
|
||||
|
||||
Tree node;
|
||||
|
||||
//node.setValue<T>(value);
|
||||
@ -70,6 +72,7 @@ void TreeTest::onRun() {
|
||||
testTreeValue<v_float64>(16);
|
||||
|
||||
{
|
||||
OATPP_LOGD(TAG, "Case 1")
|
||||
Tree node;
|
||||
oatpp::String original = "Hello World!";
|
||||
node.setString(original);
|
||||
@ -79,6 +82,7 @@ void TreeTest::onRun() {
|
||||
}
|
||||
|
||||
{
|
||||
OATPP_LOGD(TAG, "Case 2")
|
||||
Tree node1;
|
||||
Tree node2;
|
||||
|
||||
@ -93,6 +97,7 @@ void TreeTest::onRun() {
|
||||
}
|
||||
|
||||
{
|
||||
OATPP_LOGD(TAG, "Case 3")
|
||||
Tree node1;
|
||||
Tree node2;
|
||||
|
||||
@ -105,6 +110,7 @@ void TreeTest::onRun() {
|
||||
}
|
||||
|
||||
{
|
||||
OATPP_LOGD(TAG, "Case 4")
|
||||
std::vector<Tree> originalVector(10);
|
||||
for(v_uint32 i = 0; i < 10; i ++) {
|
||||
originalVector.at(i).setValue(i);
|
||||
@ -132,6 +138,7 @@ void TreeTest::onRun() {
|
||||
}
|
||||
|
||||
{
|
||||
OATPP_LOGD(TAG, "Case 5")
|
||||
TreeMap originalMap;
|
||||
for(v_uint32 i = 0; i < 10; i ++) {
|
||||
originalMap["node_" + utils::Conversion::int32ToStr(static_cast<v_int32>(i))].setValue(i);
|
||||
@ -156,6 +163,7 @@ void TreeTest::onRun() {
|
||||
}
|
||||
|
||||
{
|
||||
OATPP_LOGD(TAG, "Case 6")
|
||||
Tree article;
|
||||
oatpp::Tree ot;
|
||||
|
||||
@ -176,6 +184,120 @@ void TreeTest::onRun() {
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
OATPP_LOGD(TAG, "Attributes Case 1")
|
||||
OATPP_LOGD(TAG, "size of Tree::Attributes='%lu'", sizeof(Tree::Attributes))
|
||||
|
||||
Tree::Attributes attr;
|
||||
|
||||
attr["key1"] = "value1";
|
||||
attr["key1"] = "value1.2";
|
||||
attr["key2"] = "value2";
|
||||
|
||||
OATPP_ASSERT(attr.size() == 2)
|
||||
|
||||
OATPP_ASSERT(attr["key1"] == "value1.2")
|
||||
OATPP_ASSERT(attr["key2"] == "value2")
|
||||
OATPP_ASSERT(attr["key3"] == nullptr) // key3 added
|
||||
|
||||
OATPP_ASSERT(attr.size() == 3)
|
||||
|
||||
OATPP_ASSERT(attr[0].second.get() == "value1.2")
|
||||
OATPP_ASSERT(attr[1].second.get() == "value2")
|
||||
OATPP_ASSERT(attr[2].second.get() == nullptr)
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
OATPP_LOGD(TAG, "Attributes Case 2")
|
||||
|
||||
Tree::Attributes attr1;
|
||||
Tree::Attributes attr2;
|
||||
|
||||
attr1["key1"] = "value1";
|
||||
attr1["key2"] = "value2";
|
||||
attr1["key3"] = nullptr;
|
||||
|
||||
attr2["key1"] = "v1";
|
||||
attr2["key2"] = "v2";
|
||||
|
||||
attr2 = attr1;
|
||||
|
||||
attr1["key1"] = "1";
|
||||
attr1["key2"] = "2";
|
||||
attr1["key3"] = "3";
|
||||
|
||||
OATPP_ASSERT(attr1[0].second.get() == "1")
|
||||
OATPP_ASSERT(attr1[1].second.get() == "2")
|
||||
OATPP_ASSERT(attr1[2].second.get() == "3")
|
||||
|
||||
OATPP_ASSERT(attr1["key1"] == "1")
|
||||
OATPP_ASSERT(attr1["key2"] == "2")
|
||||
OATPP_ASSERT(attr1["key3"] == "3")
|
||||
|
||||
OATPP_ASSERT(attr2[0].second.get() == "value1")
|
||||
OATPP_ASSERT(attr2[1].second.get() == "value2")
|
||||
OATPP_ASSERT(attr2[2].second.get() == nullptr)
|
||||
|
||||
OATPP_ASSERT(attr2["key1"] == "value1")
|
||||
OATPP_ASSERT(attr2["key2"] == "value2")
|
||||
OATPP_ASSERT(attr2["key3"] == nullptr)
|
||||
|
||||
Tree::Attributes attr3;
|
||||
attr2 = attr3;
|
||||
|
||||
OATPP_ASSERT(attr2.empty())
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
OATPP_LOGD(TAG, "Attributes Case 3")
|
||||
|
||||
Tree tree1;
|
||||
Tree tree2;
|
||||
|
||||
tree1 = "hello";
|
||||
tree2 = "world";
|
||||
|
||||
tree1.attributes()["key1"] = "value1";
|
||||
tree1.attributes()["key2"] = "value2";
|
||||
tree1.attributes()["key3"] = nullptr;
|
||||
|
||||
tree2.attributes()["key1"] = "v1";
|
||||
tree2.attributes()["key2"] = "v2";
|
||||
|
||||
tree2 = tree1;
|
||||
|
||||
tree1.attributes()["key1"] = "1";
|
||||
tree1.attributes()["key2"] = "2";
|
||||
tree1.attributes()["key3"] = "3";
|
||||
|
||||
OATPP_ASSERT(tree1.attributes()[0].second.get() == "1")
|
||||
OATPP_ASSERT(tree1.attributes()[1].second.get() == "2")
|
||||
OATPP_ASSERT(tree1.attributes()[2].second.get() == "3")
|
||||
|
||||
OATPP_ASSERT(tree1.attributes()["key1"] == "1")
|
||||
OATPP_ASSERT(tree1.attributes()["key2"] == "2")
|
||||
OATPP_ASSERT(tree1.attributes()["key3"] == "3")
|
||||
|
||||
OATPP_ASSERT(tree2.attributes()[0].second.get() == "value1")
|
||||
OATPP_ASSERT(tree2.attributes()[1].second.get() == "value2")
|
||||
OATPP_ASSERT(tree2.attributes()[2].second.get() == nullptr)
|
||||
|
||||
OATPP_ASSERT(tree2.attributes()["key1"] == "value1")
|
||||
OATPP_ASSERT(tree2.attributes()["key2"] == "value2")
|
||||
OATPP_ASSERT(tree2.attributes()["key3"] == nullptr)
|
||||
|
||||
Tree tree3;
|
||||
tree2 = tree3;
|
||||
|
||||
OATPP_ASSERT(tree2.attributes().empty())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}}
|
||||
|
Loading…
Reference in New Issue
Block a user