mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-22 22:16:37 +08:00
introduce oatpp::Tree - mapping-enabled wrapper over data::mapping::Tree.
This commit is contained in:
parent
8ae59cdba1
commit
5460bd404d
@ -114,6 +114,8 @@ add_library(oatpp
|
||||
oatpp/data/type/PairList.hpp
|
||||
oatpp/data/type/Primitive.cpp
|
||||
oatpp/data/type/Primitive.hpp
|
||||
oatpp/data/type/Tree.cpp
|
||||
oatpp/data/type/Tree.hpp
|
||||
oatpp/data/type/Type.cpp
|
||||
oatpp/data/type/Type.hpp
|
||||
oatpp/data/type/UnorderedMap.cpp
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define oatpp_Types_hpp
|
||||
|
||||
#include "oatpp/data/type/Object.hpp"
|
||||
#include "oatpp/data/mapping/Tree.hpp"
|
||||
|
||||
namespace oatpp {
|
||||
|
||||
@ -45,6 +46,12 @@ namespace oatpp {
|
||||
template <class T, class Clazz = oatpp::data::type::__class::Void>
|
||||
using ObjectWrapper = oatpp::data::type::ObjectWrapper<T, Clazz>;
|
||||
|
||||
/**
|
||||
* Mapping enabled &id:oatpp::data::mapping::Tree;
|
||||
* `mapping::Tree` and `type::Tree` are inter-mappable;
|
||||
*/
|
||||
typedef oatpp::data::type::Tree Tree;
|
||||
|
||||
/**
|
||||
* ObjectWrapper over the `void*`.
|
||||
*/
|
||||
|
@ -34,6 +34,7 @@ ObjectToTreeMapper::ObjectToTreeMapper() {
|
||||
m_methods.resize(static_cast<size_t>(data::type::ClassId::getClassCount()), nullptr);
|
||||
|
||||
setMapperMethod(data::type::__class::String::CLASS_ID, &ObjectToTreeMapper::mapString);
|
||||
setMapperMethod(data::type::__class::Tree::CLASS_ID, &ObjectToTreeMapper::mapTree);
|
||||
setMapperMethod(data::type::__class::Any::CLASS_ID, &ObjectToTreeMapper::mapAny);
|
||||
|
||||
setMapperMethod(data::type::__class::Int8::CLASS_ID, &ObjectToTreeMapper::mapPrimitive<oatpp::Int8>);
|
||||
@ -72,7 +73,7 @@ void ObjectToTreeMapper::setMapperMethod(const data::type::ClassId& classId, Map
|
||||
m_methods[id] = method;
|
||||
}
|
||||
|
||||
void ObjectToTreeMapper::map(MappingState& state, const oatpp::Void& polymorph) const
|
||||
void ObjectToTreeMapper::map(State& state, const oatpp::Void& polymorph) const
|
||||
{
|
||||
auto id = static_cast<v_uint32>(polymorph.getValueType()->classId.id);
|
||||
auto& method = m_methods[id];
|
||||
@ -93,7 +94,7 @@ void ObjectToTreeMapper::map(MappingState& state, const oatpp::Void& polymorph)
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectToTreeMapper::mapString(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
|
||||
void ObjectToTreeMapper::mapString(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph) {
|
||||
if(!polymorph) {
|
||||
state.tree->setNull();
|
||||
return;
|
||||
@ -101,7 +102,16 @@ void ObjectToTreeMapper::mapString(const ObjectToTreeMapper* mapper, MappingStat
|
||||
state.tree->setString(oatpp::String(std::static_pointer_cast<std::string>(polymorph.getPtr()), oatpp::String::Class::getType()));
|
||||
}
|
||||
|
||||
void ObjectToTreeMapper::mapAny(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
|
||||
void ObjectToTreeMapper::mapTree(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph) {
|
||||
if(!polymorph) {
|
||||
state.tree->setNull();
|
||||
return;
|
||||
}
|
||||
auto tree = static_cast<mapping::Tree*>(polymorph.get());
|
||||
*state.tree = *tree; // copy
|
||||
}
|
||||
|
||||
void ObjectToTreeMapper::mapAny(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph) {
|
||||
if(!polymorph) {
|
||||
state.tree->setNull();
|
||||
return;
|
||||
@ -110,7 +120,7 @@ void ObjectToTreeMapper::mapAny(const ObjectToTreeMapper* mapper, MappingState&
|
||||
mapper->map(state, oatpp::Void(anyHandle->ptr, anyHandle->type));
|
||||
}
|
||||
|
||||
void ObjectToTreeMapper::mapEnum(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
|
||||
void ObjectToTreeMapper::mapEnum(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph) {
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const data::type::__class::AbstractEnum::PolymorphicDispatcher*>(
|
||||
polymorph.getValueType()->polymorphicDispatcher
|
||||
@ -137,7 +147,7 @@ void ObjectToTreeMapper::mapEnum(const ObjectToTreeMapper* mapper, MappingState&
|
||||
|
||||
}
|
||||
|
||||
void ObjectToTreeMapper::mapCollection(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
|
||||
void ObjectToTreeMapper::mapCollection(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph) {
|
||||
|
||||
if(!polymorph) {
|
||||
state.tree->setNull();
|
||||
@ -162,7 +172,7 @@ void ObjectToTreeMapper::mapCollection(const ObjectToTreeMapper* mapper, Mapping
|
||||
|
||||
vector.emplace_back();
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.tree = &vector[vector.size() - 1];
|
||||
nestedState.config = state.config;
|
||||
|
||||
@ -183,7 +193,7 @@ void ObjectToTreeMapper::mapCollection(const ObjectToTreeMapper* mapper, Mapping
|
||||
|
||||
}
|
||||
|
||||
void ObjectToTreeMapper::mapMap(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
|
||||
void ObjectToTreeMapper::mapMap(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph) {
|
||||
|
||||
if(!polymorph) {
|
||||
state.tree->setNull();
|
||||
@ -212,7 +222,7 @@ void ObjectToTreeMapper::mapMap(const ObjectToTreeMapper* mapper, MappingState&
|
||||
const auto& untypedKey = iterator->getKey();
|
||||
const auto& key = oatpp::String(std::static_pointer_cast<std::string>(untypedKey.getPtr()));
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.tree = &map[key];
|
||||
nestedState.config = state.config;
|
||||
|
||||
@ -230,7 +240,7 @@ void ObjectToTreeMapper::mapMap(const ObjectToTreeMapper* mapper, MappingState&
|
||||
|
||||
}
|
||||
|
||||
void ObjectToTreeMapper::mapObject(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
|
||||
void ObjectToTreeMapper::mapObject(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph) {
|
||||
|
||||
if(!polymorph) {
|
||||
state.tree->setNull();
|
||||
@ -266,7 +276,7 @@ void ObjectToTreeMapper::mapObject(const ObjectToTreeMapper* mapper, MappingStat
|
||||
|
||||
if (value || state.config->includeNullFields || (field->info.required && state.config->alwaysIncludeRequired)) {
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.tree = &map[oatpp::String(field->name)];
|
||||
nestedState.config = state.config;
|
||||
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
struct MappingState {
|
||||
struct State {
|
||||
|
||||
const Config* config;
|
||||
Tree* tree;
|
||||
@ -51,11 +51,11 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
typedef void (*MapperMethod)(const ObjectToTreeMapper*, MappingState&, const oatpp::Void&);
|
||||
typedef void (*MapperMethod)(const ObjectToTreeMapper*, State&, const oatpp::Void&);
|
||||
public:
|
||||
|
||||
template<class T>
|
||||
static void mapPrimitive(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph){
|
||||
static void mapPrimitive(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph){
|
||||
(void) mapper;
|
||||
if(polymorph){
|
||||
state.tree->setValue<typename T::ObjectType>(* static_cast<typename T::ObjectType*>(polymorph.get()));
|
||||
@ -64,14 +64,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void mapString(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
|
||||
static void mapAny(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
|
||||
static void mapEnum(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
|
||||
static void mapString(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph);
|
||||
static void mapTree(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph);
|
||||
static void mapAny(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph);
|
||||
static void mapEnum(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph);
|
||||
|
||||
static void mapCollection(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
|
||||
static void mapMap(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
|
||||
static void mapCollection(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph);
|
||||
static void mapMap(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph);
|
||||
|
||||
static void mapObject(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
|
||||
static void mapObject(const ObjectToTreeMapper* mapper, State& state, const oatpp::Void& polymorph);
|
||||
|
||||
private:
|
||||
std::vector<MapperMethod> m_methods;
|
||||
@ -81,7 +82,7 @@ public:
|
||||
|
||||
void setMapperMethod(const data::type::ClassId& classId, MapperMethod method);
|
||||
|
||||
void map(MappingState& state, const oatpp::Void& polymorph) const;
|
||||
void map(State& state, const oatpp::Void& polymorph) const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -61,7 +61,7 @@ TreeMap& TreeMap::operator = (TreeMap&& other) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Tree& TreeMap::operator [] (const oatpp::String& key) {
|
||||
Tree& TreeMap::operator [] (const type::String& key) {
|
||||
auto it = m_map.find(key);
|
||||
if(it == m_map.end()) {
|
||||
auto& result = m_map[key];
|
||||
@ -71,7 +71,7 @@ Tree& TreeMap::operator [] (const oatpp::String& key) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const Tree& TreeMap::operator [] (const oatpp::String& key) const {
|
||||
const Tree& TreeMap::operator [] (const type::String& key) const {
|
||||
auto it = m_map.find(key);
|
||||
if(it == m_map.end()) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::TreeMap::operator[]]: const operator[] can't add items.");
|
||||
@ -79,12 +79,12 @@ const Tree& TreeMap::operator [] (const oatpp::String& key) const {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::pair<oatpp::String, std::reference_wrapper<Tree>> TreeMap::operator [] (v_uint64 index) {
|
||||
std::pair<type::String, std::reference_wrapper<Tree>> TreeMap::operator [] (v_uint64 index) {
|
||||
auto& item = m_order.at(index);
|
||||
return {item.first.lock(), *item.second};
|
||||
}
|
||||
|
||||
std::pair<oatpp::String, std::reference_wrapper<const Tree>> TreeMap::operator [] (v_uint64 index) const {
|
||||
std::pair<type::String, std::reference_wrapper<const Tree>> TreeMap::operator [] (v_uint64 index) const {
|
||||
auto& item = m_order.at(index);
|
||||
return {item.first.lock(), *item.second};
|
||||
}
|
||||
@ -101,7 +101,7 @@ Tree::Attributes::Attributes()
|
||||
{}
|
||||
|
||||
Tree::Attributes::Attributes(const Attributes& other)
|
||||
: m_attributes(other.m_attributes != nullptr ? new std::unordered_map<oatpp::String, oatpp::String>(*other.m_attributes) : nullptr)
|
||||
: m_attributes(other.m_attributes != nullptr ? new std::unordered_map<type::String, type::String>(*other.m_attributes) : nullptr)
|
||||
{}
|
||||
|
||||
Tree::Attributes::Attributes(Attributes&& other) noexcept
|
||||
@ -115,7 +115,7 @@ Tree::Attributes& Tree::Attributes::operator = (const Attributes& other) {
|
||||
if(m_attributes) {
|
||||
*m_attributes = *other.m_attributes;
|
||||
} else {
|
||||
m_attributes = new std::unordered_map<oatpp::String, oatpp::String>(*other.m_attributes);
|
||||
m_attributes = new std::unordered_map<type::String, type::String>(*other.m_attributes);
|
||||
}
|
||||
} else {
|
||||
delete m_attributes;
|
||||
@ -169,7 +169,7 @@ Tree::Tree(Tree&& other) noexcept
|
||||
other.m_data = 0;
|
||||
}
|
||||
|
||||
Tree::Tree(const oatpp::String& value)
|
||||
Tree::Tree(const type::String& value)
|
||||
: Tree()
|
||||
{
|
||||
setString(value);
|
||||
@ -189,7 +189,7 @@ Tree& Tree::operator = (Tree&& other) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Tree& Tree::operator = (const oatpp::String& value) {
|
||||
Tree& Tree::operator = (const type::String& value) {
|
||||
setString(value);
|
||||
return *this;
|
||||
}
|
||||
@ -221,7 +221,7 @@ void Tree::deleteValueObject() {
|
||||
break;
|
||||
|
||||
case Type::STRING: {
|
||||
auto data = reinterpret_cast<oatpp::String *>(m_data);
|
||||
auto data = reinterpret_cast<type::String *>(m_data);
|
||||
delete data;
|
||||
break;
|
||||
}
|
||||
@ -236,7 +236,7 @@ void Tree::deleteValueObject() {
|
||||
break;
|
||||
}
|
||||
case Type::PAIRS: {
|
||||
auto data = reinterpret_cast<std::vector<std::pair<oatpp::String, Tree>> *>(m_data);
|
||||
auto data = reinterpret_cast<std::vector<std::pair<type::String, Tree>> *>(m_data);
|
||||
delete data;
|
||||
break;
|
||||
}
|
||||
@ -248,15 +248,15 @@ void Tree::deleteValueObject() {
|
||||
}
|
||||
}
|
||||
|
||||
Tree::operator oatpp::String () {
|
||||
Tree::operator type::String () {
|
||||
return getString();
|
||||
}
|
||||
|
||||
Tree& Tree::operator [] (const oatpp::String& key) {
|
||||
Tree& Tree::operator [] (const type::String& key) {
|
||||
return getMap()[key];
|
||||
}
|
||||
|
||||
const Tree& Tree::operator [] (const oatpp::String& key) const {
|
||||
const Tree& Tree::operator [] (const type::String& key) const {
|
||||
return getMap()[key];
|
||||
}
|
||||
|
||||
@ -304,11 +304,11 @@ void Tree::setCopy(const Tree& other) {
|
||||
}
|
||||
|
||||
case Type::STRING: {
|
||||
auto otherData = reinterpret_cast<oatpp::String *>(other.m_data);
|
||||
auto otherData = reinterpret_cast<type::String *>(other.m_data);
|
||||
if(otherData == nullptr) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::setCopy()]: other.data is null, other.type is 'STRING'");
|
||||
}
|
||||
auto ptr = new oatpp::String(*otherData);
|
||||
auto ptr = new type::String(*otherData);
|
||||
m_data = reinterpret_cast<LARGEST_TYPE>(ptr);
|
||||
break;
|
||||
}
|
||||
@ -331,11 +331,11 @@ void Tree::setCopy(const Tree& other) {
|
||||
break;
|
||||
}
|
||||
case Type::PAIRS: {
|
||||
auto otherData = reinterpret_cast<std::vector<std::pair<oatpp::String, Tree>> *>(other.m_data);
|
||||
auto otherData = reinterpret_cast<std::vector<std::pair<type::String, Tree>> *>(other.m_data);
|
||||
if(otherData == nullptr) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::setCopy()]: other.data is null, other.type is 'PAIRS'");
|
||||
}
|
||||
auto ptr = new std::vector<std::pair<oatpp::String, Tree>>(*otherData);
|
||||
auto ptr = new std::vector<std::pair<type::String, Tree>>(*otherData);
|
||||
m_data = reinterpret_cast<LARGEST_TYPE>(ptr);
|
||||
break;
|
||||
}
|
||||
@ -385,10 +385,10 @@ void Tree::setFloat(v_float64 value) {
|
||||
std::memcpy (&m_data, &value, sizeof(v_float64));
|
||||
}
|
||||
|
||||
void Tree::setString(const oatpp::String& value) {
|
||||
void Tree::setString(const type::String& value) {
|
||||
deleteValueObject();
|
||||
m_type = Type::STRING;
|
||||
auto data = new oatpp::String(value);
|
||||
auto data = new type::String(value);
|
||||
m_data = reinterpret_cast<LARGEST_TYPE>(data);
|
||||
}
|
||||
|
||||
@ -413,10 +413,10 @@ void Tree::setMap(const TreeMap& value) {
|
||||
m_data = reinterpret_cast<LARGEST_TYPE>(data);
|
||||
}
|
||||
|
||||
void Tree::setPairs(const std::vector<std::pair<oatpp::String, Tree>>& value) {
|
||||
void Tree::setPairs(const std::vector<std::pair<type::String, Tree>>& value) {
|
||||
deleteValueObject();
|
||||
m_type = Type::PAIRS;
|
||||
auto data = new std::vector<std::pair<oatpp::String, Tree>>(value);
|
||||
auto data = new std::vector<std::pair<type::String, Tree>>(value);
|
||||
m_data = reinterpret_cast<LARGEST_TYPE>(data);
|
||||
}
|
||||
|
||||
@ -577,11 +577,11 @@ v_float64 Tree::getFloat() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
const oatpp::String& Tree::getString() const {
|
||||
const type::String& Tree::getString() const {
|
||||
if(m_type != Type::STRING) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::getString()]: NOT a STRING.");
|
||||
}
|
||||
auto data = reinterpret_cast<const oatpp::String*>(m_data);
|
||||
auto data = reinterpret_cast<const type::String*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
@ -601,11 +601,11 @@ const TreeMap& Tree::getMap() const {
|
||||
return *data;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<oatpp::String, Tree>>& Tree::getPairs() const {
|
||||
const std::vector<std::pair<type::String, Tree>>& Tree::getPairs() const {
|
||||
if(m_type != Type::PAIRS) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::getPairs()]: NOT a PAIRS.");
|
||||
}
|
||||
auto data = reinterpret_cast<const std::vector<std::pair<oatpp::String, Tree>>*>(m_data);
|
||||
auto data = reinterpret_cast<const std::vector<std::pair<type::String, Tree>>*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
@ -631,14 +631,14 @@ TreeMap& Tree::getMap() {
|
||||
return *data;
|
||||
}
|
||||
|
||||
std::vector<std::pair<oatpp::String, Tree>>& Tree::getPairs() {
|
||||
std::vector<std::pair<type::String, Tree>>& Tree::getPairs() {
|
||||
if(m_type == Type::UNDEFINED) {
|
||||
setPairs({});
|
||||
}
|
||||
if(m_type != Type::MAP) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::Tree::getMap()]: NOT a MAP.");
|
||||
}
|
||||
auto data = reinterpret_cast<std::vector<std::pair<oatpp::String, Tree>>*>(m_data);
|
||||
auto data = reinterpret_cast<std::vector<std::pair<type::String, Tree>>*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
@ -650,19 +650,19 @@ const Tree::Attributes& Tree::attributes() const {
|
||||
return m_attributes;
|
||||
}
|
||||
|
||||
oatpp::String Tree::debugPrint(v_uint32 indent0, v_uint32 indentDelta, bool firstLineIndent) const {
|
||||
type::String Tree::debugPrint(v_uint32 indent0, v_uint32 indentDelta, bool firstLineIndent) const {
|
||||
|
||||
stream::BufferOutputStream ss;
|
||||
for(v_uint32 i = 0; i < indent0; i ++) {
|
||||
ss << " ";
|
||||
}
|
||||
oatpp::String indentStr0 = ss.toString();
|
||||
type::String indentStr0 = ss.toString();
|
||||
|
||||
ss.setCurrentPosition(0);
|
||||
for(v_uint32 i = 0; i < indentDelta; i ++) {
|
||||
ss << " ";
|
||||
}
|
||||
oatpp::String indentDeltaStr = ss.toString();
|
||||
type::String indentDeltaStr = ss.toString();
|
||||
|
||||
ss.setCurrentPosition(0);
|
||||
if(firstLineIndent) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef oatpp_data_mapping_Tree_hpp
|
||||
#define oatpp_data_mapping_Tree_hpp
|
||||
|
||||
#include "oatpp/Types.hpp"
|
||||
#include "oatpp/data/type/Object.hpp"
|
||||
|
||||
namespace oatpp { namespace data { namespace mapping {
|
||||
|
||||
@ -72,7 +72,7 @@ public:
|
||||
|
||||
class Attributes {
|
||||
private:
|
||||
std::unordered_map<oatpp::String, oatpp::String>* m_attributes;
|
||||
std::unordered_map<type::String, type::String>* m_attributes;
|
||||
public:
|
||||
|
||||
Attributes();
|
||||
@ -111,7 +111,7 @@ public:
|
||||
setValue<T>(value);
|
||||
}
|
||||
|
||||
explicit Tree(const oatpp::String& value);
|
||||
explicit Tree(const type::String& value);
|
||||
|
||||
~Tree();
|
||||
|
||||
@ -124,7 +124,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
Tree& operator = (const oatpp::String& value);
|
||||
Tree& operator = (const type::String& value);
|
||||
|
||||
template <typename T, typename enabled = typename NodePrimitiveType<T>::value_type>
|
||||
operator T () const {
|
||||
@ -165,10 +165,10 @@ public:
|
||||
|
||||
}
|
||||
|
||||
operator oatpp::String ();
|
||||
operator type::String ();
|
||||
|
||||
Tree& operator [] (const oatpp::String& key);
|
||||
const Tree& operator [] (const oatpp::String& key) const;
|
||||
Tree& operator [] (const type::String& key);
|
||||
const Tree& operator [] (const type::String& key) const;
|
||||
|
||||
Tree& operator [] (v_uint64 index);
|
||||
const Tree& operator [] (v_uint64 index) const;
|
||||
@ -202,11 +202,11 @@ public:
|
||||
void setInteger(v_int64 value);
|
||||
void setFloat(v_float64 value);
|
||||
|
||||
void setString(const oatpp::String& value);
|
||||
void setString(const type::String& value);
|
||||
void setVector(const std::vector<Tree>& value);
|
||||
void setVector(v_uint64 size);
|
||||
void setMap(const TreeMap& value);
|
||||
void setPairs(const std::vector<std::pair<oatpp::String, Tree>>& value);
|
||||
void setPairs(const std::vector<std::pair<type::String, Tree>>& value);
|
||||
|
||||
bool isNull() const;
|
||||
bool isUndefined() const;
|
||||
@ -219,26 +219,26 @@ public:
|
||||
v_int64 getInteger() const;
|
||||
v_float64 getFloat() const;
|
||||
|
||||
const oatpp::String& getString() const;
|
||||
const type::String& getString() const;
|
||||
|
||||
const std::vector<Tree>& getVector() const;
|
||||
const TreeMap& getMap() const;
|
||||
const std::vector<std::pair<oatpp::String, Tree>>& getPairs() const;
|
||||
const std::vector<std::pair<type::String, Tree>>& getPairs() const;
|
||||
|
||||
std::vector<Tree>& getVector();
|
||||
TreeMap& getMap();
|
||||
std::vector<std::pair<oatpp::String, Tree>>& getPairs();
|
||||
std::vector<std::pair<type::String, Tree>>& getPairs();
|
||||
|
||||
Attributes& attributes();
|
||||
const Attributes& attributes() const;
|
||||
|
||||
oatpp::String debugPrint(v_uint32 indent0 = 0, v_uint32 indentDelta = 2, bool firstLineIndent = true) const;
|
||||
type::String debugPrint(v_uint32 indent0 = 0, v_uint32 indentDelta = 2, bool firstLineIndent = true) const;
|
||||
|
||||
};
|
||||
|
||||
class TreeMap {
|
||||
private:
|
||||
std::unordered_map<oatpp::String, Tree> m_map;
|
||||
std::unordered_map<type::String, Tree> m_map;
|
||||
std::vector<std::pair<std::weak_ptr<std::string>, Tree*>> m_order;
|
||||
public:
|
||||
|
||||
@ -250,11 +250,11 @@ public:
|
||||
TreeMap& operator = (const TreeMap& other);
|
||||
TreeMap& operator = (TreeMap&& other) noexcept;
|
||||
|
||||
Tree& operator [] (const oatpp::String& key);
|
||||
const Tree& operator [] (const oatpp::String& key) const;
|
||||
Tree& operator [] (const type::String& key);
|
||||
const Tree& operator [] (const type::String& key) const;
|
||||
|
||||
std::pair<oatpp::String, std::reference_wrapper<Tree>> operator [] (v_uint64 index);
|
||||
std::pair<oatpp::String, std::reference_wrapper<const Tree>> operator [] (v_uint64 index) const;
|
||||
std::pair<type::String, std::reference_wrapper<Tree>> operator [] (v_uint64 index);
|
||||
std::pair<type::String, std::reference_wrapper<const Tree>> operator [] (v_uint64 index) const;
|
||||
|
||||
v_uint64 size() const;
|
||||
|
||||
|
@ -34,6 +34,8 @@ TreeToObjectMapper::TreeToObjectMapper() {
|
||||
m_methods.resize(static_cast<size_t>(data::type::ClassId::getClassCount()), nullptr);
|
||||
|
||||
setMapperMethod(data::type::__class::String::CLASS_ID, &TreeToObjectMapper::mapString);
|
||||
|
||||
setMapperMethod(data::type::__class::Tree::CLASS_ID, &TreeToObjectMapper::mapTree);
|
||||
setMapperMethod(data::type::__class::Any::CLASS_ID, &TreeToObjectMapper::mapAny);
|
||||
|
||||
setMapperMethod(data::type::__class::Int8::CLASS_ID, &TreeToObjectMapper::mapPrimitive<oatpp::Int8>);
|
||||
@ -72,7 +74,7 @@ void TreeToObjectMapper::setMapperMethod(const data::type::ClassId& classId, Map
|
||||
m_methods[id] = method;
|
||||
}
|
||||
|
||||
oatpp::Void TreeToObjectMapper::map(MappingState& state, const Type* type) const {
|
||||
oatpp::Void TreeToObjectMapper::map(State& state, const Type* type) const {
|
||||
auto id = static_cast<v_uint32>(type->classId.id);
|
||||
auto& method = m_methods[id];
|
||||
if(method) {
|
||||
@ -124,7 +126,7 @@ const Type* TreeToObjectMapper::guessType(const Tree& node) {
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void TreeToObjectMapper::mapString(const TreeToObjectMapper* mapper, MappingState& state, const Type* type) {
|
||||
oatpp::Void TreeToObjectMapper::mapString(const TreeToObjectMapper* mapper, State& state, const Type* type) {
|
||||
|
||||
(void) mapper;
|
||||
(void) type;
|
||||
@ -142,7 +144,13 @@ oatpp::Void TreeToObjectMapper::mapString(const TreeToObjectMapper* mapper, Mapp
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void TreeToObjectMapper::mapAny(const TreeToObjectMapper* mapper, MappingState& state, const Type* type) {
|
||||
oatpp::Void TreeToObjectMapper::mapTree(const TreeToObjectMapper* mapper, State& state, const Type* type) {
|
||||
(void) type;
|
||||
(void) mapper;
|
||||
return oatpp::Tree(std::make_shared<mapping::Tree>(*state.tree), oatpp::Tree::Class::getType());
|
||||
}
|
||||
|
||||
oatpp::Void TreeToObjectMapper::mapAny(const TreeToObjectMapper* mapper, State& state, const Type* type) {
|
||||
(void) type;
|
||||
if(state.tree->isNull()){
|
||||
return oatpp::Void(Any::Class::getType());
|
||||
@ -157,7 +165,7 @@ oatpp::Void TreeToObjectMapper::mapAny(const TreeToObjectMapper* mapper, Mapping
|
||||
return oatpp::Void(Any::Class::getType());
|
||||
}
|
||||
|
||||
oatpp::Void TreeToObjectMapper::mapEnum(const TreeToObjectMapper* mapper, MappingState& state, const Type* type) {
|
||||
oatpp::Void TreeToObjectMapper::mapEnum(const TreeToObjectMapper* mapper, State& state, const Type* type) {
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const data::type::__class::AbstractEnum::PolymorphicDispatcher*>(
|
||||
type->polymorphicDispatcher
|
||||
@ -191,7 +199,7 @@ oatpp::Void TreeToObjectMapper::mapEnum(const TreeToObjectMapper* mapper, Mappin
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void TreeToObjectMapper::mapCollection(const TreeToObjectMapper* mapper, MappingState& state, const Type* type) {
|
||||
oatpp::Void TreeToObjectMapper::mapCollection(const TreeToObjectMapper* mapper, State& state, const Type* type) {
|
||||
|
||||
if(state.tree->getType() != Tree::Type::VECTOR) {
|
||||
if(state.tree->isNull()){
|
||||
@ -210,7 +218,7 @@ oatpp::Void TreeToObjectMapper::mapCollection(const TreeToObjectMapper* mapper,
|
||||
|
||||
v_int64 index = 0;
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.config = state.config;
|
||||
|
||||
for(const auto& node : vector) {
|
||||
@ -234,7 +242,7 @@ oatpp::Void TreeToObjectMapper::mapCollection(const TreeToObjectMapper* mapper,
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void TreeToObjectMapper::mapMap(const TreeToObjectMapper* mapper, MappingState& state, const Type* type) {
|
||||
oatpp::Void TreeToObjectMapper::mapMap(const TreeToObjectMapper* mapper, State& state, const Type* type) {
|
||||
|
||||
if(state.tree->getType() != Tree::Type::MAP) {
|
||||
if(state.tree->isNull()){
|
||||
@ -257,7 +265,7 @@ oatpp::Void TreeToObjectMapper::mapMap(const TreeToObjectMapper* mapper, Mapping
|
||||
const auto& treeMap = state.tree->getMap();
|
||||
auto treeMapSize = treeMap.size();
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.config = state.config;
|
||||
|
||||
for(v_uint64 i = 0; i < treeMapSize; i ++) {
|
||||
@ -282,7 +290,7 @@ oatpp::Void TreeToObjectMapper::mapMap(const TreeToObjectMapper* mapper, Mapping
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void TreeToObjectMapper::mapObject(const TreeToObjectMapper* mapper, MappingState& state, const Type* type) {
|
||||
oatpp::Void TreeToObjectMapper::mapObject(const TreeToObjectMapper* mapper, State& state, const Type* type) {
|
||||
|
||||
if(state.tree->getType() != Tree::Type::MAP) {
|
||||
if(state.tree->isNull()){
|
||||
@ -314,7 +322,7 @@ oatpp::Void TreeToObjectMapper::mapObject(const TreeToObjectMapper* mapper, Mapp
|
||||
polymorphs.emplace_back(field, &node.second.get()); // store polymorphs for later processing.
|
||||
} else {
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.tree = &node.second.get();
|
||||
nestedState.config = state.config;
|
||||
|
||||
@ -345,7 +353,7 @@ oatpp::Void TreeToObjectMapper::mapObject(const TreeToObjectMapper* mapper, Mapp
|
||||
for(auto& p : polymorphs) {
|
||||
auto selectedType = p.first->info.typeSelector->selectType(static_cast<oatpp::BaseObject *>(object.get()));
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.tree = p.second;
|
||||
nestedState.config = state.config;
|
||||
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
struct MappingState {
|
||||
struct State {
|
||||
|
||||
const Config* config;
|
||||
const Tree* tree;
|
||||
@ -49,11 +49,11 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
typedef oatpp::Void (*MapperMethod)(const TreeToObjectMapper*, MappingState&, const Type* const);
|
||||
typedef oatpp::Void (*MapperMethod)(const TreeToObjectMapper*, State&, const Type* const);
|
||||
public:
|
||||
|
||||
template<class T>
|
||||
static oatpp::Void mapPrimitive(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type){
|
||||
static oatpp::Void mapPrimitive(const TreeToObjectMapper* mapper, State& state, const Type* const type){
|
||||
(void) mapper;
|
||||
(void) type;
|
||||
if(state.tree->isPrimitive()) {
|
||||
@ -68,14 +68,15 @@ public:
|
||||
|
||||
static const Type* guessType(const Tree& node);
|
||||
|
||||
static oatpp::Void mapString(const TreeToObjectMapper* mapper, MappingState& state, const Type* type);
|
||||
static oatpp::Void mapAny(const TreeToObjectMapper* mapper, MappingState& state, const Type* type);
|
||||
static oatpp::Void mapEnum(const TreeToObjectMapper* mapper, MappingState& state, const Type* type);
|
||||
static oatpp::Void mapString(const TreeToObjectMapper* mapper, State& state, const Type* type);
|
||||
static oatpp::Void mapTree(const TreeToObjectMapper* mapper, State& state, const Type* type);
|
||||
static oatpp::Void mapAny(const TreeToObjectMapper* mapper, State& state, const Type* type);
|
||||
static oatpp::Void mapEnum(const TreeToObjectMapper* mapper, State& state, const Type* type);
|
||||
|
||||
static oatpp::Void mapCollection(const TreeToObjectMapper* mapper, MappingState& state, const Type* type);
|
||||
static oatpp::Void mapMap(const TreeToObjectMapper* mapper, MappingState& state, const Type* type);
|
||||
static oatpp::Void mapCollection(const TreeToObjectMapper* mapper, State& state, const Type* type);
|
||||
static oatpp::Void mapMap(const TreeToObjectMapper* mapper, State& state, const Type* type);
|
||||
|
||||
static oatpp::Void mapObject(const TreeToObjectMapper* mapper, MappingState& state, const Type* type);
|
||||
static oatpp::Void mapObject(const TreeToObjectMapper* mapper, State& state, const Type* type);
|
||||
|
||||
private:
|
||||
std::vector<MapperMethod> m_methods;
|
||||
@ -85,7 +86,7 @@ public:
|
||||
|
||||
void setMapperMethod(const data::type::ClassId& classId, MapperMethod method);
|
||||
|
||||
oatpp::Void map(MappingState& state, const Type* type) const;
|
||||
oatpp::Void map(State& state, const Type* type) const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "./Type.hpp"
|
||||
|
||||
#include "./Tree.hpp"
|
||||
#include "./Any.hpp"
|
||||
#include "./Primitive.hpp"
|
||||
#include "./Enum.hpp"
|
||||
|
41
src/oatpp/data/type/Tree.cpp
Normal file
41
src/oatpp/data/type/Tree.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 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 "./Tree.hpp"
|
||||
|
||||
namespace oatpp { namespace data { namespace type {
|
||||
|
||||
namespace __class {
|
||||
|
||||
const ClassId Tree::CLASS_ID("Tree");
|
||||
|
||||
Type* Tree::getType() {
|
||||
static Type type(CLASS_ID);
|
||||
return &type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}}}
|
61
src/oatpp/data/type/Tree.hpp
Normal file
61
src/oatpp/data/type/Tree.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 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_type_Tree_hpp
|
||||
#define oatpp_data_type_Tree_hpp
|
||||
|
||||
#include "./Type.hpp"
|
||||
|
||||
namespace oatpp { namespace data { namespace mapping {
|
||||
|
||||
class Tree; // FWD
|
||||
|
||||
}}}
|
||||
|
||||
namespace oatpp { namespace data { namespace type {
|
||||
|
||||
namespace __class {
|
||||
|
||||
/**
|
||||
* Tree class.
|
||||
*/
|
||||
class Tree {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Class Id.
|
||||
*/
|
||||
static const ClassId CLASS_ID;
|
||||
|
||||
static Type *getType();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
typedef ObjectWrapper<mapping::Tree, __class::Tree> Tree;
|
||||
|
||||
}}}
|
||||
|
||||
#endif //oatpp_data_type_Tree_hpp
|
@ -29,7 +29,7 @@
|
||||
|
||||
namespace oatpp { namespace json {
|
||||
|
||||
void Deserializer::deserializeNull(MappingState& state) {
|
||||
void Deserializer::deserializeNull(State& state) {
|
||||
if(state.caret->isAtText("null", true)){
|
||||
state.tree->setNull();
|
||||
} else {
|
||||
@ -37,7 +37,7 @@ void Deserializer::deserializeNull(MappingState& state) {
|
||||
}
|
||||
}
|
||||
|
||||
void Deserializer::deserializeNumber(MappingState& state) {
|
||||
void Deserializer::deserializeNumber(State& state) {
|
||||
if (!Utils::findDecimalSeparatorInCurrentNumber(*state.caret)) {
|
||||
state.tree->setInteger(state.caret->parseInt());
|
||||
} else {
|
||||
@ -45,7 +45,7 @@ void Deserializer::deserializeNumber(MappingState& state) {
|
||||
}
|
||||
}
|
||||
|
||||
void Deserializer::deserializeBoolean(MappingState& state) {
|
||||
void Deserializer::deserializeBoolean(State& state) {
|
||||
if(state.caret->isAtText("true", true)) {
|
||||
state.tree->setValue<bool>(true);
|
||||
} else if(state.caret->isAtText("false", true)) {
|
||||
@ -55,11 +55,11 @@ void Deserializer::deserializeBoolean(MappingState& state) {
|
||||
}
|
||||
}
|
||||
|
||||
void Deserializer::deserializeString(MappingState& state) {
|
||||
void Deserializer::deserializeString(State& state) {
|
||||
state.tree->setString(Utils::parseString(*state.caret));
|
||||
}
|
||||
|
||||
void Deserializer::deserializeArray(MappingState& state) {
|
||||
void Deserializer::deserializeArray(State& state) {
|
||||
|
||||
if(state.caret->canContinueAtChar('[', 1)) {
|
||||
|
||||
@ -76,7 +76,7 @@ void Deserializer::deserializeArray(MappingState& state) {
|
||||
|
||||
vector.emplace_back();
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.caret = state.caret;
|
||||
nestedState.config = state.config;
|
||||
nestedState.tree = &vector[vector.size() - 1];
|
||||
@ -108,7 +108,7 @@ void Deserializer::deserializeArray(MappingState& state) {
|
||||
|
||||
}
|
||||
|
||||
void Deserializer::deserializeMap(MappingState& state) {
|
||||
void Deserializer::deserializeMap(State& state) {
|
||||
|
||||
if(state.caret->canContinueAtChar('{', 1)) {
|
||||
|
||||
@ -135,7 +135,7 @@ void Deserializer::deserializeMap(MappingState& state) {
|
||||
|
||||
state.caret->skipBlankChars();
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.caret = state.caret;
|
||||
nestedState.config = state.config;
|
||||
nestedState.tree = &map[key];
|
||||
@ -164,7 +164,7 @@ void Deserializer::deserializeMap(MappingState& state) {
|
||||
|
||||
}
|
||||
|
||||
void Deserializer::deserialize(MappingState& state) {
|
||||
void Deserializer::deserialize(State& state) {
|
||||
|
||||
state.caret->skipBlankChars();
|
||||
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
struct MappingState {
|
||||
struct State {
|
||||
const Config* config;
|
||||
data::mapping::Tree* tree;
|
||||
utils::parser::Caret* caret;
|
||||
@ -63,17 +63,17 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
static void deserializeNull(MappingState& state);
|
||||
static void deserializeNumber(MappingState& state);
|
||||
static void deserializeBoolean(MappingState& state);
|
||||
static void deserializeString(MappingState& state);
|
||||
static void deserializeNull(State& state);
|
||||
static void deserializeNumber(State& state);
|
||||
static void deserializeBoolean(State& state);
|
||||
static void deserializeString(State& state);
|
||||
|
||||
static void deserializeArray(MappingState& state);
|
||||
static void deserializeMap(MappingState& state);
|
||||
static void deserializeArray(State& state);
|
||||
static void deserializeMap(State& state);
|
||||
|
||||
public:
|
||||
|
||||
static void deserialize(MappingState& state);
|
||||
static void deserialize(State& state);
|
||||
|
||||
};
|
||||
|
||||
|
@ -32,22 +32,8 @@ ObjectMapper::ObjectMapper(const SerializerConfig& serializerConfig, const Deser
|
||||
, m_deserializerConfig(deserializerConfig)
|
||||
{}
|
||||
|
||||
void ObjectMapper::write(data::stream::ConsistentOutputStream* stream, const oatpp::Void& variant, data::mapping::ErrorStack& errorStack) const {
|
||||
|
||||
data::mapping::Tree tree;
|
||||
{
|
||||
data::mapping::ObjectToTreeMapper::MappingState state;
|
||||
state.config = &m_serializerConfig.mapper;
|
||||
state.tree = &tree;
|
||||
m_objectToTreeMapper.map(state, variant);
|
||||
if(!state.errorStack.empty()) {
|
||||
errorStack = std::move(state.errorStack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Serializer::MappingState state;
|
||||
void ObjectMapper::writeTree(data::stream::ConsistentOutputStream* stream, const data::mapping::Tree& tree, data::mapping::ErrorStack& errorStack) const {
|
||||
Serializer::State state;
|
||||
state.config = &m_serializerConfig.json;
|
||||
state.tree = &tree;
|
||||
Serializer::serializeToStream(stream, state);
|
||||
@ -57,6 +43,29 @@ void ObjectMapper::write(data::stream::ConsistentOutputStream* stream, const oat
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMapper::write(data::stream::ConsistentOutputStream* stream, const oatpp::Void& variant, data::mapping::ErrorStack& errorStack) const {
|
||||
|
||||
/* if variant is Tree - we can serialize it right away */
|
||||
if(variant.getValueType() == oatpp::Tree::Class::getType()) {
|
||||
auto tree = static_cast<const data::mapping::Tree*>(variant.get());
|
||||
writeTree(stream, *tree, errorStack);
|
||||
return;
|
||||
}
|
||||
|
||||
data::mapping::Tree tree;
|
||||
data::mapping::ObjectToTreeMapper::State state;
|
||||
|
||||
state.config = &m_serializerConfig.mapper;
|
||||
state.tree = &tree;
|
||||
|
||||
m_objectToTreeMapper.map(state, variant);
|
||||
if(!state.errorStack.empty()) {
|
||||
errorStack = std::move(state.errorStack);
|
||||
return;
|
||||
}
|
||||
|
||||
writeTree(stream, tree, errorStack);
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void ObjectMapper::read(utils::parser::Caret& caret, const data::type::Type* type, data::mapping::ErrorStack& errorStack) const {
|
||||
@ -64,7 +73,7 @@ oatpp::Void ObjectMapper::read(utils::parser::Caret& caret, const data::type::Ty
|
||||
data::mapping::Tree tree;
|
||||
|
||||
{
|
||||
Deserializer::MappingState state;
|
||||
Deserializer::State state;
|
||||
state.caret = ⁁
|
||||
state.tree = &tree;
|
||||
state.config = &m_deserializerConfig.json;
|
||||
@ -75,8 +84,13 @@ oatpp::Void ObjectMapper::read(utils::parser::Caret& caret, const data::type::Ty
|
||||
}
|
||||
}
|
||||
|
||||
/* if expected type is Tree (root element is Tree) - then we can just move deserialized tree */
|
||||
if(type == data::type::Tree::Class::getType()) {
|
||||
return oatpp::Tree(std::make_shared<data::mapping::Tree>(std::move(tree)));
|
||||
}
|
||||
|
||||
{
|
||||
data::mapping::TreeToObjectMapper::MappingState state;
|
||||
data::mapping::TreeToObjectMapper::State state;
|
||||
state.tree = &tree;
|
||||
state.config = &m_deserializerConfig.mapper;
|
||||
const auto & result = m_treeToObjectMapper.map(state, type);
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
Serializer::Config json;
|
||||
};
|
||||
|
||||
private:
|
||||
void writeTree(data::stream::ConsistentOutputStream* stream, const data::mapping::Tree& tree, data::mapping::ErrorStack& errorStack) const;
|
||||
private:
|
||||
SerializerConfig m_serializerConfig;
|
||||
DeserializerConfig m_deserializerConfig;
|
||||
|
@ -37,20 +37,20 @@ void Serializer::serializeString(data::stream::ConsistentOutputStream* stream, c
|
||||
stream->writeCharSimple('\"');
|
||||
}
|
||||
|
||||
void Serializer::serializeNull(MappingState& state) {
|
||||
void Serializer::serializeNull(State& state) {
|
||||
state.stream->writeSimple("null");
|
||||
}
|
||||
|
||||
void Serializer::serializeString(MappingState& state) {
|
||||
void Serializer::serializeString(State& state) {
|
||||
const auto& str = state.tree->getString();
|
||||
serializeString(state.stream, str->data(), static_cast<v_buff_size>(str->size()), state.config->escapeFlags);
|
||||
}
|
||||
|
||||
void Serializer::serializeArray(MappingState& state) {
|
||||
void Serializer::serializeArray(State& state) {
|
||||
|
||||
state.stream->writeCharSimple('[');
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.stream = state.stream;
|
||||
nestedState.config = state.config;
|
||||
|
||||
@ -82,11 +82,11 @@ void Serializer::serializeArray(MappingState& state) {
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeMap(MappingState& state) {
|
||||
void Serializer::serializeMap(State& state) {
|
||||
|
||||
state.stream->writeCharSimple('{');
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.stream = state.stream;
|
||||
nestedState.config = state.config;
|
||||
|
||||
@ -122,11 +122,11 @@ void Serializer::serializeMap(MappingState& state) {
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializePairs(MappingState& state) {
|
||||
void Serializer::serializePairs(State& state) {
|
||||
|
||||
state.stream->writeCharSimple('{');
|
||||
|
||||
MappingState nestedState;
|
||||
State nestedState;
|
||||
nestedState.stream = state.stream;
|
||||
nestedState.config = state.config;
|
||||
|
||||
@ -162,11 +162,14 @@ void Serializer::serializePairs(MappingState& state) {
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serialize(MappingState& state) {
|
||||
void Serializer::serialize(State& state) {
|
||||
|
||||
switch (state.tree->getType()) {
|
||||
|
||||
case data::mapping::Tree::Type::UNDEFINED: break;
|
||||
case data::mapping::Tree::Type::UNDEFINED:
|
||||
state.errorStack.push("[oatpp::json::Serializer::serialize()]: "
|
||||
"UNDEFINED tree node is NOT serializable. To fix: set node value.");
|
||||
return;
|
||||
case data::mapping::Tree::Type::NULL_VALUE: serializeNull(state); return;
|
||||
|
||||
case data::mapping::Tree::Type::INTEGER: state.stream->writeAsString(state.tree->getInteger()); return;
|
||||
@ -200,13 +203,13 @@ void Serializer::serialize(MappingState& state) {
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeToStream(data::stream::ConsistentOutputStream* stream, MappingState& state) {
|
||||
void Serializer::serializeToStream(data::stream::ConsistentOutputStream* stream, State& state) {
|
||||
|
||||
if(state.config->useBeautifier) {
|
||||
|
||||
json::Beautifier beautifier(stream, " ", "\n");
|
||||
|
||||
MappingState beautifulState;
|
||||
State beautifulState;
|
||||
beautifulState.stream = &beautifier;
|
||||
beautifulState.tree = state.tree;
|
||||
beautifulState.config = state.config;
|
||||
|
@ -77,7 +77,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
struct MappingState {
|
||||
struct State {
|
||||
|
||||
const Config* config;
|
||||
const data::mapping::Tree* tree;
|
||||
@ -95,17 +95,17 @@ private:
|
||||
v_buff_size size,
|
||||
v_uint32 escapeFlags);
|
||||
|
||||
static void serializeNull(MappingState& state);
|
||||
static void serializeString(MappingState& state);
|
||||
static void serializeArray(MappingState& state);
|
||||
static void serializeMap(MappingState& state);
|
||||
static void serializePairs(MappingState& state);
|
||||
static void serializeNull(State& state);
|
||||
static void serializeString(State& state);
|
||||
static void serializeArray(State& state);
|
||||
static void serializeMap(State& state);
|
||||
static void serializePairs(State& state);
|
||||
|
||||
static void serialize(MappingState& state);
|
||||
static void serialize(State& state);
|
||||
|
||||
public:
|
||||
|
||||
static void serializeToStream(data::stream::ConsistentOutputStream* stream, MappingState& state);
|
||||
static void serializeToStream(data::stream::ConsistentOutputStream* stream, State& state);
|
||||
|
||||
};
|
||||
|
||||
|
@ -80,172 +80,174 @@ namespace {
|
||||
void runTests() {
|
||||
|
||||
|
||||
oatpp::Environment::printCompilationConfig();
|
||||
|
||||
OATPP_LOGD("Tests", "oatpp::String size=%lu", sizeof(oatpp::String))
|
||||
OATPP_LOGD("Tests", "std::string size=%lu", sizeof(std::string))
|
||||
OATPP_LOGD("Tests", "Vector size=%lu", sizeof(std::vector<int>))
|
||||
OATPP_LOGD("Tests", "Map size=%lu", sizeof(std::unordered_map<oatpp::String, oatpp::String>))
|
||||
OATPP_LOGD("Tests", "Tree size=%lu", sizeof(oatpp::data::mapping::Tree))
|
||||
|
||||
//return;
|
||||
|
||||
|
||||
OATPP_LOGD("Tests", "coroutine handle size=%lu", sizeof(oatpp::async::CoroutineHandle))
|
||||
OATPP_LOGD("Tests", "coroutine size=%lu", sizeof(oatpp::async::AbstractCoroutine))
|
||||
OATPP_LOGD("Tests", "action size=%lu", sizeof(oatpp::async::Action))
|
||||
OATPP_LOGD("Tests", "class count=%d", oatpp::data::type::ClassId::getClassCount())
|
||||
|
||||
auto names = oatpp::data::type::ClassId::getRegisteredClassNames();
|
||||
v_int32 i = 0;
|
||||
for(auto& name : names) {
|
||||
OATPP_LOGD("CLASS", "%d --> '%s'", i, name)
|
||||
i ++;
|
||||
}
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::LoggerTest);
|
||||
OATPP_RUN_TEST(oatpp::base::CommandLineArgumentsTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::share::MemoryLabelTest);
|
||||
OATPP_RUN_TEST(oatpp::data::share::LazyStringMapTest);
|
||||
OATPP_RUN_TEST(oatpp::data::share::StringTemplateTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::buffer::ProcessorTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::stream::BufferStreamTest);
|
||||
|
||||
// oatpp::Environment::printCompilationConfig();
|
||||
//
|
||||
// OATPP_LOGD("Tests", "oatpp::String size=%lu", sizeof(oatpp::String))
|
||||
// OATPP_LOGD("Tests", "std::string size=%lu", sizeof(std::string))
|
||||
// OATPP_LOGD("Tests", "Vector size=%lu", sizeof(std::vector<int>))
|
||||
// OATPP_LOGD("Tests", "Map size=%lu", sizeof(std::unordered_map<oatpp::String, oatpp::String>))
|
||||
// OATPP_LOGD("Tests", "Tree size=%lu", sizeof(oatpp::data::mapping::Tree))
|
||||
//
|
||||
// //return;
|
||||
//
|
||||
//
|
||||
// OATPP_LOGD("Tests", "coroutine handle size=%lu", sizeof(oatpp::async::CoroutineHandle))
|
||||
// OATPP_LOGD("Tests", "coroutine size=%lu", sizeof(oatpp::async::AbstractCoroutine))
|
||||
// OATPP_LOGD("Tests", "action size=%lu", sizeof(oatpp::async::Action))
|
||||
// OATPP_LOGD("Tests", "class count=%d", oatpp::data::type::ClassId::getClassCount())
|
||||
//
|
||||
// auto names = oatpp::data::type::ClassId::getRegisteredClassNames();
|
||||
// v_int32 i = 0;
|
||||
// for(auto& name : names) {
|
||||
// OATPP_LOGD("CLASS", "%d --> '%s'", i, name)
|
||||
// i ++;
|
||||
// }
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::test::LoggerTest);
|
||||
// OATPP_RUN_TEST(oatpp::base::CommandLineArgumentsTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::share::MemoryLabelTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::share::LazyStringMapTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::share::StringTemplateTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::buffer::ProcessorTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::stream::BufferStreamTest);
|
||||
//
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::mapping::TreeTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::mapping::TreeToObjectMapperTest);
|
||||
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::type::ObjectWrapperTest);
|
||||
OATPP_RUN_TEST(oatpp::data::type::TypeTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::type::StringTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::type::PrimitiveTest);
|
||||
OATPP_RUN_TEST(oatpp::data::type::ListTest);
|
||||
OATPP_RUN_TEST(oatpp::data::type::VectorTest);
|
||||
OATPP_RUN_TEST(oatpp::data::type::UnorderedSetTest);
|
||||
OATPP_RUN_TEST(oatpp::data::type::PairListTest);
|
||||
OATPP_RUN_TEST(oatpp::data::type::UnorderedMapTest);
|
||||
OATPP_RUN_TEST(oatpp::data::type::AnyTest);
|
||||
OATPP_RUN_TEST(oatpp::data::type::EnumTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::type::ObjectTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::type::InterpretationTest);
|
||||
OATPP_RUN_TEST(oatpp::data::mapping::TypeResolverTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::data::resource::InMemoryDataTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::async::ConditionVariableTest);
|
||||
OATPP_RUN_TEST(oatpp::async::LockTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::utils::parser::CaretTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::provider::PoolTest);
|
||||
OATPP_RUN_TEST(oatpp::provider::PoolTemplateTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::json::EnumTest);
|
||||
OATPP_RUN_TEST(oatpp::json::BooleanTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::json::UnorderedSetTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::json::DeserializerTest);
|
||||
|
||||
//
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::type::ObjectWrapperTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::type::TypeTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::type::StringTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::type::PrimitiveTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::type::ListTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::type::VectorTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::type::UnorderedSetTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::type::PairListTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::type::UnorderedMapTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::type::AnyTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::type::EnumTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::type::ObjectTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::type::InterpretationTest);
|
||||
// OATPP_RUN_TEST(oatpp::data::mapping::TypeResolverTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::data::resource::InMemoryDataTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::async::ConditionVariableTest);
|
||||
// OATPP_RUN_TEST(oatpp::async::LockTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::utils::parser::CaretTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::provider::PoolTest);
|
||||
// OATPP_RUN_TEST(oatpp::provider::PoolTemplateTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::json::EnumTest);
|
||||
// OATPP_RUN_TEST(oatpp::json::BooleanTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::json::UnorderedSetTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::json::DeserializerTest);
|
||||
//
|
||||
OATPP_RUN_TEST(oatpp::json::DTOMapperPerfTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::json::DTOMapperTest);
|
||||
OATPP_RUN_TEST(oatpp::test::encoding::Base64Test);
|
||||
OATPP_RUN_TEST(oatpp::test::encoding::UnicodeTest);
|
||||
OATPP_RUN_TEST(oatpp::test::encoding::UrlTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::network::UrlTest);
|
||||
OATPP_RUN_TEST(oatpp::test::network::ConnectionPoolTest);
|
||||
OATPP_RUN_TEST(oatpp::test::network::monitor::ConnectionMonitorTest);
|
||||
OATPP_RUN_TEST(oatpp::test::network::virtual_::PipeTest);
|
||||
OATPP_RUN_TEST(oatpp::test::network::virtual_::InterfaceTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::web::protocol::http::encoding::ChunkedTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::web::mime::multipart::StatefulParserTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::web::server::HttpRouterTest);
|
||||
OATPP_RUN_TEST(oatpp::test::web::server::api::ApiControllerTest);
|
||||
OATPP_RUN_TEST(oatpp::test::web::server::handler::AuthorizationHandlerTest);
|
||||
|
||||
{
|
||||
|
||||
oatpp::test::web::server::ServerStopTest test_virtual(0);
|
||||
test_virtual.run();
|
||||
|
||||
oatpp::test::web::server::ServerStopTest test_port(8000);
|
||||
test_port.run();
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
oatpp::test::web::PipelineTest test_virtual(0, 3000);
|
||||
test_virtual.run();
|
||||
|
||||
oatpp::test::web::PipelineTest test_port(8000, 3000);
|
||||
test_port.run();
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
oatpp::test::web::PipelineAsyncTest test_virtual(0, 3000);
|
||||
test_virtual.run();
|
||||
|
||||
oatpp::test::web::PipelineAsyncTest test_port(8000, 3000);
|
||||
test_port.run();
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
oatpp::test::web::FullTest test_virtual(0, 1000);
|
||||
test_virtual.run();
|
||||
|
||||
oatpp::test::web::FullTest test_port(8000, 5);
|
||||
test_port.run();
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
oatpp::test::web::FullAsyncTest test_virtual(0, 1000);
|
||||
test_virtual.run();
|
||||
|
||||
oatpp::test::web::FullAsyncTest test_port(8000, 5);
|
||||
test_port.run();
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
oatpp::test::web::FullAsyncClientTest test_virtual(0, 1000);
|
||||
test_virtual.run(20);
|
||||
|
||||
oatpp::test::web::FullAsyncClientTest test_port(8000, 5);
|
||||
test_port.run(1);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
oatpp::test::web::ClientRetryTest test_virtual(0);
|
||||
test_virtual.run();
|
||||
|
||||
oatpp::test::web::ClientRetryTest test_port(8000);
|
||||
test_port.run();
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::json::DTOMapperTest);
|
||||
// OATPP_RUN_TEST(oatpp::test::encoding::Base64Test);
|
||||
// OATPP_RUN_TEST(oatpp::test::encoding::UnicodeTest);
|
||||
// OATPP_RUN_TEST(oatpp::test::encoding::UrlTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::test::network::UrlTest);
|
||||
// OATPP_RUN_TEST(oatpp::test::network::ConnectionPoolTest);
|
||||
// OATPP_RUN_TEST(oatpp::test::network::monitor::ConnectionMonitorTest);
|
||||
// OATPP_RUN_TEST(oatpp::test::network::virtual_::PipeTest);
|
||||
// OATPP_RUN_TEST(oatpp::test::network::virtual_::InterfaceTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::test::web::protocol::http::encoding::ChunkedTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::test::web::mime::multipart::StatefulParserTest);
|
||||
//
|
||||
// OATPP_RUN_TEST(oatpp::test::web::server::HttpRouterTest);
|
||||
// OATPP_RUN_TEST(oatpp::test::web::server::api::ApiControllerTest);
|
||||
// OATPP_RUN_TEST(oatpp::test::web::server::handler::AuthorizationHandlerTest);
|
||||
//
|
||||
// {
|
||||
//
|
||||
// oatpp::test::web::server::ServerStopTest test_virtual(0);
|
||||
// test_virtual.run();
|
||||
//
|
||||
// oatpp::test::web::server::ServerStopTest test_port(8000);
|
||||
// test_port.run();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// {
|
||||
//
|
||||
// oatpp::test::web::PipelineTest test_virtual(0, 3000);
|
||||
// test_virtual.run();
|
||||
//
|
||||
// oatpp::test::web::PipelineTest test_port(8000, 3000);
|
||||
// test_port.run();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// {
|
||||
//
|
||||
// oatpp::test::web::PipelineAsyncTest test_virtual(0, 3000);
|
||||
// test_virtual.run();
|
||||
//
|
||||
// oatpp::test::web::PipelineAsyncTest test_port(8000, 3000);
|
||||
// test_port.run();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// {
|
||||
//
|
||||
// oatpp::test::web::FullTest test_virtual(0, 1000);
|
||||
// test_virtual.run();
|
||||
//
|
||||
// oatpp::test::web::FullTest test_port(8000, 5);
|
||||
// test_port.run();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// {
|
||||
//
|
||||
// oatpp::test::web::FullAsyncTest test_virtual(0, 1000);
|
||||
// test_virtual.run();
|
||||
//
|
||||
// oatpp::test::web::FullAsyncTest test_port(8000, 5);
|
||||
// test_port.run();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// {
|
||||
//
|
||||
// oatpp::test::web::FullAsyncClientTest test_virtual(0, 1000);
|
||||
// test_virtual.run(20);
|
||||
//
|
||||
// oatpp::test::web::FullAsyncClientTest test_port(8000, 5);
|
||||
// test_port.run(1);
|
||||
//
|
||||
// }
|
||||
//
|
||||
// {
|
||||
//
|
||||
// oatpp::test::web::ClientRetryTest test_virtual(0);
|
||||
// test_virtual.run();
|
||||
//
|
||||
// oatpp::test::web::ClientRetryTest test_port(8000);
|
||||
// test_port.run();
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
||||
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ void TreeToObjectMapperTest::onRun() {
|
||||
tree["map"]["nested_2"]["i32"] = 2;
|
||||
tree["map"]["nested_3"]["i32"] = 3;
|
||||
|
||||
TreeToObjectMapper::MappingState state;
|
||||
TreeToObjectMapper::State state;
|
||||
state.config = &config;
|
||||
state.tree = &tree;
|
||||
|
||||
@ -116,7 +116,7 @@ void TreeToObjectMapperTest::onRun() {
|
||||
|
||||
Tree clonedTree;
|
||||
|
||||
ObjectToTreeMapper::MappingState reverseState;
|
||||
ObjectToTreeMapper::State reverseState;
|
||||
reverseState.config = &reverseConfig;
|
||||
reverseState.tree = &clonedTree;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user