• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "js_xml.h"
17 #include "securec.h"
18 namespace OHOS::xml {
DealNapiStrValue(napi_env env,const napi_value napiStr,std::string & result)19     napi_status XmlSerializer::DealNapiStrValue(napi_env env, const napi_value napiStr, std::string &result)
20     {
21         std::string buffer = "";
22         size_t bufferSize = 0;
23         napi_status status = napi_ok;
24         status = napi_get_value_string_utf8(env, napiStr, nullptr, -1, &bufferSize);
25         buffer.reserve(bufferSize + 1);
26         buffer.resize(bufferSize);
27         if (status != napi_ok) {
28             HILOG_ERROR("can not get buffer size");
29             return status;
30         }
31         if (bufferSize > 0) {
32             status = napi_get_value_string_utf8(env, napiStr, buffer.data(), bufferSize + 1, &bufferSize);
33             if (status != napi_ok) {
34                 HILOG_ERROR("can not get buffer value");
35                 return status;
36             }
37         }
38         if (buffer.data() != nullptr) {
39             result = buffer;
40         }
41         return status;
42     }
SplicNsp()43     void XmlSerializer::SplicNsp()
44     {
45         elementStack[depth_ * 3] = elementStack[(depth_ - 1) * 3]; // 3: number of args
46         elementStack[depth_ * 3 + 1] = elementStack[(depth_ - 1) * 3 + 1]; // 3: number of args
47         if (multNsp[depth_ - 1].size() == 0) {
48             return;
49         }
50         if (type == "isAttri" || type == "isStart") {
51             for (int i = 0; i < CurNspNum; ++i) {
52                 out_.append(" xmlns:");
53                 out_.append(multNsp[depth_ - 1][i * 2]); // 2: number of args
54                 out_.append("=\"");
55                 out_.append(multNsp[depth_ - 1][i * 2 + 1]); // 2: number of args
56                 out_.append("\"");
57             }
58             multNsp[depth_ - 1].clear();
59             CurNspNum = 0;
60         }
61     }
62 
NextItem()63     void XmlSerializer::NextItem()
64     {
65         out_.append("\r\n");
66         for (size_t i = 0; i < depth_; i++) {
67             out_.append("  ");
68         }
69     }
Replace(std::string str,const std::string & str1,const std::string & str2)70     std::string Replace(std::string str, const std::string &str1, const std::string &str2)
71     {
72         size_t iPos = 0;
73         while ((iPos = str.find(str1)) != std::string::npos) {
74             str = str.substr(0, iPos) + str2 + str.substr(iPos + str1.size());
75         }
76         return str;
77     }
SetDeclaration()78     void XmlSerializer::SetDeclaration()
79     {
80         if (isHasDecl) {
81             xmlSerializerError_ = "illegal position for declaration";
82             return;
83         }
84         isHasDecl = true;
85         out_ = "";
86         out_.append("<?xml version=\"1.0\"");
87         out_.append(" encoding=\"");
88         out_.append(encoding_);
89         out_.append("\"?>");
90         type = "isDecl";
91         size_t iLenTemp = out_.length();
92         if (iLength_ > iPos_ + iLenTemp - 1) {
93             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
94                 iPos_ += iLenTemp;
95             } else {
96                 HILOG_ERROR("SetDeclaration memcpy_s failed");
97             }
98         }
99     }
SetNamespace(std::string prefix,const std::string & nsTemp)100     void XmlSerializer::SetNamespace(std::string prefix, const std::string &nsTemp)
101     {
102         out_ = "";
103         if (type == "isStart" || type == "isAttri") {
104             SplicNsp();
105             out_.append(">");
106         }
107         elementStack[depth_ * 3] = prefix; // 3: number of args
108         elementStack[depth_ * 3 + 1] = nsTemp; // 3: number of args
109         multNsp[depth_][CurNspNum * 2] = elementStack[depth_ * 3]; // 3: number of args 2: number of args
110         multNsp[depth_][CurNspNum * 2 + 1] = elementStack[depth_ * 3 + 1]; // 3: number of args 2: number of args
111         ++CurNspNum;
112         type = "isNsp";
113         size_t iLenTemp = out_.length();
114         if (iLength_ > iPos_ + iLenTemp - 1) {
115             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
116                 iPos_ += iLenTemp;
117             } else {
118                 HILOG_ERROR("SetNamespace memcpy_s failed");
119             }
120         }
121     }
StartElement(const std::string & name)122     void XmlSerializer::StartElement(const std::string &name)
123     {
124         out_ = "";
125         if (type == "isStart" || type == "isAttri") {
126             SplicNsp();
127             out_.append(">");
128         }
129         if (type != "" && type != "isDecl") {
130             NextItem();
131         }
132         elementStack[depth_ * 3 + 2] = name; // 3: number of args 2: number of args
133         out_.append("<");
134         if (elementStack[depth_ * 3] != "") { // 3: number of args
135             out_.append(elementStack[depth_ * 3]); // 3: number of args
136             out_.append(":");
137         } else if (depth_ != 0) {
138             if (elementStack[(depth_ - 1) * 3] != "") { // 3: number of args
139                 elementStack[depth_ * 3] = elementStack[(depth_ - 1) * 3]; // 3: number of args
140                 out_.append(elementStack[depth_ * 3]); // 3: number of args
141                 out_.append(":");
142             }
143         }
144         out_.append(elementStack[depth_ * 3 + 2]); // 3: number of args 2: number of args
145         type = "isStart";
146         ++depth_;
147         elementStack.push_back("");
148         elementStack.push_back("");
149         elementStack.push_back("");
150         size_t iLenTemp = out_.length();
151         if (iLength_ > iPos_ + iLenTemp - 1) {
152             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
153                 iPos_ += iLenTemp;
154             } else {
155                 HILOG_ERROR("StartElement memcpy_s failed");
156             }
157         }
158     }
SetAttributes(const std::string & name,const std::string & value)159     void XmlSerializer::SetAttributes(const std::string &name, const std::string &value)
160     {
161         out_ = "";
162         if (type != "isStart" && type != "isAttri") {
163             xmlSerializerError_ = "illegal position for attribute";
164         }
165         out_.append(" ");
166         out_.append(name);
167         out_.append("=\"");
168         WriteEscaped(value);
169         out_.append("\"");
170         type = "isAttri";
171         size_t iLenTemp = out_.length();
172         if (iLength_ > iPos_ + iLenTemp - 1) {
173             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
174                 iPos_ += iLenTemp;
175             } else {
176                 HILOG_ERROR("SetAttributes memcpy_s failed");
177             }
178         }
179     }
EndElement()180     void XmlSerializer::EndElement()
181     {
182         out_ = "";
183         size_t iLenTemp = 0;
184         if (type == "isStart" || type == "isAttri") {
185             SplicNsp();
186             out_.append("/>");
187             type = "isEndTag";
188             --depth_;
189             iLenTemp = out_.length();
190             if (iLength_ > iPos_ + iLenTemp - 1) {
191                 if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
192                     iPos_ += iLenTemp;
193                 } else {
194                 HILOG_ERROR("StartElement memcpy_s failed");
195                 }
196             }
197             return;
198         }
199         --depth_;
200         if (type != "isText") {
201             NextItem();
202         }
203         out_.append("</");
204         if (elementStack[depth_ * 3] != "") { // 3: number of args
205             out_.append(elementStack[depth_ * 3]); // 3: number of args
206             out_.append(":");
207         }
208         out_.append(elementStack[depth_ * 3 + 2]); // 3: number of args 2: number of args
209         elementStack[depth_ * 3] = ""; // 3: number of args
210         elementStack[depth_ * 3 + 1] = ""; // 3: number of args
211         type = "isEndTag";
212         out_.append(">");
213         iLenTemp = out_.length();
214         if (iLength_ > iPos_ + iLenTemp - 1) {
215             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
216                 iPos_ += iLenTemp;
217             } else {
218                 HILOG_ERROR("EndElement memcpy_s failed");
219             }
220         }
221     }
AddEmptyElement(std::string name)222     void XmlSerializer::AddEmptyElement(std::string name)
223     {
224         out_ = "";
225         if (type == "isStart" || type == "isAttri") {
226             SplicNsp();
227             out_.append(">");
228         }
229         if (type != "") {
230             NextItem();
231         }
232         out_.append("<");
233         out_.append(name);
234         out_.append("/>");
235         type = "isAddEmpElem";
236         size_t iLenTemp = out_.length();
237         if (iLength_ > iPos_ + iLenTemp - 1) {
238             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
239                 iPos_ += iLenTemp;
240             } else {
241                 HILOG_ERROR("AddEmptyElement memcpy_s failed");
242             }
243         }
244     }
SetText(const std::string & text)245     void XmlSerializer::SetText(const std::string &text)
246     {
247         out_ = "";
248         if (type == "isStart" || type == "isAttri") {
249             SplicNsp();
250             out_.append(">");
251         }
252         WriteEscaped(text);
253         type = "isText";
254         size_t iLenTemp = out_.length();
255         if (iLength_ > iPos_ + iLenTemp - 1) {
256             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
257                 iPos_ += iLenTemp;
258             } else {
259                 HILOG_ERROR("SetText memcpy_s failed");
260             }
261         }
262     }
SetComment(const std::string & comment)263     void XmlSerializer::SetComment(const std::string &comment)
264     {
265         out_ = "";
266         if (type == "isStart" || type == "isAttri") {
267             SplicNsp();
268             out_.append(">");
269         }
270         if (type != "") {
271             NextItem();
272         }
273         out_ += "<!--" + comment + "-->";
274         type = "isCom";
275         size_t iLenTemp = out_.length();
276         if (iLength_ > iPos_ + iLenTemp - 1) {
277             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
278                 iPos_ += iLenTemp;
279             } else {
280                 HILOG_ERROR("SetComment memcpy_s failed");
281             }
282         }
283     }
SetCData(std::string data)284     void XmlSerializer::SetCData(std::string data)
285     {
286         out_ = "";
287         if (type == "isStart" || type == "isAttri") {
288             SplicNsp();
289             out_.append(">");
290         }
291         if (type != "") {
292             NextItem();
293         }
294         data = Replace(data, "]]>", "]]]]><![CDATA[>");
295         out_ += "<![CDATA[" + data + "]]>";
296         type = "isCData";
297         size_t iLenTemp = out_.length();
298         if (iLength_ > iPos_ + iLenTemp - 1) {
299             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
300                 iPos_ += iLenTemp;
301             } else {
302                 HILOG_ERROR("SetCData memcpy_s failed");
303             }
304         }
305     }
SetDocType(const std::string & text)306     void XmlSerializer::SetDocType(const std::string &text)
307     {
308         out_ = "";
309         if (type == "isStart" || type == "isAttri") {
310             SplicNsp();
311             out_.append(">");
312         }
313         if (type != "") {
314             NextItem();
315         }
316         out_ += "<!DOCTYPE " + text + ">";
317         type = "isDocType";
318         size_t iLenTemp = out_.length();
319         if (iLength_ > iPos_ + iLenTemp - 1) {
320             if (memcpy_s(pStart_ + iPos_, iLength_ - iPos_, out_.c_str(), iLenTemp) == EOK) {
321                 iPos_ += iLenTemp;
322             } else {
323                 HILOG_ERROR("SetDocType memcpy_s failed");
324             }
325         }
326     }
327 
WriteEscaped(std::string s)328     void XmlSerializer::WriteEscaped(std::string s)
329     {
330         size_t len = s.length();
331         for (size_t i = 0; i < len; ++i) {
332             char c = s[i];
333             switch (c) {
334                 case '\'':
335                     out_.append("&apos;");
336                     break;
337                 case '\"':
338                     out_.append("&quot;");
339                     break;
340                 case '&':
341                     out_.append("&amp;");
342                     break;
343                 case '>':
344                     out_.append("&gt");
345                     break;
346                 case '<':
347                     out_.append("&lt;");
348                     break;
349                 default:
350                     out_ += c;
351             }
352         }
353     }
354 
XmlSerializerError()355     std::string XmlSerializer::XmlSerializerError()
356     {
357         return xmlSerializerError_;
358     }
359 
DealOptionInfo(napi_env env,napi_value napiObj)360     napi_value XmlPullParser::DealOptionInfo(napi_env env, napi_value napiObj)
361     {
362         std::vector<std::string> vctOptions = {
363             "supportDoctype", "ignoreNameSpace", "tagValueCallbackFunction",
364             "attributeValueCallbackFunction", "tokenValueCallbackFunction"
365         };
366         size_t vctLength = vctOptions.size();
367         for (size_t i = 0; i < vctLength; ++i) {
368             napi_value recvTemp = nullptr;
369             bool bRecv = false;
370             napi_get_named_property(env, napiObj, vctOptions[i].c_str(), &recvTemp);
371             napi_valuetype valuetype;
372             NAPI_CALL(env, napi_typeof(env, recvTemp, &valuetype));
373             if (valuetype == napi_boolean && (napi_get_value_bool(env, recvTemp, &bRecv)) == napi_ok) {
374                 switch (i) {
375                     case 0: // 0:supportDoctype
376                         bDoctype_ = bRecv;
377                         break;
378                     case 1: // 1:ignoreNameSpace
379                         bIgnoreNS_ = bRecv;
380                         break;
381                     default:
382                         break;
383                 }
384             } else if (valuetype == napi_function) {
385                 NAPI_ASSERT(env, recvTemp != nullptr, "Parameter is empty.");
386                 switch (i) {
387                     case 2: // 2:tagValueCallbackFunction
388                         tagFunc_ = recvTemp;
389                         break;
390                     case 3: // 3:attributeValueCallbackFunction
391                         attrFunc_ = recvTemp;
392                         break;
393                     case 4: // 4:tokenValueCallbackFunction
394                         tokenFunc_ = recvTemp;
395                         break;
396                     default:
397                         break;
398                 }
399             }
400         }
401         return nullptr;
402     }
403 
PushSrcLinkList(std::string strBuffer)404     void XmlPullParser::PushSrcLinkList(std::string strBuffer)
405     {
406         auto pNew = new SrcLinkList;
407         srcLinkList_->next = pNew;
408         pNew->strBuffer = strBuffer;
409         pNew->position = 0;
410         pNew->max = strBuffer.size();
411         srcLinkList_ = pNew;
412     }
413 
PopSrcLinkList()414     void XmlPullParser::PopSrcLinkList()
415     {
416         SrcLinkList* pTemp = srcLinkList_;
417         if (srcLinkList_) {
418             srcLinkList_ = srcLinkList_->next;
419         }
420         if (pTemp != nullptr) {
421             delete pTemp;
422             pTemp = nullptr;
423         }
424     }
425 
DealLength(size_t minimum)426     bool XmlPullParser::DealLength(size_t minimum)
427     {
428         while (srcLinkList_->next != nullptr) {
429             if (position_ < max_) {
430                 xmlPullParserError_ = "Unbalanced entity!";
431             }
432             PopSrcLinkList();
433             if (max_ - position_ >= minimum) {
434                 return true;
435             }
436         }
437         for (size_t i = 0; i < position_; i++) {
438             if (strXml_[i] == '\n') {
439                 bufferStartLine_++;
440                 bufferStartColumn_ = 0;
441             } else {
442                 bufferStartColumn_++;
443             }
444         }
445         if (keyInfo_ != "") {
446             keyInfo_.append(strXml_, 0, position_);
447         }
448 
449         if (max_ != position_) {
450             max_ -= position_;
451             for (size_t j = 0; j < max_; ++j) {
452                 strXml_[j] = strXml_[position_ + j];
453             }
454         } else {
455             max_ = 0;
456         }
457         if (position_ != strXml_.size()) {
458             position_ = 0;
459         }
460         if (strXml_.size() - max_ > 0 && position_ == 0) {
461             max_ += strXml_.size() - max_;
462             if (max_ >= minimum) {
463                 return true;
464             }
465         }
466         return false;
467     }
468 
GetNSCount(size_t iTemp)469     size_t XmlPullParser::GetNSCount(size_t iTemp)
470     {
471         if (iTemp > depth) {
472             xmlPullParserError_ = " IndexOutOfBoundsException";
473         }
474         return nspCounts_[depth];
475     }
476 
XmlPullParserError() const477     std::string XmlPullParser::XmlPullParserError() const
478     {
479         return xmlPullParserError_;
480     }
481 
ParseToken(napi_env env,napi_value thisVar) const482     bool XmlPullParser::ParseToken(napi_env env, napi_value thisVar) const
483     {
484         napi_value returnVal = nullptr;
485         size_t argc = 2; // 2: number of args
486         napi_value key = nullptr;
487         napi_create_int32(env, (int)type, &key);
488         napi_value parseInfo  = nullptr;
489         napi_create_object(env, &parseInfo);
490         auto object = new ParseInfo();
491         napi_wrap(env, parseInfo, object, nullptr, nullptr, nullptr);
492         static napi_property_descriptor xmlDesc[] = {
493             DECLARE_NAPI_FUNCTION("getDepth", XmlPullParser::ParseInfo::GetDepth),
494             DECLARE_NAPI_FUNCTION("getColumnNumber", XmlPullParser::ParseInfo::GetColumnNumber),
495             DECLARE_NAPI_FUNCTION("getLineNumber", XmlPullParser::ParseInfo::GetLineNumber),
496             DECLARE_NAPI_FUNCTION("getAttributeCount", XmlPullParser::ParseInfo::GetAttributeCount),
497             DECLARE_NAPI_FUNCTION("getName", XmlPullParser::ParseInfo::GetName),
498             DECLARE_NAPI_FUNCTION("getNamespace", XmlPullParser::ParseInfo::GetNamespace),
499             DECLARE_NAPI_FUNCTION("getPrefix", XmlPullParser::ParseInfo::GetPrefix),
500             DECLARE_NAPI_FUNCTION("getText", XmlPullParser::ParseInfo::GetText),
501             DECLARE_NAPI_FUNCTION("isEmptyElementTag", XmlPullParser::ParseInfo::IsEmptyElementTag),
502             DECLARE_NAPI_FUNCTION("isWhitespace", XmlPullParser::ParseInfo::IsWhitespace)
503         };
504         napi_define_properties(env, parseInfo, sizeof(xmlDesc) / sizeof(xmlDesc[0]), xmlDesc);
505         napi_set_named_property(env, parseInfo, "MainInfo", thisVar);
506         napi_value argv[2] = {key, parseInfo}; // 2: number of args
507         napi_call_function(env, parseInfo, tokenFunc_, argc, argv, &returnVal);
508         bool bRec = false;
509         napi_get_value_bool(env, returnVal, &bRec);
510         if (object != nullptr) {
511             delete object;
512             object = nullptr;
513         }
514         return bRec;
515     }
516 
ParseAttri(napi_env env,napi_value thisVar) const517     bool XmlPullParser::ParseAttri(napi_env env, napi_value thisVar) const
518     {
519         for (size_t i = 0; i < attriCount_; ++i) {
520             napi_value returnVal = nullptr;
521             size_t argc = 3; // 3: number of args
522             napi_value global = nullptr;
523             napi_get_global(env, &global);
524             napi_value key = nullptr;
525             napi_create_string_utf8(env, attributes[i * 4 + 2].c_str(), // 4 and 2: number of args
526                 attributes[i * 4 + 2].size(), &key); // 4 and 2: number of args
527             napi_value value = nullptr;
528             napi_create_string_utf8(env, attributes[i * 4 + 3].c_str(), // 4 and 3: number of args
529                 attributes[i * 4 + 3].size(), &value); // 3 and 4: number of args
530             napi_value argv[3] = {key, value, thisVar};
531             napi_call_function(env, global, attrFunc_, argc, argv, &returnVal);
532             bool bRec = false;
533             napi_get_value_bool(env, returnVal, &bRec);
534             if (!bRec) {
535                 return bRec;
536             }
537         }
538         return true;
539     }
540 
Parse(napi_env env,napi_value thisVar)541     void XmlPullParser::Parse(napi_env env, napi_value thisVar)
542     {
543         if (tagFunc_ || attrFunc_ || tokenFunc_) {
544             while (type != TagEnum::END_DOCUMENT) {
545                 ParseOneTag();
546                 bool bRec = false;
547                 if (tagFunc_ && type == TagEnum::START_TAG) {
548                     napi_value returnVal = nullptr;
549                     size_t argc = 3; // 3: number of args
550                     napi_value global = nullptr;
551                     napi_get_global(env, &global);
552                     napi_value key = nullptr;
553                     napi_create_string_utf8(env, name_.c_str(), name_.size(), &key);
554                     napi_value value = nullptr;
555                     napi_create_string_utf8(env, text_.c_str(), text_.size(), &value);
556                     napi_value argv[3] = {key, value, thisVar};
557                     napi_call_function(env, global, tagFunc_, argc, argv, &returnVal);
558                     napi_get_value_bool(env, returnVal, &bRec);
559                 }
560                 if (tagFunc_ && type == TagEnum::START_TAG && !bRec) {
561                     break;
562                 }
563                 if (attrFunc_ && attriCount_) {
564                     bRec = ParseAttri(env, thisVar);
565                     attriCount_ = 0;
566                 }
567                 if (attrFunc_ && attriCount_ && !bRec) {
568                     break;
569                 }
570                 if (tokenFunc_) {
571                     bRec = ParseToken(env, thisVar);
572                 }
573                 if (tokenFunc_ && !bRec) {
574                     break;
575                 }
576             }
577         }
578     }
579 
DealExclamationGroup()580     TagEnum XmlPullParser::DealExclamationGroup()
581     {
582         switch (strXml_[position_ + 2]) { // 2:  number of args
583             case 'D':
584                 return TagEnum::DOCDECL;
585             case '[':
586                 return TagEnum::CDSECT;
587             case '-':
588                 return TagEnum::COMMENT;
589             case 'E':
590                 switch (strXml_[position_ + 3]) { // 3:  number of args
591                     case 'L':
592                         return TagEnum::ELEMENTDECL;
593                     case 'N':
594                         return TagEnum::ENTITYDECL;
595                     default:
596                         break;
597                 }
598                 xmlPullParserError_ = "Unexpected <!";
599                 break;
600             case 'A':
601                 return TagEnum::ATTLISTDECL;
602             case 'N':
603                 return TagEnum::NOTATIONDECL;
604             default:
605                 break;
606         }
607         return TagEnum::ERROR1;
608     }
609 
DealLtGroup()610     TagEnum XmlPullParser::DealLtGroup()
611     {
612         if (position_ + 3 >= max_ && !DealLength(4)) { // 4: number of args 3: number of args
613             xmlPullParserError_ = ("Dangling <");
614         }
615         char cTemp = strXml_[position_ + 1];
616         if (cTemp == '/') {
617             return TagEnum::END_TAG;
618         } else if (cTemp == '?') {
619             std::string strXml = strXml_.substr(position_ + 2, 4);  // 2 and 4:position and length
620             MakeStrUpper(strXml);
621             if (max_ >= position_ + 5 && strXml == tagText_.XML) { // 5: number of args
622                 return TagEnum::XML_DECLARATION;
623             } else {
624                 return TagEnum::INSTRUCTION;
625             }
626         } else if (cTemp == '!') {
627             return DealExclamationGroup();
628         } else {
629             return TagEnum::START_TAG;
630         }
631     }
632 
ParseTagType(bool inDeclaration)633     TagEnum XmlPullParser::ParseTagType(bool inDeclaration)
634     {
635         if (bStartDoc_) {
636             bStartDoc_ = false;
637             return TagEnum::START_DOCUMENT;
638         }
639         if (position_ >= max_ && !DealLength(1)) {
640             return TagEnum::END_DOCUMENT;
641         }
642         switch (strXml_[position_]) {
643             case '&':
644                 return TagEnum::ENTITY_REFERENCE;
645             case '<':
646                 return DealLtGroup();
647             case '%':
648                 return inDeclaration ? TagEnum::PARAMETER_ENTITY_REF : TagEnum::TEXT;
649             default:
650                 return TagEnum::TEXT;
651         }
652     }
653 
MakeStrUpper(std::string & src) const654     void XmlPullParser::MakeStrUpper(std::string &src) const
655     {
656         size_t i = 0;
657 
658         while (i < src.size()) {
659             if (src[i] >= 'A' && src[i] <= 'Z') {
660                 src[i] += 32; // 32: number of args
661             }
662             ++i;
663         }
664     }
665 
SkipText(std::string chars)666     void XmlPullParser::SkipText(std::string chars)
667     {
668         if (position_ + chars.size() > max_ && !DealLength(chars.size())) {
669             xmlPullParserError_ = "expected: '" + chars + "' but was EOF";
670             return;
671         }
672         size_t len = chars.length();
673         if (strXml_.substr(position_, len) != chars) {
674             xmlPullParserError_ = "expected: \"" + chars + "\" but was \"" + strXml_.substr(position_, len) + "...\"";
675         }
676         position_ += len;
677     }
678 
PriorDealChar()679     int XmlPullParser::PriorDealChar()
680     {
681         if (position_ < max_ || DealLength(1)) {
682             return strXml_[position_];
683         }
684         return -1;
685     }
SkipChar(char expected)686     void XmlPullParser::SkipChar(char expected)
687     {
688         int c = PriorDealChar();
689         if (c != expected) {
690             xmlPullParserError_ = "expected:";
691             if (c == -1) {
692                 return;
693             }
694         }
695         position_++;
696     }
697 
ParseNameInner(size_t start)698     std::string XmlPullParser::ParseNameInner(size_t start)
699     {
700         std::string result = "";
701         char c = 0;
702         while (true) {
703             if (position_ >= max_) {
704                 result.append(strXml_, start, position_ - start);
705                 if (!DealLength(1)) {
706                     return result;
707                 }
708                 start = position_;
709             }
710             c = strXml_[position_];
711             if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
712                 (c >= '0' && c <= '9') || c == '_' || c == '-' ||
713                 c == ':' || c == '.') {
714                 position_++;
715                 continue;
716             }
717             result.append(strXml_, start, position_ - start);
718             return result;
719         }
720     }
721 
ParseName()722     std::string XmlPullParser::ParseName()
723     {
724         if (position_ >= max_ && !DealLength(1)) {
725             xmlPullParserError_ = "name expected";
726             return "";
727         }
728         size_t start = position_;
729         char c = strXml_[position_];
730         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
731             c == '_' || c == ':' || relaxed) {
732             position_++;
733         } else {
734             xmlPullParserError_ = "name expected";
735             return "";
736         }
737         return ParseNameInner(start);
738     }
739 
SkipInvalidChar()740     void XmlPullParser::SkipInvalidChar()
741     {
742         while (position_ < max_ || DealLength(1)) {
743             unsigned char temp = strXml_[position_];
744             if (temp > ' ') {
745                 break;
746             }
747             position_++;
748         }
749     }
750 
ParseEntityFunc(size_t start,std::string & out,bool isEntityToken,TextEnum textEnum)751     void XmlPullParser::ParseEntityFunc(size_t start, std::string &out, bool isEntityToken, TextEnum textEnum)
752     {
753         std::string strEntity = out.substr(start + 1, out.length() - 1);
754         if (isEntityToken) {
755             name_ = strEntity;
756         }
757         if (strEntity.size() && strEntity[0] == '#') {
758             int c = 0;
759             if (strEntity.size() >= 2 && strEntity[1] == 'x') { // 2: number of args
760                 c = std::stoi(strEntity.substr(2), nullptr, 16); // 16: number of args 2: number of args
761             } else {
762                 c = std::stoi(strEntity.substr(1), nullptr);
763             }
764             out = "";
765             out += static_cast<char>(c);
766             bUnresolved_ = false;
767             return;
768         }
769         if (textEnum == TextEnum::ENTITY_DECL) {
770             return;
771         }
772         if (DEFAULT_ENTITIES.count(strEntity) != 0) {
773             out = "";
774             bUnresolved_ = false;
775             out.append(strEntity);
776             return;
777         }
778         std::string resolved = " ";
779         if (documentEntities.size() != 0 && (resolved = strEntity) != "") {
780             out = "";
781             bUnresolved_ = false;
782             if (bDocDecl) {
783                 PushSrcLinkList(resolved);
784             } else {
785                 out.append(resolved);
786             }
787             return;
788         }
789         if (sysInfo_ != "") {
790             out = "";
791             return;
792         }
793         bUnresolved_ = true;
794     }
795 
ParseEntity(std::string & out,bool isEntityToken,bool throwOnResolveFailure,TextEnum textEnum)796     void XmlPullParser::ParseEntity(std::string &out, bool isEntityToken, bool throwOnResolveFailure, TextEnum textEnum)
797     {
798         size_t start = out.length();
799         if (strXml_[position_++] != '&') {
800             xmlPullParserError_ = "Should not be reached";
801         }
802         out += '&';
803         while (true) {
804             int c = PriorDealChar();
805             if (c == ';') {
806                 out += ';';
807                 position_++;
808                 break;
809             } else if (c >= 128 || // 128: number of args
810                 (c >= '0' && c <= '9') ||
811                 (c >= 'a' && c <= 'z') ||
812                 (c >= 'A' && c <= 'Z') ||
813                 c == '_' ||
814                 c == '-' ||
815                 c == '#') {
816                 position_++;
817                 out.push_back(static_cast<char>(c));
818             } else if (relaxed) {
819                 return;
820             } else {
821                 xmlPullParserError_ = "unterminated entity ref";
822             }
823         }
824         ParseEntityFunc(start, out, isEntityToken, textEnum);
825     }
826 
ParseTagValueFunc(char & c,bool bFlag,TextEnum textEnum,size_t & start,std::string & result)827     bool XmlPullParser::ParseTagValueFunc(char &c, bool bFlag, TextEnum textEnum,
828         size_t &start, std::string &result)
829     {
830         if (c == '\r') {
831             if ((position_ + 1 < max_ || DealLength(2)) && strXml_[position_ + 1] == '\n') { // 2: number of args
832                 position_++;
833             }
834             c = (textEnum == TextEnum::ATTRI) ? ' ' : '\n';
835         } else if (c == '\n') {
836             c = ' ';
837         } else if (c == '&') {
838             bWhitespace_ = false;
839             ParseEntity(result, false, bFlag, textEnum);
840             start = position_;
841             return false;
842         } else if (c == '<') {
843             if (textEnum == TextEnum::ATTRI) {
844                 xmlPullParserError_ = "Illegal: \"<\" inside attribute value";
845             }
846             bWhitespace_ = false;
847         } else if (c == ']') {
848             if ((position_ + 2 < max_ || DealLength(3)) && // 2: number of args 3: number of args
849                 strXml_[position_ + 1] == ']' && strXml_[position_ + 2] == '>') { // 2: number of args
850                 xmlPullParserError_ = "Illegal: \"]]>\" outside CDATA section";
851             }
852             bWhitespace_ = false;
853         } else if (c == '%') {
854             xmlPullParserError_ = "This parser doesn't support parameter entities";
855         } else {
856             xmlPullParserError_ = "AssertionError";
857         }
858         return true;
859     }
860 
DealWhiteSpace(unsigned char c)861     void XmlPullParser::DealWhiteSpace(unsigned char c)
862     {
863         if (bWhitespace_ && c <= ' ') {
864             bWhitespace_ = true;
865         } else {
866             bWhitespace_ = false;
867         }
868     }
869 
ParseTagValueInner(size_t & start,std::string & result,char delimiter,TextEnum textEnum,bool bFlag)870     size_t XmlPullParser::ParseTagValueInner(size_t &start, std::string &result,
871         char delimiter, TextEnum textEnum, bool bFlag)
872     {
873         if (position_ >= max_) {
874             if (start < position_) {
875                 result.append(strXml_, start, position_ - start);
876             }
877             if (!DealLength(1)) {
878                 result = (result != "" ? result : "");
879                 return 0;
880             }
881             start = position_;
882         }
883         unsigned char c = strXml_[position_];
884         if (c == delimiter ||
885             (delimiter == ' ' && (c <= ' ' || c == '>')) ||
886             (c == '&' && !bFlag)) {
887                 return 1;
888             }
889         if (c != '\r' && (c != '\n' || textEnum != TextEnum::ATTRI) &&
890             c != '&' && c != '<' && (c != ']' || textEnum != TextEnum::TEXT)
891             && (c != '%' || textEnum != TextEnum::ENTITY_DECL)) {
892                 DealWhiteSpace(c);
893                 position_++;
894                 return 2; // 2: break flag
895         }
896         result.append(strXml_, start, position_ - start);
897         return c;
898     }
899 
ParseTagValue(char delimiter,bool resolveEntities,bool throwOnResolveFailure,TextEnum textEnum)900     std::string XmlPullParser::ParseTagValue(char delimiter, bool resolveEntities,
901         bool throwOnResolveFailure, TextEnum textEnum)
902     {
903         size_t start = position_;
904         std::string result = "";
905         if (textEnum == TextEnum::TEXT && text_ != "") {
906             result.append(text_);
907         }
908         while (true) {
909             char cRecv = static_cast<char>(ParseTagValueInner(start, result, delimiter, textEnum, resolveEntities));
910             if (cRecv == 0) {
911                 return result;
912             } else if (cRecv == 1) {
913                 break;
914             } else if (cRecv == 2) { // 2: break flag
915                 continue;
916             } else if (!ParseTagValueFunc(cRecv, throwOnResolveFailure, textEnum, start, result)) {
917                 continue;
918             }
919             ++position_;
920             result = result + static_cast<char>(cRecv);
921             start = position_;
922         }
923         result.append(strXml_, start, position_ - start);
924         return result;
925     }
926 
GetNamespace(const std::string & prefix)927     std::string XmlPullParser::GetNamespace(const std::string &prefix)
928     {
929         size_t temp = GetNSCount(depth) << 1;
930         if (temp) {
931             size_t i = temp - 2; // 2: number of args
932             for (; i >= 0; i -= 2) { // 2: number of args
933                 if (prefix == "" && nspStack_[i] == "") {
934                     return nspStack_[i + 1];
935                 } else if (prefix == nspStack_[i]) {
936                     return nspStack_[i + 1];
937                 }
938                 if (!i) {
939                     break;
940                 }
941             }
942         }
943         return "";
944     }
945 
Replace(std::string & strTemp,std::string strSrc,std::string strDes) const946     void XmlPullParser::Replace(std::string& strTemp, std::string strSrc, std::string strDes) const
947     {
948         size_t iPos = 0;
949         while ((iPos = strTemp.find(strSrc)) != std::string::npos) {
950             strTemp.replace(iPos, strSrc.size(), strDes);
951         }
952     }
ParseNspFunc(size_t & i,const std::string & attrName,bool & any)953     void XmlPullParser::ParseNspFunc(size_t &i, const std::string &attrName, bool &any)
954     {
955         size_t j = (nspCounts_[depth]++) << 1;
956         size_t uiSize = nspStack_.size();
957         if (uiSize < j + 2) { // 2: number of args
958             nspStack_.resize(j + 16); // 16: number of args
959         }
960         nspStack_[j] = attrName;
961         nspStack_[j + 1] = attributes[i + 3]; // 3: number of args
962         if (attrName != "" && attributes[i + 3].empty()) { // 3: number of args
963             xmlPullParserError_ = "illegal empty namespace";
964         }
965         if (bKeepNsAttri) {
966             attributes[i] = "http://www.w3.org/2000/xmlns/";
967             any = true;
968         } else {
969             for (size_t iCount = i; iCount < ((--attriCount_) << 2); ++iCount) { // 2: number of args
970                 attributes[iCount] = attributes[iCount + 4]; // 4: number of args
971             }
972             i -= 4; // 4:
973         }
974     }
ParseNspFunction()975     void XmlPullParser::ParseNspFunction()
976     {
977         int i = (attriCount_ << 2) - 4; // 4: number of args 2: number of args
978         for (; i >= 0; i -= 4) { // 4: number of args
979             std::string attrName = attributes[i + 2]; // 2: number of args
980             size_t cut = attrName.find(':');
981             if (cut == 0 && !relaxed) {
982                 xmlPullParserError_ = "illegal attribute name: ";
983             } else if (cut != std::string::npos) {
984                 std::string attrPrefix = attrName.substr(0, cut);
985                 attrName = attrName.substr(cut + 1);
986                 std::string attrNs = GetNamespace(attrPrefix);
987                 if (attrNs == "" && !relaxed) {
988                     xmlPullParserError_ = ("Undefined Prefix: " + attrPrefix + " in ");
989                 }
990                 attributes[i] = attrNs;
991                 attributes[i + 1] = attrPrefix;
992                 attributes[i + 2] = attrName; // 2: number of args
993             }
994         }
995     }
ParseNsp()996     bool XmlPullParser::ParseNsp()
997     {
998         bool any = false;
999         size_t cut = 0;
1000         for (size_t i = 0; i < (attriCount_ << 2); i += 4) { // 2 and 4: number of args
1001             std::string attrName = attributes[i + 2]; // 2: number of args
1002             cut = attrName.find(':');
1003             std::string prefix;
1004             if (cut != std::string::npos) {
1005                 prefix = attrName.substr(0, cut);
1006                 attrName = attrName.substr(cut + 1);
1007             } else if (attrName == ("xmlns")) {
1008                 prefix = attrName;
1009                 attrName = "";
1010             } else {
1011                 continue;
1012             }
1013             if (!(prefix == "xmlns")) {
1014                 any = true;
1015             } else {
1016                 ParseNspFunc(i, attrName, any);
1017             }
1018         }
1019         if (any) {
1020             ParseNspFunction();
1021         }
1022         cut = name_.find(':');
1023         if (cut == 0) {
1024             xmlPullParserError_ = "illegal tag name: " + name_;
1025         }
1026         if (cut != std::string::npos) {
1027             prefix_ = name_.substr(0, cut);
1028             name_ = name_.substr(cut + 1);
1029         }
1030         namespace_ = GetNamespace(prefix_);
1031         return any;
1032     }
1033 
ParseStartTagFuncDeal(bool throwOnResolveFailure)1034     bool XmlPullParser::ParseStartTagFuncDeal(bool throwOnResolveFailure)
1035     {
1036         std::string attrName = ParseName();
1037         int i = (attriCount_++) * 4; // 4: number of args
1038         attributes.resize(attributes.size() + 4); // 4: number of args
1039         attributes[i] = "";
1040         attributes[i + 1] = "";
1041         attributes[i + 2] = attrName; // 2: number of args
1042         SkipInvalidChar();
1043         if (position_ >= max_ && !DealLength(1)) {
1044             xmlPullParserError_ = "UNEXPECTED_EOF";
1045             return false;
1046         }
1047         if (strXml_[position_] == '=') {
1048             position_++;
1049             SkipInvalidChar();
1050             if (position_ >= max_) {
1051                 xmlPullParserError_ = "UNEXPECTED_EOF";
1052                 return false;
1053             }
1054             char delimiter = strXml_[position_];
1055             if (delimiter == '\'' || delimiter == '"') {
1056                 position_++;
1057             } else if (relaxed) {
1058                 delimiter = ' ';
1059             } else {
1060                 xmlPullParserError_ = "attr value delimiter missing!";
1061             }
1062             attributes[i + 3] = ParseTagValue(delimiter, true, // 3: number of args
1063                 throwOnResolveFailure, TextEnum::ATTRI); // 3: number of args
1064             if (delimiter != ' ' && PriorDealChar() == delimiter) {
1065                 position_++;
1066             }
1067         } else {
1068             attributes[i + 3] = attrName; // 3: number of args
1069         }
1070         return true;
1071     }
1072 
ParseStartTagFunc(bool xmldecl,bool throwOnResolveFailure)1073     bool XmlPullParser::ParseStartTagFunc(bool xmldecl, bool throwOnResolveFailure)
1074     {
1075         while (true) {
1076             SkipInvalidChar();
1077             if (position_ >= max_ && DealLength(1)) {
1078                 xmlPullParserError_ = "UNEXPECTED_EOF";
1079                 return false;
1080             }
1081             unsigned char temp = strXml_[position_];
1082             if (xmldecl) {
1083                 if (temp == '?') {
1084                     position_++;
1085                     SkipChar('>');
1086                     return false;
1087                 }
1088             } else {
1089                 if (temp == '/') {
1090                     bEndFlag_ = true;
1091                     position_++;
1092                     SkipInvalidChar();
1093                     SkipChar('>');
1094                     break;
1095                 } else if (temp == '>') {
1096                     position_++;
1097                     break;
1098                 }
1099             }
1100             bool bRecv = ParseStartTagFuncDeal(throwOnResolveFailure);
1101             if (!bRecv) {
1102                 return false;
1103             }
1104         }
1105         return true;
1106     }
1107 
ParseStartTag(bool xmldecl,bool throwOnResolveFailure)1108     void XmlPullParser::ParseStartTag(bool xmldecl, bool throwOnResolveFailure)
1109     {
1110         if (!xmldecl) {
1111             SkipChar('<');
1112         }
1113         name_ = ParseName();
1114         attriCount_ = 0;
1115         bool bRecv = ParseStartTagFunc(xmldecl, throwOnResolveFailure);
1116         if (!bRecv) {
1117             return;
1118         }
1119         size_t sp = depth++ * 4; // 4: number of args
1120         elementStack_.resize(sp + 4); // 4: number of args
1121         elementStack_[sp + 3] = name_; // 3: number of args
1122         if (depth >= nspCounts_.size()) {
1123             nspCounts_.resize(depth + 4); // 4: number of args
1124         }
1125         nspCounts_[depth] = nspCounts_[depth - 1];
1126         if (!bIgnoreNS_) {
1127             ParseNsp();
1128         } else {
1129             namespace_ = "";
1130         }
1131         if (defaultAttributes.size() != 0) {
1132             std::map<std::string, std::string> elementDefaultAttributes = defaultAttributes[name_];
1133             if (elementDefaultAttributes.size() != 0) {
1134                 for (std::map<std::string, std::string>::iterator iter = elementDefaultAttributes.begin();
1135                     iter != elementDefaultAttributes.end(); ++iter) {
1136                 }
1137             }
1138         }
1139         elementStack_[sp] = namespace_;
1140         elementStack_[sp + 1] = prefix_;
1141         elementStack_[sp + 2] = name_; // 2: number of args
1142     }
1143 
ParseDeclaration()1144     void XmlPullParser::ParseDeclaration()
1145     {
1146         if (bufferStartLine_ != 0 || bufferStartColumn_ != 0 || position_ != 0) {
1147             xmlPullParserError_ = "processing instructions must not start with xml";
1148         }
1149         SkipText(tagText_.START_PROCESSING_INSTRUCTION);
1150         ParseStartTag(true, true);
1151         if (attriCount_ < 1 || attributes[2] != "version") { // 2: number of args
1152             xmlPullParserError_ = "version expected";
1153         }
1154         version_ = attributes[3]; // 3: number of args
1155         size_t pos = 1;
1156         if (pos < attriCount_ && (attributes[2 + 4]) == "encoding") { // 4: number of args 2: number of args
1157             encoding_ = attributes[3 + 4]; // 3: number of args 4: number of args
1158             pos++;
1159         }
1160         if (pos < attriCount_ && (attributes[4 * pos + 2]) == "standalone") { // 4: number of args 2: number of args
1161             std::string st = attributes[3 + 4 * pos]; // 3: number of args 4: number of args
1162             if (st == "yes") {
1163                 bAlone_ = true;
1164             } else if (st == "no") {
1165                 bAlone_ = false;
1166             } else {
1167                 xmlPullParserError_ = "illegal standalone value: " + st;
1168             }
1169             pos++;
1170         }
1171         if (pos != attriCount_) {
1172             xmlPullParserError_ = "unexpected attributes in XML declaration";
1173         }
1174         bWhitespace_ = true;
1175         text_ = "";
1176     }
1177 
ParseEndTag()1178     void XmlPullParser::ParseEndTag()
1179     {
1180         SkipChar('<');
1181         SkipChar('/');
1182         name_ = ParseName();
1183         SkipInvalidChar();
1184         SkipChar('>');
1185         if (depth == 0) {
1186             xmlPullParserError_ = "read end tag " + name_ + " with no tags open";
1187             type = TagEnum::COMMENT;
1188             return;
1189         }
1190         size_t sp = (depth - 1) * 4; // 4: number of args
1191         if (name_ == elementStack_[sp + 3]) { // 3: number of args
1192             namespace_ = elementStack_[sp];
1193             prefix_ = elementStack_[sp + 1];
1194             name_ = elementStack_[sp + 2]; // 2: number of args
1195         } else if (!relaxed) {
1196             xmlPullParserError_ = "expected: /" + elementStack_[sp + 3] + " read: " + name_; // 3: number of args
1197         }
1198     }
1199 
ParseDelimiterInfo(std::string delimiter,bool returnText)1200     std::string XmlPullParser::ParseDelimiterInfo(std::string delimiter, bool returnText)
1201     {
1202         size_t start = position_;
1203         std::string result = "";
1204         if (returnText && text_ != "") {
1205             result.append(text_);
1206         }
1207         bool bFlag = true;
1208         while (bFlag) {
1209             if (position_ + (delimiter).length() > max_) {
1210                 if (start < position_ && returnText) {
1211                     result.append(strXml_, start, position_ - start);
1212                 }
1213                 if (!DealLength(delimiter.length())) {
1214                     type = TagEnum::COMMENT;
1215                     return "";
1216                 }
1217                 start = position_;
1218             }
1219             size_t i = 0;
1220             for (; i < delimiter.length(); i++) {
1221                 if (strXml_[position_ + i] != delimiter[i]) {
1222                     position_++;
1223                     break;
1224                 }
1225             }
1226             if (i == delimiter.length()) {
1227                 bFlag = false;
1228             }
1229         }
1230         size_t end = position_;
1231         position_ += delimiter.length();
1232         if (!returnText) {
1233             return "";
1234         } else {
1235             result.append(strXml_, start, end - start);
1236             return result;
1237         }
1238     }
ParseDelimiter(bool returnText)1239     std::string XmlPullParser::ParseDelimiter(bool returnText)
1240     {
1241         int quote = PriorDealChar();
1242         std::string delimiter;
1243         if (quote == '"') {
1244             delimiter = tagText_.DOUBLE_QUOTE;
1245         } else if (quote == '\'') {
1246             delimiter = tagText_.SINGLE_QUOTE;
1247         } else {
1248             xmlPullParserError_ = "Expected a quoted std::string ";
1249         }
1250         position_++;
1251         return ParseDelimiterInfo(delimiter, returnText);
1252     }
1253 
ParserDoctInnerInfo(bool requireSystemName,bool assignFields)1254     bool XmlPullParser::ParserDoctInnerInfo(bool requireSystemName, bool assignFields)
1255     {
1256         SkipInvalidChar();
1257         int c = PriorDealChar();
1258         if (c == 'S') {
1259             SkipText(tagText_.SYSTEM);
1260         } else if (c == 'P') {
1261             SkipText(tagText_.PUBLIC);
1262             SkipInvalidChar();
1263             if (assignFields) {
1264                 pubInfo_ = ParseDelimiter(true);
1265             } else {
1266                 ParseDelimiter(false);
1267             }
1268         } else {
1269             return false;
1270         }
1271         SkipInvalidChar();
1272         if (!requireSystemName) {
1273             int delimiter = PriorDealChar();
1274             if (delimiter != '"' && delimiter != '\'') {
1275                 return true; // no system name!
1276             }
1277         }
1278         if (assignFields) {
1279             sysInfo_ = ParseDelimiter(true);
1280         } else {
1281             ParseDelimiter(false);
1282         }
1283         return true;
1284     }
1285 
ParseComment(bool returnText)1286     void XmlPullParser::ParseComment(bool returnText)
1287     {
1288         SkipText(tagText_.START_COMMENT);
1289         if (relaxed) {
1290             std::string strTemp = ParseDelimiterInfo(tagText_.END_COMMENT, returnText);
1291             if (returnText) {
1292                 text_ = strTemp;
1293             }
1294         }
1295         std::string commentText = ParseDelimiterInfo(tagText_.COMMENT_DOUBLE_DASH, returnText);
1296         if (PriorDealChar() != '>') {
1297             xmlPullParserError_ = "Comments may not contain -- ";
1298         }
1299         position_++;
1300         if (returnText) {
1301             text_ = commentText;
1302         }
1303     }
ParseSpecText()1304     void XmlPullParser::ParseSpecText()
1305     {
1306         SkipInvalidChar();
1307         int c = PriorDealChar();
1308         if (c == '(') {
1309             int iDepth = 0;
1310             do {
1311                 if (c == '(') {
1312                     iDepth++;
1313                 } else if (c == ')') {
1314                     iDepth--;
1315                 } else if (c == -1) {
1316                     xmlPullParserError_ = "Unterminated element content spec ";
1317                 }
1318                 position_++;
1319                 c = PriorDealChar();
1320             } while (iDepth > 0);
1321             if (c == '*' || c == '?' || c == '+') {
1322                 position_++;
1323             }
1324         } else if (c == tagText_.EMPTY[0]) {
1325             SkipText(tagText_.EMPTY);
1326         } else if (c == tagText_.ANY[0]) {
1327             SkipText(tagText_.ANY);
1328         } else {
1329             xmlPullParserError_ = "Expected element content spec ";
1330         }
1331     }
ParseInnerEleDec()1332     void XmlPullParser::ParseInnerEleDec()
1333     {
1334         SkipText(tagText_.START_ELEMENT);
1335         SkipInvalidChar();
1336         ParseName();
1337         ParseSpecText();
1338         SkipInvalidChar();
1339         SkipChar('>');
1340     }
1341 
ParseInnerAttriDeclFunc(int & c)1342     void XmlPullParser::ParseInnerAttriDeclFunc(int &c)
1343     {
1344         if (c == '(') {
1345             position_++;
1346             while (true) {
1347                 SkipInvalidChar();
1348                 ParseName();
1349                 SkipInvalidChar();
1350                 c = PriorDealChar();
1351                 if (c == ')') {
1352                     position_++;
1353                     break;
1354                 } else if (c == '|') {
1355                     position_++;
1356                 } else {
1357                     xmlPullParserError_ = "Malformed attribute type ";
1358                 }
1359             }
1360         } else {
1361             ParseName();
1362         }
1363     }
1364 
ParseInnerAttriDecl()1365     void XmlPullParser::ParseInnerAttriDecl()
1366     {
1367         SkipText(tagText_.START_ATTLIST);
1368         SkipInvalidChar();
1369         std::string elementName = ParseName();
1370         while (true) {
1371             SkipInvalidChar();
1372             int c = PriorDealChar();
1373             if (c == '>') {
1374                 position_++;
1375                 return;
1376             }
1377             std::string attributeName = ParseName();
1378             SkipInvalidChar();
1379             if (position_ + 1 >= max_ && !DealLength(2)) { // 2: lengths
1380                 xmlPullParserError_ = "Malformed attribute list ";
1381             }
1382             if (strXml_[position_] == tagText_.NOTATION[0] && strXml_[position_ + 1] == tagText_.NOTATION[1]) {
1383                 SkipText(tagText_.NOTATION);
1384                 SkipInvalidChar();
1385             }
1386             c = PriorDealChar();
1387             ParseInnerAttriDeclFunc(c);
1388             SkipInvalidChar();
1389             c = PriorDealChar();
1390             if (c == '#') {
1391                 position_++;
1392                 c = PriorDealChar();
1393                 if (c == 'R') {
1394                     SkipText(tagText_.REQUIRED);
1395                 } else if (c == 'I') {
1396                     SkipText(tagText_.IMPLIED);
1397                 } else if (c == 'F') {
1398                     SkipText(tagText_.FIXED);
1399                 } else {
1400                     xmlPullParserError_ = "Malformed attribute type";
1401                 }
1402                 SkipInvalidChar();
1403                 c = PriorDealChar();
1404             }
1405             if (c == '"' || c == '\'') {
1406                 position_++;
1407                 std::string value = ParseTagValue(static_cast<char>(c), true, true, TextEnum::ATTRI);
1408                 if (PriorDealChar() == c) {
1409                     position_++;
1410                 }
1411             }
1412         }
1413     }
1414 
ParseEntityDecl()1415     void XmlPullParser::ParseEntityDecl()
1416     {
1417         SkipText(tagText_.START_ENTITY);
1418         bool generalEntity = true;
1419         SkipInvalidChar();
1420         if (PriorDealChar() == '%') {
1421             generalEntity = false;
1422             position_++;
1423             SkipInvalidChar();
1424         }
1425         std::string name = ParseName();
1426         SkipInvalidChar();
1427         int quote = PriorDealChar();
1428         std::string entityValue;
1429         if (quote == '"' || quote == '\'') {
1430             position_++;
1431             entityValue = ParseTagValue(static_cast<char>(quote), true, false, TextEnum::ENTITY_DECL);
1432             if (PriorDealChar() == quote) {
1433                 position_++;
1434             }
1435         } else if (ParserDoctInnerInfo(true, false)) {
1436             entityValue = "";
1437             SkipInvalidChar();
1438             if (PriorDealChar() == tagText_.NDATA[0]) {
1439                 SkipText(tagText_.NDATA);
1440                 SkipInvalidChar();
1441                 ParseName();
1442             }
1443         } else {
1444             xmlPullParserError_ = "Expected entity value or external ID";
1445         }
1446         if (generalEntity && bDocDecl) {
1447             documentEntities[name] = entityValue;
1448         }
1449         SkipInvalidChar();
1450         SkipChar('>');
1451     }
ParseInneNotaDecl()1452     void XmlPullParser::ParseInneNotaDecl()
1453     {
1454         SkipText(tagText_.START_NOTATION);
1455         SkipInvalidChar();
1456         ParseName();
1457         if (!ParserDoctInnerInfo(false, false)) {
1458             xmlPullParserError_ = "Expected external ID or public ID for notation ";
1459         }
1460         SkipInvalidChar();
1461         SkipChar('>');
1462     }
ReadInternalSubset()1463     void XmlPullParser::ReadInternalSubset()
1464     {
1465         SkipChar('[');
1466         while (true) {
1467             SkipInvalidChar();
1468             if (PriorDealChar() == ']') {
1469                 position_++;
1470                 return;
1471             }
1472             TagEnum declarationType = ParseTagType(true);
1473             switch (declarationType) {
1474                 case TagEnum::ELEMENTDECL:
1475                     ParseInnerEleDec();
1476                     break;
1477                 case TagEnum::ATTLISTDECL:
1478                     ParseInnerAttriDecl();
1479                     break;
1480                 case TagEnum::ENTITYDECL:
1481                     ParseEntityDecl();
1482                     break;
1483                 case TagEnum::NOTATIONDECL:
1484                     ParseInneNotaDecl();
1485                     break;
1486                 case TagEnum::INSTRUCTION:
1487                     SkipText(tagText_.START_PROCESSING_INSTRUCTION);
1488                     ParseDelimiterInfo(tagText_.END_PROCESSING_INSTRUCTION, false);
1489                     break;
1490                 case TagEnum::COMMENT:
1491                     ParseComment(false);
1492                     break;
1493                 case TagEnum::PARAMETER_ENTITY_REF:
1494                     xmlPullParserError_ = "Parameter entity references are not supported ";
1495                     break;
1496                 default:
1497                     xmlPullParserError_ = "Unexpected token";
1498                     break;
1499             }
1500         }
1501     }
ParseDoctype(bool saveDtdText)1502     void XmlPullParser::ParseDoctype(bool saveDtdText)
1503     {
1504         SkipText(tagText_.START_DOCTYPE);
1505         size_t startPosition = 0;
1506         if (saveDtdText) {
1507             keyInfo_ = "";
1508             startPosition = position_;
1509         }
1510         SkipInvalidChar();
1511         ParseName();
1512         ParserDoctInnerInfo(true, true);
1513         SkipInvalidChar();
1514         if (PriorDealChar() == '[') {
1515             ReadInternalSubset();
1516         }
1517         SkipInvalidChar();
1518         if (saveDtdText) {
1519             keyInfo_.append(strXml_, 0, position_);
1520             keyInfo_ = keyInfo_.substr(startPosition);
1521             text_ = keyInfo_;
1522             keyInfo_ = "";
1523         }
1524         SkipChar('>');
1525     }
1526 
ParseText()1527     void XmlPullParser::ParseText()
1528     {
1529         text_ = ParseTagValue('<', false, false, TextEnum::TEXT);
1530         std::string strTemp = text_;
1531         Replace(strTemp, "\r", "");
1532         Replace(strTemp, "\n", "");
1533         Replace(strTemp, " ", "");
1534         if ((depth == 0 && bWhitespace_) || strTemp.size() == 0) {
1535             type = TagEnum::WHITESPACE;
1536         }
1537     }
1538 
ParseCdect()1539     void XmlPullParser::ParseCdect()
1540     {
1541         SkipText(tagText_.START_CDATA);
1542         text_ = ParseDelimiterInfo(tagText_.END_CDATA, true);
1543     }
1544 
ParseOneTagFunc()1545     TagEnum XmlPullParser::ParseOneTagFunc()
1546     {
1547         switch (type) {
1548             case TagEnum::START_DOCUMENT:
1549                 return type;
1550             case TagEnum::START_TAG: {
1551                 ParseStartTag(false, false);
1552                 return type; }
1553             case TagEnum::END_TAG: {
1554                 ParseEndTag();
1555                 return type; }
1556             case TagEnum::END_DOCUMENT:
1557                 return type;
1558             case TagEnum::ENTITY_REFERENCE: {
1559                 std::string entityTextBuilder;
1560                 ParseEntity(entityTextBuilder, true, false, TextEnum::TEXT);
1561                 text_ = entityTextBuilder;
1562                 return TagEnum::OK;
1563                 }
1564             case TagEnum::TEXT:
1565                 ParseText();
1566                 return TagEnum::OK;
1567             case TagEnum::CDSECT:
1568                 ParseCdect();
1569                 return TagEnum::OK;
1570             case TagEnum::COMMENT:
1571                 ParseComment(true);
1572                 return TagEnum::OK;
1573             case TagEnum::INSTRUCTION:
1574                 ParseInstruction();
1575                 return TagEnum::OK;
1576             case TagEnum::DOCDECL:
1577                 ParseDoctype(true);
1578                 return TagEnum::OK;
1579             default:
1580                 xmlPullParserError_ = "Unexpected token";
1581                 return TagEnum::ERROR1;
1582         }
1583     }
1584 
ParseOneTag()1585     TagEnum XmlPullParser::ParseOneTag()
1586     {
1587         if (type == TagEnum::END_TAG) {
1588             depth--;
1589         }
1590         if (bEndFlag_) {
1591             bEndFlag_ = false;
1592             type = TagEnum::END_TAG;
1593             return type;
1594         }
1595         ParserPriorDeal();
1596         while (true) {
1597             TagEnum typeTem = ParseOneTagFunc();
1598             if (typeTem == TagEnum::ERROR1) {
1599                 return TagEnum::ERROR1;
1600             } else if (typeTem != TagEnum::OK) {
1601                 return typeTem;
1602             }
1603             if (depth == 0 && (type == TagEnum::ENTITY_REFERENCE || type == TagEnum::TEXT || type == TagEnum::CDSECT)) {
1604                 xmlPullParserError_ = "Unexpected token";
1605             }
1606             if (type == TagEnum::DOCDECL && (!bDoctype_)) {
1607                 ParseOneTag();
1608             }
1609             return type;
1610         }
1611     }
1612 
ParserPriorDeal()1613     void XmlPullParser::ParserPriorDeal()
1614     {
1615         type = ParseTagType(false);
1616         if (type == TagEnum::XML_DECLARATION) {
1617             ParseDeclaration();
1618             type = ParseTagType(false);
1619         }
1620         text_ = "";
1621         bWhitespace_ = true;
1622         prefix_ = "";
1623         name_ = "";
1624         namespace_ = "";
1625         attriCount_ = 0;
1626     }
1627 
ParseInstruction()1628     void XmlPullParser::ParseInstruction()
1629     {
1630         SkipText(tagText_.START_PROCESSING_INSTRUCTION);
1631         text_ = ParseDelimiterInfo(tagText_.END_PROCESSING_INSTRUCTION, true);
1632     }
1633 
GetColumnNumber() const1634     int XmlPullParser::GetColumnNumber() const
1635     {
1636         size_t result = bufferStartColumn_;
1637         for (size_t i = 0; i < position_; i++) {
1638             if (strXml_[i] == '\n') {
1639                 result = 0;
1640             } else {
1641                 result++;
1642             }
1643         }
1644         return result + 1;
1645     }
GetDepth() const1646     int XmlPullParser::GetDepth() const
1647     {
1648         return depth;
1649     }
GetLineNumber() const1650     int XmlPullParser::GetLineNumber() const
1651     {
1652         int result = bufferStartLine_;
1653         for (size_t i = 0; i < position_; i++) {
1654             if (strXml_[i] == '\n') {
1655                 result++;
1656             }
1657         }
1658         return result + 1;
1659     }
GetName() const1660     std::string XmlPullParser::GetName() const
1661     {
1662         return name_;
1663     }
1664 
GetPrefix() const1665     std::string XmlPullParser::GetPrefix() const
1666     {
1667         return prefix_;
1668     }
GetText() const1669     std::string XmlPullParser::GetText() const
1670     {
1671         if (type < TagEnum::TEXT || (type == TagEnum::ENTITY_REFERENCE && bUnresolved_)) {
1672             return "";
1673         } else {
1674             return text_;
1675         }
1676     }
IsEmptyElementTag() const1677     bool XmlPullParser::IsEmptyElementTag() const
1678     {
1679         return bEndFlag_;
1680     }
1681 
GetAttributeCount() const1682     int XmlPullParser::GetAttributeCount() const
1683     {
1684         return attriCount_;
1685     }
1686 
IsWhitespace() const1687     bool XmlPullParser::IsWhitespace() const
1688     {
1689         return bWhitespace_;
1690     }
1691 
GetNamespace() const1692     std::string XmlPullParser::GetNamespace() const
1693     {
1694         return namespace_;
1695     }
1696 
GetColumnNumber(napi_env env,napi_callback_info info)1697     napi_value XmlPullParser::ParseInfo::GetColumnNumber(napi_env env, napi_callback_info info)
1698     {
1699         napi_value thisVar = nullptr;
1700         napi_value mainVar = nullptr;
1701         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1702         void *obj = nullptr;
1703         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1704         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1705         napi_value result = nullptr;
1706         if (obj != nullptr) {
1707             int temp = (reinterpret_cast<XmlPullParser *>(obj))->GetColumnNumber();
1708             napi_create_int32(env, temp, &result);
1709         }
1710         return result;
1711     }
1712 
GetDepth(napi_env env,napi_callback_info info)1713     napi_value XmlPullParser::ParseInfo::GetDepth(napi_env env, napi_callback_info info)
1714     {
1715         napi_value thisVar = nullptr;
1716         napi_value mainVar = nullptr;
1717         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1718         void *obj = nullptr;
1719         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1720         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1721         napi_value result = nullptr;
1722         if (obj != nullptr) {
1723             int temp = (reinterpret_cast<XmlPullParser *>(obj))->GetDepth();
1724             napi_create_int32(env, temp, &result);
1725         }
1726         return result;
1727     }
1728 
GetLineNumber(napi_env env,napi_callback_info info)1729     napi_value XmlPullParser::ParseInfo::GetLineNumber(napi_env env, napi_callback_info info)
1730     {
1731         napi_value thisVar = nullptr;
1732         napi_value mainVar = nullptr;
1733         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1734         void *obj = nullptr;
1735         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1736         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1737         napi_value result = nullptr;
1738         if (obj != nullptr) {
1739             int temp = (reinterpret_cast<XmlPullParser *>(obj))->GetLineNumber();
1740             napi_create_int32(env, temp, &result);
1741         }
1742         return result;
1743     }
1744 
GetName(napi_env env,napi_callback_info info)1745     napi_value XmlPullParser::ParseInfo::GetName(napi_env env, napi_callback_info info)
1746     {
1747         napi_value thisVar = nullptr;
1748         napi_value mainVar = nullptr;
1749         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1750         void *obj = nullptr;
1751         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1752         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1753         napi_value result = nullptr;
1754         if (obj != nullptr) {
1755             std::string temp = (reinterpret_cast<XmlPullParser *>(obj))->GetName();
1756             napi_create_string_utf8(env, temp.c_str(), temp.length(), &result);
1757         }
1758         return result;
1759     }
1760 
GetNamespace(napi_env env,napi_callback_info info)1761     napi_value XmlPullParser::ParseInfo::GetNamespace(napi_env env, napi_callback_info info)
1762     {
1763         napi_value thisVar = nullptr;
1764         napi_value mainVar = nullptr;
1765         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1766         void *obj = nullptr;
1767         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1768         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1769         napi_value result = nullptr;
1770         if (obj != nullptr) {
1771             std::string temp = (reinterpret_cast<XmlPullParser *>(obj))->GetNamespace();
1772             napi_create_string_utf8(env, temp.c_str(), temp.length(), &result);
1773         }
1774         return result;
1775     }
1776 
GetPrefix(napi_env env,napi_callback_info info)1777     napi_value XmlPullParser::ParseInfo::GetPrefix(napi_env env, napi_callback_info info)
1778     {
1779         napi_value thisVar = nullptr;
1780         napi_value mainVar = nullptr;
1781         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1782         void *obj = nullptr;
1783         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1784         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1785         napi_value result = nullptr;
1786         if (obj != nullptr) {
1787             std::string temp = (reinterpret_cast<XmlPullParser *>(obj))->GetPrefix();
1788             napi_create_string_utf8(env, temp.c_str(), temp.length(), &result);
1789         }
1790         return result;
1791     }
1792 
GetText(napi_env env,napi_callback_info info)1793     napi_value XmlPullParser::ParseInfo::GetText(napi_env env, napi_callback_info info)
1794     {
1795         napi_value thisVar = nullptr;
1796         napi_value mainVar = nullptr;
1797         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1798         void *obj = nullptr;
1799         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1800         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1801         napi_value result = nullptr;
1802         if (obj != nullptr) {
1803             std::string temp = (reinterpret_cast<XmlPullParser *>(obj))->GetText();
1804             napi_create_string_utf8(env, temp.c_str(), temp.length(), &result);
1805         }
1806         return result;
1807     }
1808 
IsEmptyElementTag(napi_env env,napi_callback_info info)1809     napi_value XmlPullParser::ParseInfo::IsEmptyElementTag(napi_env env, napi_callback_info info)
1810     {
1811         napi_value thisVar = nullptr;
1812         napi_value mainVar = nullptr;
1813         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1814         void *obj = nullptr;
1815         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1816         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1817         napi_value result = nullptr;
1818         if (obj != nullptr) {
1819             bool temp = (reinterpret_cast<XmlPullParser *>(obj))->IsEmptyElementTag();
1820             napi_get_boolean(env, temp, &result);
1821         }
1822         return result;
1823     }
1824 
IsWhitespace(napi_env env,napi_callback_info info)1825     napi_value XmlPullParser::ParseInfo::IsWhitespace(napi_env env, napi_callback_info info)
1826     {
1827         napi_value thisVar = nullptr;
1828         napi_value mainVar = nullptr;
1829         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1830         void *obj = nullptr;
1831         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1832         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1833         napi_value result = nullptr;
1834         if (obj != nullptr) {
1835             bool temp = (reinterpret_cast<XmlPullParser *>(obj))->IsWhitespace();
1836             napi_get_boolean(env, temp, &result);
1837         }
1838         return result;
1839     }
1840 
GetAttributeCount(napi_env env,napi_callback_info info)1841     napi_value XmlPullParser::ParseInfo::GetAttributeCount(napi_env env, napi_callback_info info)
1842     {
1843         napi_value thisVar = nullptr;
1844         napi_value mainVar = nullptr;
1845         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1846         void *obj = nullptr;
1847         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1848         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1849         napi_value result = nullptr;
1850         if (obj != nullptr) {
1851             int temp = (reinterpret_cast<XmlPullParser *>(obj))->GetAttributeCount();
1852             napi_create_int32(env, temp, &result);
1853         }
1854         return result;
1855     }
1856 } // namespace OHOS::Xml
1857 
1858