diff -r 6bcc0aa4be39 -r 889504eac4fb xml/cxmllibrary/src/encoder/src/StringTable.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml/cxmllibrary/src/encoder/src/StringTable.c Tue Aug 31 17:02:56 2010 +0300 @@ -0,0 +1,721 @@ +/* +* Copyright (c) 2000 - 2001 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include +#include +#include +#include +#include +#include +#include "cxml_internal.h" + +/* ------------------------------------------------------------------------- * + private methods + * ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- */ +static +NW_Status_t +NW_Encoder_StringItem_initialize(NW_Encoder_StringItem_t *strItem, + NW_String_t *str) +{ + NW_Status_t status = NW_STAT_SUCCESS; + + if (strItem == NULL){ + return NW_STAT_BAD_INPUT_PARAM; + } + + if(str == NULL) + { + return NW_STAT_BAD_INPUT_PARAM; + } + + + strItem->data.storage = CXML_Mem_Malloc(str->length + 1); + + if(strItem->data.storage == NULL) + { + return NW_STAT_OUT_OF_MEMORY; + } + + NW_Mem_memcpy(strItem->data.storage,str->storage,str->length); + + strItem->data.storage[str->length] = '\0'; + + if (status == NW_STAT_SUCCESS) + { + strItem->frequency = 1; + strItem->data.length = str->length; + } + else + { + status = NW_STAT_OUT_OF_MEMORY; + } + + return status; +} + +/* + * Finds string contained in an item (AttrValItem or Text Item) + * An item can be string, extension, entity, opaque, or token + * Only extension and string may contain strings + * Returns NW_STAT_BAD_INPUT_PARAM + * NW_STAT_SUCCESS + */ +/* ------------------------------------------------------------------------- */ +static +NW_Status_t +NW_Encoder_StringTable_getItemString(NW_Encoder_StringTable_t *strTable, + NW_DOM_AttrVal_t *item) +{ + NW_Uint32 ignoreVal; + + if ((strTable == NULL) || (item == NULL)){ + return NW_STAT_BAD_INPUT_PARAM; + } + + switch(item->type) { + case NW_DOM_ATTR_VAL_STRING: + return NW_Encoder_StringTable_append(strTable, &item->component.string, + NW_FALSE, &ignoreVal); + + case NW_DOM_ATTR_VAL_EXTENSION: + { + NW_Uint8 t; /* 8-bit token */ + + t = (NW_Uint8)(item->component.ext.token); + if ((item->component.ext.type == NW_TINYDOM_EXTENSION_TYPE_NORMAL) + && ((t == NW_WBXML_EXT_T_0) + || (t == NW_WBXML_EXT_T_1) + || (t == NW_WBXML_EXT_T_2))) { + return NW_Encoder_StringTable_append(strTable, + &(item->component.ext.value.string), + NW_FALSE, &ignoreVal); + } + break; + } + default: + break; + } + return NW_STAT_SUCCESS; +} + +/** + * Finds strings in an attribute - iterates over attribute values + * Returns NW_STAT_BAD_INPUT_PARAM + * NW_STAT_SUCCESS + */ +/* ------------------------------------------------------------------------- */ +static +NW_Status_t +NW_Encoder_StringTable_getAttributeStrings(NW_Encoder_StringTable_t *strTable, + NW_DOM_AttributeHandle_t *attrHandle) +{ + NW_Status_t status; + NW_DOM_AttrVal_t attrVal; + NW_Uint16 token; + NW_Uint16 fqToken; + + if ((strTable == NULL) || (attrHandle == NULL)){ + return NW_STAT_BAD_INPUT_PARAM; + } + + fqToken = NW_DOM_AttributeHandle_getToken(attrHandle); + NW_ASSERT(fqToken); + token = (NW_Uint16)(fqToken & NW_WBXML_MASK_TOKEN); + if (token == NW_WBXML_LITERAL) + { + NW_Uint32 ignoreVal; + NW_String_t attributeName; + + status = NW_DOM_AttributeHandle_getName(attrHandle, &attributeName); + if (status != NW_STAT_SUCCESS){ + return status; + } + status = NW_Encoder_StringTable_append(strTable, &attributeName, NW_TRUE, + &ignoreVal); + } + + while (NW_DOM_AttributeHandle_getNextVal(attrHandle, &attrVal) == NW_STAT_WBXML_ITERATE_MORE) + { + status = NW_Encoder_StringTable_getItemString(strTable, &attrVal); + if (status != NW_STAT_SUCCESS){ + return status; + } + } + + return NW_STAT_SUCCESS; +} + +/** + * Finds strings in an Element Node + * Returns NW_STAT_BAD_INPUT_PARAM + * NW_STAT_SUCCESS + */ +/* ------------------------------------------------------------------------- */ +static +NW_Status_t +NW_Encoder_StringTable_getElementStrings(NW_Encoder_StringTable_t *strTable, + NW_DOM_ElementNode_t *e) +{ + NW_Status_t status; + NW_DOM_AttributeListIterator_t listIterator; + NW_DOM_AttributeHandle_t attrHandle; + NW_Uint32 fqToken; + NW_Uint8 token; + + if ((strTable == NULL) || (e == NULL)){ + return NW_STAT_BAD_INPUT_PARAM; + } + + fqToken = NW_DOM_ElementNode_getTagToken(e); + if (fqToken == 0){ + return NW_STAT_FAILURE; + } + + token = (NW_Uint8)(fqToken & NW_WBXML_MASK_TOKEN); + + /* put element in table if it is LITERAL tag */ + if (token == NW_WBXML_LITERAL) + { + NW_String_t elementName; + NW_Uint32 ignoreVal; + + if (NW_DOM_ElementNode_getTagName(e, &elementName) != NW_STAT_SUCCESS){ + return NW_STAT_FAILURE; + } + status = NW_Encoder_StringTable_append(strTable, &elementName, NW_TRUE, + &ignoreVal); + if (status != NW_STAT_SUCCESS){ + return status; + } + } + + /* go through attribute strings */ + if (NW_DOM_ElementNode_hasAttributes(e)) + { + status = NW_DOM_ElementNode_getAttributeListIterator(e, &listIterator); + if (status != NW_STAT_SUCCESS){ + return status; + } + while (NW_DOM_AttributeListIterator_getNextAttribute(&listIterator, &attrHandle) == NW_STAT_WBXML_ITERATE_MORE) + { + status = NW_Encoder_StringTable_getAttributeStrings(strTable, &attrHandle); + if (status != NW_STAT_SUCCESS){ + return status; + } + } + } + return NW_STAT_SUCCESS; +} + +/** + * Finds strings in a TextNode + * Returns NW_STAT_BAD_INPUT_PARAM + * NW_STAT_SUCCESS + */ +/* ------------------------------------------------------------------------- */ +static +NW_Status_t +NW_Encoder_StringTable_getTextStrings(NW_Encoder_StringTable_t *strTable, + NW_DOM_TextNode_t *textNode) +{ + NW_DOM_TextItemIterator_t textIter; + NW_DOM_TextItem_t item; + NW_Status_t status; + + if ((strTable == NULL) || (textNode == NULL)) + { + return NW_STAT_BAD_INPUT_PARAM; + } + + (void) NW_DOM_TextNode_getTextItemIterator(textNode, &textIter); + while (NW_DOM_TextItemIterator_getNextTextItem(&textIter, &item) == NW_STAT_WBXML_ITERATE_MORE) + { + status = NW_Encoder_StringTable_getItemString(strTable, &item); + if (status != NW_STAT_SUCCESS){ + return status; + } + } + return NW_STAT_SUCCESS; +} + +/** + * Finds strings in a Node (Recursive in nature) + * So it finds strings in entire tree + * Returns NW_STAT_BAD_INPUT_PARAM + * NW_STAT_SUCCESS + */ +/* ------------------------------------------------------------------------- */ +static +NW_Status_t +NW_Encoder_StringTable_getNodeStrings(NW_Encoder_StringTable_t *strTable, + NW_DOM_Node_t *node, + NW_WBXML_Dictionary_t *dictionary) +{ + NW_Uint32 type; + + type = NW_DOM_Node_getNodeType(node); + + if ((strTable == NULL) || (node == NULL)){ + return NW_STAT_BAD_INPUT_PARAM; + } + + switch (type) + { + case NW_DOM_ELEMENT_NODE: + { + NW_Encoder_StringTable_getElementStrings(strTable, node); + if (NW_DOM_Node_getFirstChild(node)) + { + NW_Encoder_StringTable_getNodeStrings(strTable, NW_DOM_Node_getFirstChild(node), dictionary); + } + + if (NW_DOM_Node_getNextSibling(node)) + { + NW_Encoder_StringTable_getNodeStrings(strTable, NW_DOM_Node_getNextSibling(node), dictionary); + } + } + break; + + case NW_DOM_TEXT_NODE: + NW_Encoder_StringTable_getTextStrings(strTable, node); + + if (NW_DOM_Node_getNextSibling(node)) + { + NW_Encoder_StringTable_getNodeStrings (strTable, NW_DOM_Node_getNextSibling(node), dictionary); + } + + break; + + case NW_DOM_PROCESSING_INSTRUCTION_NODE: +/* PiPrint (node, encoding); */ + + if (NW_DOM_Node_getNextSibling(node)) + { + NW_Encoder_StringTable_getNodeStrings (strTable, NW_DOM_Node_getNextSibling(node), dictionary); + } + + break; + + default: + if (NW_DOM_Node_getNextSibling(node)) + { + NW_Encoder_StringTable_getNodeStrings (strTable, NW_DOM_Node_getNextSibling(node), dictionary); + } + } + return NW_STAT_SUCCESS; +} + +/** + * Finds all the string in document + * Returns NW_STAT_BAD_INPUT_PARAM + * NW_STAT_OUT_OF_MEMORY + * NW_STAT_SUCCESS + */ +/* ------------------------------------------------------------------------- */ +static +NW_Status_t +NW_Encoder_StringTable_findDocStrings(NW_Encoder_StringTable_t *strTable, + NW_DOM_DocumentNode_t *doc, + NW_WBXML_Dictionary_t *dictionary) +{ + NW_String_t docType; + NW_DOM_ElementNode_t *elem; + NW_Status_t status; + + if ((strTable == NULL) || (doc == NULL)){ + return NW_STAT_BAD_INPUT_PARAM; + } + + if (NW_DOM_DocumentNode_getPublicIdAsNumber(doc) == 0) + { + NW_Uint32 ignoreVal; + status = NW_DOM_DocumentNode_getPublicId(doc, &docType); + if (status != NW_STAT_SUCCESS){ + return status; + } + status = NW_Encoder_StringTable_append(strTable, &docType, NW_TRUE, + &ignoreVal); + if (status != NW_STAT_SUCCESS){ + return status; + } + } + elem = NW_DOM_DocumentNode_getDocumentElement(doc); + status = NW_Encoder_StringTable_getNodeStrings(strTable, elem, dictionary); + return status; +} + +/* ------------------------------------------------------------------------- * + public methods + * ------------------------------------------------------------------------- */ + +/* + * Creates a new String Table + */ +/* ------------------------------------------------------------------------- */ +EXPORT_C +NW_Encoder_StringTable_t * +NW_Encoder_StringTable_new() +{ + NW_Encoder_StringTable_t* strTable; + + strTable = (NW_Encoder_StringTable_t*) + NW_Mem_Malloc(sizeof(NW_Encoder_StringTable_t)); + if (strTable != NULL){ + strTable->vector = CXML_Vector_Construct(sizeof(NW_Encoder_StringItem_t), 4); + if(strTable->vector == NULL) + { + NW_Mem_Free(strTable); + return NULL; + } + } + + return strTable; +} + +/* + * Deletes a String Table + */ +/* ------------------------------------------------------------------------- */ + +EXPORT_C void +NW_Encoder_StringTable_delete(NW_Encoder_StringTable_t* strTable) +{ + CXML_Vector_t* vectorObj = NULL; + NW_Encoder_StringItem_t* strItem = NULL; + CXML_Vector_Metric_t index; + + if (strTable == NULL) + { + return; + } + + if(strTable->vector) + { + vectorObj = strTable->vector; + } + + //Free the data memory. + + + for (index = 0; index < vectorObj->size; index++) + { + strItem = (NW_Encoder_StringItem_t*) CXML_Vector_AddressAt(vectorObj,index); + if(strItem) + { + if((strItem->data).storage) + { + NW_Mem_Free ( (strItem->data).storage); + } + } + }/*end for() */ + + CXML_Vector_Destruct(strTable->vector); + NW_Mem_Free(strTable); +} + +/* returns number of elements in the string table */ +/* ------------------------------------------------------------------------- */ +EXPORT_C CXML_Vector_Metric_t +NW_Encoder_StringTable_GetSize(NW_Encoder_StringTable_t *strTable) +{ + return (NW_Uint32)strTable->vector->size; +} + +/** + * Appends new found string in the document to the list. If the string + * was already present in the list, then it increases its frequency, + * otherwise it creates a new StringItem in the list + * + * MODIFIED index n= of the string into the table + * + * Returns NW_STAT_BAD_INPUT_PARAM + * NW_STAT_STR_TBL_OVERFLOW + * NW_STAT_OUT_OF_MEMORY + * NW_STAT_SUCCESS + */ +/* ------------------------------------------------------------------------- */ +NW_Status_t +NW_Encoder_StringTable_append(NW_Encoder_StringTable_t *strTable, + NW_String_t *string, + NW_Bool literalOrDocType, + NW_Uint32 *extensionByteOffset) +{ + NW_Encoder_StringItem_t* strItem; + NW_Encoder_StringItem_t newStrItem; + NW_Uint32 ignoreVal; + NW_Status_t status; + + if ((strTable == NULL) || (string == NULL)){ + return NW_STAT_BAD_INPUT_PARAM; + } + + newStrItem.data.storage = NULL; + + /* Also, there can be malformed document. cXML parser wants to limits + * non DTD elements or attributes. So check current number of elements + * in the parser. This is for security reasons. + */ + + if((NW_Uint32)strTable->vector->size > CXML_MAX_STRTBL_ITEMS) + { + return NW_STAT_STR_TBL_OVERFLOW; + } + + /* Find if string is already there in the string table. By design + if string isn't found, then *extensionByteOffset has value equal to + the offset of the new item to add which is just the count of all + bytes already in the string table. */ + strItem = NW_Encoder_StringTable_find(strTable, string, &ignoreVal, + extensionByteOffset); + if (strItem != NULL) { + strItem->frequency++; + return NW_STAT_SUCCESS; + } + /* string not found, create a new entry. We need a duplicating the + * strings. + */ + + status = NW_Encoder_StringItem_initialize(&newStrItem, string); + + + if (status != NW_STAT_SUCCESS){ + return status; + } + if (literalOrDocType){ + newStrItem.frequency = 2; + } + CXML_Vector_InsertAt(strTable->vector, &newStrItem, + CXML_Vector_AtEnd, NULL); + + + return NW_STAT_SUCCESS; +} + +/* + * Finds a string in the list and returns the corresponding + * StringItem, otherwise returns NULL + */ +/* ------------------------------------------------------------------------- */ +NW_Encoder_StringItem_t* +NW_Encoder_StringTable_find(NW_Encoder_StringTable_t *strTable, + NW_String_t *string, + NW_Uint32 *strIndex, + NW_Uint32 *byteOffset) +{ + CXML_Vector_Metric_t index; + + if ((strTable == NULL) || (string == NULL)){ + return NULL; + } + *strIndex = 0; + *byteOffset = 0; + for (index = 0; + index < strTable->vector->size; + index++) + { + NW_Encoder_StringItem_t *item; + + item = (NW_Encoder_StringItem_t*) + CXML_Vector_ElementAt(strTable->vector, index); + if (NW_String_equals(string, &item->data)) + { + *strIndex = index; + return item; + } + *byteOffset = *byteOffset + NW_String_getByteCount(&item->data); + } + return NULL; +} + +/** + * Finds the string at a given index + */ +/* ------------------------------------------------------------------------- */ +NW_Status_t +NW_Encoder_StringTable_get(NW_Encoder_StringTable_t *strTable, + NW_Uint32 index, + NW_String_t* string) +{ + NW_Encoder_StringItem_t *strItem; + + strItem = (NW_Encoder_StringItem_t*) + CXML_Vector_ElementAt(strTable->vector, + (CXML_Vector_Metric_t)index); + + if (strItem){ + string->storage = strItem->data.storage; + string->length = strItem->data.length; + return NW_STAT_SUCCESS; + } + return NW_STAT_FAILURE; +} + +/** + * Finds item at a given index + */ +/* ------------------------------------------------------------------------- */ +NW_Encoder_StringItem_t* +NW_Encoder_StringTable_getItemAt(NW_Encoder_StringTable_t *strTable, + NW_Uint32 index) +{ + return (NW_Encoder_StringItem_t*) + CXML_Vector_ElementAt(strTable->vector, + (CXML_Vector_Metric_t)index); +} + +/** + * Removes a string item + */ +/* ------------------------------------------------------------------------- */ +NW_Status_t +NW_Encoder_StringTable_removeAt(NW_Encoder_StringTable_t *strTable, + CXML_Vector_Metric_t index) +{ + return CXML_Vector_RemoveAt(strTable->vector, (CXML_Vector_Metric_t)index); +} + +/* + * Returns the total number of bytes used for storing all the + * strings in the list + */ +/* ------------------------------------------------------------------------- */ +EXPORT_C NW_Uint32 +NW_Encoder_StringTable_getTotalBytes(NW_Encoder_StringTable_t *strTable) +{ + NW_Uint32 byteLength; + CXML_Vector_Metric_t index; + + byteLength = 0; + + for (index = 0; + index < strTable->vector->size; + index++) + { + NW_Encoder_StringItem_t *strItem; + + strItem = (NW_Encoder_StringItem_t*) + CXML_Vector_ElementAt(strTable->vector, index); + byteLength += strItem->data.length; + } + + return byteLength; +} + +/* ------------------------------------------------------------------------- */ +EXPORT_C NW_Status_t +NW_Encoder_StringTable_createFromDOM(NW_Encoder_StringTable_t *strTable, + NW_DOM_DocumentNode_t *doc, + NW_WBXML_Dictionary_t *dictionary) +{ + + /* make a table of strings in the document */ + NW_Encoder_StringTable_findDocStrings(strTable, doc, dictionary); + + /* The string table will be freed once at the end. So, don't do + * this here. This is causing the memory leak otherwise. + */ + return NW_STAT_SUCCESS; +} + + +/* callback implementations */ +/* ------------------------------------------------------------------------- */ +EXPORT_C NW_Status_t +NW_Encoder_StringTable_getStringTableOffset(void* pStringTableObject, + NW_Uint32 byteCount, + const NW_Uint8* pString, + NW_Bool* pFound, + NW_Uint32* pTableOffset) +{ + NW_Encoder_StringItem_t *strItem; + NW_Uint32 strIndex; + NW_String_t string; + + string.storage = (NW_Byte*)pString; + string.length = byteCount; + + strItem = NW_Encoder_StringTable_find((NW_Encoder_StringTable_t*) pStringTableObject, + &string, &strIndex, pTableOffset); + + if (strItem == NULL) + *pFound = NW_FALSE; + else + *pFound = NW_TRUE; + + return NW_STAT_SUCCESS; +} + +/* ------------------------------------------------------------------------- */ +EXPORT_C NW_Status_t +NW_Encoder_StringTable_addToStringTable(void* pStringTableObject, + NW_Uint32 byteCount, + const NW_Uint8* pString, + NW_Uint32* pTableOffset) +{ + NW_String_t string; + + string.storage = (NW_Byte*)pString; + string.length = byteCount; + *pTableOffset = 0; + return NW_Encoder_StringTable_append((NW_Encoder_StringTable_t*) pStringTableObject, + &string, NW_TRUE, pTableOffset); +} + +/* ------------------------------------------------------------------------- */ +EXPORT_C NW_Status_t +NW_Encoder_StringTable_StringTableIterateInit(void* pStringTableObject, + void* pStringTableIterator) +{ + NW_Encoder_StringTableIterator_t *strIterator; + + strIterator = (NW_Encoder_StringTableIterator_t*)pStringTableIterator; + strIterator->strTable = (NW_Encoder_StringTable_t*)pStringTableObject; + strIterator->currentIndex = 0; + return NW_STAT_SUCCESS; +} + +/* at end of string table return byteCount = 0 */ +/* ------------------------------------------------------------------------- */ +EXPORT_C NW_Status_t +NW_Encoder_StringTable_StringTableIterateNext(void* pStringTableIterator, + NW_Uint32* pByteCount, + NW_Uint8** ppBuf) +{ + NW_Encoder_StringTableIterator_t *strIterator; + CXML_Vector_Metric_t size; + NW_String_t string; + NW_Status_t status; + + strIterator = (NW_Encoder_StringTableIterator_t*)pStringTableIterator; + size = NW_Encoder_StringTable_GetSize(strIterator->strTable); + + if (strIterator->currentIndex >= size){ + return NW_STAT_WBXML_ITERATE_DONE; + } + status = NW_Encoder_StringTable_get(strIterator->strTable, strIterator->currentIndex, &string); + if (status != NW_STAT_SUCCESS){ + return status; + } + *pByteCount = string.length; + *ppBuf = string.storage; + strIterator->currentIndex++; + return NW_STAT_WBXML_ITERATE_MORE; +} +