a8/a8/xobject.cc
aozhiwei e591648ac9 1
2022-12-16 17:04:15 +08:00

598 lines
18 KiB
C++

#include <assert.h>
#include <a8/a8.h>
#include <a8/xobject.h>
#include <json/reader.h>
#include <tinyxml2.h>
namespace a8
{
XObject::XObject()
{
}
XObject::XObject(a8::XValue& val)
{
type_ = XOT_SIMPLE;
value_.x_value = new a8::XValue(val);
}
XObject::XObject(const a8::XObject& v)
{
switch (v.type_) {
case XOT_SIMPLE:
{
value_.x_value = new a8::XValue();
}
break;
case XOT_ARRAY:
{
value_.array_value = new std::vector<std::shared_ptr<a8::XObject>>();
}
break;
case XOT_OBJECT:
{
value_.object_value = new std::map<std::string, std::shared_ptr<a8::XObject>>();
}
break;
default:
{
abort();
}
break;
}
type_ = v.type_;
*this = v;
}
XObject::~XObject()
{
switch (type_) {
case XOT_SIMPLE:
{
if (value_.x_value) {
delete value_.x_value;
value_.x_value = nullptr;
}
}
break;
case XOT_ARRAY:
{
if (value_.array_value) {
delete value_.array_value;
value_.array_value = nullptr;
}
}
break;
case XOT_OBJECT:
{
if (value_.object_value) {
delete value_.object_value;
value_.object_value = nullptr;
}
}
break;
}
}
unsigned char XObject::GetType()
{
return type_;
}
int XObject::Size()
{
assert(type_ == XOT_ARRAY);
if (type_ == XOT_ARRAY) {
return value_.array_value->size();
} else {
abort();
return 0;
}
}
void XObject::Reset()
{
switch (type_) {
case a8::XOT_SIMPLE:
{
}
break;
case a8::XOT_ARRAY:
{
delete value_.array_value;
type_ = XOT_SIMPLE;
value_.x_value = new a8::XValue();
}
break;
case a8::XOT_OBJECT:
{
delete value_.object_value;
type_ = XOT_SIMPLE;
value_.x_value = new a8::XValue();
}
break;
default:
abort();
}
}
void XObject::DeepCopy(a8::XObject& to)
{
to.Reset();
switch (type_) {
case a8::XOT_SIMPLE:
{
if (value_.x_value) {
if (!to.value_.x_value) {
to.value_.x_value = new a8::XValue();
}
value_.x_value->DeepCopy(*to.value_.x_value);
} else {
if (to.value_.x_value) {
delete to.value_.x_value;
to.value_.x_value = nullptr;
}
}
}
break;
case a8::XOT_ARRAY:
{
to.type_ = XOT_ARRAY;
to.value_.array_value = new std::vector<std::shared_ptr<a8::XObject>>();
for (auto& value : *value_.array_value) {
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
value->DeepCopy(*xobj_ptr.get());
to.value_.array_value->push_back(xobj_ptr);
}
}
break;
case a8::XOT_OBJECT:
{
to.type_ = XOT_OBJECT;
to.value_.object_value = new std::map<std::string, std::shared_ptr<a8::XObject>>();
for (auto& pair : *value_.object_value) {
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
pair.second->DeepCopy(*xobj_ptr.get());
(*(to.value_.object_value))[pair.first] = xobj_ptr;
}
}
break;
default:
abort();
}
}
a8::XValue XObject::AsXValue()
{
assert(type_ == XOT_SIMPLE);
if (type_ != XOT_SIMPLE) {
abort();
return a8::XValue();
}
return type_ == XOT_SIMPLE && value_.x_value ? *value_.x_value : a8::XValue();
}
std::shared_ptr<a8::XObject> XObject::operator[] (int idx)
{
return At(idx);
}
std::shared_ptr<a8::XObject> XObject::operator[] (const std::string& key)
{
return At(key);
}
std::shared_ptr<a8::XObject> XObject::At(int i)
{
assert(type_ == XOT_ARRAY);
if (type_ == XOT_ARRAY) {
return value_.array_value->at(i);
} else {
abort();
return std::shared_ptr<a8::XObject>();
}
}
std::shared_ptr<a8::XObject> XObject::At(const std::string& key)
{
assert(type_ == XOT_OBJECT);
if (type_ == XOT_OBJECT) {
auto itr = value_.object_value->find(key);
return itr != value_.object_value->end() ? itr->second : std::shared_ptr<a8::XObject>();
} else {
abort();
return std::shared_ptr<a8::XObject>();
}
}
std::shared_ptr<a8::XObject> XObject::At(const char* key)
{
return At(std::string(key));
}
a8::XValue XObject::Get(const std::string& key, a8::XValue defval)
{
if (type_ == XOT_OBJECT) {
auto itr = value_.object_value->find(key);
return itr != value_.object_value->end() ? itr->second->AsXValue() : defval;
} else {
return defval;
}
}
bool XObject::HasKey(const std::string& key)
{
assert(type_ == XOT_OBJECT);
if (type_ == XOT_OBJECT) {
auto itr = value_.object_value->find(key);
return itr != value_.object_value->end();
} else {
abort();
return false;
}
}
bool XObject::HasKey(int i)
{
assert(type_ == XOT_ARRAY);
if (type_ == XOT_ARRAY) {
return i >= 0 && i < (int)value_.array_value->size();
} else {
abort();
return false;
}
}
const a8::XObject& XObject::operator=(const a8::XObject& obj)
{
switch (obj.type_) {
case XOT_SIMPLE:
{
if (!value_.x_value) {
value_.x_value = new a8::XValue();
} else {
*value_.x_value = a8::XValue();
}
if (obj.value_.x_value) {
*value_.x_value = *obj.value_.x_value;
}
}
break;
case XOT_ARRAY:
{
if (!value_.array_value) {
value_.array_value = new std::vector<std::shared_ptr<a8::XObject>>();
}
*value_.array_value = *obj.value_.array_value;
}
break;
case XOT_OBJECT:
{
if (!value_.object_value) {
value_.object_value = new std::map<std::string, std::shared_ptr<a8::XObject>>();
}
*value_.object_value = *obj.value_.object_value;
}
break;
}
type_ = obj.type_;
return *this;
}
a8::XObject& XObject::Move(a8::XObject& a)
{
a.type_ = type_;
a.value_ = value_;
type_ = XOT_SIMPLE;
value_.x_value = {0};
return *this;
}
bool XObject::ReadFromFile(const std::string& filename)
{
std::string data;
if (!a8::ReadStringFromFile(filename, data)) {
return false;
}
return ReadFromJsonString(data);
}
bool XObject::ReadFromJsonFile(const std::string& filename)
{
std::string data;
if (!a8::ReadStringFromFile(filename, data)) {
return false;
}
return ReadFromJsonString(data);
}
bool XObject::ReadFromJsonString(const std::string& json_data)
{
Json::Reader reader;
Json::Value root;
if (!reader.parse(json_data, root)) {
return false;
}
JsonValueToXObject(root, *this);
return true;
}
bool XObject::ReadFromXmlFile(const std::string& filename)
{
std::string data;
if (!a8::ReadStringFromFile(filename, data)) {
return false;
}
return ReadFromXmlString(data);
}
bool XObject::ReadFromXmlString(const std::string& xmldata)
{
tinyxml2::XMLDocument xmldoc;
if (tinyxml2::XML_SUCCESS != xmldoc.Parse(xmldata.data(), xmldata.size())) {
return false;
}
tinyxml2::XMLElement* root = xmldoc.RootElement();
if (!root) {
return false;
}
XmlElementToXObject(root, *this);
return true;
}
void XObject::ReadFromUrlQueryString(const std::string& query_string)
{
type_ = a8::XOT_OBJECT;
value_.object_value = new std::map<std::string, std::shared_ptr<a8::XObject>>();
std::vector<std::string> params;
a8::Split(query_string, params, '&');
for(unsigned int i = 0; i < params.size(); i++){
int pos = params[i].find('=');
if(pos > 0){
std::string key = params[i].substr(0, pos);
std::string val = params[i].substr(pos + 1, params[i].size() - pos);
val = a8::UrlDecode(val);
{
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
xobj_ptr->type_ = a8::XOT_SIMPLE;
xobj_ptr->value_.x_value = new a8::XValue(val);
(*value_.object_value)[key] = xobj_ptr;
}
}
}
}
void XObject::ToJsonStr(std::string& data)
{
if (type_ == a8::XOT_SIMPLE) {
switch (value_.x_value->Type()){
case XVT_INT:
case XVT_UINT:
case XVT_FLOAT:
data.append(value_.x_value->GetString());
break;
default:
data.append("\"" + a8::JsonEscapeString(value_.x_value->GetString()) + "\"");
break;
}
} else if (type_ == a8::XOT_ARRAY) {
data.push_back('[');
for (auto& val : *value_.array_value) {
val->ToJsonStr(data);
data.push_back(',');
}
if (data[data.size() - 1] == ',') {
data[data.size() - 1] = ']';
} else {
data.push_back(']');
}
} else if (type_ == a8::XOT_OBJECT) {
data.push_back('{');
for (auto& pair : *value_.object_value) {
data.append("\"" + pair.first + "\":");
pair.second->ToJsonStr(data);
data.push_back(',');
}
if (data[data.size() - 1] == ',') {
data[data.size() - 1] = '}';
} else {
data.push_back('}');
}
}
}
std::string XObject::ToJsonStr()
{
std::string data;
ToJsonStr(data);
return data;
}
void XObject::ToUrlEncodeStr(std::string& data)
{
if (type_ == a8::XOT_OBJECT) {
for (auto& pair : *value_.object_value) {
data.append("&" + pair.first + "=" + a8::UrlEncode(pair.second->AsXValue().GetString()));
}
}
}
void XObject::ToKVList(std::map<std::string, std::string>& kv_list)
{
if (type_ == a8::XOT_OBJECT) {
for (auto& pair : *value_.object_value) {
kv_list[pair.first + ""] = pair.second->AsXValue().GetString() + "";
}
}
}
void XObject::GetKeys(std::vector<std::string>& keys)
{
if (type_ == a8::XOT_OBJECT) {
for (auto& pair : *value_.object_value) {
keys.push_back(pair.first);
}
}
}
void XObject::JsonValueToXObject(Json::Value& json_val, a8::XObject& xobject)
{
Json::ValueType val_type = json_val.type();
switch (val_type) {
case Json::ValueType::nullValue:
{
xobject.type_ = a8::XOT_SIMPLE;
xobject.value_.x_value = new a8::XValue();
}
break;
case Json::ValueType::intValue:
{
xobject.type_ = a8::XOT_SIMPLE;
xobject.value_.x_value = new a8::XValue(json_val.asLargestInt());
}
break;
case Json::ValueType::uintValue:
{
xobject.type_ = a8::XOT_SIMPLE;
xobject.value_.x_value = new a8::XValue(json_val.asLargestUInt());
}
break;
case Json::ValueType::realValue:
{
xobject.type_ = a8::XOT_SIMPLE;
xobject.value_.x_value = new a8::XValue(json_val.asDouble());
}
break;
case Json::ValueType::stringValue:
{
xobject.type_ = a8::XOT_SIMPLE;
xobject.value_.x_value = new a8::XValue(json_val.asString());
}
break;
case Json::ValueType::booleanValue:
{
xobject.type_ = a8::XOT_SIMPLE;
xobject.value_.x_value = new a8::XValue(json_val.asBool() ? 1 : 0);
}
break;
case Json::ValueType::arrayValue:
{
xobject.type_ = a8::XOT_ARRAY;
xobject.value_.array_value = new std::vector<std::shared_ptr<a8::XObject>>();
xobject.value_.array_value->reserve(json_val.size());
for (unsigned int i = 0; i < json_val.size(); ++i) {
std::shared_ptr<a8::XObject> xobject_ptr = std::make_shared<a8::XObject>();
JsonValueToXObject(json_val[i], *xobject_ptr);
xobject.value_.array_value->push_back(xobject_ptr);
}
}
break;
case Json::ValueType::objectValue:
{
xobject.type_ = a8::XOT_OBJECT;
xobject.value_.object_value = new std::map<std::string, std::shared_ptr<a8::XObject>>();
for (std::string& key : json_val.getMemberNames()) {
std::shared_ptr<a8::XObject> xobject_ptr = std::make_shared<a8::XObject>();
JsonValueToXObject(json_val[key], *xobject_ptr);
(*xobject.value_.object_value)[key] = xobject_ptr;
}
}
break;
default:
{
assert(false);
abort();
}
break;
}
}
void XObject::XmlElementToXObject(tinyxml2::XMLElement* xml_ele, a8::XObject& xobject)
{
//初始化对象
{
xobject.type_ = a8::XOT_OBJECT;
xobject.value_.object_value = new std::map<std::string, std::shared_ptr<a8::XObject>>();
{
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
xobj_ptr->type_ = a8::XOT_ARRAY;
xobj_ptr->value_.array_value = new std::vector<std::shared_ptr<a8::XObject>>();
(*xobject.value_.object_value)[std::string("attr_names")] = xobj_ptr;
}
{
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
xobj_ptr->value_.x_value = new a8::XValue(xml_ele->GetText());
(*xobject.value_.object_value)[std::string("node_value")] = xobj_ptr;
}
}
//读取节点所有属性已经属性名 attr_names:存储所有的属性名
{
const tinyxml2::XMLAttribute* attr = xml_ele->FirstAttribute();
while (attr) {
{
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
xobj_ptr->value_.x_value = new a8::XValue(attr->Value());
(*xobject.value_.object_value)[std::string("attrs.") + attr->Name()] = xobj_ptr;
}
{
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
xobj_ptr->value_.x_value = new a8::XValue(attr->Name());
(*xobject.value_.object_value)[std::string("attr_names")]->value_.array_value->push_back(xobj_ptr);
}
attr = attr->Next();
}
}
//读取所有子节点并按 child_node.属性名 分类存储 child_nodes:存储所有的子节点
{
std::shared_ptr<a8::XObject> child_nodes_ptr = std::make_shared<a8::XObject>();
child_nodes_ptr->type_ = a8::XOT_ARRAY;
child_nodes_ptr->value_.array_value = new std::vector<std::shared_ptr<a8::XObject>>();
(*xobject.value_.object_value)["child_nodes"] = child_nodes_ptr;
std::map<std::string, std::vector<std::shared_ptr<a8::XObject>>*> child_classes_hash;
tinyxml2::XMLElement* child_node = xml_ele->FirstChildElement();
while (child_node) {
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
XmlElementToXObject(child_node, *xobj_ptr);
child_nodes_ptr->value_.array_value->push_back(xobj_ptr);
{
auto itr = child_classes_hash.find(child_node->Name());
if (itr != child_classes_hash.end()) {
itr->second->push_back(xobj_ptr);
} else {
child_classes_hash[child_node->Name()] = new std::vector<std::shared_ptr<a8::XObject>>({xobj_ptr});
}
}
child_node = child_node->NextSiblingElement();
}
//按属性分类
for (auto& pair : child_classes_hash) {
std::shared_ptr<a8::XObject> xobj_ptr = std::make_shared<a8::XObject>();
xobj_ptr->type_ = a8::XOT_ARRAY;
xobj_ptr->value_.array_value = pair.second;
(*xobject.value_.object_value)[std::string("child_node.") + pair.first] = xobj_ptr;
}
}
}
void XObject::ConvertObject()
{
type_ = XOT_OBJECT;
value_.object_value = new std::map<std::string, std::shared_ptr<a8::XObject>>();
}
void XObject::ConvertArray()
{
type_ = XOT_ARRAY;
value_.array_value = new std::vector<std::shared_ptr<a8::XObject>>();
}
}