• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 int32_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 
xml_ignore_blank(uint8_t * buffer)27 static 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 
xml_goto_tagend(uint8_t * buffer)38 static 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 
xml_match_tag(uint8_t * buffer)72 static 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 
XML_DOM_getAttr(uint8_t * buffer,uint8_t ** pName,int32_t * nameLen,uint8_t ** pValue,int32_t * valueLen)108 uint8_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 
XML_DOM_getValue(uint8_t * buffer,uint8_t ** pValue,int32_t * valueLen)176 uint8_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 
XML_DOM_getTag(uint8_t * buffer,int32_t * tagLen,int32_t * tagType)264 uint8_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 
XML_DOM_getNode(uint8_t * buffer,const uint8_t * const node)336 uint8_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 
XML_DOM_getNodeValue(uint8_t * buffer,uint8_t * node,uint8_t ** value,int32_t * valueLen)404 uint8_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 
XML_DOM_getNextNode(uint8_t * buffer,uint8_t ** pNodeName,int32_t * nodenameLen)449 uint8_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
WBXML_DOM_getNode(uint8_t * buffer,int32_t bufferLen,uint8_t * node)476 uint8_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 
WBXML_DOM_getNodeValue(uint8_t * buffer,int32_t bufferLen,uint8_t * node,uint8_t ** value,int32_t * valueLen)529 uint8_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
WBXML_GetUintVar(const uint8_t * const buffer,int32_t * len)584 int32_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 
WBXML_DOM_Init(WBXML * pWbxml,uint8_t * buffer,int32_t bufferLen)604 XML_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 
WBXML_DOM_Rewind(WBXML * pWbxml)631 void WBXML_DOM_Rewind(WBXML * pWbxml)
632 {
633     pWbxml->curPtr = pWbxml->Content;
634 }
635 
WBXML_DOM_Eof(WBXML * pWbxml)636 XML_BOOL WBXML_DOM_Eof(WBXML * pWbxml)
637 {
638     if (pWbxml->curPtr > pWbxml->End)
639         return XML_TRUE;
640 
641     return XML_FALSE;
642 }
643 
WBXML_DOM_GetTag(WBXML * pWbxml)644 uint8_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 
WBXML_DOM_GetChar(WBXML * pWbxml)662 uint8_t WBXML_DOM_GetChar(WBXML * pWbxml)
663 {
664     return *pWbxml->curPtr++;
665 }
666 
WBXML_DOM_Seek(WBXML * pWbxml,int32_t offset)667 void WBXML_DOM_Seek(WBXML * pWbxml, int32_t offset)
668 {
669     pWbxml->curPtr += offset;
670 }
671 
WBXML_DOM_GetUIntVar(WBXML * pWbxml)672 uint8_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
685 static int32_t malloc_times = 0;
686 static int32_t free_times = 0;
XML_PrintMallocInfo()687 void 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 
xml_malloc(int32_t size)696 void *xml_malloc(int32_t size)
697 {
698 #ifdef DEBUG_MODE
699     malloc_times++;
700 #endif
701     return malloc(size);
702 }
703 
xml_free(void * buffer)704 void xml_free(void *buffer)
705 {
706 #ifdef DEBUG_MODE
707     free_times++;
708 #endif
709     free(buffer);
710 }
711 
xml_tree_fillnode(uint8_t ** buf,int32_t tagLen)712 XML_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 
XML_makeTree(uint8_t ** buf)759 XML_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 
XML_freeTree(XML_TREE * pTree)804 void 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