1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <xml/xml_tinyParser.h> 18 19int32_t xml_errno; 20 21#ifdef XML_DOM_PARSER 22 23#define XML_IS_WHITESPACE(x) ((x) == '\t' || (x) == '\n' || (x) == ' ' || (x) == '\r') 24#define XML_IS_NAMECHAR(ch) (isalpha(ch) || isdigit(ch) || ch ==':' || \ 25 ch == '_' || ch == '-' || ch =='.') 26 27static uint8_t *xml_ignore_blank(uint8_t *buffer) 28{ 29 if (NULL == buffer) 30 return NULL; 31 32 while (XML_IS_WHITESPACE(*buffer)) 33 buffer++; 34 35 return buffer; 36} 37 38static uint8_t *xml_goto_tagend(uint8_t *buffer) 39{ 40 int32_t nameLen, valueLen; 41 uint8_t *name, *value; 42 43 if (NULL == buffer) 44 return NULL; 45 46 /* Ignore the start-tag */ 47 if (*buffer == '<') { 48 buffer++; 49 while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) 50 buffer++; 51 if (NULL == buffer) 52 return NULL; 53 } 54 55 do { 56 if (NULL == (buffer = xml_ignore_blank(buffer))) 57 return NULL; 58 59 if (*buffer == '>' || (*buffer == '/' && *(buffer + 1) == '>')) 60 return buffer; 61 62 if (NULL == 63 XML_DOM_getAttr(buffer, &name, &nameLen, &value, &valueLen)) 64 return NULL; 65 66 buffer = value + valueLen + 1; 67 } while (*buffer != '\0'); 68 69 return NULL; 70} 71 72static uint8_t *xml_match_tag(uint8_t *buffer) 73{ 74 int32_t tagLen, tagType, bal; 75 76 if (NULL == buffer) 77 return NULL; 78 79 bal = 0; 80 do { 81 if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType))) 82 return NULL; 83 84 switch (tagType) { 85 case XML_TAG_SELF: 86 case XML_TAG_START: 87 if (NULL == (buffer = xml_goto_tagend(buffer + tagLen + 1))) 88 return NULL; 89 if (strncmp((char *)buffer, "/>", 2) == 0) { 90 buffer += 2; 91 } else { 92 bal++; 93 } 94 break; 95 96 case XML_TAG_END: 97 if (bal <= 0) 98 return NULL; 99 buffer = buffer + tagLen + 2; 100 bal--; 101 break; 102 } 103 } while (bal != 0); 104 105 return buffer; 106} 107 108uint8_t *XML_DOM_getAttr(uint8_t *buffer, uint8_t **pName, int32_t *nameLen, 109 uint8_t **pValue, int32_t *valueLen) 110{ 111 uint8_t charQuoted; 112 113 if (NULL == buffer) { 114 XML_ERROR(XML_ERROR_BUFFER_NULL); 115 return NULL; 116 } 117 118 /* Ignore the tag */ 119 if (*buffer == '<') { 120 buffer++; 121 /* Ignore the STag */ 122 while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) 123 buffer++; 124 if (NULL == buffer) 125 return NULL; 126 } 127 128 if (NULL == (buffer = xml_ignore_blank(buffer))) { 129 XML_ERROR(XML_ERROR_BUFFER_NULL); 130 return NULL; 131 } 132 133 /* Name */ 134 *pName = buffer; 135 while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) 136 buffer++; 137 if (NULL == buffer) { 138 XML_ERROR(XML_ERROR_ATTR_NAME); 139 return NULL; 140 } 141 *nameLen = buffer - *pName; 142 if (*nameLen <= 0) { 143 XML_ERROR(XML_ERROR_ATTR_NAME); 144 return NULL; 145 } 146 147 /* '=' */ 148 buffer = xml_ignore_blank(buffer); 149 if (NULL == buffer || *buffer != '=') { 150 XML_ERROR(XML_ERROR_ATTR_MISSED_EQUAL); 151 return NULL; 152 } 153 154 /* Value */ 155 buffer++; 156 buffer = xml_ignore_blank(buffer); 157 if (NULL == buffer || (*buffer != '"' && *buffer != '\'')) { 158 XML_ERROR(XML_ERROR_ATTR_VALUE); 159 return NULL; 160 } 161 charQuoted = *buffer++; 162 *pValue = buffer; 163 while (*buffer != '\0' && *buffer != charQuoted) 164 buffer++; 165 if (*buffer != charQuoted) { 166 XML_ERROR(XML_ERROR_ATTR_VALUE); 167 return NULL; 168 } 169 *valueLen = buffer - *pValue; 170 171 XML_ERROR(XML_ERROR_OK); 172 173 return buffer + 1; 174} 175 176uint8_t *XML_DOM_getValue(uint8_t *buffer, uint8_t **pValue, int32_t *valueLen) 177{ 178 uint8_t *pEnd; 179 180 if (NULL == buffer) { 181 XML_ERROR(XML_ERROR_BUFFER_NULL); 182 return NULL; 183 } 184 185 /* Ignore the STag */ 186 if (*buffer == '<') { 187 buffer++; 188 /* If it's an end_tag, no value should be returned */ 189 if (*buffer == '/') { 190 *valueLen = 0; 191 XML_ERROR(XML_ERROR_NOVALUE); 192 return NULL; 193 } 194 195 while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) 196 buffer++; 197 if (NULL == buffer) { 198 XML_ERROR(XML_ERROR_BUFFER_NULL); 199 return NULL; 200 } 201 202 if (NULL == (buffer = xml_goto_tagend(buffer))) { 203 XML_ERROR(XML_ERROR_PROPERTY_END); 204 return NULL; 205 } 206 } 207 208 /* <test/> node found */ 209 if (*buffer == '/') { 210 if (*(buffer + 1) != '>') { 211 XML_ERROR(XML_ERROR_PROPERTY_END); 212 return NULL; 213 } 214 XML_ERROR(XML_ERROR_OK); 215 *valueLen = 0; 216 return buffer; 217 } 218 219 if (*buffer == '>') 220 buffer++; 221 222 if (NULL == (buffer = xml_ignore_blank(buffer))) { 223 XML_ERROR(XML_ERROR_BUFFER_NULL); 224 return NULL; 225 } 226 227 /* the following is a tag instead of the value */ 228 if (*buffer == '<') { /* nono value, such as <test></test> */ 229 buffer++; 230 if (*buffer != '/') { 231 XML_ERROR(XML_ERROR_ENDTAG); 232 return NULL; 233 } 234 *valueLen = 0; 235 XML_ERROR(XML_ERROR_OK); 236 return NULL; 237 } 238 239 *pValue = buffer; 240 pEnd = NULL; 241 while (*buffer != '\0' && *buffer != '<') { 242 if (!XML_IS_WHITESPACE(*buffer)) 243 pEnd = buffer; 244 buffer++; 245 } 246 if (*buffer != '<' || pEnd == NULL) { 247 XML_ERROR(XML_ERROR_VALUE); 248 return NULL; 249 } 250 251 *valueLen = pEnd - *pValue + 1; 252 253 buffer++; 254 if (*buffer != '/') { 255 XML_ERROR(XML_ERROR_ENDTAG); 256 return NULL; 257 } 258 259 XML_ERROR(XML_ERROR_OK); 260 261 return buffer - 1; 262} 263 264uint8_t *XML_DOM_getTag(uint8_t *buffer, int32_t *tagLen, int32_t *tagType) 265{ 266 uint8_t *pStart; 267 268 /* WARNING: <!-- --> comment is not supported in this verison */ 269 if (NULL == buffer) { 270 XML_ERROR(XML_ERROR_BUFFER_NULL); 271 return NULL; 272 } 273 274 do { 275 while (*buffer != '<') { 276 if (*buffer == '\0') { 277 XML_ERROR(XML_ERROR_BUFFER_NULL); 278 return NULL; 279 } 280 281 if (*buffer == '\"' || *buffer == '\'') { 282 uint8_t charQuoted = *buffer; 283 buffer++; 284 while (*buffer != '\0' && *buffer != charQuoted) 285 buffer++; 286 if (*buffer == '\0') { 287 XML_ERROR(XML_ERROR_BUFFER_NULL); 288 return NULL; 289 } 290 } 291 buffer++; 292 } 293 buffer++; 294 } while (*buffer == '!' || *buffer == '?'); 295 296 pStart = buffer - 1; 297 298 if (*buffer == '/') { 299 buffer++; 300 *tagType = XML_TAG_END; 301 } else { 302 /* check here if it is self-end-tag */ 303 uint8_t *pCheck = xml_goto_tagend(pStart); 304 if (pCheck == NULL) { 305 XML_ERROR(XML_ERROR_PROPERTY_END); 306 return NULL; 307 } 308 309 if (*pCheck == '>') 310 *tagType = XML_TAG_START; 311 else if (strncmp((char *)pCheck, "/>", 2) == 0) 312 *tagType = XML_TAG_SELF; 313 else { 314 XML_ERROR(XML_ERROR_PROPERTY_END); 315 return NULL; 316 } 317 } 318 319 while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) 320 buffer++; 321 if (NULL == buffer) { 322 XML_ERROR(XML_ERROR_BUFFER_NULL); 323 return NULL; 324 } 325 326 if (*tagType == XML_TAG_END) 327 *tagLen = buffer - pStart - 2; 328 else 329 *tagLen = buffer - pStart - 1; 330 331 XML_ERROR(XML_ERROR_OK); 332 333 return pStart; 334} 335 336uint8_t *XML_DOM_getNode(uint8_t *buffer, const uint8_t *const node) 337{ 338 uint8_t *pStart; 339 uint8_t buf[XML_MAX_PROPERTY_LEN + 2]; 340 uint8_t *nodeStr = buf; 341 uint8_t *retPtr = NULL; 342 int32_t tagLen, tagType; 343 uint8_t *lastNode = (uint8_t *)""; 344 345 if (NULL == buffer) { 346 XML_ERROR(XML_ERROR_BUFFER_NULL); 347 return NULL; 348 } 349 350 strncpy((char *)nodeStr, (char *)node, XML_MAX_PROPERTY_LEN); 351 strcat((char *)nodeStr, "\\"); 352 pStart = (uint8_t *)strchr((char *)nodeStr, '\\'); 353 354 while (pStart != NULL) { 355 *pStart = '\0'; 356 357 /* get the first start_tag from buffer */ 358 if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType))) { 359 XML_ERROR(XML_ERROR_NO_SUCH_NODE); 360 return NULL; 361 } 362 363 if (tagType == XML_TAG_END) { 364 if (0 == 365 strncmp((char *)lastNode, (char *)(buffer + 2), strlen((char *)lastNode))) 366 XML_ERROR(XML_ERROR_NO_SUCH_NODE); 367 else 368 XML_ERROR(XML_ERROR_NO_START_TAG); 369 return NULL; 370 } 371 372 /* wrong node, contiue to fetch the next node */ 373 if ((int32_t) strlen((char *)nodeStr) != tagLen 374 || strncmp((char *)nodeStr, (char *)(buffer + 1), tagLen) != 0) { 375 /* we should ignore all the middle code */ 376 buffer = xml_match_tag(buffer); 377 continue; 378 } 379 380 retPtr = buffer; /* retPtr starts with '<xxx>' */ 381 buffer += (tagLen + 1); 382 383 if (tagType == XML_TAG_SELF) { 384 nodeStr = pStart + 1; 385 break; 386 } 387 388 lastNode = nodeStr; 389 nodeStr = pStart + 1; 390 pStart = (uint8_t *)strchr((char *)nodeStr, '\\'); 391 } 392 393 /* Check 5: nodeStr should be empty here */ 394 if (*nodeStr != '\0') { 395 XML_ERROR(XML_ERROR_NO_SUCH_NODE); 396 return NULL; 397 } 398 399 XML_ERROR(XML_ERROR_OK); 400 401 return retPtr; 402} 403 404uint8_t *XML_DOM_getNodeValue(uint8_t *buffer, uint8_t *node, 405 uint8_t **value, int32_t *valueLen) 406{ 407 uint8_t *pStart; 408 uint8_t *lastTag; 409 410 if (NULL == node || NULL == buffer) { 411 XML_ERROR(XML_ERROR_BUFFER_NULL); 412 return NULL; 413 } 414 415 lastTag = node + strlen((char *)node) - 1; 416 while (lastTag >= node && *lastTag != '\\') 417 lastTag--; 418 lastTag++; 419 420 if (NULL == (pStart = XML_DOM_getNode(buffer, node))) 421 return NULL; 422 423 pStart += (strlen((char *)lastTag) + 1); 424 425 if (NULL == (pStart = xml_goto_tagend(pStart))) { 426 XML_ERROR(XML_ERROR_PROPERTY_END); 427 return NULL; 428 } 429 430 if (NULL == (pStart = XML_DOM_getValue(pStart, value, valueLen))) 431 return NULL; 432 433 /* Check the end tag */ 434#ifdef XML_DOM_CHECK_ENDTAG 435 if (strncmp((char *)pStart, "/>", 2) == 0) { 436 437 } else if (strncmp((char *)lastTag, (char *)(pStart + 2), strlen((char *)lastTag)) != 438 0) { 439 XML_ERROR(XML_ERROR_ENDTAG); 440 return NULL; 441 } 442#endif 443 444 XML_ERROR(XML_ERROR_OK); 445 446 return *value; 447} 448 449uint8_t *XML_DOM_getNextNode(uint8_t *buffer, uint8_t **pNodeName, int32_t *nodenameLen) 450{ 451 int32_t tagType; 452 453 if (NULL == buffer) 454 return NULL; 455 456 do { 457 if (NULL == 458 (buffer = XML_DOM_getTag(buffer + 1, nodenameLen, &tagType))) { 459 XML_ERROR(XML_ERROR_NO_SUCH_NODE); 460 return NULL; 461 } 462 } while (tagType == XML_TAG_END); 463 464 *pNodeName = buffer + 1; 465 466 XML_ERROR(XML_ERROR_OK); 467 468 return buffer; 469} 470 471#endif /* XML_DOM_PARSER */ 472 473#ifdef WBXML_DOM_PARSER 474 475#ifdef WBXML_OLD_VERSION 476uint8_t *WBXML_DOM_getNode(uint8_t *buffer, int32_t bufferLen, 477 uint8_t *node) 478{ 479 int32_t i = 0, j = 0; 480 481 if (NULL == buffer || node == NULL) { 482 XML_ERROR(XML_ERROR_BUFFER_NULL); 483 return NULL; 484 } 485 486 while (i < bufferLen) { 487 if (WBXML_GET_TAG(buffer[i]) == WBXML_GET_TAG(node[j])) { 488 j++; 489 if (node[j] == '\0') 490 break; 491 492 /* Check if there is the content(it should have content) */ 493 if (!WBXML_HAS_CONTENT(buffer[i])) { 494 /*XML_ERROR(WBXML_ERROR_MISSED_CONTENT); */ 495 XML_ERROR(XML_ERROR_NO_SUCH_NODE); 496 return NULL; 497 } 498 499 /* Ignore the attrib filed */ 500 if (WBXML_HAS_ATTR(buffer[i])) { 501 while (i < bufferLen && buffer[i] != WBXML_ATTR_END) 502 i++; 503 if (i >= bufferLen) 504 break; 505 } 506 } 507 i++; 508 509 /* Ignore the content filed */ 510 if (buffer[i] == WBXML_STR_I) { 511 while (i < bufferLen && buffer[i] != WBXML_END) 512 i++; 513 if (i >= bufferLen) 514 break; 515 i++; 516 } 517 } 518 519 if (i >= bufferLen) { 520 XML_ERROR(XML_ERROR_NO_SUCH_NODE); 521 return NULL; 522 } 523 524 XML_ERROR(XML_ERROR_OK); 525 526 return buffer + i + 1; 527} 528 529uint8_t *WBXML_DOM_getNodeValue(uint8_t *buffer, int32_t bufferLen, 530 uint8_t *node, 531 uint8_t **value, int32_t *valueLen) 532{ 533 int32_t i; 534 uint8_t *pEnd; 535 536 *value = NULL; 537 *valueLen = 0; 538 539 pEnd = buffer + bufferLen; 540 buffer = WBXML_DOM_getNode(buffer, bufferLen, node); 541 if (NULL == buffer) { 542 XML_ERROR(XML_ERROR_NO_SUCH_NODE); 543 return NULL; 544 } 545 546 if (*buffer == WBXML_OPAUE) { 547 buffer++; 548 *valueLen = WBXML_GetUintVar(buffer, &i); 549 if (*valueLen < 0) { 550 XML_ERROR(WBXML_ERROR_MBUINT32); 551 return NULL; 552 } 553 buffer += i; 554 *value = buffer; 555 return *value; 556 } 557 558 if (*buffer != WBXML_STR_I) { 559 XML_ERROR(WBXML_ERROR_MISSED_STARTTAG); 560 return NULL; 561 } 562 563 buffer++; 564 565 i = 0; 566 while ((buffer + i) < pEnd && buffer[i] != WBXML_END) 567 i++; 568 569 if (buffer[i] != WBXML_END) { 570 XML_ERROR(WBXML_ERROR_MISSED_ENDTAG); 571 return NULL; 572 } 573 574 *value = buffer; 575 *valueLen = i; 576 XML_ERROR(XML_ERROR_OK); 577 578 return *value; 579} 580#endif /* WBXML_OLD_VERSION */ 581 582#define MAX_UINT_VAR_BYTE 4 583#define UINTVAR_INVALID -1 584int32_t WBXML_GetUintVar(const uint8_t *const buffer, int32_t *len) 585{ 586 int32_t i, byteLen; 587 int32_t sum; 588 589 byteLen = 0; 590 while ((buffer[byteLen] & 0x80) > 0 && byteLen < MAX_UINT_VAR_BYTE) 591 byteLen++; 592 593 if (byteLen > MAX_UINT_VAR_BYTE) 594 return UINTVAR_INVALID; 595 596 *len = byteLen + 1; 597 sum = buffer[byteLen]; 598 for (i = byteLen - 1; i >= 0; i--) 599 sum += ((buffer[i] & 0x7F) << 7 * (byteLen - i)); 600 601 return sum; 602} 603 604XML_BOOL WBXML_DOM_Init(WBXML * pWbxml, uint8_t *buffer, 605 int32_t bufferLen) 606{ 607 int32_t num, len; 608 609 pWbxml->End = buffer + bufferLen; 610 pWbxml->version = *buffer++; 611 if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len))) 612 return XML_FALSE; 613 buffer += len; 614 pWbxml->publicid = num; 615 if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len))) 616 return XML_FALSE; 617 buffer += len; 618 pWbxml->charset = num; 619 if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len))) 620 return XML_FALSE; 621 buffer += len; 622 pWbxml->strTable = buffer; 623 pWbxml->strTableLen = num; 624 buffer += num; 625 pWbxml->curPtr = pWbxml->Content = buffer; 626 pWbxml->depth = 0; 627 628 return XML_TRUE; 629} 630 631void WBXML_DOM_Rewind(WBXML * pWbxml) 632{ 633 pWbxml->curPtr = pWbxml->Content; 634} 635 636XML_BOOL WBXML_DOM_Eof(WBXML * pWbxml) 637{ 638 if (pWbxml->curPtr > pWbxml->End) 639 return XML_TRUE; 640 641 return XML_FALSE; 642} 643 644uint8_t WBXML_DOM_GetTag(WBXML * pWbxml) 645{ 646 uint8_t tagChar; 647 648 if (pWbxml->curPtr > pWbxml->End) 649 return XML_EOF; 650 651 tagChar = *pWbxml->curPtr; 652 pWbxml->curPtr++; 653 654 if (WBXML_GET_TAG(tagChar) == WBXML_CONTENT_END) 655 pWbxml->depth--; 656 else 657 pWbxml->depth++; 658 659 return tagChar; 660} 661 662uint8_t WBXML_DOM_GetChar(WBXML * pWbxml) 663{ 664 return *pWbxml->curPtr++; 665} 666 667void WBXML_DOM_Seek(WBXML * pWbxml, int32_t offset) 668{ 669 pWbxml->curPtr += offset; 670} 671 672uint8_t WBXML_DOM_GetUIntVar(WBXML * pWbxml) 673{ 674 int32_t num, len; 675 676 num = WBXML_GetUintVar(pWbxml->curPtr, &len); 677 pWbxml->curPtr += len; 678 679 return (uint8_t)num; 680} 681 682#ifdef XML_TREE_STRUCTURE 683 684#ifdef DEBUG_MODE 685static int32_t malloc_times = 0; 686static int32_t free_times = 0; 687void XML_PrintMallocInfo() 688{ 689 printf("====XML_PrintMallocInfo====\n"); 690 printf(" Total malloc times:%d\n", malloc_times); 691 printf(" Total free times:%d\n", free_times); 692 printf("===========================\n"); 693} 694#endif 695 696void *xml_malloc(int32_t size) 697{ 698#ifdef DEBUG_MODE 699 malloc_times++; 700#endif 701 return malloc(size); 702} 703 704void xml_free(void *buffer) 705{ 706#ifdef DEBUG_MODE 707 free_times++; 708#endif 709 free(buffer); 710} 711 712XML_TREE *xml_tree_fillnode(uint8_t **buf, int32_t tagLen) 713{ 714 XML_TREE *Tree; 715 uint8_t *pAttr, *pName, *pValue; 716 int32_t nameLen, valueLen; 717 uint8_t *buffer = *buf; 718 719 if (NULL == (Tree = (XML_TREE *) xml_malloc(sizeof(XML_TREE)))) 720 return NULL; 721 memset(Tree, 0, sizeof(XML_TREE)); 722 723 strncpy((char *)Tree->tag, (char *)++buffer, tagLen); 724 buffer += tagLen; 725 pAttr = buffer; 726 727 /* attribute */ 728 while (NULL != 729 (pAttr = 730 XML_DOM_getAttr(pAttr, &pName, &nameLen, &pValue, 731 &valueLen))) { 732 XML_TREE_ATTR *attr; 733 if (NULL == 734 (attr = (XML_TREE_ATTR *) xml_malloc(sizeof(XML_TREE_ATTR)))) 735 return NULL; 736 memset(attr, 0, sizeof(XML_TREE_ATTR)); 737 strncpy((char *)attr->name, (char *)pName, nameLen); 738 strncpy((char *)attr->value, (char *)pValue, valueLen); 739 buffer = pValue + valueLen + 1; 740 741 if (NULL != Tree->attr) // no attribute now 742 Tree->last_attr->next = attr; 743 else 744 Tree->attr = attr; 745 Tree->last_attr = attr; 746 } 747 748 /* value */ 749 pAttr = XML_DOM_getValue(buffer, &pValue, &valueLen); 750 if (pAttr != NULL && valueLen > 0) { 751 strncpy((char *)Tree->value, (char *)pValue, valueLen); 752 buffer = pValue + valueLen; 753 } 754 755 *buf = buffer; 756 return Tree; 757} 758 759XML_TREE *XML_makeTree(uint8_t **buf) 760{ 761 uint8_t *pBuf; 762 int32_t valueLen, tagType; 763 uint8_t *buffer = *buf; 764 XML_TREE *TreeHead = NULL; 765 766 if (NULL == (buffer = XML_DOM_getTag(buffer, &valueLen, &tagType))) 767 return NULL; 768 if (XML_TAG_END == tagType) 769 return NULL; 770 if (NULL == (TreeHead = xml_tree_fillnode(&buffer, valueLen))) 771 return NULL; 772 if (XML_TAG_SELF == tagType) { 773 *buf = buffer; 774 return TreeHead; 775 } 776 777 do { 778 if (NULL == (pBuf = XML_DOM_getTag(buffer, &valueLen, &tagType))) 779 return NULL; 780 781 switch (tagType) { 782 case XML_TAG_SELF: 783 case XML_TAG_START: 784 if (NULL == TreeHead->child) 785 TreeHead->child = XML_makeTree(&buffer); 786 else if (NULL == TreeHead->child->last_brother) { 787 TreeHead->child->brother = XML_makeTree(&buffer); 788 TreeHead->child->last_brother = TreeHead->child->brother; 789 } else { 790 TreeHead->child->last_brother->brother = 791 XML_makeTree(&buffer); 792 TreeHead->child->last_brother = 793 TreeHead->child->last_brother->brother; 794 } 795 break; 796 case XML_TAG_END: 797 *buf = pBuf; 798 return TreeHead; 799 } 800 buffer++; 801 } while (1); 802} 803 804void XML_freeTree(XML_TREE * pTree) 805{ 806 XML_TREE *p, *pNext; 807 XML_TREE_ATTR *pa, *lastpa; 808 809 if (NULL == pTree) 810 return; 811 812 p = pTree->brother; 813 while (NULL != p) { 814 pNext = p->brother; 815 p->brother = NULL; 816 XML_freeTree(p); 817 p = pNext; 818 } 819 820 if (NULL != pTree->child) 821 XML_freeTree(pTree->child); 822 823 pa = pTree->attr; 824 while (NULL != pa) { 825 lastpa = pa; 826 pa = pa->next; 827 xml_free(lastpa); 828 } 829 xml_free(pTree); 830} 831 832#endif /* XML_TREE_STRUCTURE */ 833 834#endif /* WBXML_DOM_PARSER */ 835