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