#include #include #include #include #include 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>(); } break; case XOT_OBJECT: { value_.object_value = new std::map>(); } 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>(); for (auto& value : *value_.array_value) { std::shared_ptr xobj_ptr = std::make_shared(); 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>(); for (auto& pair : *value_.object_value) { std::shared_ptr xobj_ptr = std::make_shared(); 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 XObject::operator[] (int idx) { return At(idx); } std::shared_ptr XObject::operator[] (const std::string& key) { return At(key); } std::shared_ptr XObject::At(int i) { assert(type_ == XOT_ARRAY); if (type_ == XOT_ARRAY) { return value_.array_value->at(i); } else { abort(); return std::shared_ptr(); } } std::shared_ptr 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(); } else { abort(); return std::shared_ptr(); } } std::shared_ptr 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>(); } *value_.array_value = *obj.value_.array_value; } break; case XOT_OBJECT: { if (!value_.object_value) { value_.object_value = new std::map>(); } *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::vector 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 xobj_ptr = std::make_shared(); 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& 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& 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>(); xobject.value_.array_value->reserve(json_val.size()); for (unsigned int i = 0; i < json_val.size(); ++i) { std::shared_ptr xobject_ptr = std::make_shared(); 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>(); for (std::string& key : json_val.getMemberNames()) { std::shared_ptr xobject_ptr = std::make_shared(); 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::shared_ptr xobj_ptr = std::make_shared(); xobj_ptr->type_ = a8::XOT_ARRAY; xobj_ptr->value_.array_value = new std::vector>(); (*xobject.value_.object_value)[std::string("attr_names")] = xobj_ptr; } { std::shared_ptr xobj_ptr = std::make_shared(); 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 xobj_ptr = std::make_shared(); xobj_ptr->value_.x_value = new a8::XValue(attr->Value()); (*xobject.value_.object_value)[std::string("attrs.") + attr->Name()] = xobj_ptr; } { std::shared_ptr xobj_ptr = std::make_shared(); 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 child_nodes_ptr = std::make_shared(); child_nodes_ptr->type_ = a8::XOT_ARRAY; child_nodes_ptr->value_.array_value = new std::vector>(); (*xobject.value_.object_value)["child_nodes"] = child_nodes_ptr; std::map>*> child_classes_hash; tinyxml2::XMLElement* child_node = xml_ele->FirstChildElement(); while (child_node) { std::shared_ptr xobj_ptr = std::make_shared(); 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>({xobj_ptr}); } } child_node = child_node->NextSiblingElement(); } //按属性分类 for (auto& pair : child_classes_hash) { std::shared_ptr xobj_ptr = std::make_shared(); 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>(); } void XObject::ConvertArray() { type_ = XOT_ARRAY; value_.array_value = new std::vector>(); } }