Types. Introduce Any.

This commit is contained in:
lganzzzo 2020-04-25 02:54:52 +03:00
parent 2c037d1cc1
commit 0d951e3c56
9 changed files with 435 additions and 2 deletions

View File

@ -74,6 +74,8 @@ add_library(oatpp
oatpp/core/data/buffer/Processor.hpp
oatpp/core/data/mapping/ObjectMapper.cpp
oatpp/core/data/mapping/ObjectMapper.hpp
oatpp/core/data/mapping/type/Any.cpp
oatpp/core/data/mapping/type/Any.hpp
oatpp/core/data/mapping/type/List.cpp
oatpp/core/data/mapping/type/List.hpp
oatpp/core/data/mapping/type/ListMap.cpp

View File

@ -25,10 +25,17 @@
#ifndef oatpp_Types_hpp
#define oatpp_Types_hpp
#include "oatpp/core/data/mapping/type/Any.hpp"
#include "oatpp/core/data/mapping/type/Object.hpp"
namespace oatpp {
/**
* `Any` - container for mapping-enabled types.
* &id:oatpp::data::mapping::type::Any;
*/
typedef oatpp::data::mapping::type::Any Any;
/**
* Mapping-Enabled String type. &id:oatpp::data::mapping::type::String; <br>
* For `oatpp::String` methods see &id:oatpp::base::StrBuffer;

View File

@ -0,0 +1,96 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************/
#include "Any.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
const ClassId Any::CLASS_ID("Any");
}
Any::Any()
: PolymorphicWrapper(__class::Any::getType())
{}
Any::Any(std::nullptr_t) : Any() {}
Any::Any(const AbstractObjectWrapper& polymorph)
: PolymorphicWrapper(std::make_shared<AnyHandle>(polymorph.getPtr(), polymorph.valueType), __class::Any::getType())
{}
Any::Any(const Any& other)
: PolymorphicWrapper(std::make_shared<AnyHandle>(other.m_ptr->ptr, other.m_ptr->type), __class::Any::getType())
{}
Any::Any(Any&& other)
: PolymorphicWrapper(std::move(other.m_ptr), __class::Any::getType())
{}
void Any::store(const AbstractObjectWrapper& polymorph) {
m_ptr = std::make_shared<AnyHandle>(polymorph.getPtr(), polymorph.valueType);
}
const Type* const Any::getStoredType() {
if(m_ptr) {
return m_ptr->type;
}
return nullptr;
}
Any& Any::operator=(std::nullptr_t) {
m_ptr.reset();
return *this;
}
Any& Any::operator=(const AbstractObjectWrapper& other) {
m_ptr = std::make_shared<AnyHandle>(other.getPtr(), other.valueType);
return *this;
}
Any& Any::operator=(const Any& other) {
if(other) {
m_ptr = std::make_shared<AnyHandle>(other.m_ptr->ptr, other.m_ptr->type);
} else {
m_ptr.reset();
}
return *this;
}
Any& Any::operator=(Any&& other) {
m_ptr = std::move(other.m_ptr);
return *this;
}
bool Any::operator == (const Any& other) {
if(!m_ptr && !other.m_ptr) return true;
if(!m_ptr || !other.m_ptr) return false;
return m_ptr->ptr.get() == other.m_ptr->ptr.get();
}
bool Any::operator != (const Any& other) {
return !operator == (other);
}
}}}}

View File

@ -0,0 +1,110 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************/
#ifndef oatpp_data_mapping_type_Any_hpp
#define oatpp_data_mapping_type_Any_hpp
#include "./Type.hpp"
#include "oatpp/core/collection/LinkedList.hpp"
#include "oatpp/core/base/memory/ObjectPool.hpp"
#include "oatpp/core/base/Countable.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class Any {
public:
static const ClassId CLASS_ID;
static Type *getType() {
static Type type(CLASS_ID, nullptr);
return &type;
}
};
}
class AnyHandle : public base::Countable {
public:
AnyHandle(const std::shared_ptr<base::Countable>& objPtr, const Type* const objType)
: ptr(objPtr)
, type(objType)
{}
std::shared_ptr<base::Countable> ptr;
const Type* const type;
};
class Any : public PolymorphicWrapper<AnyHandle>{
public:
Any();
Any(std::nullptr_t);
Any(const AbstractObjectWrapper& polymorph);
Any(const Any& other);
Any(Any&& other);
void store(const AbstractObjectWrapper& polymorph);
const Type* const getStoredType();
template<class WrapperType>
WrapperType retrieve() {
if(m_ptr) {
if(m_ptr->type != WrapperType::Class::getType()) {
throw std::runtime_error("[oatpp::data::mapping::type::Any::retrieve()]: Error. The value type doesn't match.");
}
return WrapperType(std::static_pointer_cast<typename WrapperType::ObjectType>(m_ptr->ptr), m_ptr->type);
}
return nullptr;
}
Any& operator=(std::nullptr_t);
Any& operator=(const AbstractObjectWrapper& other);
Any& operator=(const Any& other);
Any& operator=(Any&& other);
bool operator == (const Any& other);
bool operator != (const Any& other);
};
}}}}
#endif //oatpp_data_mapping_type_Any_hpp

View File

