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