2
0
mirror of https://github.com/oatpp/oatpp.git synced 2025-04-12 18:50:22 +08:00

data::Tree: map both ordered and random-accessed. dynamic casting

This commit is contained in:
Leonid Stryzhevskyi 2024-04-26 06:33:14 +03:00
parent 5461fb2f08
commit 4a7795c221
3 changed files with 510 additions and 182 deletions
src/oatpp/data
test/oatpp/data

@ -26,43 +26,83 @@
namespace oatpp { namespace data {
Tree::Node::Node()
: m_type(Type::NULL_VALUE)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Tree::Map
Tree& Tree::Map::operator [] (const oatpp::String& key) {
auto it = m_map.find(key);
if(it == m_map.end()) {
auto& result = m_map[key];
m_order.push_back(key);
return result;
}
return it->second;
}
const Tree& Tree::Map::operator [] (const oatpp::String& key) const {
auto it = m_map.find(key);
if(it == m_map.end()) {
throw std::runtime_error("[oatpp::data::Tree::Map::operator[]]: const operator[] can't add items.");
}
return it->second;
}
std::pair<oatpp::String, std::reference_wrapper<Tree>> Tree::Map::operator [] (v_uint64 index) {
auto& key = m_order.at(index);
return {key, m_map[key]};
}
std::pair<oatpp::String, std::reference_wrapper<const Tree>> Tree::Map::operator [] (v_uint64 index) const {
auto& key = m_order.at(index);
return {key, m_map.at(key)};
}
v_uint64 Tree::Map::size() const {
return m_map.size();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Tree
Tree::Tree()
: m_type(Type::UNDEFINED)
, m_data(0)
{}
Tree::Node::Node(const Node& other)
: Node()
Tree::Tree(const Tree& other)
: Tree()
{
setCopy(other);
}
Tree::Node::Node(Node&& other) noexcept
Tree::Tree(Tree&& other) noexcept
: m_type(other.m_type)
, m_data(other.m_data)
{
other.m_type = Type::NULL_VALUE;
other.m_type = Type::UNDEFINED;
other.m_data = 0;
}
Tree::Node::~Node() {
Tree::~Tree() {
deleteValueObject();
}
Tree::Node& Tree::Node::operator = (const Node& other) {
Tree& Tree::operator = (const Tree& other) {
setCopy(other);
return *this;
}
Tree::Node& Tree::Node::operator = (Node&& other) noexcept {
setMove(std::forward<Node>(other));
Tree& Tree::operator = (Tree&& other) noexcept {
setMove(std::forward<Tree>(other));
return *this;
}
void Tree::Node::deleteValueObject() {
void Tree::deleteValueObject() {
switch (m_type) {
case Type::UNDEFINED:
case Type::NULL_VALUE:
case Type::INTEGER:
@ -89,12 +129,12 @@ void Tree::Node::deleteValueObject() {
break;
}
case Type::VECTOR: {
auto data = reinterpret_cast<std::vector<Node> *>(m_data);
auto data = reinterpret_cast<std::vector<Tree> *>(m_data);
delete data;
break;
}
case Type::MAP: {
auto data = reinterpret_cast<std::vector<std::pair<oatpp::String, Node>> *>(m_data);
auto data = reinterpret_cast<Map *>(m_data);
delete data;
break;
}
@ -106,17 +146,38 @@ void Tree::Node::deleteValueObject() {
}
}
Tree::Node::Type Tree::Node::getType() const {
Tree::operator oatpp::String () {
return getString();
}
Tree& Tree::operator [] (const oatpp::String& key) {
return getMap()[key];
}
const Tree& Tree::operator [] (const oatpp::String& key) const {
return getMap()[key];
}
Tree& Tree::operator [] (v_uint64 index) {
return getVector().at(index);
}
const Tree& Tree::operator [] (v_uint64 index) const {
return getVector().at(index);
}
Tree::Type Tree::getType() const {
return m_type;
}
void Tree::Node::setCopy(const Node& other) {
void Tree::setCopy(const Tree& other) {
deleteValueObject();
m_type = other.m_type;
switch (other.m_type) {
case Type::UNDEFINED:
case Type::NULL_VALUE:
break;
@ -142,27 +203,27 @@ void Tree::Node::setCopy(const Node& other) {
case Type::STRING: {
auto otherData = reinterpret_cast<oatpp::String *>(other.m_data);
if(otherData == nullptr) {
throw std::runtime_error("[oatpp::data::Tree::Node::setCopy()]: other.data is null, other.type is 'STRING'");
throw std::runtime_error("[oatpp::data::Tree::setCopy()]: other.data is null, other.type is 'STRING'");
}
auto ptr = new oatpp::String(*otherData);
m_data = reinterpret_cast<LARGEST_TYPE>(ptr);
break;
}
case Type::VECTOR: {
auto otherData = reinterpret_cast<std::vector<Node> *>(other.m_data);
auto otherData = reinterpret_cast<std::vector<Tree> *>(other.m_data);
if(otherData == nullptr) {
throw std::runtime_error("[oatpp::data::Tree::Node::setCopy()]: other.data is null, other.type is 'VECTOR'");
throw std::runtime_error("[oatpp::data::Tree::setCopy()]: other.data is null, other.type is 'VECTOR'");
}
auto ptr = new std::vector<Node>(*otherData);
auto ptr = new std::vector<Tree>(*otherData);
m_data = reinterpret_cast<LARGEST_TYPE>(ptr);
break;
}
case Type::MAP: {
auto otherData = reinterpret_cast<std::vector<std::pair<oatpp::String, Node>> *>(other.m_data);
auto otherData = reinterpret_cast<Map *>(other.m_data);
if(otherData == nullptr) {
throw std::runtime_error("[oatpp::data::Tree::Node::setCopy()]: other.data is null, other.type is 'MAP'");
throw std::runtime_error("[oatpp::data::Tree::setCopy()]: other.data is null, other.type is 'MAP'");
}
auto ptr = new std::vector<std::pair<oatpp::String, Node>>(*otherData);
auto ptr = new Map(*otherData);
m_data = reinterpret_cast<LARGEST_TYPE>(ptr);
break;
}
@ -175,7 +236,7 @@ void Tree::Node::setCopy(const Node& other) {
}
void Tree::Node::setMove(Node&& other) {
void Tree::setMove(Tree&& other) {
deleteValueObject();
m_type = other.m_type;
m_data = other.m_data;
@ -183,104 +244,254 @@ void Tree::Node::setMove(Node&& other) {
other.m_data = 0;
}
void Tree::Node::setNull() {
void Tree::setNull() {
deleteValueObject();
m_type = Type::NULL_VALUE;
m_data = 0;
}
void Tree::Node::setInteger(v_int64 value) {
void Tree::setUndefined() {
deleteValueObject();
m_type = Type::UNDEFINED;
m_data = 0;
}
void Tree::setInteger(v_int64 value) {
deleteValueObject();
m_type = Type::INTEGER;
std::memcpy (&m_data, &value, sizeof(v_int64));
}
void Tree::Node::setFloat(v_float64 value) {
void Tree::setFloat(v_float64 value) {
deleteValueObject();
m_type = Type::FLOAT;
std::memcpy (&m_data, &value, sizeof(v_float64));
}
void Tree::Node::setString(const oatpp::String& value) {
void Tree::setString(const oatpp::String& value) {
deleteValueObject();
m_type = Type::STRING;
auto data = new oatpp::String(value);
m_data = reinterpret_cast<LARGEST_TYPE>(data);
}
void Tree::Node::setVector(const std::vector<Node>& value) {
void Tree::setVector(const std::vector<Tree>& value) {
deleteValueObject();
m_type = Type::VECTOR;
auto data = new std::vector<Node>(value);
auto data = new std::vector<Tree>(value);
m_data = reinterpret_cast<LARGEST_TYPE>(data);
}
void Tree::Node::setMap(const std::vector<std::pair<oatpp::String, Node>>& value) {
void Tree::setVector(v_uint64 size) {
deleteValueObject();
m_type = Type::VECTOR;
auto data = new std::vector<Tree>(size);
m_data = reinterpret_cast<LARGEST_TYPE>(data);
}
void Tree::setMap(const Map& value) {
deleteValueObject();
m_type = Type::MAP;
auto data = new std::vector<std::pair<oatpp::String, Node>>(value);
auto data = new Map(value);
m_data = reinterpret_cast<LARGEST_TYPE>(data);
}
bool Tree::Node::isNull() const {
bool Tree::isNull() const {
return m_type == Type::NULL_VALUE;
}
v_int64 Tree::Node::getInteger() const {
bool Tree::isUndefined() const {
return m_type == Type::UNDEFINED;
}
bool Tree::isPrimitive() const {
switch (m_type) {
case Type::UNDEFINED:
case Type::NULL_VALUE:
return false;
case Type::INTEGER:
case Type::FLOAT:
case Type::BOOL:
case Type::INT_8:
case Type::UINT_8:
case Type::INT_16:
case Type::UINT_16:
case Type::INT_32:
case Type::UINT_32:
case Type::INT_64:
case Type::UINT_64:
case Type::FLOAT_32:
case Type::FLOAT_64:
return true;
case Type::STRING:
case Type::VECTOR:
case Type::MAP:
default:
return false;
}
}
v_int32 Tree::primitiveDataSize() const {
switch (m_type) {
case Type::UNDEFINED:
case Type::NULL_VALUE:
return -1;
case Type::INTEGER:
case Type::FLOAT: return 8;
case Type::BOOL:
case Type::INT_8:
case Type::UINT_8: return 1;
case Type::INT_16:
case Type::UINT_16: return 2;
case Type::INT_32:
case Type::UINT_32: return 4;
case Type::INT_64:
case Type::UINT_64: return 8;
case Type::FLOAT_32: return 4;
case Type::FLOAT_64: return 8;
case Type::STRING:
case Type::VECTOR:
case Type::MAP:
default:
return -1;
}
}
bool Tree::isFloatPrimitive() const {
switch (m_type) {
case Type::UNDEFINED:
case Type::NULL_VALUE:
case Type::INTEGER: return false;
case Type::FLOAT: return true;
case Type::BOOL:
case Type::INT_8:
case Type::UINT_8:
case Type::INT_16:
case Type::UINT_16:
case Type::INT_32:
case Type::UINT_32:
case Type::INT_64:
case Type::UINT_64: return false;
case Type::FLOAT_32:
case Type::FLOAT_64: return true;
case Type::STRING:
case Type::VECTOR:
case Type::MAP:
default:
return false;
}
}
bool Tree::isIntPrimitive() const {
switch (m_type) {
case Type::UNDEFINED:
case Type::NULL_VALUE:
return false;
case Type::INTEGER: return true;
case Type::FLOAT: return false;
case Type::BOOL:
case Type::INT_8:
case Type::UINT_8:
case Type::INT_16:
case Type::UINT_16:
case Type::INT_32:
case Type::UINT_32:
case Type::INT_64:
case Type::UINT_64: return true;
case Type::FLOAT_32:
case Type::FLOAT_64:
case Type::STRING:
case Type::VECTOR:
case Type::MAP:
default:
return false;
}
}
v_int64 Tree::getInteger() const {
if(m_type != Type::INTEGER) {
throw std::runtime_error("[oatpp::data::Tree::Node::getInteger()]: NOT an arbitrary INTEGER.");
throw std::runtime_error("[oatpp::data::Tree::getInteger()]: NOT an arbitrary INTEGER.");
}
v_int64 result;
std::memcpy (&result, &m_data, sizeof(v_float64));
return result;
}
v_float64 Tree::Node::getFloat() const {
v_float64 Tree::getFloat() const {
if(m_type != Type::FLOAT) {
throw std::runtime_error("[oatpp::data::Tree::Node::getInteger()]: NOT an arbitrary FLOAT.");
throw std::runtime_error("[oatpp::data::Tree::getFloat()]: NOT an arbitrary FLOAT.");
}
v_float64 result;
std::memcpy (&result, &m_data, sizeof(v_float64));
return result;
}
const oatpp::String& Tree::Node::getString() const {
const oatpp::String& Tree::getString() const {
if(m_type != Type::STRING) {
throw std::runtime_error("[oatpp::data::Tree::Node::getInteger()]: NOT a STRING.");
throw std::runtime_error("[oatpp::data::Tree::getString()]: NOT a STRING.");
}
auto data = reinterpret_cast<const oatpp::String*>(m_data);
return *data;
}
const std::vector<Tree::Node>& Tree::Node::getVector() const {
const std::vector<Tree>& Tree::getVector() const {
if(m_type != Type::VECTOR) {
throw std::runtime_error("[oatpp::data::Tree::Node::getInteger()]: NOT a VECTOR.");
throw std::runtime_error("[oatpp::data::Tree::getVector()]: NOT a VECTOR.");
}
auto data = reinterpret_cast<const std::vector<Tree::Node>*>(m_data);
auto data = reinterpret_cast<const std::vector<Tree>*>(m_data);
return *data;
}
const std::vector<std::pair<oatpp::String, Tree::Node>>& Tree::Node::getMap() const {
const Tree::Map& Tree::getMap() const {
if(m_type != Type::MAP) {
throw std::runtime_error("[oatpp::data::Tree::Node::getInteger()]: NOT a MAP.");
throw std::runtime_error("[oatpp::data::Tree::getMap()]: NOT a MAP.");
}
auto data = reinterpret_cast<const std::vector<std::pair<oatpp::String, Tree::Node>>*>(m_data);
auto data = reinterpret_cast<const Map*>(m_data);
return *data;
}
std::vector<Tree::Node>& Tree::Node::getVector() {
std::vector<Tree>& Tree::getVector() {
if(m_type == Type::UNDEFINED) {
setVector({});
}
if(m_type != Type::VECTOR) {
throw std::runtime_error("[oatpp::data::Tree::Node::getInteger()]: NOT a VECTOR.");
throw std::runtime_error("[oatpp::data::Tree::getVector()]: NOT a VECTOR.");
}
auto data = reinterpret_cast<std::vector<Tree::Node>*>(m_data);
auto data = reinterpret_cast<std::vector<Tree>*>(m_data);
return *data;
}
std::vector<std::pair<oatpp::String, Tree::Node>>& Tree::Node::getMap() {
if(m_type != Type::MAP) {
throw std::runtime_error("[oatpp::data::Tree::Node::getInteger()]: NOT a MAP.");
Tree::Map& Tree::getMap() {
if(m_type == Type::UNDEFINED) {
setMap({});
}
auto data = reinterpret_cast<std::vector<std::pair<oatpp::String, Tree::Node>>*>(m_data);
if(m_type != Type::MAP) {
throw std::runtime_error("[oatpp::data::Tree::getMap()]: NOT a MAP.");
}
auto data = reinterpret_cast<Map*>(m_data);
return *data;
}

@ -32,174 +32,271 @@ namespace oatpp { namespace data {
class Tree {
public:
class Node {
public:
enum class Type : v_int32 {
enum class Type : v_int32 {
UNDEFINED = -1,
NULL_VALUE = 0,
NULL_VALUE = 0,
INTEGER = 1,
FLOAT = 2,
INTEGER = 1,
FLOAT = 2,
BOOL = 3,
BOOL = 3,
INT_8 = 4,
UINT_8 = 5,
INT_16 = 6,
UINT_16 = 7,
INT_32 = 8,
UINT_32 = 9,
INT_64 = 10,
UINT_64 = 11,
INT_8 = 4,
UINT_8 = 5,
INT_16 = 6,
UINT_16 = 7,
INT_32 = 8,
UINT_32 = 9,
INT_64 = 10,
UINT_64 = 11,
FLOAT_32 = 12,
FLOAT_64 = 13,
FLOAT_32 = 12,
FLOAT_64 = 13,
STRING = 14,
STRING = 14,
VECTOR = 15,
MAP = 16
VECTOR = 15,
MAP = 16
};
template<typename T>
struct NodePrimitiveType {
};
private:
typedef v_uint64 LARGEST_TYPE;
private:
void deleteValueObject();
private:
Type m_type;
LARGEST_TYPE m_data;
public:
Node();
Node(const Node& other);
Node(Node&& other) noexcept;
~Node();
Node& operator = (const Node& other);
Node& operator = (Node&& other) noexcept;
Type getType() const;
void setCopy(const Node& other);
void setMove(Node&& other);
template <typename T>
void setValue(T value) {
deleteValueObject();
m_type = NodePrimitiveType<T>::type;
m_data = 0;
std::memcpy (&m_data, &value, sizeof(T));
}
template<typename T>
T getValue() const {
if(m_type != NodePrimitiveType<T>::type) {
throw std::runtime_error(std::string("[oatpp::data::Tree::Node::getValue()]: NOT a ") + NodePrimitiveType<T>::name);
}
T result;
std::memcpy (&result, &m_data, sizeof(T));
return result;
}
void setNull();
void setInteger(v_int64 value);
void setFloat(v_float64 value);
void setString(const oatpp::String& value);
void setVector(const std::vector<Node>& value);
void setMap(const std::vector<std::pair<oatpp::String, Node>>& value);
bool isNull() const;
v_int64 getInteger() const;
v_float64 getFloat() const;
const oatpp::String& getString() const;
const std::vector<Node>& getVector() const;
const std::vector<std::pair<oatpp::String, Node>>& getMap() const;
std::vector<Node>& getVector();
std::vector<std::pair<oatpp::String, Node>>& getMap();
};
template<typename T>
struct NodePrimitiveType {
};
public:
class Map {
private:
std::unordered_map<oatpp::String, Tree> m_map;
std::vector<oatpp::String> m_order;
public:
Tree& operator [] (const oatpp::String& key);
const Tree& operator [] (const oatpp::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;
v_uint64 size() const;
};
private:
typedef v_uint64 LARGEST_TYPE;
private:
void deleteValueObject();
private:
Type m_type;
LARGEST_TYPE m_data;
public:
Tree();
Tree(const Tree& other);
Tree(Tree&& other) noexcept;
template<typename T, typename enabled = typename NodePrimitiveType<T>::value_type>
explicit Tree (T value)
: Tree()
{
setValue<T>(value);
}
explicit Tree(const oatpp::String& value)
: Tree()
{
setString(value);
}
~Tree();
Tree& operator = (const Tree& other);
Tree& operator = (Tree&& other) noexcept;
template<typename T, typename enabled = typename NodePrimitiveType<T>::value_type>
Tree& operator = (T value) {
setValue<T>(value);
return *this;
}
Tree& operator = (const oatpp::String& value) {
setString(value);
return *this;
}
template <typename T, typename enabled = typename NodePrimitiveType<T>::value_type>
operator T () const {
auto size = primitiveDataSize();
if(size < 0) {
throw std::runtime_error("[oatpp::data::Tree::operator T ()]: Value NOT a Primitive type.");
}
if(isIntPrimitive()) {
LARGEST_TYPE value = 0;
std::memcpy (&value, &m_data, static_cast<size_t>(size));
return static_cast<T>(value);
}
if(isFloatPrimitive()) {
if(size == 4) {
v_float32 value;
std::memcpy (&value, &m_data, static_cast<size_t>(size));
return static_cast<T>(value);
} else if(size == 8) {
v_float64 value;
std::memcpy (&value, &m_data, static_cast<size_t>(size));
return static_cast<T>(value);
}
}
throw std::runtime_error("[oatpp::data::Tree::operator T ()]: Unable to autocast.");
}
operator oatpp::String ();
Tree& operator [] (const oatpp::String& key);
const Tree& operator [] (const oatpp::String& key) const;
Tree& operator [] (v_uint64 index);
const Tree& operator [] (v_uint64 index) const;
Type getType() const;
void setCopy(const Tree& other);
void setMove(Tree&& other);
template <typename T>
void setValue(T value) {
deleteValueObject();
m_type = NodePrimitiveType<T>::type;
m_data = 0;
std::memcpy (&m_data, &value, sizeof(T));
}
template<typename T>
T getValue() const {
if(m_type != NodePrimitiveType<T>::type) {
throw std::runtime_error(std::string("[oatpp::data::Tree::getValue()]: NOT a ") + NodePrimitiveType<T>::name);
}
T result;
std::memcpy (&result, &m_data, sizeof(T));
return result;
}
void setNull();
void setUndefined();
void setInteger(v_int64 value);
void setFloat(v_float64 value);
void setString(const oatpp::String& value);
void setVector(const std::vector<Tree>& value);
void setVector(v_uint64 size);
void setMap(const Map& value);
bool isNull() const;
bool isUndefined() const;
bool isPrimitive() const;
v_int32 primitiveDataSize() const;
bool isFloatPrimitive() const;
bool isIntPrimitive() const;
v_int64 getInteger() const;
v_float64 getFloat() const;
const oatpp::String& getString() const;
const std::vector<Tree>& getVector() const;
const Map& getMap() const;
std::vector<Tree>& getVector();
Map& getMap();
};
//////////////////////////////////////////////////////
// Tree::NodePrimitiveType
template<>
struct Tree::Node::NodePrimitiveType<bool> {
struct Tree::NodePrimitiveType<bool> {
static constexpr Type type = Type::BOOL;
static constexpr const char* name = "BOOL";
typedef bool value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_int8> {
struct Tree::NodePrimitiveType<v_int8> {
static constexpr Type type = Type::INT_8;
static constexpr const char* name = "INT_8";
typedef v_int8 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_uint8> {
struct Tree::NodePrimitiveType<v_uint8> {
static constexpr Type type = Type::UINT_8;
static constexpr const char* name = "UINT_8";
typedef v_uint8 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_int16> {
struct Tree::NodePrimitiveType<v_int16> {
static constexpr Type type = Type::INT_16;
static constexpr const char* name = "INT_16";
typedef v_int16 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_uint16> {
struct Tree::NodePrimitiveType<v_uint16> {
static constexpr Type type = Type::UINT_16;
static constexpr const char* name = "UINT_16";
typedef v_uint16 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_int32> {
struct Tree::NodePrimitiveType<v_int32> {
static constexpr Type type = Type::INT_32;
static constexpr const char* name = "INT_32";
typedef v_int32 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_uint32> {
struct Tree::NodePrimitiveType<v_uint32> {
static constexpr Type type = Type::UINT_32;
static constexpr const char* name = "UINT_32";
typedef v_uint32 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_int64> {
struct Tree::NodePrimitiveType<v_int64> {
static constexpr Type type = Type::INT_64;
static constexpr const char* name = "INT_64";
typedef v_int64 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_uint64> {
struct Tree::NodePrimitiveType<v_uint64> {
static constexpr Type type = Type::UINT_64;
static constexpr const char* name = "UINT_64";
typedef v_uint64 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_float32> {
struct Tree::NodePrimitiveType<v_float32> {
static constexpr Type type = Type::FLOAT_32;
static constexpr const char* name = "FLOAT_32";
typedef v_float32 value_type;
};
template<>
struct Tree::Node::NodePrimitiveType<v_float64> {
struct Tree::NodePrimitiveType<v_float64> {
static constexpr Type type = Type::FLOAT_64;
static constexpr const char* name = "FLOAT_64";
typedef v_float64 value_type;
};
}}

@ -34,11 +34,12 @@ namespace oatpp { namespace data {
namespace {
template<typename T>
void testNodeValue(T value) {
void testTreeValue(T value) {
Tree::Node node;
Tree node;
node.setValue<T>(value);
//node.setValue<T>(value);
node = value;
auto v = node.getValue<T>();
OATPP_ASSERT(v == value && "value check")
@ -56,20 +57,20 @@ void testNodeValue(T value) {
void TreeTest::onRun() {
testNodeValue<bool>(true);
testNodeValue<v_int8>(16);
testNodeValue<v_uint8>(16);
testNodeValue<v_int16>(16);
testNodeValue<v_uint16>(16);
testNodeValue<v_int32>(16);
testNodeValue<v_uint32>(16);
testNodeValue<v_int64>(16);
testNodeValue<v_uint64>(16);
testNodeValue<v_float32>(16);
testNodeValue<v_float64>(16);
testTreeValue<bool>(true);
testTreeValue<v_int8>(16);
testTreeValue<v_uint8>(16);
testTreeValue<v_int16>(16);
testTreeValue<v_uint16>(16);
testTreeValue<v_int32>(16);
testTreeValue<v_uint32>(16);
testTreeValue<v_int64>(16);
testTreeValue<v_uint64>(16);
testTreeValue<v_float32>(16);
testTreeValue<v_float64>(16);
{
Tree::Node node;
Tree node;
oatpp::String original = "Hello World!";
node.setString(original);
auto stored = node.getString();
@ -78,38 +79,38 @@ void TreeTest::onRun() {
}
{
Tree::Node node1;
Tree::Node node2;
Tree node1;
Tree node2;
node1.setString("Hello World!");
node2 = node1;
OATPP_ASSERT(node1.getString() == "Hello World!")
OATPP_ASSERT(node1.getType() == Tree::Node::Type::STRING)
OATPP_ASSERT(node1.getType() == Tree::Type::STRING)
OATPP_ASSERT(node2.getString() == "Hello World!")
OATPP_ASSERT(node2.getType() == Tree::Node::Type::STRING)
OATPP_ASSERT(node2.getType() == Tree::Type::STRING)
}
{
Tree::Node node1;
Tree::Node node2;
Tree node1;
Tree node2;
node1.setString("Hello World!");
node2 = std::move(node1);
OATPP_ASSERT(node1.isNull())
OATPP_ASSERT(node2.getString() == "Hello World!")
OATPP_ASSERT(node2.getType() == Tree::Node::Type::STRING)
OATPP_ASSERT(node2.getType() == Tree::Type::STRING)
}
{
std::vector<Tree::Node> originalVector(10);
std::vector<Tree> originalVector(10);
for(v_uint32 i = 0; i < 10; i ++) {
originalVector.at(i).setValue(i);
}
Tree::Node node;
Tree node;
node.setVector(originalVector);
auto& vector = node.getVector();
@ -131,13 +132,12 @@ void TreeTest::onRun() {
}
{
std::vector<std::pair<oatpp::String, Tree::Node>> originalMap(10);
Tree::Map originalMap;
for(v_uint32 i = 0; i < 10; i ++) {
originalMap.at(i).first = "node_" + utils::Conversion::int32ToStr(i);
originalMap.at(i).second.setValue(i);
originalMap["node_" + utils::Conversion::int32ToStr(static_cast<v_int32>(i))].setValue(i);
}
Tree::Node node;
Tree node;
node.setMap(originalMap);
auto& map = node.getMap();
@ -145,12 +145,32 @@ void TreeTest::onRun() {
OATPP_ASSERT(map.size() == originalMap.size())
for(v_uint32 i = 0; i < originalMap.size(); i ++) {
OATPP_ASSERT(originalMap.at(i).first = map.at(i).first)
OATPP_ASSERT(originalMap.at(i).second.getValue<v_uint32>() == map.at(i).second.getValue<v_uint32>())
OATPP_ASSERT(originalMap[i].first == map[i].first)
OATPP_ASSERT(originalMap[i].second.get().getValue<v_uint32>() == map[i].second.get().getValue<v_uint32>())
}
originalMap.resize(5);
OATPP_ASSERT(map.size() == 10)
originalMap[0].second.get().setValue<v_uint32>(100);
OATPP_ASSERT(map[0].second.get().getValue<v_uint32>() == 0)
OATPP_ASSERT(originalMap[0].second.get().getValue<v_uint32>() == 100)
}
{
Tree article;
article["name"] = "Hello World!";
article["pages"] = 96;
article["references"].setVector(2);
article["references"][0]["author"] = "Alexander";
article["references"][1]["author"] = "Leonid";
article["references"].getVector().size();
v_int32 value = article["pages"];
oatpp::String author = article["references"][0]["author"];
OATPP_LOGD(TAG, "pages=%d', refs='%s', node_type=%d", value, author->c_str(), static_cast<v_int32>(article.getType()))
}