@ -152,7 +152,7 @@ public:
return *this;
}
PolymorphicWrapper& operator=(const PolymorphicWrapper<T>&& other){
PolymorphicWrapper& operator=(PolymorphicWrapper<T>&& other){
m_ptr = std::move(other.m_ptr);
return *this;
}
@ -258,7 +258,7 @@ public:
return *this;
}
ObjectWrapper& operator=(const PolymorphicWrapper<T>&& other){
ObjectWrapper& operator=(PolymorphicWrapper<T>&& other){
if(this->valueType != other.valueType){
OATPP_LOGE("ObjectWrapper", "Invalid class cast");
throw std::runtime_error("[oatpp::data::mapping::type::ObjectWrapper]: Invalid class cast");

View File

@ -15,6 +15,8 @@ add_executable(oatppAllTests
oatpp/core/base/memory/PerfTest.hpp
oatpp/core/data/buffer/ProcessorTest.cpp
oatpp/core/data/buffer/ProcessorTest.hpp
oatpp/core/data/mapping/type/AnyTest.cpp
oatpp/core/data/mapping/type/AnyTest.hpp
oatpp/core/data/mapping/type/TypeTest.cpp
oatpp/core/data/mapping/type/TypeTest.hpp
oatpp/core/data/share/LazyStringMapTest.cpp

View File

@ -39,6 +39,8 @@
#include "oatpp/core/parser/CaretTest.hpp"
#include "oatpp/core/data/mapping/type/TypeTest.hpp"
#include "oatpp/core/data/mapping/type/AnyTest.hpp"
#include "oatpp/core/base/collection/LinkedListTest.hpp"
#include "oatpp/core/base/memory/MemoryPoolTest.hpp"
#include "oatpp/core/base/memory/PerfTest.hpp"
@ -82,6 +84,7 @@ void runTests() {
OATPP_RUN_TEST(oatpp::test::core::data::stream::BufferStreamTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::TypeTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::AnyTest);
OATPP_RUN_TEST(oatpp::test::async::LockTest);

View File

@ -0,0 +1,171 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************/
#include "AnyTest.hpp"
#include "oatpp/core/data/mapping/type/Any.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/core/macro/codegen.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
namespace {
#include OATPP_CODEGEN_BEGIN(DTO)
class Dto1 : public oatpp::Object {
DTO_INIT(Dto1, Object);
};
class Dto2 : public oatpp::Object {
DTO_INIT(Dto2, Object);
};
class Test : public oatpp::Object {
DTO_INIT(Test, Object);
DTO_FIELD(oatpp::Any, any);
};
#include OATPP_CODEGEN_END(DTO)
}
void AnyTest::onRun() {
{
oatpp::Any any;
OATPP_ASSERT(!any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == nullptr);
}
{
oatpp::Any any(nullptr);
OATPP_ASSERT(!any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == nullptr);
}
{
oatpp::Any any(oatpp::String("Hello Any!"));
OATPP_ASSERT(any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
auto str = any.retrieve<oatpp::String>();
OATPP_ASSERT(str == "Hello Any!");
}
{
oatpp::Any any(oatpp::Int32(32));
OATPP_ASSERT(any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == oatpp::data::mapping::type::__class::Int32::getType());
any.store(oatpp::String("Hello Any!"));
OATPP_ASSERT(any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
auto str = any.retrieve<oatpp::String>();
OATPP_ASSERT(str == "Hello Any!");
}
{
oatpp::Any any(Dto1::createShared());
OATPP_ASSERT(any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == Dto1::ObjectWrapper::Class::getType());
bool wasError = false;
try {
auto obj = any.retrieve<Dto2::ObjectWrapper>(); // wrong object
} catch (std::runtime_error& e) {
wasError = true;
}
OATPP_ASSERT(wasError);
}
{
oatpp::Any any1(oatpp::String("Hello!"));
oatpp::Any any2;
any2 = any1;
OATPP_ASSERT(any1);
OATPP_ASSERT(any2);
OATPP_ASSERT(any1.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any2.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any1.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
OATPP_ASSERT(any2.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
OATPP_ASSERT(any1 == any2);
OATPP_ASSERT(any1.getPtr().get() != any2.getPtr().get());
auto str1 = any1.retrieve<oatpp::String>();
auto str2 = any2.retrieve<oatpp::String>();
OATPP_ASSERT(str1 == str2);
OATPP_ASSERT(str1.get() == str2.get() && str1 == "Hello!");
}
{
oatpp::Any any1(oatpp::String("Hello!"));
oatpp::Any any2;
any2 = std::move(any1);
OATPP_ASSERT(!any1);
OATPP_ASSERT(any2);
OATPP_ASSERT(any1.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any2.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any1.getStoredType() == nullptr);
OATPP_ASSERT(any2.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
OATPP_ASSERT(any1 != any2);
OATPP_ASSERT(any1.getPtr().get() != any2.getPtr().get());
auto str1 = any1.retrieve<oatpp::String>();
auto str2 = any2.retrieve<oatpp::String>();
OATPP_ASSERT(str1 != str2);
OATPP_ASSERT(str2 == "Hello!");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************/
#ifndef oatpp_test_core_data_mapping_type_AnyTest_hpp
#define oatpp_test_core_data_mapping_type_AnyTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class AnyTest : public UnitTest{
public:
AnyTest():UnitTest("TEST[core::data::mapping::type::AnyTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_AnyTest_hpp */