DTO. Enum. Populate metadata.

This commit is contained in:
lganzzzo 2020-05-04 04:55:45 +03:00
parent b52eeed67a
commit 66d34683f7
11 changed files with 312 additions and 77 deletions

View File

@ -80,6 +80,8 @@ add_library(oatpp
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/Enum.cpp
oatpp/core/data/mapping/type/Enum.hpp
oatpp/core/data/mapping/type/List.cpp
oatpp/core/data/mapping/type/List.hpp
oatpp/core/data/mapping/type/PairList.cpp

View File

@ -43,10 +43,20 @@ OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(MACRO, (__VA_ARGS__)) (NAME, __VA_
// VALUE MACRO
#define OATPP_MACRO_DTO_ENUM_VALUE_1(NAME, VAL) \
IMPL{ NAME = VAL }
{ \
oatpp::data::mapping::type::EnumValueInfo<EnumType> entry = {EnumType::NAME, index ++, #NAME}; \
info.byName.insert({#NAME, entry}); \
info.byValue.insert({static_cast<v_uint64>(EnumType::NAME), entry}); \
info.byIndex.push_back(entry); \
}
#define OATPP_MACRO_DTO_ENUM_VALUE_2(NAME, VAL, QUALIFIER) \
IMPL{ NAME (QUALIFIER) = VAL }
{ \
oatpp::data::mapping::type::EnumValueInfo<EnumType> entry = {EnumType::NAME, index ++, QUALIFIER}; \
info.byName.insert({QUALIFIER, entry}); \
info.byValue.insert({static_cast<v_uint64>(EnumType::NAME), entry}); \
info.byIndex.push_back(entry); \
}
#define OATPP_MACRO_DTO_ENUM_VALUE(NAME, PARAM_LIST) \
OATPP_MACRO_DTO_ENUM_MACRO_SELECTOR(OATPP_MACRO_DTO_ENUM_VALUE_, NAME, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
@ -60,31 +70,30 @@ OATPP_MACRO_DTO_ENUM_PARAM_NAME X = OATPP_MACRO_DTO_ENUM_PARAM_VALUE X
, OATPP_MACRO_DTO_ENUM_PARAM_NAME X = OATPP_MACRO_DTO_ENUM_PARAM_VALUE X
#define OATPP_MACRO_DTO_ENUM_PARAM_PUT(INDEX, COUNT, X) \
{ \
"name": OATPP_MACRO_DTO_ENUM_PARAM_NAME X; \
"value": OATPP_MACRO_DTO_ENUM_PARAM_VALUE X; \
"name-str": OATPP_MACRO_DTO_ENUM_PARAM_NAME_STR X; \
"value-str": OATPP_MACRO_DTO_ENUM_PARAM_VALUE_STR X; \
"body": { \
OATPP_MACRO_DTO_ENUM_PARAM_MACRO X \
} \
}
OATPP_MACRO_DTO_ENUM_PARAM_MACRO X
// ENUM MACRO
#define OATPP_ENUM_0(NAME, ORDINAL_TYPE) \
enum NAME : ORDINAL_TYPE {}; \
enum class NAME : ORDINAL_TYPE {}; \
\
template<> \
struct EnumInfo <NAME> { \
public: \
typedef ORDINAL_TYPE ValueType; \
public: \
static constexpr const char* name = #NAME; \
};
class Z__OATPP_ENUM_META_##NAME : public oatpp::data::mapping::type::EnumMeta<NAME> { \
private: \
\
static bool init() { \
auto& info = EnumMeta<NAME>::__info; \
info.nameQualifier = #NAME; \
return true; \
} \
\
private: \
static bool initialized; \
}; \
\
bool Z__OATPP_ENUM_META_##NAME::initialized = Z__OATPP_ENUM_META_##NAME::init();
#define OATPP_ENUM_1(NAME, ORDINAL_TYPE, ...) \
enum NAME : ORDINAL_TYPE { \
enum class NAME : ORDINAL_TYPE { \
OATPP_MACRO_FOREACH_FIRST_AND_REST( \
OATPP_MACRO_DTO_ENUM_PARAM_DECL_FIRST, \
OATPP_MACRO_DTO_ENUM_PARAM_DECL_REST, \
@ -92,16 +101,22 @@ enum NAME : ORDINAL_TYPE { \
) \
}; \
\
template<> \
struct EnumInfo <NAME> { \
public: \
typedef ORDINAL_TYPE ValueType; \
public: \
static constexpr const char* name = #NAME; \
\
OATPP_MACRO_FOREACH(OATPP_MACRO_DTO_ENUM_PARAM_PUT, __VA_ARGS__) \
\
};
class Z__OATPP_ENUM_META_##NAME : public oatpp::data::mapping::type::EnumMeta<NAME> { \
private: \
\
static bool init() { \
auto& info = EnumMeta<NAME>::__info; \
v_int32 index = 0; \
info.nameQualifier = #NAME; \
OATPP_MACRO_FOREACH(OATPP_MACRO_DTO_ENUM_PARAM_PUT, __VA_ARGS__) \
return true; \
} \
\
private: \
static bool initialized; \
}; \
\
bool Z__OATPP_ENUM_META_##NAME::initialized = Z__OATPP_ENUM_META_##NAME::init();
// Chooser

View File

@ -106,6 +106,12 @@ namespace oatpp {
*/
typedef oatpp::data::mapping::type::Object Object;
/*
* Mapping-Enabled Enum. &id:oatpp::data::mapping::type::Enum;
*/
template <class T>
using Enum = oatpp::data::mapping::type::Enum<T>;
/*
* Mapping-Enabled List. &id:oatpp::data::mapping::type::Vector;
*/

View File

@ -0,0 +1,33 @@
/***************************************************************************
*
* 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 "Enum.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
const ClassId AbstractEnum::CLASS_ID("Enum");
}
}}}}

View File

@ -0,0 +1,166 @@
/***************************************************************************
*
* 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_Enum_hpp
#define oatpp_data_mapping_type_Enum_hpp
#include "./Primitive.hpp"
#include "oatpp/core/data/share/MemoryLabel.hpp"
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class AbstractEnum {
public:
static const ClassId CLASS_ID;
public:
class AbstractPolymorphicDispatcher {
public:
};
};
template<class T>
class Enum;
}
template<typename T>
struct EnumValueInfo {
const T value;
const v_int32 index;
const data::share::StringKeyLabel name;
};
template<typename T>
struct EnumInfo {
public:
const char* nameQualifier;
std::unordered_map<data::share::StringKeyLabel, EnumValueInfo<T>> byName;
std::unordered_map<v_uint64, EnumValueInfo<T>> byValue;
std::vector<EnumValueInfo<T>> byIndex;
};
template<class T>
class Enum; // FWD
template<class T>
class EnumMeta {
friend __class::Enum<T>;
friend Enum<T>;
public:
typedef T EnumType;
protected:
static EnumInfo<T> __info;
};
template<class T>
EnumInfo<T> EnumMeta<T>::__info;
template<class T>
class Enum : public ObjectWrapper<T, __class::Enum<T>>{
public:
typedef typename std::underlying_type<T>::type UnderlyingType;
public:
static EnumValueInfo<T> getEntryByName(const String& name) {
auto it = EnumMeta<T>::__info.byName.find(name);
if(it != EnumMeta<T>::__info.byName.end()) {
return it->second;
}
throw std::runtime_error("[oatpp::data::mapping::type::Enum::getEntryByName()]: Error. Entry not found.");
}
static EnumValueInfo<T> getEntryByValue(T value) {
auto it = EnumMeta<T>::__info.byValue.find(static_cast<v_uint64>(value));
if(it != EnumMeta<T>::__info.byValue.end()) {
return it->second;
}
throw std::runtime_error("[oatpp::data::mapping::type::Enum::getEntryByValue()]: Error. Entry not found.");
}
static EnumValueInfo<T> getEntryByUnderlyingValue(UnderlyingType value) {
auto it = EnumMeta<T>::__info.byValue.find(static_cast<v_uint64>(value));
if(it != EnumMeta<T>::__info.byValue.end()) {
return it->second;
}
throw std::runtime_error("[oatpp::data::mapping::type::Enum::getEntryByUnderlyingValue()]: Error. Entry not found.");
}
static EnumValueInfo<T> getEntryByIndex(v_int32 index) {
if(index >= 0 && index < EnumMeta<T>::__info.byIndex.size()) {
return EnumMeta<T>::__info.byIndex[index];
}
throw std::runtime_error("[oatpp::data::mapping::type::Enum::getEntryByIndex()]: Error. Entry not found.");
}
static const std::vector<EnumValueInfo<T>>& getEntries() {
return EnumMeta<T>::__info.byIndex;
}
};
namespace __class {
template<class T>
class Enum : public AbstractEnum {
private:
class PolymorphicDispatcher : public AbstractPolymorphicDispatcher {
public:
};
private:
static type::Void creator() {
return type::Void(std::make_shared<T>(), getType());
}
static Type createType() {
Type type(__class::AbstractEnum::CLASS_ID, type::EnumMeta<T>::__info.nameQualifier, &creator, nullptr, new PolymorphicDispatcher());
return type;
}
public:
static Type* getType() {
static Type type = createType();
return &type;
}
};
}
}}}}
#endif // oatpp_data_mapping_type_Enum_hpp

View File

@ -29,6 +29,7 @@
#include "./Any.hpp"
#include "./Primitive.hpp"
#include "./Enum.hpp"
#include "./UnorderedMap.hpp"
#include "./PairList.hpp"
#include "./List.hpp"

View File

@ -39,6 +39,8 @@ namespace oatpp { namespace data { namespace share {
*/
template<class Key>
class LazyStringMap {
public:
typedef oatpp::data::mapping::type::String String;
private:
mutable concurrency::SpinLock m_lock;
mutable bool m_fullyInitialized;
@ -181,7 +183,7 @@ public:
* @param key
* @return
*/
oatpp::String get(const Key& key) const {
String get(const Key& key) const {
std::lock_guard<concurrency::SpinLock> lock(m_lock);

View File

@ -42,7 +42,7 @@ StringKeyLabel::StringKeyLabel(const char* constText)
: oatpp::data::share::MemoryLabel(nullptr, (p_char8)constText, std::strlen(constText))
{}
StringKeyLabel::StringKeyLabel(const oatpp::String& str)
StringKeyLabel::StringKeyLabel(const String& str)
: oatpp::data::share::MemoryLabel(str.getPtr(), str->getData(), str->getSize())
{}
@ -54,7 +54,7 @@ StringKeyLabelCI::StringKeyLabelCI(const char* constText)
: oatpp::data::share::MemoryLabel(nullptr, (p_char8)constText, std::strlen(constText))
{}
StringKeyLabelCI::StringKeyLabelCI(const oatpp::String& str)
StringKeyLabelCI::StringKeyLabelCI(const String& str)
: oatpp::data::share::MemoryLabel(str.getPtr(), str->getData(), str->getSize())
{}
@ -66,7 +66,7 @@ StringKeyLabelCI_FAST::StringKeyLabelCI_FAST(const char* constText)
: oatpp::data::share::MemoryLabel(nullptr, (p_char8)constText, std::strlen(constText))
{}
StringKeyLabelCI_FAST::StringKeyLabelCI_FAST(const oatpp::String& str)
StringKeyLabelCI_FAST::StringKeyLabelCI_FAST(const String& str)
: oatpp::data::share::MemoryLabel(str.getPtr(), str->getData(), str->getSize())
{}

View File

@ -26,7 +26,7 @@
#define oatpp_data_share_MemoryLabel_hpp
#include "oatpp/core/base/StrBuffer.hpp"
#include "oatpp/core/Types.hpp"
#include "oatpp/core/data/mapping/type/Primitive.hpp"
namespace oatpp { namespace data { namespace share {
@ -36,6 +36,8 @@ namespace oatpp { namespace data { namespace share {
* You may allocate separate buffer for data copy later once you need it.
*/
class MemoryLabel {
public:
typedef oatpp::data::mapping::type::String String;
protected:
mutable std::shared_ptr<base::StrBuffer> m_memoryHandle;
mutable p_char8 m_data;
@ -134,8 +136,8 @@ public:
* Create oatpp::String from memory label
* @return oatpp::String(data, size)
*/
oatpp::String toString() const {
return oatpp::String((const char*) m_data, m_size, true);
String toString() const {
return String((const char*) m_data, m_size, true);
}
/**
@ -164,7 +166,7 @@ public:
StringKeyLabel(const std::shared_ptr<base::StrBuffer>& memHandle, p_char8 data, v_buff_size size);
StringKeyLabel(const char* constText);
StringKeyLabel(const oatpp::String& str);
StringKeyLabel(const String& str);
bool operator==(const StringKeyLabel &other) const {
return m_size == other.m_size && base::StrBuffer::equals(m_data, other.m_data, m_size);
@ -188,7 +190,7 @@ public:
StringKeyLabelCI(const std::shared_ptr<base::StrBuffer>& memHandle, p_char8 data, v_buff_size size);
StringKeyLabelCI(const char* constText);
StringKeyLabelCI(const oatpp::String& str);
StringKeyLabelCI(const String& str);
bool operator==(const StringKeyLabelCI &other) const {
return m_size == other.m_size && base::StrBuffer::equalsCI(m_data, other.m_data, m_size);
@ -212,7 +214,7 @@ public:
StringKeyLabelCI_FAST(const std::shared_ptr<base::StrBuffer>& memHandle, p_char8 data, v_buff_size size);
StringKeyLabelCI_FAST(const char* constText);
StringKeyLabelCI_FAST(const oatpp::String& str);
StringKeyLabelCI_FAST(const String& str);
bool operator==(const StringKeyLabelCI_FAST &other) const {
return m_size == other.m_size && base::StrBuffer::equalsCI_FAST(m_data, other.m_data, m_size);

View File

@ -55,6 +55,7 @@
#include "oatpp/core/async/Coroutine.hpp"
#include "oatpp/core/Types.hpp"
#include "oatpp/core/data/mapping/type/Enum.hpp"
#include "oatpp/core/concurrency/SpinLock.hpp"
#include "oatpp/core/base/Environment.hpp"
@ -63,42 +64,25 @@
#include <mutex>
#ifdef OATPP_ENABLE_ALL_TESTS_MAIN
namespace {
//
//#include OATPP_CODEGEN_BEGIN(DTO)
//
//ENUM(MyEnum0, v_int32)
//
//ENUM(MyEnum1, v_int32,
// VALUE(CODE_1, 1001, "Error - code 1"),
// VALUE(CODE_2, 1002)
//)
//
//#include OATPP_CODEGEN_END(DTO)
//
//enum MyE : v_int32 {
//
//};
//
//enum MyE1 : v_int32 {
//
//};
//
//template<typename T>
//struct EnumInfo {
// typedef T Enum;
// static constexpr const char* name = "Unknown";
//};
//
//template<>
//struct EnumInfo <MyE> {
// static constexpr const char* name = "MyE";
//};
//
//template<>
//struct EnumInfo <int> : public oatpp::String {
// static constexpr const char* name = "MyE1";
//};
#include OATPP_CODEGEN_BEGIN(DTO)
ENUM(MyEnum0, v_int32)
ENUM(MyEnum1, v_int32,
VALUE(CODE_1, 1001, "Error - code 1"),
VALUE(CODE_2, 1002),
VALUE(CODE_3, -1)
)
ENUM(MyEnum2, v_uint64,
VALUE(CODE_1, 1001, "Error - code 1"),
VALUE(CODE_2, 1002)
)
#include OATPP_CODEGEN_END(DTO)
void runTests() {
@ -107,9 +91,32 @@ void runTests() {
OATPP_LOGD("aaa", "coroutine size=%d", sizeof(oatpp::async::AbstractCoroutine));
OATPP_LOGD("aaa", "action size=%d", sizeof(oatpp::async::Action));
//OATPP_LOGD("AAA", "e-name='%s'", EnumInfo<int>::name);
v_uint16 v = static_cast<v_uint16>(MyEnum1::CODE_3);
OATPP_LOGD("AAA", "name='%s'", oatpp::Enum<MyEnum1>::Class::getType()->nameQualifier);
OATPP_LOGD("AAA", "name='%s'", oatpp::Enum<MyEnum2>::Class::getType()->nameQualifier);
{
auto entry = oatpp::Enum<MyEnum1>::getEntryByName("Error - code 1");
OATPP_LOGD("Entry", "name='%s', value=%d, index=%d", entry.name.toString()->getData(), entry.value, entry.index);
}
{
auto entry = oatpp::Enum<MyEnum1>::getEntryByValue(MyEnum1::CODE_3);
OATPP_LOGD("Entry", "name='%s', value=%d, index=%d", entry.name.toString()->getData(), entry.value, entry.index);
}
{
auto entry = oatpp::Enum<MyEnum1>::getEntryByIndex(2);
OATPP_LOGD("Entry", "name='%s', value=%d, index=%d", entry.name.toString()->getData(), entry.value, entry.index);
}
{
auto entry = oatpp::Enum<MyEnum1>::getEntryByUnderlyingValue(1003);
OATPP_LOGD("Entry", "name='%s', value=%d, index=%d", entry.name.toString()->getData(), entry.value, entry.index);
}
/*
OATPP_RUN_TEST(oatpp::test::base::CommandLineArgumentsTest);
OATPP_RUN_TEST(oatpp::test::memory::MemoryPoolTest);
@ -222,7 +229,7 @@ void runTests() {
test_port.run();
}
*/
}
}

View File

@ -25,6 +25,7 @@
#include "LazyStringMapTest.hpp"
#include "oatpp/core/data/share/LazyStringMap.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace share {