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("'"); 351 break; 352 case '\"': 353 out_.append("""); 354 break; 355 case '&': 356 out_.append("&"); 357 break; 358 case '>': 359 out_.append(">"); 360 break; 361 case '<': 362 out_.append("<"); 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