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:
parent
5461fb2f08
commit
4a7795c221
@ -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()))
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user