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_handle_scope scope = nullptr;
500         napi_status status = napi_open_handle_scope(env, &scope);
501         if (status != napi_ok) {
502             HILOG_ERROR("XmlPullParser::open scope failed!");
503             return false;
504         }
505         napi_value returnVal = nullptr;
506         size_t argc = 2; // 2: number of args
507         napi_value key = nullptr;
508         napi_create_int32(env, (int)type, &key);
509         napi_value parseInfo  = nullptr;
510         napi_create_object(env, &parseInfo);
511         auto object = new ParseInfo();
512         napi_wrap(env, parseInfo, object, nullptr, nullptr, nullptr);
513         static napi_property_descriptor xmlDesc[] = {
514             DECLARE_NAPI_FUNCTION("getDepth", XmlPullParser::ParseInfo::GetDepth),
515             DECLARE_NAPI_FUNCTION("getColumnNumber", XmlPullParser::ParseInfo::GetColumnNumber),
516             DECLARE_NAPI_FUNCTION("getLineNumber", XmlPullParser::ParseInfo::GetLineNumber),
517             DECLARE_NAPI_FUNCTION("getAttributeCount", XmlPullParser::ParseInfo::GetAttributeCount),
518             DECLARE_NAPI_FUNCTION("getName", XmlPullParser::ParseInfo::GetName),
519             DECLARE_NAPI_FUNCTION("getNamespace", XmlPullParser::ParseInfo::GetNamespace),
520             DECLARE_NAPI_FUNCTION("getPrefix", XmlPullParser::ParseInfo::GetPrefix),
521             DECLARE_NAPI_FUNCTION("getText", XmlPullParser::ParseInfo::GetText),
522             DECLARE_NAPI_FUNCTION("isEmptyElementTag", XmlPullParser::ParseInfo::IsEmptyElementTag),
523             DECLARE_NAPI_FUNCTION("isWhitespace", XmlPullParser::ParseInfo::IsWhitespace)
524         };
525         napi_define_properties(env, parseInfo, sizeof(xmlDesc) / sizeof(xmlDesc[0]), xmlDesc);
526         napi_set_named_property(env, parseInfo, "MainInfo", thisVar);
527         napi_value argv[2] = {key, parseInfo}; // 2: number of args
528         napi_call_function(env, parseInfo, tokenFunc_, argc, argv, &returnVal);
529         bool bRec = false;
530         napi_get_value_bool(env, returnVal, &bRec);
531         if (object != nullptr) {
532             delete object;
533             object = nullptr;
534         }
535         napi_close_handle_scope(env, scope);
536         return bRec;
537     }
538 
ParseAttri(napi_env env,napi_value thisVar) const539     bool XmlPullParser::ParseAttri(napi_env env, napi_value thisVar) const
540     {
541         for (size_t i = 0; i < attriCount_; ++i) {
542             napi_value returnVal = nullptr;
543             size_t argc = 3; // 3: number of args
544             napi_value global = nullptr;
545             napi_get_global(env, &global);
546             napi_value key = nullptr;
547             napi_create_string_utf8(env, attributes[i * 4 + 2].c_str(), // 4 and 2: number of args
548                 attributes[i * 4 + 2].size(), &key); // 4 and 2: number of args
549             napi_value value = nullptr;
550             napi_create_string_utf8(env, attributes[i * 4 + 3].c_str(), // 4 and 3: number of args
551                 attributes[i * 4 + 3].size(), &value); // 3 and 4: number of args
552             napi_value argv[3] = {key, value, thisVar};
553             napi_call_function(env, global, attrFunc_, argc, argv, &returnVal);
554             bool bRec = false;
555             napi_get_value_bool(env, returnVal, &bRec);
556             if (!bRec) {
557                 return bRec;
558             }
559         }
560         return true;
561     }
562 
DealCdata(std::string data)563     std::string XmlPullParser::DealCdata(std::string data)
564     {
565         std::string_view cDataBegin = "<![CDATA[";
566         std::string_view cDataEnd = "]]>";
567         size_t foundPosBegin = data.find(cDataBegin);
568         size_t foundPosEnd = data.find(cDataEnd);
569         size_t count = 0;
570         while (foundPosBegin != std::string::npos) {
571             std::string temp = data.substr(foundPosBegin, foundPosEnd - foundPosBegin + cDataEnd.length());
572             std::string resStr = "";
573             for (char c : temp) {
574                 if (c == '\r') {
575                     resStr += "\\r";
576                     count++;
577                 } else if (c == '\n') {
578                     resStr += "\\n";
579                     count++;
580                 } else {
581                     resStr += c;
582                 }
583             }
584             data.replace(foundPosBegin, temp.length(), resStr);
585             foundPosBegin = data.find(cDataBegin, foundPosBegin + 1);
586             foundPosEnd = data.find(cDataEnd, foundPosEnd + count + 1);
587         }
588         return data;
589     }
590 
Parse(napi_env env,napi_value thisVar,bool deprecated)591     void XmlPullParser::Parse(napi_env env, napi_value thisVar, bool deprecated)
592     {
593         if (deprecated) {
594             strXml_ = DealCdata(strXml_);
595         }
596         if (tagFunc_ || attrFunc_ || tokenFunc_) {
597             while (type != TagEnum::END_DOCUMENT) {
598                 if (ParseOneTag() == TagEnum::ERROR) {
599                     break;
600                 }
601                 bool bRec = false;
602                 if (tagFunc_) {
603                     napi_value returnVal = nullptr;
604                     size_t argc = 3; // 3: number of args
605                     napi_value global = nullptr;
606                     napi_get_global(env, &global);
607                     napi_value key = nullptr;
608                     napi_create_string_utf8(env, name_.c_str(), name_.size(), &key);
609                     napi_value value = nullptr;
610                     napi_create_string_utf8(env, text_.c_str(), text_.size(), &value);
611                     napi_value argv[3] = {key, value, thisVar};
612                     napi_call_function(env, global, tagFunc_, argc, argv, &returnVal);
613                     napi_get_value_bool(env, returnVal, &bRec);
614                 }
615                 if (tagFunc_ && type == TagEnum::START_TAG && !bRec) {
616                     break;
617                 }
618                 if (tokenFunc_) {
619                     bRec = ParseToken(env, thisVar);
620                 }
621                 if (tokenFunc_ && !bRec) {
622                     break;
623                 }
624                 if (attrFunc_ && attriCount_) {
625                     bRec = ParseAttri(env, thisVar);
626                     attriCount_ = 0;
627                 }
628                 if (attrFunc_ && attriCount_ && !bRec) {
629                     break;
630                 }
631             }
632         }
633     }
634 
DealExclamationGroup()635     TagEnum XmlPullParser::DealExclamationGroup()
636     {
637         switch (strXml_[position_ + 2]) { // 2:  number of args
638             case 'D':
639                 return TagEnum::DOCDECL;
640             case '[':
641                 return TagEnum::CDSECT;
642             case '-':
643                 return TagEnum::COMMENT;
644             case 'E':
645                 switch (strXml_[position_ + 3]) { // 3:  number of args
646                     case 'L':
647                         return TagEnum::ELEMENTDECL;
648                     case 'N':
649                         return TagEnum::ENTITYDECL;
650                     default:
651                         break;
652                 }
653                 xmlPullParserError_ = "Unexpected <!";
654                 break;
655             case 'A':
656                 return TagEnum::ATTLISTDECL;
657             case 'N':
658                 return TagEnum::NOTATIONDECL;
659             default:
660                 break;
661         }
662         return TagEnum::ERROR;
663     }
664 
DealLtGroup()665     TagEnum XmlPullParser::DealLtGroup()
666     {
667         if (position_ + 3 >= max_ && !DealLength(4)) { // 4: number of args 3: number of args
668             xmlPullParserError_ = ("Dangling <");
669         }
670         char cTemp = strXml_[position_ + 1];
671         if (cTemp == '/') {
672             return TagEnum::END_TAG;
673         } else if (cTemp == '?') {
674             std::string strXml = strXml_.substr(position_ + 2, 4);  // 2 and 4:position and length
675             MakeStrUpper(strXml);
676             if (max_ >= position_ + 5 && strXml == tagText_.XML) { // 5: number of args
677                 return TagEnum::XML_DECLARATION;
678             } else {
679                 return TagEnum::INSTRUCTION;
680             }
681         } else if (cTemp == '!') {
682             return DealExclamationGroup();
683         } else {
684             return TagEnum::START_TAG;
685         }
686     }
687 
ParseTagType(bool inDeclaration)688     TagEnum XmlPullParser::ParseTagType(bool inDeclaration)
689     {
690         if (bStartDoc_) {
691             bStartDoc_ = false;
692             return TagEnum::START_DOCUMENT;
693         }
694         if (position_ >= max_ && !DealLength(1)) {
695             return TagEnum::END_DOCUMENT;
696         }
697         switch (strXml_[position_]) {
698             case '&':
699                 if (apiVersion_ >= APIVerIsolation_.API12) {
700                     return TagEnum::ENTITY_REFERENCE;
701                 } else {
702                     return inDeclaration ? TagEnum::ENTITY_REFERENCE : TagEnum::TEXT;
703                 }
704             case '<':
705                 return DealLtGroup();
706             case '%':
707                 return inDeclaration ? TagEnum::PARAMETER_ENTITY_REF : TagEnum::TEXT;
708             default:
709                 return TagEnum::TEXT;
710         }
711     }
712 
MakeStrUpper(std::string & src) const713     void XmlPullParser::MakeStrUpper(std::string &src) const
714     {
715         size_t i = 0;
716 
717         while (i < src.size()) {
718             if (src[i] >= 'A' && src[i] <= 'Z') {
719                 src[i] += 32; // 32: number of args
720             }
721             ++i;
722         }
723     }
724 
SkipText(std::string chars)725     void XmlPullParser::SkipText(std::string chars)
726     {
727         if (position_ + chars.size() > max_ && !DealLength(chars.size())) {
728             xmlPullParserError_ = "expected: '" + chars + "' but was EOF";
729             return;
730         }
731         size_t len = chars.length();
732         if (strXml_.substr(position_, len) != chars) {
733             xmlPullParserError_ = "expected: \"" + chars + "\" but was \"" + strXml_.substr(position_, len) + "...\"";
734         }
735         position_ += len;
736     }
737 
PriorDealChar()738     int XmlPullParser::PriorDealChar()
739     {
740         if (position_ < max_ || DealLength(1)) {
741             return strXml_[position_];
742         }
743         return -1;
744     }
745 
SkipChar(char expected)746     void XmlPullParser::SkipChar(char expected)
747     {
748         int c = PriorDealChar();
749         if (c != expected) {
750             xmlPullParserError_ = "expected:";
751             if (c == -1) {
752                 return;
753             }
754         }
755         position_++;
756     }
757 
ParseNameInner(size_t start)758     std::string XmlPullParser::ParseNameInner(size_t start)
759     {
760         std::string result = "";
761         char c = 0;
762         while (true) {
763             if (position_ >= max_) {
764                 result.append(strXml_, start, position_ - start);
765                 if (!DealLength(1)) {
766                     return result;
767                 }
768                 start = position_;
769             }
770             c = strXml_[position_];
771             if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
772                 (c >= '0' && c <= '9') || c == '_' || c == '-' ||
773                 c == ':' || c == '.') {
774                 position_++;
775                 continue;
776             }
777             result.append(strXml_, start, position_ - start);
778             return result;
779         }
780     }
781 
ParseName()782     std::string XmlPullParser::ParseName()
783     {
784         if (position_ >= max_ && !DealLength(1)) {
785             xmlPullParserError_ = "name expected";
786             return "";
787         }
788         size_t start = position_;
789         char c = strXml_[position_];
790         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
791             c == '_' || c == ':' || relaxed) {
792             position_++;
793         } else {
794             xmlPullParserError_ = "The node name contains invalid characters: ";
795             xmlPullParserError_ += c;
796             return "";
797         }
798         return ParseNameInner(start);
799     }
800 
SkipInvalidChar()801     void XmlPullParser::SkipInvalidChar()
802     {
803         while (position_ < max_ || DealLength(1)) {
804             unsigned char temp = strXml_[position_];
805             if (temp > ' ') {
806                 break;
807             }
808             position_++;
809         }
810     }
811 
ParseEntityFunc(size_t start,std::string & out,bool isEntityToken,TextEnum textEnum)812     void XmlPullParser::ParseEntityFunc(size_t start, std::string &out, bool isEntityToken, TextEnum textEnum)
813     {
814         std::string strEntity = out.substr(start + 1, out.length() - 1);
815         if (isEntityToken) {
816             name_ = strEntity;
817         }
818         if (strEntity.size() && strEntity[0] == '#') {
819             int c = 0;
820             if (strEntity.size() >= 2 && strEntity[1] == 'x') { // 2: number of args
821                 c = std::stoi(strEntity.substr(2), nullptr, 16); // 16: number of args 2: number of args
822             } else {
823                 c = std::stoi(strEntity.substr(1), nullptr);
824             }
825             out = "";
826             out += static_cast<char>(c);
827             bUnresolved_ = false;
828             return;
829         }
830         if (textEnum == TextEnum::ENTITY_DECL) {
831             return;
832         }
833         if (DEFAULT_ENTITIES.count(strEntity) != 0) {
834             out = out.substr(0, start);
835             bUnresolved_ = false;
836             out.append(DEFAULT_ENTITIES[strEntity]);
837             return;
838         }
839         std::string resolved = " ";
840         if (documentEntities.size() != 0 && (resolved = strEntity) != "") {
841             out = "";
842             bUnresolved_ = false;
843             if (bDocDecl) {
844                 PushSrcLinkList(resolved);
845             } else {
846                 out.append(resolved);
847             }
848             return;
849         }
850         if (sysInfo_ != "") {
851             out = "";
852             return;
853         }
854         bUnresolved_ = true;
855     }
856 
ParseEntity(std::string & out,bool isEntityToken,bool throwOnResolveFailure,TextEnum textEnum)857     void XmlPullParser::ParseEntity(std::string &out,
858                                     bool isEntityToken,
859                                     bool throwOnResolveFailure,
860                                     TextEnum textEnum)
861     {
862         size_t start = out.length();
863         if (strXml_[position_++] != '&') {
864             xmlPullParserError_ = "Should not be reached";
865         }
866         out += '&';
867         while (true) {
868             int c = PriorDealChar();
869             if (c == ';') {
870                 out += ';';
871                 position_++;
872                 break;
873             } else if (c >= 128 || // 128: number of args
874                 (c >= '0' && c <= '9') ||
875                 (c >= 'a' && c <= 'z') ||
876                 (c >= 'A' && c <= 'Z') ||
877                 c == '_' ||
878                 c == '-' ||
879                 c == '#') {
880                 position_++;
881                 out.push_back(static_cast<char>(c));
882             } else if (relaxed) {
883                 return;
884             } else {
885                 xmlPullParserError_ = "unterminated entity ref";
886                 break;
887             }
888         }
889         ParseEntityFunc(start, out, isEntityToken, textEnum);
890     }
891 
ParseTagValueFunc(char & c,bool bFlag,TextEnum textEnum,size_t & start,std::string & result)892     bool XmlPullParser::ParseTagValueFunc(char &c, bool bFlag, TextEnum textEnum,
893         size_t &start, std::string &result)
894     {
895         if (c == '\r') {
896             if ((position_ + 1 < max_ || DealLength(2)) && strXml_[position_ + 1] == '\n') { // 2: number of args
897                 position_++;
898             }
899             c = (textEnum == TextEnum::ATTRI) ? ' ' : '\n';
900         } else if (c == '\n') {
901             c = ' ';
902         } else if (c == '&') {
903             bWhitespace_ = false;
904             ParseEntity(result, false, bFlag, textEnum);
905             start = position_;
906             return false;
907         } else if (c == '<') {
908             if (textEnum == TextEnum::ATTRI) {
909                 xmlPullParserError_ = "Illegal: \"<\" inside attribute value";
910             }
911             bWhitespace_ = false;
912         } else if (c == ']') {
913             if ((position_ + 2 < max_ || DealLength(3)) && // 2: number of args 3: number of args
914                 strXml_[position_ + 1] == ']' && strXml_[position_ + 2] == '>') { // 2: number of args
915                 xmlPullParserError_ = "Illegal: \"]]>\" outside CDATA section";
916             }
917             bWhitespace_ = false;
918         } else if (c == '%') {
919             xmlPullParserError_ = "This parser doesn't support parameter entities";
920         } else {
921             xmlPullParserError_ = "AssertionError";
922         }
923         return true;
924     }
925 
DealWhiteSpace(unsigned char c)926     void XmlPullParser::DealWhiteSpace(unsigned char c)
927     {
928         if (bWhitespace_ && c <= ' ') {
929             bWhitespace_ = true;
930         } else {
931             bWhitespace_ = false;
932         }
933     }
934 
ParseTagValueInner(size_t & start,std::string & result,char delimiter,TextEnum textEnum,bool bFlag)935     size_t XmlPullParser::ParseTagValueInner(size_t &start, std::string &result,
936         char delimiter, TextEnum textEnum, bool bFlag)
937     {
938         if (position_ >= max_) {
939             if (start < position_) {
940                 result.append(strXml_, start, position_ - start);
941             }
942             if (!DealLength(1)) {
943                 result = (result != "" ? result : "");
944                 return 0;
945             }
946             start = position_;
947         }
948         unsigned char c = strXml_[position_];
949         if (c == delimiter ||
950             (delimiter == ' ' && (c <= ' ' || c == '>')) ||
951             (c == '&' && !bFlag)) {
952                 return 1;
953             }
954         if (c != '\r' && (c != '\n' || textEnum != TextEnum::ATTRI) &&
955             c != '&' && c != '<' && (c != ']' || textEnum != TextEnum::TEXT) &&
956             (c != '%' || textEnum != TextEnum::ENTITY_DECL)) {
957                 DealWhiteSpace(c);
958                 position_++;
959                 return 2; // 2: break flag
960         }
961         result.append(strXml_, start, position_ - start);
962         return c;
963     }
964 
ParseTagValue(char delimiter,bool resolveEntities,bool throwOnResolveFailure,TextEnum textEnum)965     std::string XmlPullParser::ParseTagValue(char delimiter, bool resolveEntities,
966         bool throwOnResolveFailure, TextEnum textEnum)
967     {
968         size_t start = position_;
969         std::string result = "";
970         if (textEnum == TextEnum::TEXT && text_ != "") {
971             result.append(text_);
972         }
973         while (true) {
974             char cRecv = static_cast<char>(ParseTagValueInner(start, result, delimiter, textEnum, resolveEntities));
975             if (cRecv == 0) {
976                 return result;
977             } else if (cRecv == 1) {
978                 break;
979             } else if (cRecv == 2) { // 2: break flag
980                 continue;
981             } else if (!ParseTagValueFunc(cRecv, throwOnResolveFailure, textEnum, start, result)) {
982                 continue;
983             }
984             ++position_;
985             result = result + static_cast<char>(cRecv);
986             start = position_;
987         }
988         result.append(strXml_, start, position_ - start);
989         return result;
990     }
991 
GetNamespace(const std::string & prefix)992     std::string XmlPullParser::GetNamespace(const std::string &prefix)
993     {
994         size_t temp = GetNSCount(depth) << 1;
995         if (temp) {
996             size_t i = temp - 2; // 2: number of args
997             for (; i >= 0; i -= 2) { // 2: number of args
998                 if (prefix == "" && nspStack_[i] == "") {
999                     return nspStack_[i + 1];
1000                 } else if (prefix == nspStack_[i]) {
1001                     return nspStack_[i + 1];
1002                 }
1003                 if (!i) {
1004                     break;
1005                 }
1006             }
1007         }
1008         return "";
1009     }
1010 
Replace(std::string & strTemp,std::string strSrc,std::string strDes) const1011     void XmlPullParser::Replace(std::string& strTemp, std::string strSrc, std::string strDes) const
1012     {
1013         size_t iPos = 0;
1014         while ((iPos = strTemp.find(strSrc)) != std::string::npos) {
1015             strTemp.replace(iPos, strSrc.size(), strDes);
1016         }
1017     }
1018 
ParseNspFunc(size_t & i,const std::string & attrName,bool & any)1019     void XmlPullParser::ParseNspFunc(size_t &i, const std::string &attrName, bool &any)
1020     {
1021         size_t j = (nspCounts_[depth]++) << 1;
1022         size_t uiSize = nspStack_.size();
1023         if (uiSize < j + 2) { // 2: number of args
1024             nspStack_.resize(j + 16); // 16: number of args
1025         }
1026         nspStack_[j] = attrName;
1027         nspStack_[j + 1] = attributes[i + 3]; // 3: number of args
1028         if (attrName != "" && attributes[i + 3].empty()) { // 3: number of args
1029             xmlPullParserError_ = "illegal empty namespace";
1030         }
1031         if (bKeepNsAttri) {
1032             attributes[i] = "http://www.w3.org/2000/xmlns/";
1033             any = true;
1034         } else {
1035             for (size_t iCount = i; iCount < ((--attriCount_) << 2); ++iCount) { // 2: number of args
1036                 attributes[iCount] = attributes[iCount + 4]; // 4: number of args
1037             }
1038             i -= 4; // 4:
1039         }
1040     }
1041 
ParseNspFunction()1042     void XmlPullParser::ParseNspFunction()
1043     {
1044         int i = (attriCount_ << 2) - 4; // 4: number of args 2: number of args
1045         for (; i >= 0; i -= 4) { // 4: number of args
1046             std::string attrName = attributes[i + 2]; // 2: number of args
1047             size_t cut = attrName.find(':');
1048             if (cut == 0 && !relaxed) {
1049                 xmlPullParserError_ = "illegal attribute name: ";
1050             } else if (cut != std::string::npos) {
1051                 std::string attrPrefix = attrName.substr(0, cut);
1052                 attrName = attrName.substr(cut + 1);
1053                 std::string attrNs = GetNamespace(attrPrefix);
1054                 if (attrNs == "" && !relaxed) {
1055                     xmlPullParserError_ = ("Undefined Prefix: " + attrPrefix + " in ");
1056                 }
1057                 attributes[i] = attrNs;
1058                 attributes[i + 1] = attrPrefix;
1059                 attributes[i + 2] = attrName; // 2: number of args
1060             }
1061         }
1062     }
1063 
ParseNsp()1064     bool XmlPullParser::ParseNsp()
1065     {
1066         bool any = false;
1067         size_t cut = 0;
1068         for (size_t i = 0; i < (attriCount_ << 2); i += 4) { // 2 and 4: number of args
1069             std::string attrName = attributes[i + 2]; // 2: number of args
1070             cut = attrName.find(':');
1071             std::string prefix;
1072             if (cut != std::string::npos) {
1073                 prefix = attrName.substr(0, cut);
1074                 attrName = attrName.substr(cut + 1);
1075             } else if (attrName == ("xmlns")) {
1076                 prefix = attrName;
1077                 attrName = "";
1078             } else {
1079                 continue;
1080             }
1081             if (!(prefix == "xmlns")) {
1082                 any = true;
1083             } else {
1084                 ParseNspFunc(i, attrName, any);
1085             }
1086         }
1087         if (any) {
1088             ParseNspFunction();
1089         }
1090         cut = name_.find(':');
1091         if (cut == 0) {
1092             xmlPullParserError_ = "illegal tag name: " + name_;
1093         }
1094         if (cut != std::string::npos) {
1095             prefix_ = name_.substr(0, cut);
1096             name_ = name_.substr(cut + 1);
1097         }
1098         namespace_ = GetNamespace(prefix_);
1099         return any;
1100     }
1101 
ParseStartTagFuncDeal(bool throwOnResolveFailure)1102     bool XmlPullParser::ParseStartTagFuncDeal(bool throwOnResolveFailure)
1103     {
1104         std::string attrName = ParseName();
1105         if (attrName.empty()) {
1106             return false;
1107         }
1108         int i = (attriCount_++) * 4; // 4: number of args
1109         attributes.resize(attributes.size() + 4); // 4: number of args
1110         attributes[i] = "";
1111         attributes[i + 1] = "";
1112         attributes[i + 2] = attrName; // 2: number of args
1113         SkipInvalidChar();
1114         if (position_ >= max_ && !DealLength(1)) {
1115             xmlPullParserError_ = "UNEXPECTED_EOF";
1116             return false;
1117         }
1118         if (strXml_[position_] == '=') {
1119             position_++;
1120             SkipInvalidChar();
1121             if (position_ >= max_) {
1122                 xmlPullParserError_ = "UNEXPECTED_EOF";
1123                 return false;
1124             }
1125             char delimiter = strXml_[position_];
1126             if (delimiter == '\'' || delimiter == '"') {
1127                 position_++;
1128             } else if (relaxed) {
1129                 delimiter = ' ';
1130             } else {
1131                 xmlPullParserError_ = "attr value delimiter missing!";
1132                 return false;
1133             }
1134             attributes[i + 3] = ParseTagValue(delimiter, true, // 3: number of args
1135                 throwOnResolveFailure, TextEnum::ATTRI); // 3: number of args
1136             if (delimiter != ' ' && PriorDealChar() == delimiter) {
1137                 position_++;
1138             }
1139         } else {
1140             attributes[i + 3] = attrName; // 3: number of args
1141         }
1142         return true;
1143     }
1144 
ParseStartTagFunc(bool xmldecl,bool throwOnResolveFailure)1145     TagEnum XmlPullParser::ParseStartTagFunc(bool xmldecl, bool throwOnResolveFailure)
1146     {
1147         while (true) {
1148             SkipInvalidChar();
1149             if (position_ >= max_ && DealLength(1)) {
1150                 xmlPullParserError_ = "UNEXPECTED_EOF";
1151                 return TagEnum::ERROR;
1152             }
1153             unsigned char temp = strXml_[position_];
1154             if (xmldecl) {
1155                 if (temp == '?') {
1156                     position_++;
1157                     SkipChar('>');
1158                     return TagEnum::XML_DECLARATION;
1159                 }
1160             } else {
1161                 if (temp == '/') {
1162                     bEndFlag_ = true;
1163                     position_++;
1164                     SkipInvalidChar();
1165                     SkipChar('>');
1166                     break;
1167                 } else if (temp == '>') {
1168                     position_++;
1169                     break;
1170                 }
1171             }
1172             bool bRecv = ParseStartTagFuncDeal(throwOnResolveFailure);
1173             if (!bRecv) {
1174                 return TagEnum::ERROR;
1175             }
1176         }
1177         return TagEnum::OK;
1178     }
1179 
ParseStartTag(bool xmldecl,bool throwOnResolveFailure)1180     TagEnum XmlPullParser::ParseStartTag(bool xmldecl, bool throwOnResolveFailure)
1181     {
1182         if (!xmldecl) {
1183             SkipChar('<');
1184         }
1185         name_ = ParseName();
1186         attriCount_ = 0;
1187         TagEnum bRecv = ParseStartTagFunc(xmldecl, throwOnResolveFailure);
1188         if (bRecv != TagEnum::OK) {
1189             return bRecv;
1190         }
1191         size_t sp = depth++ * 4; // 4: number of args
1192         elementStack_.resize(sp + 4); // 4: number of args
1193         elementStack_[sp + 3] = name_; // 3: number of args
1194         if (depth >= nspCounts_.size()) {
1195             nspCounts_.resize(depth + 4); // 4: number of args
1196         }
1197         nspCounts_[depth] = nspCounts_[depth - 1];
1198         if (!bIgnoreNS_) {
1199             ParseNsp();
1200         } else {
1201             namespace_ = "";
1202         }
1203         if (defaultAttributes.size() != 0) {
1204             std::map<std::string, std::string> elementDefaultAttributes = defaultAttributes[name_];
1205             if (elementDefaultAttributes.size() != 0) {
1206                 for (std::map<std::string, std::string>::iterator iter = elementDefaultAttributes.begin();
1207                     iter != elementDefaultAttributes.end(); ++iter) {
1208                 }
1209             }
1210         }
1211         elementStack_[sp] = namespace_;
1212         elementStack_[sp + 1] = prefix_;
1213         elementStack_[sp + 2] = name_; // 2: number of args
1214         return TagEnum::OK;
1215     }
1216 
ParseDeclaration()1217     void XmlPullParser::ParseDeclaration()
1218     {
1219         if (bufferStartLine_ != 0 || bufferStartColumn_ != 0 || position_ != 0) {
1220             xmlPullParserError_ = "processing instructions must not start with xml";
1221         }
1222         SkipText(tagText_.START_PROCESSING_INSTRUCTION);
1223         ParseStartTag(true, true);
1224         if (attriCount_ < 1 || attributes[2] != "version") { // 2: number of args
1225             xmlPullParserError_ = "version expected";
1226         }
1227         version_ = attributes[3]; // 3: number of args
1228         size_t pos = 1;
1229         if (pos < attriCount_ && (attributes[2 + 4]) == "encoding") { // 4: number of args 2: number of args
1230             encoding_ = attributes[3 + 4]; // 3: number of args 4: number of args
1231             pos++;
1232         }
1233         if (pos < attriCount_ && (attributes[4 * pos + 2]) == "standalone") { // 4: number of args 2: number of args
1234             std::string st = attributes[3 + 4 * pos]; // 3: number of args 4: number of args
1235             if (st == "yes") {
1236                 bAlone_ = true;
1237             } else if (st == "no") {
1238                 bAlone_ = false;
1239             } else {
1240                 xmlPullParserError_ = "illegal standalone value: " + st;
1241             }
1242             pos++;
1243         }
1244         if (pos != attriCount_) {
1245             xmlPullParserError_ = "unexpected attributes in XML declaration";
1246         }
1247         bWhitespace_ = true;
1248         text_ = "";
1249     }
1250 
ParseEndTag()1251     bool XmlPullParser::ParseEndTag()
1252     {
1253         SkipChar('<');
1254         SkipChar('/');
1255         name_ = ParseName();
1256         if (name_.empty()) {
1257             return false;
1258         }
1259         SkipInvalidChar();
1260         SkipChar('>');
1261         if (depth == 0) {
1262             xmlPullParserError_ = "read end tag " + name_ + " with no tags open";
1263             type = TagEnum::COMMENT;
1264             return true;
1265         }
1266         size_t sp = (depth - 1) * 4; // 4: number of args
1267         if (name_ == elementStack_[sp + 3]) { // 3: number of args
1268             namespace_ = elementStack_[sp];
1269             prefix_ = elementStack_[sp + 1];
1270             name_ = elementStack_[sp + 2]; // 2: number of args
1271         } else if (!relaxed) {
1272             xmlPullParserError_ = "expected: /" + elementStack_[sp + 3] + " read: " + name_; // 3: number of args
1273         }
1274         return true;
1275     }
1276 
ParseDelimiterInfo(std::string delimiter,bool returnText)1277     std::string XmlPullParser::ParseDelimiterInfo(std::string delimiter, bool returnText)
1278     {
1279         size_t start = position_;
1280         std::string result = "";
1281         if (returnText && text_ != "") {
1282             result.append(text_);
1283         }
1284         bool bFlag = true;
1285         while (bFlag) {
1286             if (position_ + (delimiter).length() > max_) {
1287                 if (start < position_ && returnText) {
1288                     result.append(strXml_, start, position_ - start);
1289                 }
1290                 if (!DealLength(delimiter.length())) {
1291                     type = TagEnum::COMMENT;
1292                     return "";
1293                 }
1294                 start = position_;
1295             }
1296             size_t i = 0;
1297             for (; i < delimiter.length(); i++) {
1298                 if (strXml_[position_ + i] != delimiter[i]) {
1299                     position_++;
1300                     break;
1301                 }
1302             }
1303             if (i == delimiter.length()) {
1304                 bFlag = false;
1305             }
1306         }
1307         size_t end = position_;
1308         position_ += delimiter.length();
1309         if (!returnText) {
1310             return "";
1311         } else {
1312             result.append(strXml_, start, end - start);
1313             return result;
1314         }
1315     }
1316 
ParseDelimiter(bool returnText)1317     std::string XmlPullParser::ParseDelimiter(bool returnText)
1318     {
1319         int quote = PriorDealChar();
1320         std::string delimiter;
1321         if (quote == '"') {
1322             delimiter = tagText_.DOUBLE_QUOTE;
1323         } else if (quote == '\'') {
1324             delimiter = tagText_.SINGLE_QUOTE;
1325         } else {
1326             xmlPullParserError_ = "Expected a quoted std::string ";
1327         }
1328         position_++;
1329         return ParseDelimiterInfo(delimiter, returnText);
1330     }
1331 
ParserDoctInnerInfo(bool requireSystemName,bool assignFields)1332     bool XmlPullParser::ParserDoctInnerInfo(bool requireSystemName, bool assignFields)
1333     {
1334         SkipInvalidChar();
1335         int c = PriorDealChar();
1336         if (c == 'S') {
1337             SkipText(tagText_.SYSTEM);
1338         } else if (c == 'P') {
1339             SkipText(tagText_.PUBLIC);
1340             SkipInvalidChar();
1341             if (assignFields) {
1342                 pubInfo_ = ParseDelimiter(true);
1343             } else {
1344                 ParseDelimiter(false);
1345             }
1346         } else {
1347             return false;
1348         }
1349         SkipInvalidChar();
1350         if (!requireSystemName) {
1351             int delimiter = PriorDealChar();
1352             if (delimiter != '"' && delimiter != '\'') {
1353                 return true; // no system name!
1354             }
1355         }
1356         if (assignFields) {
1357             sysInfo_ = ParseDelimiter(true);
1358         } else {
1359             ParseDelimiter(false);
1360         }
1361         return true;
1362     }
1363 
ParseComment(bool returnText)1364     void XmlPullParser::ParseComment(bool returnText)
1365     {
1366         SkipText(tagText_.START_COMMENT);
1367         if (relaxed) {
1368             std::string strTemp = ParseDelimiterInfo(tagText_.END_COMMENT, returnText);
1369             if (returnText) {
1370                 text_ = strTemp;
1371             }
1372         }
1373         std::string commentText = ParseDelimiterInfo(tagText_.COMMENT_DOUBLE_DASH, returnText);
1374         if (PriorDealChar() != '>') {
1375             xmlPullParserError_ = "Comments may not contain -- ";
1376         }
1377         position_++;
1378         if (returnText) {
1379             text_ = commentText;
1380         }
1381     }
1382 
ParseSpecText()1383     void XmlPullParser::ParseSpecText()
1384     {
1385         SkipInvalidChar();
1386         int c = PriorDealChar();
1387         if (c == '(') {
1388             int iDepth = 0;
1389             do {
1390                 if (c == '(') {
1391                     iDepth++;
1392                 } else if (c == ')') {
1393                     iDepth--;
1394                 } else if (c == -1) {
1395                     xmlPullParserError_ = "Unterminated element content spec ";
1396                 }
1397                 position_++;
1398                 c = PriorDealChar();
1399             } while (iDepth > 0);
1400             if (c == '*' || c == '?' || c == '+') {
1401                 position_++;
1402             }
1403         } else if (c == tagText_.EMPTY[0]) {
1404             SkipText(tagText_.EMPTY);
1405         } else if (c == tagText_.ANY[0]) {
1406             SkipText(tagText_.ANY);
1407         } else {
1408             xmlPullParserError_ = "Expected element content spec ";
1409         }
1410     }
1411 
ParseInnerEleDec()1412     void XmlPullParser::ParseInnerEleDec()
1413     {
1414         SkipText(tagText_.START_ELEMENT);
1415         SkipInvalidChar();
1416         ParseName();
1417         ParseSpecText();
1418         SkipInvalidChar();
1419         SkipChar('>');
1420     }
1421 
ParseInnerAttriDeclFunc(int & c)1422     void XmlPullParser::ParseInnerAttriDeclFunc(int &c)
1423     {
1424         if (c == '(') {
1425             position_++;
1426             while (true) {
1427                 SkipInvalidChar();
1428                 ParseName();
1429                 SkipInvalidChar();
1430                 c = PriorDealChar();
1431                 if (c == ')') {
1432                     position_++;
1433                     break;
1434                 } else if (c == '|') {
1435                     position_++;
1436                 } else {
1437                     xmlPullParserError_ = "Malformed attribute type ";
1438                 }
1439             }
1440         } else {
1441             ParseName();
1442         }
1443     }
1444 
ParseInnerAttriDecl()1445     void XmlPullParser::ParseInnerAttriDecl()
1446     {
1447         SkipText(tagText_.START_ATTLIST);
1448         SkipInvalidChar();
1449         std::string elementName = ParseName();
1450         while (true) {
1451             SkipInvalidChar();
1452             int c = PriorDealChar();
1453             if (c == '>') {
1454                 position_++;
1455                 return;
1456             }
1457             std::string attributeName = ParseName();
1458             SkipInvalidChar();
1459             if (position_ + 1 >= max_ && !DealLength(2)) { // 2: lengths
1460                 xmlPullParserError_ = "Malformed attribute list ";
1461             }
1462             if (strXml_[position_] == tagText_.NOTATION[0] && strXml_[position_ + 1] == tagText_.NOTATION[1]) {
1463                 SkipText(tagText_.NOTATION);
1464                 SkipInvalidChar();
1465             }
1466             c = PriorDealChar();
1467             ParseInnerAttriDeclFunc(c);
1468             SkipInvalidChar();
1469             c = PriorDealChar();
1470             if (c == '#') {
1471                 position_++;
1472                 c = PriorDealChar();
1473                 if (c == 'R') {
1474                     SkipText(tagText_.REQUIRED);
1475                 } else if (c == 'I') {
1476                     SkipText(tagText_.IMPLIED);
1477                 } else if (c == 'F') {
1478                     SkipText(tagText_.FIXED);
1479                 } else {
1480                     xmlPullParserError_ = "Malformed attribute type";
1481                 }
1482                 SkipInvalidChar();
1483                 c = PriorDealChar();
1484             }
1485             if (c == '"' || c == '\'') {
1486                 position_++;
1487                 std::string value = ParseTagValue(static_cast<char>(c), true, true, TextEnum::ATTRI);
1488                 if (PriorDealChar() == c) {
1489                     position_++;
1490                 }
1491             }
1492         }
1493     }
1494 
ParseEntityDecl()1495     void XmlPullParser::ParseEntityDecl()
1496     {
1497         SkipText(tagText_.START_ENTITY);
1498         bool generalEntity = true;
1499         SkipInvalidChar();
1500         if (PriorDealChar() == '%') {
1501             generalEntity = false;
1502             position_++;
1503             SkipInvalidChar();
1504         }
1505         std::string name = ParseName();
1506         SkipInvalidChar();
1507         int quote = PriorDealChar();
1508         std::string entityValue;
1509         if (quote == '"' || quote == '\'') {
1510             position_++;
1511             entityValue = ParseTagValue(static_cast<char>(quote), true, false, TextEnum::ENTITY_DECL);
1512             if (PriorDealChar() == quote) {
1513                 position_++;
1514             }
1515         } else if (ParserDoctInnerInfo(true, false)) {
1516             entityValue = "";
1517             SkipInvalidChar();
1518             if (PriorDealChar() == tagText_.NDATA[0]) {
1519                 SkipText(tagText_.NDATA);
1520                 SkipInvalidChar();
1521                 ParseName();
1522             }
1523         } else {
1524             xmlPullParserError_ = "Expected entity value or external ID";
1525         }
1526         if (generalEntity && bDocDecl) {
1527             documentEntities[name] = entityValue;
1528         }
1529         SkipInvalidChar();
1530         SkipChar('>');
1531     }
1532 
ParseInneNotaDecl()1533     void XmlPullParser::ParseInneNotaDecl()
1534     {
1535         SkipText(tagText_.START_NOTATION);
1536         SkipInvalidChar();
1537         ParseName();
1538         if (!ParserDoctInnerInfo(false, false)) {
1539             xmlPullParserError_ = "Expected external ID or public ID for notation ";
1540         }
1541         SkipInvalidChar();
1542         SkipChar('>');
1543     }
1544 
ReadInternalSubset()1545     void XmlPullParser::ReadInternalSubset()
1546     {
1547         SkipChar('[');
1548         while (true) {
1549             SkipInvalidChar();
1550             if (PriorDealChar() == ']') {
1551                 position_++;
1552                 return;
1553             }
1554             TagEnum declarationType = ParseTagType(true);
1555             switch (declarationType) {
1556                 case TagEnum::ELEMENTDECL:
1557                     ParseInnerEleDec();
1558                     break;
1559                 case TagEnum::ATTLISTDECL:
1560                     ParseInnerAttriDecl();
1561                     break;
1562                 case TagEnum::ENTITYDECL:
1563                     ParseEntityDecl();
1564                     break;
1565                 case TagEnum::NOTATIONDECL:
1566                     ParseInneNotaDecl();
1567                     break;
1568                 case TagEnum::INSTRUCTION:
1569                     SkipText(tagText_.START_PROCESSING_INSTRUCTION);
1570                     ParseDelimiterInfo(tagText_.END_PROCESSING_INSTRUCTION, false);
1571                     break;
1572                 case TagEnum::COMMENT:
1573                     ParseComment(false);
1574                     break;
1575                 case TagEnum::PARAMETER_ENTITY_REF:
1576                     xmlPullParserError_ = "Parameter entity references are not supported ";
1577                     break;
1578                 default:
1579                     xmlPullParserError_ = "Unexpected token";
1580                     break;
1581             }
1582         }
1583     }
1584 
ParseDoctype(bool saveDtdText)1585     void XmlPullParser::ParseDoctype(bool saveDtdText)
1586     {
1587         SkipText(tagText_.START_DOCTYPE);
1588         size_t startPosition = 0;
1589         if (saveDtdText) {
1590             keyInfo_ = "";
1591             startPosition = position_;
1592         }
1593         SkipInvalidChar();
1594         ParseName();
1595         ParserDoctInnerInfo(true, true);
1596         SkipInvalidChar();
1597         if (PriorDealChar() == '[') {
1598             ReadInternalSubset();
1599         }
1600         SkipInvalidChar();
1601         if (saveDtdText) {
1602             keyInfo_.append(strXml_, 0, position_);
1603             keyInfo_ = keyInfo_.substr(startPosition);
1604             text_ = keyInfo_;
1605             keyInfo_ = "";
1606         }
1607         SkipChar('>');
1608     }
1609 
ParseText()1610     void XmlPullParser::ParseText()
1611     {
1612         text_ = ParseTagValue('<', true, false, TextEnum::TEXT);
1613         std::string strTemp = text_;
1614         Replace(strTemp, "\r", "");
1615         Replace(strTemp, "\n", "");
1616         Replace(strTemp, " ", "");
1617         if ((depth == 0 && bWhitespace_) || strTemp.size() == 0) {
1618             type = TagEnum::WHITESPACE;
1619         }
1620     }
1621 
ParseCdect()1622     void XmlPullParser::ParseCdect()
1623     {
1624         SkipText(tagText_.START_CDATA);
1625         text_ = ParseDelimiterInfo(tagText_.END_CDATA, true);
1626     }
1627 
ParseOneTagFunc()1628     TagEnum XmlPullParser::ParseOneTagFunc()
1629     {
1630         switch (type) {
1631             case TagEnum::START_DOCUMENT:
1632                 return type;
1633             case TagEnum::START_TAG: {
1634                 if (ParseStartTag(false, false) == TagEnum::ERROR) {
1635                     return TagEnum::ERROR;
1636                 }
1637                 return type;}
1638             case TagEnum::END_TAG: {
1639                 if (ParseEndTag()) {
1640                     return type;
1641                 }
1642                 return TagEnum::ERROR;}
1643             case TagEnum::END_DOCUMENT:
1644                 return type;
1645             case TagEnum::ENTITY_REFERENCE: {
1646                 std::string entityTextBuilder;
1647                 ParseEntity(entityTextBuilder, true, false, TextEnum::TEXT);
1648                 text_ = entityTextBuilder;
1649                 return TagEnum::OK;
1650                 }
1651             case TagEnum::TEXT:
1652                 ParseText();
1653                 return TagEnum::OK;
1654             case TagEnum::CDSECT:
1655                 ParseCdect();
1656                 return TagEnum::OK;
1657             case TagEnum::COMMENT:
1658                 ParseComment(true);
1659                 return TagEnum::OK;
1660             case TagEnum::INSTRUCTION:
1661                 ParseInstruction();
1662                 return TagEnum::OK;
1663             case TagEnum::DOCDECL:
1664                 ParseDoctype(true);
1665                 return TagEnum::OK;
1666             default:
1667                 xmlPullParserError_ = "Unexpected token";
1668                 return TagEnum::ERROR;
1669         }
1670     }
1671 
ParseOneTag()1672     TagEnum XmlPullParser::ParseOneTag()
1673     {
1674         if (type == TagEnum::END_TAG) {
1675             depth--;
1676         }
1677         if (bEndFlag_) {
1678             bEndFlag_ = false;
1679             type = TagEnum::END_TAG;
1680             return type;
1681         }
1682         ParserPriorDeal();
1683         while (true) {
1684             TagEnum typeTem = ParseOneTagFunc();
1685             if (typeTem != TagEnum::OK) {
1686                 return typeTem;
1687             }
1688             if (depth == 0 && (type == TagEnum::ENTITY_REFERENCE || type == TagEnum::TEXT || type == TagEnum::CDSECT)) {
1689                 std::string errMsg = "";
1690                 if (!text_.empty()) {
1691                     errMsg = ": " + text_;
1692                 }
1693                 xmlPullParserError_ = "Unexpected token" + errMsg;
1694             }
1695             if (type == TagEnum::DOCDECL && (!bDoctype_)) {
1696                 ParseOneTag();
1697             }
1698             return type;
1699         }
1700     }
1701 
ParserPriorDeal()1702     void XmlPullParser::ParserPriorDeal()
1703     {
1704         type = ParseTagType(false);
1705         if (type == TagEnum::XML_DECLARATION) {
1706             ParseDeclaration();
1707             type = ParseTagType(false);
1708         }
1709         text_ = "";
1710         bWhitespace_ = true;
1711         prefix_ = "";
1712         name_ = "";
1713         namespace_ = "";
1714         attriCount_ = 0;
1715     }
1716 
ParseInstruction()1717     void XmlPullParser::ParseInstruction()
1718     {
1719         SkipText(tagText_.START_PROCESSING_INSTRUCTION);
1720         text_ = ParseDelimiterInfo(tagText_.END_PROCESSING_INSTRUCTION, true);
1721     }
1722 
GetColumnNumber() const1723     int XmlPullParser::GetColumnNumber() const
1724     {
1725         size_t result = 0;
1726         for (size_t i = 0; i < position_; i++) {
1727             if (strXml_[i] == '\n') {
1728                 result = 0;
1729             } else {
1730                 result++;
1731             }
1732         }
1733         return result + 1;
1734     }
1735 
GetDepth() const1736     int XmlPullParser::GetDepth() const
1737     {
1738         return depth;
1739     }
1740 
GetLineNumber() const1741     int XmlPullParser::GetLineNumber() const
1742     {
1743         int result = bufferStartLine_;
1744         for (size_t i = 0; i < position_; i++) {
1745             if (strXml_[i] == '\n') {
1746                 result++;
1747             }
1748         }
1749         return result + 1;
1750     }
1751 
GetName() const1752     std::string XmlPullParser::GetName() const
1753     {
1754         return name_;
1755     }
1756 
GetPrefix() const1757     std::string XmlPullParser::GetPrefix() const
1758     {
1759         return prefix_;
1760     }
1761 
GetText() const1762     std::string XmlPullParser::GetText() const
1763     {
1764         if (type < TagEnum::TEXT || (type == TagEnum::ENTITY_REFERENCE && bUnresolved_)) {
1765             return "";
1766         } else {
1767             return text_;
1768         }
1769     }
1770 
IsEmptyElementTag() const1771     bool XmlPullParser::IsEmptyElementTag() const
1772     {
1773         return bEndFlag_;
1774     }
1775 
GetAttributeCount() const1776     int XmlPullParser::GetAttributeCount() const
1777     {
1778         return attriCount_;
1779     }
1780 
IsWhitespace() const1781     bool XmlPullParser::IsWhitespace() const
1782     {
1783         return bWhitespace_;
1784     }
1785 
GetNamespace() const1786     std::string XmlPullParser::GetNamespace() const
1787     {
1788         return namespace_;
1789     }
1790 
GetColumnNumber(napi_env env,napi_callback_info info)1791     napi_value XmlPullParser::ParseInfo::GetColumnNumber(napi_env env, napi_callback_info info)
1792     {
1793         napi_value thisVar = nullptr;
1794         napi_value mainVar = nullptr;
1795         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1796         void *obj = nullptr;
1797         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1798         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1799         napi_value result = nullptr;
1800         if (obj != nullptr) {
1801             int temp = (reinterpret_cast<XmlPullParser *>(obj))->GetColumnNumber();
1802             napi_create_int32(env, temp, &result);
1803         }
1804         return result;
1805     }
1806 
GetDepth(napi_env env,napi_callback_info info)1807     napi_value XmlPullParser::ParseInfo::GetDepth(napi_env env, napi_callback_info info)
1808     {
1809         napi_value thisVar = nullptr;
1810         napi_value mainVar = nullptr;
1811         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1812         void *obj = nullptr;
1813         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1814         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1815         napi_value result = nullptr;
1816         if (obj != nullptr) {
1817             int temp = (reinterpret_cast<XmlPullParser *>(obj))->GetDepth();
1818             napi_create_int32(env, temp, &result);
1819         }
1820         return result;
1821     }
1822 
GetLineNumber(napi_env env,napi_callback_info info)1823     napi_value XmlPullParser::ParseInfo::GetLineNumber(napi_env env, napi_callback_info info)
1824     {
1825         napi_value thisVar = nullptr;
1826         napi_value mainVar = nullptr;
1827         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1828         void *obj = nullptr;
1829         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1830         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1831         napi_value result = nullptr;
1832         if (obj != nullptr) {
1833             int temp = (reinterpret_cast<XmlPullParser *>(obj))->GetLineNumber();
1834             napi_create_int32(env, temp, &result);
1835         }
1836         return result;
1837     }
1838 
GetName(napi_env env,napi_callback_info info)1839     napi_value XmlPullParser::ParseInfo::GetName(napi_env env, napi_callback_info info)
1840     {
1841         napi_value thisVar = nullptr;
1842         napi_value mainVar = nullptr;
1843         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1844         void *obj = nullptr;
1845         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1846         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1847         napi_value result = nullptr;
1848         if (obj != nullptr) {
1849             std::string temp = (reinterpret_cast<XmlPullParser *>(obj))->GetName();
1850             napi_create_string_utf8(env, temp.c_str(), temp.length(), &result);
1851         }
1852         return result;
1853     }
1854 
GetNamespace(napi_env env,napi_callback_info info)1855     napi_value XmlPullParser::ParseInfo::GetNamespace(napi_env env, napi_callback_info info)
1856     {
1857         napi_value thisVar = nullptr;
1858         napi_value mainVar = nullptr;
1859         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1860         void *obj = nullptr;
1861         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1862         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1863         napi_value result = nullptr;
1864         if (obj != nullptr) {
1865             std::string temp = (reinterpret_cast<XmlPullParser *>(obj))->GetNamespace();
1866             napi_create_string_utf8(env, temp.c_str(), temp.length(), &result);
1867         }
1868         return result;
1869     }
1870 
GetPrefix(napi_env env,napi_callback_info info)1871     napi_value XmlPullParser::ParseInfo::GetPrefix(napi_env env, napi_callback_info info)
1872     {
1873         napi_value thisVar = nullptr;
1874         napi_value mainVar = nullptr;
1875         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1876         void *obj = nullptr;
1877         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1878         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1879         napi_value result = nullptr;
1880         if (obj != nullptr) {
1881             std::string temp = (reinterpret_cast<XmlPullParser *>(obj))->GetPrefix();
1882             napi_create_string_utf8(env, temp.c_str(), temp.length(), &result);
1883         }
1884         return result;
1885     }
1886 
GetText(napi_env env,napi_callback_info info)1887     napi_value XmlPullParser::ParseInfo::GetText(napi_env env, napi_callback_info info)
1888     {
1889         napi_value thisVar = nullptr;
1890         napi_value mainVar = nullptr;
1891         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1892         void *obj = nullptr;
1893         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1894         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1895         napi_value result = nullptr;
1896         if (obj != nullptr) {
1897             std::string temp = (reinterpret_cast<XmlPullParser *>(obj))->GetText();
1898             napi_create_string_utf8(env, temp.c_str(), temp.length(), &result);
1899         }
1900         return result;
1901     }
1902 
IsEmptyElementTag(napi_env env,napi_callback_info info)1903     napi_value XmlPullParser::ParseInfo::IsEmptyElementTag(napi_env env, napi_callback_info info)
1904     {
1905         napi_value thisVar = nullptr;
1906         napi_value mainVar = nullptr;
1907         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1908         void *obj = nullptr;
1909         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1910         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1911         napi_value result = nullptr;
1912         if (obj != nullptr) {
1913             bool temp = (reinterpret_cast<XmlPullParser *>(obj))->IsEmptyElementTag();
1914             napi_get_boolean(env, temp, &result);
1915         }
1916         return result;
1917     }
1918 
IsWhitespace(napi_env env,napi_callback_info info)1919     napi_value XmlPullParser::ParseInfo::IsWhitespace(napi_env env, napi_callback_info info)
1920     {
1921         napi_value thisVar = nullptr;
1922         napi_value mainVar = nullptr;
1923         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1924         void *obj = nullptr;
1925         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1926         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1927         napi_value result = nullptr;
1928         if (obj != nullptr) {
1929             bool temp = (reinterpret_cast<XmlPullParser *>(obj))->IsWhitespace();
1930             napi_get_boolean(env, temp, &result);
1931         }
1932         return result;
1933     }
1934 
GetAttributeCount(napi_env env,napi_callback_info info)1935     napi_value XmlPullParser::ParseInfo::GetAttributeCount(napi_env env, napi_callback_info info)
1936     {
1937         napi_value thisVar = nullptr;
1938         napi_value mainVar = nullptr;
1939         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
1940         void *obj = nullptr;
1941         napi_get_named_property(env, thisVar, "MainInfo", &mainVar);
1942         NAPI_CALL(env, napi_unwrap(env, mainVar, &obj));
1943         napi_value result = nullptr;
1944         if (obj != nullptr) {
1945             int temp = (reinterpret_cast<XmlPullParser *>(obj))->GetAttributeCount();
1946             napi_create_int32(env, temp, &result);
1947         }
1948         return result;
1949     }
1950 } // namespace OHOS::Xml
1951 
1952