--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xml/cxmllibrary/src/encoder/src/WBXMLWriter.cpp Wed Jun 23 20:27:15 2010 +0530
@@ -0,0 +1,999 @@
+/*
+* 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 "cxml_internal.h"
+#include <xml/cxml/nw_wbxml_token.h>
+#include <xml/cxml/nw_encoder_wbxmlwriter.h>
+#include <xml/cxml/nw_wbxml_parse.h>
+#include "cxml_mem.h"
+
+// WLIU_DEBUG: #include "flogger.h"
+ /* a reserved name used for encoding tags and attributes that
+otherwise aren't in the dictionaries. zzzunknown must be in the
+dictionary for both tag names and attribute names */
+#define zzzunknownCharCount 10
+static const NW_Uint8 zzzunknown[] = {'z','z','z','u','n','k','n','o','w','n','\0'};
+#define zzzunknownEncoding HTTP_utf_8
+
+
+static
+NW_Status_t
+NW_WBXML_Writer_Memcpy(NW_WBXML_Writer_t* pW, const NW_Uint8* pBytes,
+ NW_Uint32 writeLength)
+{
+ NW_Status_t s = NW_STAT_SUCCESS;
+ if (writeLength == 0) {
+ return NW_STAT_FAILURE;
+ }
+ if (!pW->sizing) {
+ if (((pW->index + writeLength - 1) >= pW->byteCount)
+ && (pW->growBufCallback != NULL)) {
+ /* try to grow buf */
+ s = (*pW->growBufCallback)(pW, writeLength);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ }
+ if ((pW->index + writeLength - 1) >= pW->byteCount) {
+ /* grow buf unavailable or didn't alloc enough */
+ return NW_STAT_OUT_OF_MEMORY;
+ }
+ NW_Mem_memcpy(pW->pBuf + pW->index, pBytes, writeLength);
+ }
+ pW->index += writeLength;
+ return s;
+}
+
+typedef struct NW_WBXML_Multibyte_s {
+ NW_Uint8 length; /* encoded length in bytes from 1..5 */
+ NW_Uint8 buf[5];
+} NW_WBXML_Multibyte_t;
+
+/* see the WBXML specification for the definition of this function */
+static
+void
+NW_WBXML_EncodeMultibyte(NW_Uint32 x, NW_WBXML_Multibyte_t* pM)
+{
+ NW_Uint8 i;
+ NW_Uint8 littleEndian[5];
+
+ littleEndian[0] = (NW_Uint8)(x & 0x7f);
+ for (i = 1; i < 5; i++) {
+ x >>= 7; /* unsigned x, no sign extension */
+ littleEndian[i] = (NW_Uint8)(x & 0x7f);
+ if (!x) {
+ break;
+ }
+ }
+ pM->length = i;
+ for (i = 0; i < pM->length; i++) {
+ pM->buf[i] = littleEndian[pM->length - 1 - i];
+ if ((i + 1) < pM->length) {
+ pM->buf[i] |= 0x80;
+ }
+ }
+}
+
+static
+NW_Status_t
+NW_WBXML_Writer_Multibyte(NW_WBXML_Writer_t* pW, NW_Uint32 x)
+{
+ NW_WBXML_Multibyte_t multibyte;
+
+ NW_WBXML_EncodeMultibyte(x, &multibyte);
+ return NW_WBXML_Writer_Memcpy(pW, multibyte.buf,
+ multibyte.length);
+}
+
+typedef enum {
+ NW_WBXML_TAG,
+ NW_WBXML_ATTRIBUTE
+} NW_WBXML_Writer_ItemType;
+
+static
+NW_Status_t
+NW_WBXML_Writer_MaybeSwitchPage(NW_WBXML_Writer_t* pW, NW_Uint8 page,
+ NW_WBXML_Writer_ItemType itemType,
+ NW_Bool* switched)
+{
+ NW_Status_t s = NW_STAT_SUCCESS;
+ NW_Uint8 token = NW_WBXML_SWITCH_PAGE; /* global so on all code pages */
+ NW_Bool changePage = 0;
+
+ *switched = NW_FALSE;
+ switch (itemType) {
+ case NW_WBXML_TAG:
+ changePage = (NW_Bool)(page != pW->tagCodePage);
+ if (changePage) {
+ pW->tagCodePage = page;
+ // WLIU_DEBUG: pW->cp_count++;
+ }
+ break;
+ case NW_WBXML_ATTRIBUTE:
+ changePage = (NW_Bool)(page != pW->attributeCodePage);
+ if (changePage) {
+ pW->attributeCodePage = page;
+ // WLIU_DEBUG: pW->cp_count++;
+ }
+ break;
+ default:
+ s = NW_STAT_FAILURE;
+ break;
+ }
+ if (changePage) {
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ // WLIU_DEBUG: RFileLogger::WriteFormat(_L("Browser"), _L("cp_count.txt"), EFileLoggingModeAppend, _L("=== cp_count: %x, pW->index: %x \n"), pW->cp_count, pW->index);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ s = NW_WBXML_Writer_Memcpy(pW, &page, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ *switched = NW_TRUE;
+ }
+ return s;
+}
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_Header(NW_WBXML_Writer_t* pW, NW_Uint8 WBXMLVersion,
+ NW_Uint32 publicIdentifier, NW_Uint32 charsetMIBEnum,
+ NW_Uint32 stringTableByteCount)
+
+{
+ NW_Status_t s;
+ NW_Uint32 byteCount;
+ NW_Uint8* pBuf;
+ NW_Encoder_StringTableIterator_t strTableIterator;
+
+ /* header = version publicid charset stringtable */
+
+ s = NW_WBXML_Writer_Memcpy(pW, &WBXMLVersion, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ s = NW_WBXML_Writer_Multibyte(pW, publicIdentifier);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ s = NW_WBXML_Writer_Multibyte(pW, charsetMIBEnum);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ s = NW_WBXML_Writer_Multibyte(pW, stringTableByteCount);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ if (stringTableByteCount) {
+ NW_ASSERT(pW->stringTableIterateInit);
+ NW_ASSERT(pW->stringTableIterateNext);
+ s = (*(pW->stringTableIterateInit))(pW->pStringTableObject,
+ &strTableIterator);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ s = (*(pW->stringTableIterateNext))(&strTableIterator,
+ &byteCount, &pBuf);
+ while (s == NW_STAT_WBXML_ITERATE_MORE){
+ s = NW_WBXML_Writer_Memcpy(pW, pBuf, byteCount);
+ if (s != NW_STAT_SUCCESS){
+ return s;
+ }
+ s = (*(pW->stringTableIterateNext))(&strTableIterator,
+ &byteCount, &pBuf);
+ }
+ if (s != NW_STAT_WBXML_ITERATE_DONE){
+ return NW_STAT_FAILURE;
+ }
+ }
+ return NW_STAT_SUCCESS;
+}
+
+/* if boolean "set" is 1 then "or" with mask, else "and" with ~mask */
+static
+NW_Status_t
+NW_WBXML_Writer_TagFlagOp(NW_WBXML_Writer_t* pW, NW_Uint32 index,
+ NW_Uint8 mask, NW_Bool set)
+{
+ NW_Status_t s = NW_STAT_SUCCESS;
+ if (!pW->sizing) {
+ if (index < pW->byteCount) {
+ if (set) {
+ (pW->pBuf)[index] |= mask;
+ } else {
+ (pW->pBuf)[index] &= ~mask;
+ }
+ } else {
+ s = NW_STAT_FAILURE;
+ }
+ }
+ return s;
+}
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_TagSetContentFlag(NW_WBXML_Writer_t* pW, NW_Uint32 index)
+{
+ return NW_WBXML_Writer_TagFlagOp(pW, index, NW_WBXML_FLAGS_CONTENT, 1);
+}
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_TagClearContentFlag(NW_WBXML_Writer_t* pW, NW_Uint32 index)
+{
+ return NW_WBXML_Writer_TagFlagOp(pW, index, NW_WBXML_FLAGS_CONTENT, 0);
+}
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_TagSetAttributesFlag(NW_WBXML_Writer_t* pW, NW_Uint32 index)
+{
+ return NW_WBXML_Writer_TagFlagOp(pW, index, NW_WBXML_FLAGS_ATTRIBUTES, 1);
+}
+
+NW_Status_t
+NW_WBXML_Writer_TagClearAttributesFlag(NW_WBXML_Writer_t* pW, NW_Uint32 index)
+{
+ return NW_WBXML_Writer_TagFlagOp(pW, index, NW_WBXML_FLAGS_ATTRIBUTES, 0);
+}
+
+NW_Status_t
+NW_WBXML_Writer_TagToken(NW_WBXML_Writer_t* pW, NW_Uint16 fqToken,
+ NW_Uint32* pTagIndex)
+{
+ NW_Status_t s;
+ NW_Uint8 token;
+ NW_Uint8 page;
+ NW_Bool switched = NW_FALSE;
+
+ token = NW_WBXML_Dictionary_extractToken(fqToken);
+ page = NW_WBXML_Dictionary_extractPage(fqToken);
+
+ s = NW_WBXML_Writer_MaybeSwitchPage(pW, page, NW_WBXML_TAG, &switched);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ *pTagIndex = pW->index;
+ return NW_WBXML_Writer_Memcpy(pW, &token, 1); /* tag token */
+ }
+
+static
+NW_Status_t
+NW_WBXML_Writer_Literal(NW_WBXML_Writer_t* pW, NW_Uint32 stringTableIndex)
+ {
+ NW_Status_t s;
+
+ /* global in WBXML spec, so on all code pages */
+ static const NW_Uint8 literalToken = NW_WBXML_LITERAL;
+
+ s = NW_WBXML_Writer_Memcpy(pW, &literalToken, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ return NW_WBXML_Writer_Multibyte(pW, stringTableIndex);
+ }
+
+/* This function will write to the extension string Table. The buffer
+ * "pBuf" is not NULL terminated. This can handle any type of encoding.
+ */
+
+
+static
+NW_Status_t
+NW_WBXML_Writer_StringTableLiteral2(NW_WBXML_Writer_t* pW,
+ NW_Uint32 charCount,
+ const NW_Uint8* pBuf,
+ NW_Uint32 encoding)
+{
+ NW_Uint32 byteCount = 0;
+ NW_Uint32 totalByteCount = 0;
+ NW_Ucs2 c;
+ NW_Uint32 numbytes;
+ NW_Uint8* literalName = NULL;
+ NW_Status_t s = NW_STAT_SUCCESS;
+ NW_Uint32 i =0;
+ NW_Uint32 tableIndex = 0;
+
+ if(pBuf == NULL)
+ {
+ return NW_STAT_BAD_INPUT_PARAM;
+ }
+
+ if (pW->addToStringTable != NULL)
+ {
+
+ /*
+ * pBuf is not NULL terminated. So, need to use the following method.
+ */
+
+ numbytes = NW_String_readChar( (NW_Byte*) pBuf,&c,encoding);
+
+ /* Calculate the length of string. Also add the number of characters
+ * required for the NULL termination.
+ */
+
+ byteCount = (numbytes * charCount) ;
+
+ totalByteCount = byteCount + numbytes;
+
+
+ literalName = (NW_Uint8*) NW_Mem_Malloc(totalByteCount);
+
+ if (literalName != NULL)
+ {
+ (void)NW_Mem_memcpy(literalName, pBuf, byteCount );
+
+
+ for(i=0; i < numbytes; i++)
+ {
+ literalName[byteCount+i] = '\0';
+ }
+
+
+ /* During the PASS -1, the Literal is also added to the string table
+ * so the correct index of Literal can be found. The index of the literal
+ * is written in the WBXML buffer. The index is UINT 32 so (index = 01) and
+ * (index == 0x80) is encoded differently in the WBXML integer encoding. So,
+ * string table function calculates the correct index. So, the calling function
+ * should free the string table after PASS-1. Currently, PASS-1 and PASS-2 is
+ * used in the XML parser only.
+ */
+
+
+ s = (*pW->addToStringTable)(pW->pStringTableObject,
+ totalByteCount, literalName,
+ &tableIndex);
+ if (NW_STAT_IS_SUCCESS(s))
+ {
+ s = NW_WBXML_Writer_Literal(pW,tableIndex);
+ if(literalName != NULL)
+ {
+ NW_Mem_Free(literalName);
+ }
+ }
+ }/*end if (literalName != NULL) */
+ else
+ {
+ s = NW_STAT_OUT_OF_MEMORY;
+ }
+ } /*end if(pW->addToStringTable != NULL)*/
+
+return s;
+}/* NW_WBXML_Writer_StringTableLiteral2(..) */
+
+/* Examine the out parameter *pFound to see if the string was found in
+the string table. If it wasn't found, then it can't be written as a literal
+in WBXML. A failure return code means something else went wrong. The key
+part of this function is that it just queries the string table and doesn't
+try to force the string to be added to the string table. */
+static
+NW_Status_t
+NW_WBXML_Writer_StringTableLiteral(NW_WBXML_Writer_t* pW,
+ NW_Uint32 byteCount,
+ const NW_Uint8* pBuf,
+ NW_Bool* pFound)
+{
+ NW_Status_t s;
+ NW_Uint32 tableIndex = 0;
+
+ *pFound = 0;
+ if (pW->getStringTableOffset) {
+ s = (*pW->getStringTableOffset)(pW->pStringTableObject,
+ byteCount, pBuf,
+ pFound, &tableIndex);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ }
+ if (*pFound) {
+ /* global, so on all code pages */
+ static const NW_Uint8 tableRefToken = NW_WBXML_STR_T;
+
+ s = NW_WBXML_Writer_Memcpy(pW, &tableRefToken, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ return NW_WBXML_Writer_Multibyte(pW, tableIndex);
+ }
+ /* *pFound indicates whether the string table entry was found so
+ we return success */
+ return NW_STAT_SUCCESS;
+}
+
+/* charCount should not include null termination character if any exists */
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_TagString(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
+ NW_Uint32 charCount, NW_Uint32 byteCount,
+ NW_Uint8* pBuf, NW_Uint32* pTagIndex)
+{
+ NW_Status_t s;
+ NW_Uint16 fqToken;
+
+ (void) byteCount;
+
+ /* try token */
+ s = NW_WBXML_Dictionary_getTagToken2(pW->pTagDictionary, encoding,
+ charCount, pBuf, &fqToken);
+ if (NW_STAT_IS_SUCCESS(s)) {
+ return NW_WBXML_Writer_TagToken(pW, fqToken, pTagIndex);
+ }
+
+ /* try string table reference */
+ if (pW->addToStringTable != NULL)
+ {
+ *pTagIndex = pW->index;
+ s = NW_WBXML_Writer_StringTableLiteral2(pW, charCount, pBuf, encoding);
+ // Return on success or failure (out of memory, etc.) except
+ // NW_STAT_STR_TBL_OVERFLOW.
+ if (s != NW_STAT_STR_TBL_OVERFLOW)
+ {
+ return s;
+ }
+ }
+
+ /* no token, not in string table...try to encode as the unknown tag */
+ s = NW_WBXML_Dictionary_getTagToken2(pW->pTagDictionary, zzzunknownEncoding,
+ zzzunknownCharCount,
+ (NW_Uint8*)&zzzunknown[0],
+ &fqToken);
+ if (NW_STAT_IS_SUCCESS(s))
+ {
+ return NW_WBXML_Writer_TagToken(pW, fqToken, pTagIndex);
+ }
+
+ /* getting here means no token, no string table entry
+ and the reserved unknown tag is missing from the dictionary */
+ NW_ASSERT(s == NW_STAT_SUCCESS); /* force error to be caught here */
+ return s;
+}
+
+static
+NW_Status_t
+NW_WBXML_Writer_InlineString(NW_WBXML_Writer_t* pW,
+ NW_Uint32 encoding,
+ NW_Uint32 byteCount,
+ const NW_Uint8* pTextIn)
+{
+ NW_Uint8* pTextOut = (NW_Uint8*)pTextIn; /* default */
+ NW_Status_t s;
+ NW_Bool nullTerminated;
+ NW_Uint8 token = NW_WBXML_STR_I; /* global so on all code pages */
+
+ nullTerminated = NW_FALSE;
+
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ if (pTextOut != pTextIn) {
+ NW_Mem_Free(pTextOut);
+ }
+ return s;
+ }
+ s = NW_WBXML_Writer_Memcpy(pW, pTextOut, byteCount);
+ if (NW_STAT_IS_FAILURE(s)) {
+ if (pTextOut != pTextIn) {
+ NW_Mem_Free(pTextOut);
+ }
+ return s;
+ }
+ if (pTextOut != pTextIn) {
+ NW_Mem_Free(pTextOut);
+ }
+
+ /* test string to see if written bytes are already null terminated */
+ /* FUTURE MISSING UTILITY SUPPORT
+ this char encoding API isn't implemented yet
+ NW_Char_SimpleString_t n;
+ s = NW_CharEncoding_nullTermination(encoding, &n);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ test if null termination already written and if not...
+ s = NW_WBXML_Writer_Memcpy(pW, n.buf, n.byteCount);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ */
+ /* BUG HACK BEGIN
+ Should not assume null termination missing but this works
+ with the XMLP client. Remove this when char encoding
+ null termination utility support is available */
+
+ if (encoding == HTTP_iso_10646_ucs_2){
+ /* just look for any 1 bits in the UCS2 char */
+ NW_Uint8 lastChar = (pTextIn + byteCount)[-1];
+ lastChar |= (pTextIn + byteCount)[-2];
+ if (lastChar == 0){
+ nullTerminated = NW_TRUE;
+ }
+ }
+ else if ((encoding == HTTP_iso_8859_1) ||
+ (encoding == HTTP_utf_8) ||
+ (encoding == HTTP_us_ascii))
+ {
+ NW_Uint8 lastChar = (pTextIn + byteCount)[-1];
+ if (lastChar == 0){
+ nullTerminated = NW_TRUE;
+ }
+ }
+ else{
+ NW_ASSERT(0);
+ }
+ if (!nullTerminated)
+ {
+ token = 0;
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ if (encoding == HTTP_iso_10646_ucs_2) {
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ }
+ }
+ /* BUG HACK END */
+ return NW_STAT_SUCCESS;
+}
+
+/*
+1. charCount should not include null termination character if any exists
+2. if there is an attribute name but no value use valueCharCount==0,
+ valueByteCount==0 and pValue==NULL
+*/
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_AttributeAndValue2(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
+ NW_Uint32 nameCharCount, NW_Uint8* pName,
+ NW_Uint32 valueCharCount, NW_Uint32 valueByteCount,
+ NW_Uint8* pValue,
+ NW_Uint32* cp_count)
+{
+ /*
+ Note: According to the WBXML specification, attribute codes (tokens) may
+ encode all or a prefix of the attribute value as well as the attribute name.
+ The implementation here is simpler, it assumes that attribute names are
+ encoded separately from attribute values.
+ */
+ NW_Status_t s;
+ NW_Uint16 fqToken;
+ NW_Uint8 token;
+ NW_Uint8 page;
+ NW_Bool switched = NW_FALSE;
+ NW_Bool extStrTbl = NW_FALSE;
+
+ *cp_count = 0;
+ /* Note: This dictionary lookup function is insufficient to look up
+ combined attribute and value. To do that we must be able to pass both
+ the name and value and get both a return token and a character count
+ of the value characters represented by the token so we can tell if there
+ are remaing value characters to write. */
+ s = NW_WBXML_Dictionary_getAttributeNameToken(pW->pAttributeDictionary,
+ encoding,
+ nameCharCount, pName, &fqToken);
+ if (NW_STAT_IS_FAILURE(s)) {
+ /* failure here means that we should encode as the reserved unknown
+ name, so force that */
+ fqToken = NW_WBXML_LITERAL;
+ }
+ token = NW_WBXML_Dictionary_extractToken(fqToken);
+ page = NW_WBXML_Dictionary_extractPage(fqToken);
+
+
+ if ((token & NW_WBXML_MASK_TAG_ID) == NW_WBXML_LITERAL)
+ {
+
+ /* If strig table is supported then the attribute name not found
+ * in the dictionary is stored in string table a LITRAL otherwise
+ * the workaround is to encode the name as a reserved unknown.
+ */
+
+ if (pW->getStringTableOffset)
+ {
+ s = NW_WBXML_Writer_StringTableLiteral2(pW,nameCharCount,pName, encoding);
+
+ if (NW_STAT_IS_FAILURE(s))
+ {
+ return s;
+ }
+ extStrTbl = NW_TRUE;
+ }//end if(pW->getStringTableOffset)
+ else
+ {
+
+ s = NW_WBXML_Dictionary_getAttributeNameToken(pW->pAttributeDictionary,
+ zzzunknownEncoding,
+ zzzunknownCharCount,
+ (NW_Uint8*)&zzzunknown[0],
+ &fqToken);
+ if (NW_STAT_IS_FAILURE(s))
+ {
+ /* failure here means the reserved unknown name is missing from
+ the dictionary */
+ NW_ASSERT(s==NW_STAT_SUCCESS);/*force error to be caught here*/
+ return s;
+ }
+ token = NW_WBXML_Dictionary_extractToken(fqToken);
+ page = NW_WBXML_Dictionary_extractPage(fqToken);
+ }//end else
+ }//end if ((token & NW_WBXML_MASK_TAG_ID) == NW_WBXML_LITERAL)
+
+ //
+ //If attribute name is found in the dictionary only then check for the
+ // Page switching.
+ //
+
+ if(!extStrTbl)
+ {
+
+ s = NW_WBXML_Writer_MaybeSwitchPage(pW, page, NW_WBXML_ATTRIBUTE, &switched);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ if (switched)
+ *cp_count = *cp_count + 1 ;
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1); /* attribute name token */
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ }//end if(!extStrTbl)
+
+
+ if ((valueCharCount == 0) && (pValue != NULL))
+ {
+ token = NW_WBXML_STR_I; /* global so on all code pages */
+
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ token = 0;
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ if (encoding == HTTP_iso_10646_ucs_2) {
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ }
+ }
+ else
+ {
+ if ((valueCharCount != 0) && (pValue != NULL))
+ {
+ s = NW_WBXML_Dictionary_getAttributeValueToken(pW->pAttributeDictionary,
+ encoding,
+ valueCharCount, pValue,
+ &fqToken);
+ if (NW_STAT_IS_FAILURE(s)) {
+ /* failure means couldn't find a token, force to literal */
+ fqToken = NW_WBXML_LITERAL; /* page is irrelevant here */
+ }
+ token = NW_WBXML_Dictionary_extractToken(fqToken);
+ page = NW_WBXML_Dictionary_extractPage(fqToken);
+ if ((token & NW_WBXML_MASK_TAG_ID) == NW_WBXML_LITERAL)
+ {
+ s = NW_WBXML_Writer_InlineString(pW, encoding,
+ valueByteCount, pValue);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ } else {
+ s = NW_WBXML_Writer_MaybeSwitchPage(pW, page,
+ NW_WBXML_ATTRIBUTE, &switched);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ if (switched)
+ *cp_count = *cp_count + 1 ;
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);/*attr value token*/
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ }
+ }
+ }
+ return NW_STAT_SUCCESS;
+}
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_AttributeAndValue(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
+ NW_Uint32 nameCharCount, NW_Uint8* pName,
+ NW_Uint32 valueCharCount, NW_Uint32 valueByteCount,
+ NW_Uint8* pValue)
+{
+ NW_Uint32 cp_cnt = 0;
+ return NW_WBXML_Writer_AttributeAndValue2(pW, encoding, nameCharCount, pName, valueCharCount,
+ valueByteCount, pValue, &cp_cnt);
+
+}
+
+NW_Status_t
+NW_WBXML_Writer_AttributeNameString(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
+ NW_Uint32 nameCharCount,
+ NW_Uint32 nameByteCount, NW_Uint8* pName)
+{
+ NW_Status_t s;
+ NW_Uint16 fqToken;
+
+ (void) nameByteCount;
+
+ /* try token */
+ s = NW_WBXML_Dictionary_getAttributeToken2(pW->pAttributeDictionary,
+ encoding, nameCharCount,
+ pName, &fqToken,
+ NW_TRUE /* isName */);
+ if (NW_STAT_IS_SUCCESS(s)) {
+ return NW_WBXML_Writer_AttributeToken(pW, fqToken);
+ }
+
+ /* try string table */
+ if (pW->addToStringTable != NULL) {
+ s = NW_WBXML_Writer_StringTableLiteral2(pW, nameCharCount, pName, encoding);
+ return s;
+
+ }
+ /* no token, no string table so try unknown token */
+ s = NW_WBXML_Dictionary_getAttributeToken2(pW->pAttributeDictionary,
+ zzzunknownEncoding,
+ zzzunknownCharCount,
+ (NW_Uint8*)&zzzunknown[0],
+ &fqToken,
+ NW_TRUE /* isName */);
+ if (NW_STAT_IS_SUCCESS(s)) {
+ return NW_WBXML_Writer_AttributeToken(pW, fqToken);
+ }
+ NW_ASSERT(NW_STAT_IS_SUCCESS(s)); /* force debug to stop here */
+ return NW_STAT_FAILURE;
+}
+
+NW_Status_t
+NW_WBXML_Writer_AttributeToken(NW_WBXML_Writer_t* pW,
+ NW_Uint16 fqToken)
+
+{
+ NW_Status_t s;
+ NW_Uint8 token;
+ NW_Uint8 page;
+ NW_Bool switched = NW_FALSE;
+
+ token = NW_WBXML_Dictionary_extractToken(fqToken);
+ page = NW_WBXML_Dictionary_extractPage(fqToken);
+
+ s = NW_WBXML_Writer_MaybeSwitchPage(pW, page, NW_WBXML_ATTRIBUTE, &switched);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ return NW_WBXML_Writer_Memcpy(pW, &token, 1); /* attribute token */
+}
+
+NW_Status_t
+NW_WBXML_Writer_Entity(NW_WBXML_Writer_t* pW,
+ NW_Uint32 entity)
+{
+ NW_Status_t s;
+ static const NW_Uint8 entityToken = NW_WBXML_ENTITY;
+
+ s = NW_WBXML_Writer_Memcpy(pW, &entityToken, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ return NW_WBXML_Writer_Multibyte(pW, entity);
+}
+
+/*
+This is a helper function for the EXT_T_[0,1,2] forms for these extensions.
+*/
+NW_Status_t
+NW_WBXML_Writer_ExtensionUseStringTable(NW_WBXML_Writer_t* pW,
+ NW_Uint16 fqToken,
+ NW_Uint32 byteCount,
+ NW_Uint8* pBuf)
+{
+ NW_Uint32 tableIndex;
+ NW_Status_t s;
+
+ if (pW->addToStringTable != NULL) {
+ s = (*pW->addToStringTable)(pW->pStringTableObject,
+ byteCount, pBuf, &tableIndex);
+ if (NW_STAT_IS_SUCCESS(s)) {
+ return NW_WBXML_Writer_Extension(pW, fqToken, tableIndex, 0, NULL);
+ }
+ }
+ return NW_STAT_FAILURE;
+}
+
+/*
+There are three type of extensions:
+
+1. one of three possible single byte tokens
+ NW_WBXML_EXT_[0,1,2]
+2. an extension token followed by a multibyte encoded NW_Uint32 value
+ NW_WBXML_EXT_T_[0,1,2] multibyte(anonymousValue)
+3. an extension token followed by an in-line string
+ NW_WBXML_EXT_I_[0,1,2] null-terminated-string
+
+This function handles all three cases so you have to pass the appropriate
+arguments for each case:
+
+1. fqToken should be one of NW_WBXML_EXT_[0,1,2] (with any page value)
+ and anonymousValue, byteCount and pBuf should be 0 or NULL
+
+2. fqToken should be one of NW_WBXML_EXT_T_[0,1,2] (with any page value),
+ anonymousValue should be the value to multibyte encode
+ and byteCount and pBuf should be 0 and NULL
+
+3. fqToken should be one of NW_WBXML_EXT_I_[0,1,2] (with any page value),
+ byteCount should be the byte length of the null terminated string
+ pointed to by pBuf
+ and anonymousValue is ignored
+*/
+NW_Status_t
+NW_WBXML_Writer_Extension(NW_WBXML_Writer_t* pW,
+ NW_Uint16 fqToken,
+ NW_Uint32 anonymousValue,
+ NW_Uint32 byteCount,
+ NW_Uint8* pBuf)
+{
+ NW_Status_t s;
+ NW_Uint8 token = (NW_Uint8)(fqToken & NW_WBXML_MASK_TOKEN);
+
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+
+ switch (token) {
+ case NW_WBXML_EXT_0:
+ case NW_WBXML_EXT_1:
+ case NW_WBXML_EXT_2:
+ NW_ASSERT(byteCount == 0);
+ NW_ASSERT(pBuf == NULL);
+ break;
+ case NW_WBXML_EXT_T_0:
+ case NW_WBXML_EXT_T_1:
+ case NW_WBXML_EXT_T_2:
+ NW_ASSERT(byteCount == 0);
+ NW_ASSERT(pBuf == NULL);
+ s = NW_WBXML_Writer_Multibyte(pW, anonymousValue);
+ break;
+ case NW_WBXML_EXT_I_0:
+ case NW_WBXML_EXT_I_1:
+ case NW_WBXML_EXT_I_2:
+ NW_ASSERT(byteCount > 0);
+ NW_ASSERT(pBuf != NULL);
+ s = NW_WBXML_Writer_Memcpy(pW, pBuf, byteCount);
+ break;
+ default:
+ NW_ASSERT(!"wrong token");
+ return NW_STAT_FAILURE;
+ }
+ return s;
+}
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_Opaque(NW_WBXML_Writer_t* pW, NW_Uint32 byteCount,
+ NW_Uint8* pBuf)
+{
+ NW_Status_t s;
+ NW_Uint8 token = NW_WBXML_OPAQUE; /* global so on all code pages */
+ s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ s = NW_WBXML_Writer_Multibyte(pW, byteCount);
+ if (NW_STAT_IS_FAILURE(s)) {
+ return s;
+ }
+ s = NW_WBXML_Writer_Memcpy(pW, pBuf, byteCount);
+ return s;
+}
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_Text(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
+ NW_Uint32 byteCount, const NW_Uint8* pText)
+{
+ NW_Status_t s;
+ NW_Bool found = 0;
+
+ /* try string table */
+ s = NW_WBXML_Writer_StringTableLiteral(pW, byteCount, pText, &found);
+ if (NW_STAT_IS_FAILURE(s) || found) {
+ return s;
+ }
+ /* back off to inline string */
+ return NW_WBXML_Writer_InlineString(pW, encoding, byteCount, pText);
+}
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_PI(NW_WBXML_Writer_t* pW)
+{
+ NW_Uint8 piToken = 0x43; /* global, so on all code pages */
+ return NW_WBXML_Writer_Memcpy(pW, &piToken, 1);
+}
+
+
+EXPORT_C
+NW_Status_t
+NW_WBXML_Writer_End(NW_WBXML_Writer_t* pW)
+{
+ NW_Uint8 endToken = NW_WBXML_END; /* global, so on all code pages */
+ return NW_WBXML_Writer_Memcpy(pW, &endToken, 1);
+}
+
+EXPORT_C
+void
+NW_WBXML_Writer_Initialize(NW_WBXML_Writer_t* pW,
+ NW_Uint32 byteCount, NW_Uint8* pBuf,
+ NW_WBXML_Writer_GrowBuf_t growBufCallback,
+ NW_WBXML_Dictionary_t* pTagDictionary,
+ NW_WBXML_Dictionary_t* pAttributeDictionary,
+ NW_WBXML_Writer_GetStringTableOffset_t getStringTableOffset,
+ NW_WBXML_Writer_AddToStringTable_t addToStringTable,
+ void* pStringTableObject,
+ NW_WBXML_Writer_StringTableIterateInit_t stringTableIterateInit,
+ NW_WBXML_Writer_StringTableIterateNext_t stringTableIterateNext,
+ NW_Bool sizing)
+{
+ pW->index = 0;
+ pW->byteCount = byteCount;
+ pW->pBuf = pBuf;
+ pW->growBufCallback = growBufCallback;
+ pW->pTagDictionary = pTagDictionary;
+ pW->pAttributeDictionary = pAttributeDictionary;
+ pW->getStringTableOffset = getStringTableOffset;
+ pW->addToStringTable = addToStringTable;
+ pW->pStringTableObject = pStringTableObject;
+ pW->stringTableIterateInit = stringTableIterateInit;
+ pW->stringTableIterateNext = stringTableIterateNext;
+ pW->tagCodePage = 0;
+ pW->attributeCodePage = 0;
+ pW->sizing = sizing;
+ //WLIU_DEBUG: pW->cp_count = 0;
+}
+
+void
+NW_WBXML_Writer_SetToSizing(NW_WBXML_Writer_t* pW)
+{
+ pW->index = 0;
+ pW->tagCodePage = 0; /* TBD BUG ? will this give correct code pages */
+ pW->attributeCodePage = 0;/* TBD BUG ? will this give correct code pages */
+ pW->sizing = 1;
+ // WLIU_DEBUG: pW->cp_count = 0;
+}
+
+
+void
+NW_WBXML_Writer_SetToWrite(NW_WBXML_Writer_t* pW, NW_Uint32 byteCount, NW_Uint8* pBuf)
+{
+ pW->index = 0;
+ pW->byteCount = byteCount;
+ pW->pBuf = pBuf;
+ pW->tagCodePage = 0; /* TBD BUG ? will this give correct code pages */
+ pW->attributeCodePage = 0;/* TBD BUG ? will this give correct code pages */
+ pW->sizing = 0;
+ // WLIU_DEBUG: pW->cp_count = 0;
+}