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