• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "solid_xml.h"
17 #include<iostream>
18 #include<regex>
19 #include "securec.h"
20 
21 namespace OHOS {
22 namespace Global {
23 namespace Restool {
24 using namespace std;
25 const uint8_t SolidXml::SOLID_XML_MAGIC[] = "SolidXml";
26 const uint32_t SolidXml::SOLID_XML_MAGIC_LENGTH =
27     (sizeof(SolidXml::SOLID_XML_MAGIC) / sizeof(uint32_t) + 1) * sizeof(uint32_t);
28 
SolidXml(const string & xmlPath,map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & keys)29 SolidXml::SolidXml(const string &xmlPath, map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &keys)
30     : xmlPath_(xmlPath), keys_(keys)
31 {
32 }
33 
~SolidXml()34 SolidXml::~SolidXml()
35 {
36 }
37 
GenerateSolidXml(const string & filePath)38 bool SolidXml::GenerateSolidXml(const string &filePath)
39 {
40     xmlKeepBlanksDefault(0);
41     xmlDocPtr doc = xmlParseFile(xmlPath_.c_str());
42     if (doc == nullptr) {
43         return false;
44     }
45 
46     xmlNodePtr rootNode = xmlDocGetRootElement(doc);
47     if (rootNode == nullptr) {
48         xmlFreeDoc(doc);
49         return false;
50     }
51     auto root = make_shared<XmlNode>();
52     nodes_.push_back(root);
53     Compile(rootNode, root);
54     xmlFreeDoc(doc);
55     return SaveToFile(filePath);
56 }
57 
FlushNodeKeys(const string & filePath,map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & newKeys)58 bool SolidXml::FlushNodeKeys(const string &filePath, map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &newKeys)
59 {
60     if (!LoadFromFile(xmlPath_)) {
61         cerr << "Error: load " << xmlPath_ << " fail." << endl;
62         return false;
63     }
64 
65     bool firstNode = true;
66     for (auto &node : nodes_) {
67         if (!node->FlushIndex(keys_, newKeys)) {
68             cerr << "Error: flush node key fail, '" << xmlPath_ << "'" << endl;
69             return false;
70         }
71         if (firstNode && !FlushXmlnsKey(newKeys)) {
72             return false;
73         }
74         firstNode = false;
75     }
76 
77     for (auto &attr : attributes_) {
78         if (!attr->FlushIndex(keys_, newKeys)) {
79             cerr << "Error: flush attibutes key fail, '" << xmlPath_ << "'" << endl;
80             return false;
81         }
82     }
83     return SaveToFile(filePath);
84 }
85 
86 // below private
Compile(const xmlNodePtr nodePtr,shared_ptr<XmlNode> & node)87 void SolidXml::Compile(const xmlNodePtr nodePtr, shared_ptr<XmlNode> &node)
88 {
89     if (nodePtr->type == XML_COMMENT_NODE) {
90         if (nodePtr->next) {
91             Compile(nodePtr->next, node);
92         }
93         return;
94     }
95 
96     string name(reinterpret_cast<const char *>(nodePtr->name));
97     node->SetName(keys_[XmlKeyNode::KeyType::NODE]->PushKey(name));
98     CompileNameSpace(nodePtr, node);
99     CompileAttr(nodePtr->properties, node);
100 
101     if (nodePtr->children) {
102         if (nodePtr->children->type == XML_TEXT_NODE) {
103             string content(reinterpret_cast<const char *>(nodePtr->children->content));
104             node->SetValue(keys_[XmlKeyNode::KeyType::CONTENT]->PushKey(content));
105         } else {
106             auto child = make_shared<XmlNode>();
107             nodes_.push_back(child);
108             node->SetChild(nodes_.size() - 1);
109             Compile(nodePtr->children, child);
110         }
111     }
112 
113     if (nodePtr->next) {
114         auto brother = make_shared<XmlNode>();
115         nodes_.push_back(brother);
116         node->SetBrother(nodes_.size() - 1);
117         Compile(nodePtr->next, brother);
118     }
119 }
120 
CompileAttr(const xmlAttrPtr attrPtr,shared_ptr<XmlNode> & node)121 void SolidXml::CompileAttr(const xmlAttrPtr attrPtr, shared_ptr<XmlNode> &node)
122 {
123     if (attrPtr == nullptr) {
124         return;
125     }
126 
127     xmlChar *xmlValue = xmlNodeListGetString(attrPtr->doc, attrPtr->children, 1);
128     string value(reinterpret_cast<const char *>(xmlValue));
129     PretreatmentAttr(value);
130     xmlFree(xmlValue);
131     string name(reinterpret_cast<const char *>(attrPtr->name));
132     auto attr = make_shared<Node>();
133     attributes_.push_back(attr);
134     attr->SetName(keys_[XmlKeyNode::KeyType::ATTRIBUTE]->PushKey(name));
135     attr->SetValue(keys_[XmlKeyNode::KeyType::CONSTANT]->PushKey(value));
136     if (attrPtr->ns != nullptr && attrPtr->ns->prefix != nullptr) {
137         string nameSpace(reinterpret_cast<const char *>(attrPtr->ns->prefix));
138         attr->SetNameSpace(keys_[XmlKeyNode::KeyType::NODE]->PushKey(nameSpace));
139     }
140     node->AddAttribute(attributes_.size() - 1);
141     CompileAttr(attrPtr->next, node);
142 }
143 
CompileNameSpace(const xmlNodePtr nodePtr,shared_ptr<XmlNode> & node)144 void SolidXml::CompileNameSpace(const xmlNodePtr nodePtr, shared_ptr<XmlNode> &node)
145 {
146     if (nodePtr->ns && nodePtr->ns->prefix) {
147         string nameSpace(reinterpret_cast<const char *>(nodePtr->ns->prefix));
148         node->SetNameSpace(keys_[XmlKeyNode::KeyType::NODE]->PushKey(nameSpace));
149     }
150 
151     auto nsDef = nodePtr->nsDef;
152     while (nsDef) {
153         string nameSpace;
154         string href;
155         if (nsDef->prefix) {
156             nameSpace = string(reinterpret_cast<const char *>(nsDef->prefix));
157         }
158         if (nsDef->href) {
159             href = string(reinterpret_cast<const char *>(nsDef->href));
160         }
161         int32_t nameSpaceIndex = keys_[XmlKeyNode::KeyType::NODE]->PushKey(nameSpace);
162         int32_t herfIndex = keys_[XmlKeyNode::KeyType::NODE]->PushKey(href);
163         AddNampeSpaceDef(nameSpaceIndex, herfIndex);
164         nsDef = nsDef->next;
165     }
166 }
167 
RawData(ofstream & out) const168 void SolidXml::Node::RawData(ofstream &out) const
169 {
170     out.write(reinterpret_cast<const char *>(&nameSpace_), sizeof(int32_t));
171     out.write(reinterpret_cast<const char *>(&name_), sizeof(int32_t));
172     out.write(reinterpret_cast<const char *>(&value_), sizeof(int32_t));
173 }
174 
RawData(ofstream & out) const175 void SolidXml::XmlNode::RawData(ofstream &out) const
176 {
177     SolidXml::Node::RawData(out);
178     out.write(reinterpret_cast<const char *>(&child_), sizeof(int32_t));
179     out.write(reinterpret_cast<const char *>(&brother_), sizeof(int32_t));
180     int32_t attrStart = attributes_.size();
181     int32_t attrCount = attributes_.size();
182     if (!attributes_.empty()) {
183         attrStart = attributes_.at(0);
184     }
185     out.write(reinterpret_cast<const char *>(&attrStart), sizeof(int32_t));
186     out.write(reinterpret_cast<const char *>(&attrCount), sizeof(int32_t));
187 }
188 
LoadFrom(ifstream & in)189 bool SolidXml::Node::LoadFrom(ifstream &in)
190 {
191     CHECK_IO(in.read(reinterpret_cast<char *>(&nameSpace_), sizeof(int32_t)))
192     CHECK_IO(in.read(reinterpret_cast<char *>(&name_), sizeof(int32_t)));
193     CHECK_IO(in.read(reinterpret_cast<char *>(&value_), sizeof(int32_t)));
194     return true;
195 }
196 
LoadFrom(ifstream & in)197 bool SolidXml::XmlNode::LoadFrom(ifstream &in)
198 {
199     if (!SolidXml::Node::LoadFrom(in)) {
200         return false;
201     }
202     CHECK_IO(in.read(reinterpret_cast<char *>(&child_), sizeof(int32_t)));
203     CHECK_IO(in.read(reinterpret_cast<char *>(&brother_), sizeof(int32_t)));
204     int32_t attrStart = 0;
205     int32_t attrCount = 0;
206     CHECK_IO(in.read(reinterpret_cast<char *>(&attrStart), sizeof(int32_t)));
207     CHECK_IO(in.read(reinterpret_cast<char *>(&attrCount), sizeof(int32_t)));
208     for (int32_t i = attrStart; i < attrStart + attrCount; i++) {
209         attributes_.push_back(i);
210     }
211     return true;
212 }
213 
FlushIndex(const map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & oldKeys,map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & newKeys)214 bool SolidXml::Node::FlushIndex(const map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &oldKeys,
215     map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &newKeys)
216 {
217     if (!ChangeToNewKey(oldKeys, newKeys, XmlKeyNode::KeyType::NODE, nameSpace_) ||
218         !ChangeToNewKey(oldKeys, newKeys, XmlKeyNode::KeyType::ATTRIBUTE, name_) ||
219         !ChangeToNewKey(oldKeys, newKeys, XmlKeyNode::KeyType::CONSTANT, value_)) {
220         return false;
221     }
222     return true;
223 }
224 
FlushIndex(const map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & oldKeys,map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & newKeys)225 bool SolidXml::XmlNode::FlushIndex(const map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &oldKeys,
226     map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &newKeys)
227 {
228     if (!ChangeToNewKey(oldKeys, newKeys, XmlKeyNode::KeyType::NODE, nameSpace_) ||
229         !ChangeToNewKey(oldKeys, newKeys, XmlKeyNode::KeyType::NODE, name_) ||
230         !ChangeToNewKey(oldKeys, newKeys, XmlKeyNode::KeyType::CONTENT, value_)) {
231         return false;
232     }
233     return true;
234 }
235 
AddNampeSpaceDef(int32_t nameSpace,int32_t href)236 void SolidXml::AddNampeSpaceDef(int32_t nameSpace, int32_t href)
237 {
238     nameSpaces_.push_back(nameSpace);
239     hrefs_.push_back(href);
240 }
241 
SaveToFile(const std::string & filePath) const242 bool SolidXml::SaveToFile(const std::string &filePath) const
243 {
244     ofstream out(filePath, ofstream::out | ofstream::binary);
245     if (!out.is_open()) {
246         cerr << "Error: open fail," << filePath << endl;
247         return false;
248     }
249 
250     // write solid xml header
251     uint8_t magic[SOLID_XML_MAGIC_LENGTH] = {0};
252     if (memcpy_s(magic, SOLID_XML_MAGIC_LENGTH, SOLID_XML_MAGIC, sizeof(SOLID_XML_MAGIC)) != EOK) {
253         cerr << "Error: SolidXml::SaveToFile memcpy_s fail." << endl;
254         return false;
255     }
256     uint32_t version = 1;
257     uint32_t numOfNodes = nodes_.size();
258     uint32_t numOfAttributes = attributes_.size();
259     uint32_t numOfNameSpaces = nameSpaces_.size();
260     out.write(reinterpret_cast<const char *>(magic), SOLID_XML_MAGIC_LENGTH);
261     out.write(reinterpret_cast<const char *>(&version), sizeof(uint32_t));
262     out.write(reinterpret_cast<const char *>(&numOfNodes), sizeof(uint32_t));
263     out.write(reinterpret_cast<const char *>(&numOfAttributes), sizeof(uint32_t));
264     out.write(reinterpret_cast<const char *>(&numOfNameSpaces), sizeof(uint32_t));
265 
266     // write node
267     for (const auto &node : nodes_) {
268         node->RawData(out);
269     }
270 
271     // write attribute
272     for (const auto &attribute : attributes_) {
273         attribute->RawData(out);
274     }
275 
276     // write namespace
277     for (const auto &nameSpace : nameSpaces_) {
278         out.write(reinterpret_cast<const char *>(&nameSpace), sizeof(int32_t));
279     }
280 
281     // write href
282     for (const auto &href : hrefs_) {
283         out.write(reinterpret_cast<const char *>(&href), sizeof(int32_t));
284     }
285     return true;
286 }
287 
PretreatmentAttr(string & value) const288 void SolidXml::PretreatmentAttr(string &value) const
289 {
290     regex ref("^\\$\\+id:");
291     smatch result;
292     if (!regex_search(value, result, ref)) {
293         return;
294     }
295     value.replace(0, result[0].str().length(), "$id:");
296 }
297 
LoadFromFile(const string & sxmlPath)298 bool SolidXml::LoadFromFile(const string &sxmlPath)
299 {
300     ifstream in(sxmlPath, ifstream::in | ifstream::binary);
301     if (!in.is_open()) {
302         cerr << "Error: open fail," << sxmlPath << endl;
303         return false;
304     }
305 
306     char header[SOLID_XML_MAGIC_LENGTH];
307     CHECK_IO(in.read(header, SOLID_XML_MAGIC_LENGTH));
308 
309     uint32_t version = 0;
310     CHECK_IO(in.read(reinterpret_cast<char *>(&version), sizeof(uint32_t)));
311 
312     uint32_t numOfNodes = 0;
313     CHECK_IO(in.read(reinterpret_cast<char *>(&numOfNodes), sizeof(uint32_t)));
314 
315     uint32_t numOfAttributes = 0;
316     CHECK_IO(in.read(reinterpret_cast<char *>(&numOfAttributes), sizeof(uint32_t)));
317 
318     uint32_t numOfNameSpaces = 0;
319     CHECK_IO(in.read(reinterpret_cast<char *>(&numOfNameSpaces), sizeof(uint32_t)));
320 
321     for (uint32_t i = 0; i < numOfNodes; i++) {
322         auto xmlNode = make_shared<XmlNode>();
323         if (!xmlNode->LoadFrom(in)) {
324             return false;
325         }
326         nodes_.push_back(xmlNode);
327     }
328 
329     for (uint32_t i = 0; i < numOfAttributes; i++) {
330         auto attr = make_shared<Node>();
331         if (!attr->LoadFrom(in)) {
332             return false;
333         }
334         attributes_.push_back(attr);
335     }
336 
337     for (uint32_t i = 0; i < numOfNameSpaces; i++) {
338         int32_t nameSpace = -1;
339         CHECK_IO(in.read(reinterpret_cast<char *>(&nameSpace), sizeof(int32_t)));
340         nameSpaces_.push_back(nameSpace);
341     }
342 
343     for (uint32_t i = 0; i < numOfNameSpaces; i++) {
344         int32_t href = -1;
345         CHECK_IO(in.read(reinterpret_cast<char *>(&href), sizeof(int32_t)));
346         hrefs_.push_back(href);
347     }
348     return true;
349 }
350 
ChangeToNewKey(const map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & oldKeys,map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & newKeys,XmlKeyNode::KeyType keyType,int32_t & keyId)351 bool SolidXml::ChangeToNewKey(const map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &oldKeys,
352     map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &newKeys,
353     XmlKeyNode::KeyType keyType, int32_t &keyId)
354 {
355     if (keyId <= 0) {
356         return true;
357     }
358 
359     string value;
360     if (!oldKeys.at(keyType)->GetKeyValue(keyId, value)) {
361         return false;
362     }
363 
364     keyId = newKeys[keyType]->PushKey(value);
365     return true;
366 }
367 
FlushXmlnsKey(map<XmlKeyNode::KeyType,shared_ptr<XmlKeyNode>> & newKeys)368 bool SolidXml::FlushXmlnsKey(map<XmlKeyNode::KeyType, shared_ptr<XmlKeyNode>> &newKeys)
369 {
370     if (nameSpaces_.size() != hrefs_.size()) {
371         return false;
372     }
373 
374     for (uint32_t i = 0; i < nameSpaces_.size(); i++) {
375         if (!ChangeToNewKey(keys_, newKeys, XmlKeyNode::KeyType::NODE, nameSpaces_[i]) ||
376             !ChangeToNewKey(keys_, newKeys, XmlKeyNode::KeyType::NODE, hrefs_[i])) {
377             cerr << "Error: flush namespace key fail, '" << xmlPath_ << "'" << endl;
378             return false;
379         }
380     }
381     return true;
382 }
383 }
384 }
385 }
386