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