| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <xml/xml_tinyParser.h> |
| |
| int32_t xml_errno; |
| |
| #ifdef XML_DOM_PARSER |
| |
| #define XML_IS_WHITESPACE(x) ((x) == '\t' || (x) == '\n' || (x) == ' ' || (x) == '\r') |
| #define XML_IS_NAMECHAR(ch) (isalpha(ch) || isdigit(ch) || ch ==':' || \ |
| ch == '_' || ch == '-' || ch =='.') |
| |
| static uint8_t *xml_ignore_blank(uint8_t *buffer) |
| { |
| if (NULL == buffer) |
| return NULL; |
| |
| while (XML_IS_WHITESPACE(*buffer)) |
| buffer++; |
| |
| return buffer; |
| } |
| |
| static uint8_t *xml_goto_tagend(uint8_t *buffer) |
| { |
| int32_t nameLen, valueLen; |
| uint8_t *name, *value; |
| |
| if (NULL == buffer) |
| return NULL; |
| |
| /* Ignore the start-tag */ |
| if (*buffer == '<') { |
| buffer++; |
| while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) |
| buffer++; |
| if (NULL == buffer) |
| return NULL; |
| } |
| |
| do { |
| if (NULL == (buffer = xml_ignore_blank(buffer))) |
| return NULL; |
| |
| if (*buffer == '>' || (*buffer == '/' && *(buffer + 1) == '>')) |
| return buffer; |
| |
| if (NULL == |
| XML_DOM_getAttr(buffer, &name, &nameLen, &value, &valueLen)) |
| return NULL; |
| |
| buffer = value + valueLen + 1; |
| } while (*buffer != '\0'); |
| |
| return NULL; |
| } |
| |
| static uint8_t *xml_match_tag(uint8_t *buffer) |
| { |
| int32_t tagLen, tagType, bal; |
| |
| if (NULL == buffer) |
| return NULL; |
| |
| bal = 0; |
| do { |
| if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType))) |
| return NULL; |
| |
| switch (tagType) { |
| case XML_TAG_SELF: |
| case XML_TAG_START: |
| if (NULL == (buffer = xml_goto_tagend(buffer + tagLen + 1))) |
| return NULL; |
| if (strncmp((char *)buffer, "/>", 2) == 0) { |
| buffer += 2; |
| } else { |
| bal++; |
| } |
| break; |
| |
| case XML_TAG_END: |
| if (bal <= 0) |
| return NULL; |
| buffer = buffer + tagLen + 2; |
| bal--; |
| break; |
| } |
| } while (bal != 0); |
| |
| return buffer; |
| } |
| |
| uint8_t *XML_DOM_getAttr(uint8_t *buffer, uint8_t **pName, int32_t *nameLen, |
| uint8_t **pValue, int32_t *valueLen) |
| { |
| uint8_t charQuoted; |
| |
| if (NULL == buffer) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| /* Ignore the tag */ |
| if (*buffer == '<') { |
| buffer++; |
| /* Ignore the STag */ |
| while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) |
| buffer++; |
| if (NULL == buffer) |
| return NULL; |
| } |
| |
| if (NULL == (buffer = xml_ignore_blank(buffer))) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| /* Name */ |
| *pName = buffer; |
| while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) |
| buffer++; |
| if (NULL == buffer) { |
| XML_ERROR(XML_ERROR_ATTR_NAME); |
| return NULL; |
| } |
| *nameLen = buffer - *pName; |
| if (*nameLen <= 0) { |
| XML_ERROR(XML_ERROR_ATTR_NAME); |
| return NULL; |
| } |
| |
| /* '=' */ |
| buffer = xml_ignore_blank(buffer); |
| if (NULL == buffer || *buffer != '=') { |
| XML_ERROR(XML_ERROR_ATTR_MISSED_EQUAL); |
| return NULL; |
| } |
| |
| /* Value */ |
| buffer++; |
| buffer = xml_ignore_blank(buffer); |
| if (NULL == buffer || (*buffer != '"' && *buffer != '\'')) { |
| XML_ERROR(XML_ERROR_ATTR_VALUE); |
| return NULL; |
| } |
| charQuoted = *buffer++; |
| *pValue = buffer; |
| while (*buffer != '\0' && *buffer != charQuoted) |
| buffer++; |
| if (*buffer != charQuoted) { |
| XML_ERROR(XML_ERROR_ATTR_VALUE); |
| return NULL; |
| } |
| *valueLen = buffer - *pValue; |
| |
| XML_ERROR(XML_ERROR_OK); |
| |
| return buffer + 1; |
| } |
| |
| uint8_t *XML_DOM_getValue(uint8_t *buffer, uint8_t **pValue, int32_t *valueLen) |
| { |
| uint8_t *pEnd; |
| |
| if (NULL == buffer) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| /* Ignore the STag */ |
| if (*buffer == '<') { |
| buffer++; |
| /* If it's an end_tag, no value should be returned */ |
| if (*buffer == '/') { |
| *valueLen = 0; |
| XML_ERROR(XML_ERROR_NOVALUE); |
| return NULL; |
| } |
| |
| while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) |
| buffer++; |
| if (NULL == buffer) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| if (NULL == (buffer = xml_goto_tagend(buffer))) { |
| XML_ERROR(XML_ERROR_PROPERTY_END); |
| return NULL; |
| } |
| } |
| |
| /* <test/> node found */ |
| if (*buffer == '/') { |
| if (*(buffer + 1) != '>') { |
| XML_ERROR(XML_ERROR_PROPERTY_END); |
| return NULL; |
| } |
| XML_ERROR(XML_ERROR_OK); |
| *valueLen = 0; |
| return buffer; |
| } |
| |
| if (*buffer == '>') |
| buffer++; |
| |
| if (NULL == (buffer = xml_ignore_blank(buffer))) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| /* the following is a tag instead of the value */ |
| if (*buffer == '<') { /* nono value, such as <test></test> */ |
| buffer++; |
| if (*buffer != '/') { |
| XML_ERROR(XML_ERROR_ENDTAG); |
| return NULL; |
| } |
| *valueLen = 0; |
| XML_ERROR(XML_ERROR_OK); |
| return NULL; |
| } |
| |
| *pValue = buffer; |
| pEnd = NULL; |
| while (*buffer != '\0' && *buffer != '<') { |
| if (!XML_IS_WHITESPACE(*buffer)) |
| pEnd = buffer; |
| buffer++; |
| } |
| if (*buffer != '<' || pEnd == NULL) { |
| XML_ERROR(XML_ERROR_VALUE); |
| return NULL; |
| } |
| |
| *valueLen = pEnd - *pValue + 1; |
| |
| buffer++; |
| if (*buffer != '/') { |
| XML_ERROR(XML_ERROR_ENDTAG); |
| return NULL; |
| } |
| |
| XML_ERROR(XML_ERROR_OK); |
| |
| return buffer - 1; |
| } |
| |
| uint8_t *XML_DOM_getTag(uint8_t *buffer, int32_t *tagLen, int32_t *tagType) |
| { |
| uint8_t *pStart; |
| |
| /* WARNING: <!-- --> comment is not supported in this verison */ |
| if (NULL == buffer) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| do { |
| while (*buffer != '<') { |
| if (*buffer == '\0') { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| if (*buffer == '\"' || *buffer == '\'') { |
| uint8_t charQuoted = *buffer; |
| buffer++; |
| while (*buffer != '\0' && *buffer != charQuoted) |
| buffer++; |
| if (*buffer == '\0') { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| } |
| buffer++; |
| } |
| buffer++; |
| } while (*buffer == '!' || *buffer == '?'); |
| |
| pStart = buffer - 1; |
| |
| if (*buffer == '/') { |
| buffer++; |
| *tagType = XML_TAG_END; |
| } else { |
| /* check here if it is self-end-tag */ |
| uint8_t *pCheck = xml_goto_tagend(pStart); |
| if (pCheck == NULL) { |
| XML_ERROR(XML_ERROR_PROPERTY_END); |
| return NULL; |
| } |
| |
| if (*pCheck == '>') |
| *tagType = XML_TAG_START; |
| else if (strncmp((char *)pCheck, "/>", 2) == 0) |
| *tagType = XML_TAG_SELF; |
| else { |
| XML_ERROR(XML_ERROR_PROPERTY_END); |
| return NULL; |
| } |
| } |
| |
| while (buffer != NULL && XML_IS_NAMECHAR(*buffer)) |
| buffer++; |
| if (NULL == buffer) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| if (*tagType == XML_TAG_END) |
| *tagLen = buffer - pStart - 2; |
| else |
| *tagLen = buffer - pStart - 1; |
| |
| XML_ERROR(XML_ERROR_OK); |
| |
| return pStart; |
| } |
| |
| uint8_t *XML_DOM_getNode(uint8_t *buffer, const uint8_t *const node) |
| { |
| uint8_t *pStart; |
| uint8_t buf[XML_MAX_PROPERTY_LEN + 2]; |
| uint8_t *nodeStr = buf; |
| uint8_t *retPtr = NULL; |
| int32_t tagLen, tagType; |
| uint8_t *lastNode = (uint8_t *)""; |
| |
| if (NULL == buffer) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| strncpy((char *)nodeStr, (char *)node, XML_MAX_PROPERTY_LEN); |
| strcat((char *)nodeStr, "\\"); |
| pStart = (uint8_t *)strchr((char *)nodeStr, '\\'); |
| |
| while (pStart != NULL) { |
| *pStart = '\0'; |
| |
| /* get the first start_tag from buffer */ |
| if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType))) { |
| XML_ERROR(XML_ERROR_NO_SUCH_NODE); |
| return NULL; |
| } |
| |
| if (tagType == XML_TAG_END) { |
| if (0 == |
| strncmp((char *)lastNode, (char *)(buffer + 2), strlen((char *)lastNode))) |
| XML_ERROR(XML_ERROR_NO_SUCH_NODE); |
| else |
| XML_ERROR(XML_ERROR_NO_START_TAG); |
| return NULL; |
| } |
| |
| /* wrong node, contiue to fetch the next node */ |
| if ((int32_t) strlen((char *)nodeStr) != tagLen |
| || strncmp((char *)nodeStr, (char *)(buffer + 1), tagLen) != 0) { |
| /* we should ignore all the middle code */ |
| buffer = xml_match_tag(buffer); |
| continue; |
| } |
| |
| retPtr = buffer; /* retPtr starts with '<xxx>' */ |
| buffer += (tagLen + 1); |
| |
| if (tagType == XML_TAG_SELF) { |
| nodeStr = pStart + 1; |
| break; |
| } |
| |
| lastNode = nodeStr; |
| nodeStr = pStart + 1; |
| pStart = (uint8_t *)strchr((char *)nodeStr, '\\'); |
| } |
| |
| /* Check 5: nodeStr should be empty here */ |
| if (*nodeStr != '\0') { |
| XML_ERROR(XML_ERROR_NO_SUCH_NODE); |
| return NULL; |
| } |
| |
| XML_ERROR(XML_ERROR_OK); |
| |
| return retPtr; |
| } |
| |
| uint8_t *XML_DOM_getNodeValue(uint8_t *buffer, uint8_t *node, |
| uint8_t **value, int32_t *valueLen) |
| { |
| uint8_t *pStart; |
| uint8_t *lastTag; |
| |
| if (NULL == node || NULL == buffer) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| lastTag = node + strlen((char *)node) - 1; |
| while (lastTag >= node && *lastTag != '\\') |
| lastTag--; |
| lastTag++; |
| |
| if (NULL == (pStart = XML_DOM_getNode(buffer, node))) |
| return NULL; |
| |
| pStart += (strlen((char *)lastTag) + 1); |
| |
| if (NULL == (pStart = xml_goto_tagend(pStart))) { |
| XML_ERROR(XML_ERROR_PROPERTY_END); |
| return NULL; |
| } |
| |
| if (NULL == (pStart = XML_DOM_getValue(pStart, value, valueLen))) |
| return NULL; |
| |
| /* Check the end tag */ |
| #ifdef XML_DOM_CHECK_ENDTAG |
| if (strncmp((char *)pStart, "/>", 2) == 0) { |
| |
| } else if (strncmp((char *)lastTag, (char *)(pStart + 2), strlen((char *)lastTag)) != |
| 0) { |
| XML_ERROR(XML_ERROR_ENDTAG); |
| return NULL; |
| } |
| #endif |
| |
| XML_ERROR(XML_ERROR_OK); |
| |
| return *value; |
| } |
| |
| uint8_t *XML_DOM_getNextNode(uint8_t *buffer, uint8_t **pNodeName, int32_t *nodenameLen) |
| { |
| int32_t tagType; |
| |
| if (NULL == buffer) |
| return NULL; |
| |
| do { |
| if (NULL == |
| (buffer = XML_DOM_getTag(buffer + 1, nodenameLen, &tagType))) { |
| XML_ERROR(XML_ERROR_NO_SUCH_NODE); |
| return NULL; |
| } |
| } while (tagType == XML_TAG_END); |
| |
| *pNodeName = buffer + 1; |
| |
| XML_ERROR(XML_ERROR_OK); |
| |
| return buffer; |
| } |
| |
| #endif /* XML_DOM_PARSER */ |
| |
| #ifdef WBXML_DOM_PARSER |
| |
| #ifdef WBXML_OLD_VERSION |
| uint8_t *WBXML_DOM_getNode(uint8_t *buffer, int32_t bufferLen, |
| uint8_t *node) |
| { |
| int32_t i = 0, j = 0; |
| |
| if (NULL == buffer || node == NULL) { |
| XML_ERROR(XML_ERROR_BUFFER_NULL); |
| return NULL; |
| } |
| |
| while (i < bufferLen) { |
| if (WBXML_GET_TAG(buffer[i]) == WBXML_GET_TAG(node[j])) { |
| j++; |
| if (node[j] == '\0') |
| break; |
| |
| /* Check if there is the content(it should have content) */ |
| if (!WBXML_HAS_CONTENT(buffer[i])) { |
| /*XML_ERROR(WBXML_ERROR_MISSED_CONTENT); */ |
| XML_ERROR(XML_ERROR_NO_SUCH_NODE); |
| return NULL; |
| } |
| |
| /* Ignore the attrib filed */ |
| if (WBXML_HAS_ATTR(buffer[i])) { |
| while (i < bufferLen && buffer[i] != WBXML_ATTR_END) |
| i++; |
| if (i >= bufferLen) |
| break; |
| } |
| } |
| i++; |
| |
| /* Ignore the content filed */ |
| if (buffer[i] == WBXML_STR_I) { |
| while (i < bufferLen && buffer[i] != WBXML_END) |
| i++; |
| if (i >= bufferLen) |
| break; |
| i++; |
| } |
| } |
| |
| if (i >= bufferLen) { |
| XML_ERROR(XML_ERROR_NO_SUCH_NODE); |
| return NULL; |
| } |
| |
| XML_ERROR(XML_ERROR_OK); |
| |
| return buffer + i + 1; |
| } |
| |
| uint8_t *WBXML_DOM_getNodeValue(uint8_t *buffer, int32_t bufferLen, |
| uint8_t *node, |
| uint8_t **value, int32_t *valueLen) |
| { |
| int32_t i; |
| uint8_t *pEnd; |
| |
| *value = NULL; |
| *valueLen = 0; |
| |
| pEnd = buffer + bufferLen; |
| buffer = WBXML_DOM_getNode(buffer, bufferLen, node); |
| if (NULL == buffer) { |
| XML_ERROR(XML_ERROR_NO_SUCH_NODE); |
| return NULL; |
| } |
| |
| if (*buffer == WBXML_OPAUE) { |
| buffer++; |
| *valueLen = WBXML_GetUintVar(buffer, &i); |
| if (*valueLen < 0) { |
| XML_ERROR(WBXML_ERROR_MBUINT32); |
| return NULL; |
| } |
| buffer += i; |
| *value = buffer; |
| return *value; |
| } |
| |
| if (*buffer != WBXML_STR_I) { |
| XML_ERROR(WBXML_ERROR_MISSED_STARTTAG); |
| return NULL; |
| } |
| |
| buffer++; |
| |
| i = 0; |
| while ((buffer + i) < pEnd && buffer[i] != WBXML_END) |
| i++; |
| |
| if (buffer[i] != WBXML_END) { |
| XML_ERROR(WBXML_ERROR_MISSED_ENDTAG); |
| return NULL; |
| } |
| |
| *value = buffer; |
| *valueLen = i; |
| XML_ERROR(XML_ERROR_OK); |
| |
| return *value; |
| } |
| #endif /* WBXML_OLD_VERSION */ |
| |
| #define MAX_UINT_VAR_BYTE 4 |
| #define UINTVAR_INVALID -1 |
| int32_t WBXML_GetUintVar(const uint8_t *const buffer, int32_t *len) |
| { |
| int32_t i, byteLen; |
| int32_t sum; |
| |
| byteLen = 0; |
| while ((buffer[byteLen] & 0x80) > 0 && byteLen < MAX_UINT_VAR_BYTE) |
| byteLen++; |
| |
| if (byteLen > MAX_UINT_VAR_BYTE) |
| return UINTVAR_INVALID; |
| |
| *len = byteLen + 1; |
| sum = buffer[byteLen]; |
| for (i = byteLen - 1; i >= 0; i--) |
| sum += ((buffer[i] & 0x7F) << 7 * (byteLen - i)); |
| |
| return sum; |
| } |
| |
| XML_BOOL WBXML_DOM_Init(WBXML * pWbxml, uint8_t *buffer, |
| int32_t bufferLen) |
| { |
| int32_t num, len; |
| |
| pWbxml->End = buffer + bufferLen; |
| pWbxml->version = *buffer++; |
| if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len))) |
| return XML_FALSE; |
| buffer += len; |
| pWbxml->publicid = num; |
| if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len))) |
| return XML_FALSE; |
| buffer += len; |
| pWbxml->charset = num; |
| if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len))) |
| return XML_FALSE; |
| buffer += len; |
| pWbxml->strTable = buffer; |
| pWbxml->strTableLen = num; |
| buffer += num; |
| pWbxml->curPtr = pWbxml->Content = buffer; |
| pWbxml->depth = 0; |
| |
| return XML_TRUE; |
| } |
| |
| void WBXML_DOM_Rewind(WBXML * pWbxml) |
| { |
| pWbxml->curPtr = pWbxml->Content; |
| } |
| |
| XML_BOOL WBXML_DOM_Eof(WBXML * pWbxml) |
| { |
| if (pWbxml->curPtr > pWbxml->End) |
| return XML_TRUE; |
| |
| return XML_FALSE; |
| } |
| |
| uint8_t WBXML_DOM_GetTag(WBXML * pWbxml) |
| { |
| uint8_t tagChar; |
| |
| if (pWbxml->curPtr > pWbxml->End) |
| return XML_EOF; |
| |
| tagChar = *pWbxml->curPtr; |
| pWbxml->curPtr++; |
| |
| if (WBXML_GET_TAG(tagChar) == WBXML_CONTENT_END) |
| pWbxml->depth--; |
| else |
| pWbxml->depth++; |
| |
| return tagChar; |
| } |
| |
| uint8_t WBXML_DOM_GetChar(WBXML * pWbxml) |
| { |
| return *pWbxml->curPtr++; |
| } |
| |
| void WBXML_DOM_Seek(WBXML * pWbxml, int32_t offset) |
| { |
| pWbxml->curPtr += offset; |
| } |
| |
| uint8_t WBXML_DOM_GetUIntVar(WBXML * pWbxml) |
| { |
| int32_t num, len; |
| |
| num = WBXML_GetUintVar(pWbxml->curPtr, &len); |
| pWbxml->curPtr += len; |
| |
| return (uint8_t)num; |
| } |
| |
| #ifdef XML_TREE_STRUCTURE |
| |
| #ifdef DEBUG_MODE |
| static int32_t malloc_times = 0; |
| static int32_t free_times = 0; |
| void XML_PrintMallocInfo() |
| { |
| printf("====XML_PrintMallocInfo====\n"); |
| printf(" Total malloc times:%d\n", malloc_times); |
| printf(" Total free times:%d\n", free_times); |
| printf("===========================\n"); |
| } |
| #endif |
| |
| void *xml_malloc(int32_t size) |
| { |
| #ifdef DEBUG_MODE |
| malloc_times++; |
| #endif |
| return malloc(size); |
| } |
| |
| void xml_free(void *buffer) |
| { |
| #ifdef DEBUG_MODE |
| free_times++; |
| #endif |
| free(buffer); |
| } |
| |
| XML_TREE *xml_tree_fillnode(uint8_t **buf, int32_t tagLen) |
| { |
| XML_TREE *Tree; |
| uint8_t *pAttr, *pName, *pValue; |
| int32_t nameLen, valueLen; |
| uint8_t *buffer = *buf; |
| |
| if (NULL == (Tree = (XML_TREE *) xml_malloc(sizeof(XML_TREE)))) |
| return NULL; |
| memset(Tree, 0, sizeof(XML_TREE)); |
| |
| strncpy((char *)Tree->tag, (char *)++buffer, tagLen); |
| buffer += tagLen; |
| pAttr = buffer; |
| |
| /* attribute */ |
| while (NULL != |
| (pAttr = |
| XML_DOM_getAttr(pAttr, &pName, &nameLen, &pValue, |
| &valueLen))) { |
| XML_TREE_ATTR *attr; |
| if (NULL == |
| (attr = (XML_TREE_ATTR *) xml_malloc(sizeof(XML_TREE_ATTR)))) |
| return NULL; |
| memset(attr, 0, sizeof(XML_TREE_ATTR)); |
| strncpy((char *)attr->name, (char *)pName, nameLen); |
| strncpy((char *)attr->value, (char *)pValue, valueLen); |
| buffer = pValue + valueLen + 1; |
| |
| if (NULL != Tree->attr) // no attribute now |
| Tree->last_attr->next = attr; |
| else |
| Tree->attr = attr; |
| Tree->last_attr = attr; |
| } |
| |
| /* value */ |
| pAttr = XML_DOM_getValue(buffer, &pValue, &valueLen); |
| if (pAttr != NULL && valueLen > 0) { |
| strncpy((char *)Tree->value, (char *)pValue, valueLen); |
| buffer = pValue + valueLen; |
| } |
| |
| *buf = buffer; |
| return Tree; |
| } |
| |
| XML_TREE *XML_makeTree(uint8_t **buf) |
| { |
| uint8_t *pBuf; |
| int32_t valueLen, tagType; |
| uint8_t *buffer = *buf; |
| XML_TREE *TreeHead = NULL; |
| |
| if (NULL == (buffer = XML_DOM_getTag(buffer, &valueLen, &tagType))) |
| return NULL; |
| if (XML_TAG_END == tagType) |
| return NULL; |
| if (NULL == (TreeHead = xml_tree_fillnode(&buffer, valueLen))) |
| return NULL; |
| if (XML_TAG_SELF == tagType) { |
| *buf = buffer; |
| return TreeHead; |
| } |
| |
| do { |
| if (NULL == (pBuf = XML_DOM_getTag(buffer, &valueLen, &tagType))) |
| return NULL; |
| |
| switch (tagType) { |
| case XML_TAG_SELF: |
| case XML_TAG_START: |
| if (NULL == TreeHead->child) |
| TreeHead->child = XML_makeTree(&buffer); |
| else if (NULL == TreeHead->child->last_brother) { |
| TreeHead->child->brother = XML_makeTree(&buffer); |
| TreeHead->child->last_brother = TreeHead->child->brother; |
| } else { |
| TreeHead->child->last_brother->brother = |
| XML_makeTree(&buffer); |
| TreeHead->child->last_brother = |
| TreeHead->child->last_brother->brother; |
| } |
| break; |
| case XML_TAG_END: |
| *buf = pBuf; |
| return TreeHead; |
| } |
| buffer++; |
| } while (1); |
| } |
| |
| void XML_freeTree(XML_TREE * pTree) |
| { |
| XML_TREE *p, *pNext; |
| XML_TREE_ATTR *pa, *lastpa; |
| |
| if (NULL == pTree) |
| return; |
| |
| p = pTree->brother; |
| while (NULL != p) { |
| pNext = p->brother; |
| p->brother = NULL; |
| XML_freeTree(p); |
| p = pNext; |
| } |
| |
| if (NULL != pTree->child) |
| XML_freeTree(pTree->child); |
| |
| pa = pTree->attr; |
| while (NULL != pa) { |
| lastpa = pa; |
| pa = pa->next; |
| xml_free(lastpa); |
| } |
| xml_free(pTree); |
| } |
| |
| #endif /* XML_TREE_STRUCTURE */ |
| |
| #endif /* WBXML_DOM_PARSER */ |