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