xml/cxmllibrary/src/encoder/src/WBXMLWriter.cpp
branchRCL_3
changeset 21 604ca70b6235
parent 20 889504eac4fb
equal deleted inserted replaced
20:889504eac4fb 21:604ca70b6235
     1 /*
       
     2 * Copyright (c) 2000 - 2001 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "cxml_internal.h"
       
    20 #include <xml/cxml/nw_wbxml_token.h>
       
    21 #include <xml/cxml/nw_encoder_wbxmlwriter.h>
       
    22 #include <xml/cxml/nw_wbxml_parse.h>
       
    23 #include "cxml_mem.h"
       
    24 
       
    25 // WLIU_DEBUG: #include "flogger.h"
       
    26   /* a reserved name used for encoding tags and attributes that
       
    27 otherwise aren't in the dictionaries. zzzunknown must be in the
       
    28 dictionary for both tag names and attribute names */
       
    29 #define zzzunknownCharCount 10
       
    30 static const NW_Uint8 zzzunknown[] = {'z','z','z','u','n','k','n','o','w','n','\0'};
       
    31 #define zzzunknownEncoding HTTP_utf_8
       
    32 
       
    33 
       
    34 static
       
    35 NW_Status_t
       
    36 NW_WBXML_Writer_Memcpy(NW_WBXML_Writer_t* pW, const NW_Uint8* pBytes,
       
    37                        NW_Uint32 writeLength)
       
    38 {
       
    39   NW_Status_t s = NW_STAT_SUCCESS;
       
    40   if (writeLength == 0) {
       
    41     return NW_STAT_FAILURE;
       
    42   }
       
    43   if (!pW->sizing) {
       
    44     if (((pW->index + writeLength - 1) >= pW->byteCount)
       
    45         && (pW->growBufCallback != NULL)) {
       
    46       /* try to grow buf */
       
    47       s = (*pW->growBufCallback)(pW, writeLength);
       
    48       if (NW_STAT_IS_FAILURE(s)) {
       
    49         return s;
       
    50       }
       
    51     }
       
    52     if ((pW->index + writeLength - 1) >= pW->byteCount) {
       
    53       /* grow buf unavailable or didn't alloc enough */
       
    54       return NW_STAT_OUT_OF_MEMORY;
       
    55     }
       
    56     NW_Mem_memcpy(pW->pBuf + pW->index, pBytes, writeLength);
       
    57   }
       
    58   pW->index += writeLength;
       
    59   return s;
       
    60 }
       
    61 
       
    62 typedef struct NW_WBXML_Multibyte_s {
       
    63   NW_Uint8 length; /* encoded length in bytes from 1..5 */
       
    64   NW_Uint8 buf[5];
       
    65 } NW_WBXML_Multibyte_t;
       
    66 
       
    67 /* see the WBXML specification for the definition of this function */
       
    68 static
       
    69 void
       
    70 NW_WBXML_EncodeMultibyte(NW_Uint32 x, NW_WBXML_Multibyte_t* pM)
       
    71 {
       
    72   NW_Uint8 i;
       
    73   NW_Uint8 littleEndian[5];
       
    74 
       
    75   littleEndian[0] = (NW_Uint8)(x & 0x7f);
       
    76   for (i = 1; i < 5; i++) {
       
    77     x >>= 7; /* unsigned x, no sign extension */
       
    78     littleEndian[i] = (NW_Uint8)(x & 0x7f);
       
    79     if (!x) {
       
    80       break;
       
    81     }
       
    82   }
       
    83   pM->length = i;
       
    84   for (i = 0; i < pM->length; i++) {
       
    85     pM->buf[i] = littleEndian[pM->length - 1 - i];
       
    86     if ((i + 1) < pM->length) {
       
    87       pM->buf[i] |= 0x80;
       
    88     }
       
    89   }
       
    90 }
       
    91 
       
    92 static
       
    93 NW_Status_t
       
    94 NW_WBXML_Writer_Multibyte(NW_WBXML_Writer_t* pW, NW_Uint32 x)
       
    95 {
       
    96   NW_WBXML_Multibyte_t multibyte;
       
    97 
       
    98   NW_WBXML_EncodeMultibyte(x, &multibyte);
       
    99   return NW_WBXML_Writer_Memcpy(pW, multibyte.buf,
       
   100                                 multibyte.length);
       
   101 }
       
   102 
       
   103 typedef enum {
       
   104     NW_WBXML_TAG,
       
   105     NW_WBXML_ATTRIBUTE
       
   106 } NW_WBXML_Writer_ItemType;
       
   107 
       
   108 static
       
   109 NW_Status_t
       
   110 NW_WBXML_Writer_MaybeSwitchPage(NW_WBXML_Writer_t* pW, NW_Uint8 page,
       
   111                                 NW_WBXML_Writer_ItemType itemType,
       
   112                                 NW_Bool* switched)
       
   113 {
       
   114   NW_Status_t s = NW_STAT_SUCCESS;
       
   115   NW_Uint8 token = NW_WBXML_SWITCH_PAGE; /* global so on all code pages */
       
   116   NW_Bool changePage = 0;
       
   117 
       
   118   *switched = NW_FALSE;
       
   119   switch (itemType) {
       
   120   case NW_WBXML_TAG:
       
   121     changePage = (NW_Bool)(page != pW->tagCodePage);
       
   122     if (changePage) {
       
   123       pW->tagCodePage = page;
       
   124       // WLIU_DEBUG: pW->cp_count++;
       
   125     }
       
   126     break;
       
   127   case NW_WBXML_ATTRIBUTE:
       
   128     changePage = (NW_Bool)(page != pW->attributeCodePage);
       
   129     if (changePage) {
       
   130       pW->attributeCodePage = page;
       
   131       // WLIU_DEBUG: pW->cp_count++;
       
   132     }
       
   133     break;
       
   134   default:
       
   135     s = NW_STAT_FAILURE;
       
   136     break;
       
   137   }
       
   138   if (changePage) { 
       
   139     s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   140     // WLIU_DEBUG: RFileLogger::WriteFormat(_L("Browser"), _L("cp_count.txt"), EFileLoggingModeAppend, _L("=== cp_count: %x, pW->index: %x \n"), pW->cp_count, pW->index);
       
   141     if (NW_STAT_IS_FAILURE(s)) {
       
   142       return s;
       
   143     }
       
   144     s = NW_WBXML_Writer_Memcpy(pW, &page, 1);
       
   145         if (NW_STAT_IS_FAILURE(s)) {
       
   146       return s;
       
   147     }
       
   148     *switched = NW_TRUE;
       
   149   }
       
   150   return s;
       
   151 }
       
   152 
       
   153 EXPORT_C
       
   154 NW_Status_t
       
   155 NW_WBXML_Writer_Header(NW_WBXML_Writer_t* pW, NW_Uint8 WBXMLVersion,
       
   156                        NW_Uint32 publicIdentifier, NW_Uint32 charsetMIBEnum,
       
   157                        NW_Uint32 stringTableByteCount)
       
   158 
       
   159 {
       
   160   NW_Status_t s;
       
   161   NW_Uint32 byteCount;
       
   162   NW_Uint8* pBuf;
       
   163   NW_Encoder_StringTableIterator_t strTableIterator;
       
   164 
       
   165   /* header = version publicid charset stringtable */
       
   166 
       
   167   s = NW_WBXML_Writer_Memcpy(pW, &WBXMLVersion, 1);
       
   168   if (NW_STAT_IS_FAILURE(s)) {
       
   169     return s;
       
   170   }
       
   171   s = NW_WBXML_Writer_Multibyte(pW, publicIdentifier);
       
   172   if (NW_STAT_IS_FAILURE(s)) {
       
   173     return s;
       
   174   }
       
   175   s = NW_WBXML_Writer_Multibyte(pW, charsetMIBEnum);
       
   176   if (NW_STAT_IS_FAILURE(s)) {
       
   177     return s;
       
   178   }
       
   179   s = NW_WBXML_Writer_Multibyte(pW, stringTableByteCount);
       
   180   if (NW_STAT_IS_FAILURE(s)) {
       
   181     return s;
       
   182   }
       
   183   if (stringTableByteCount) {
       
   184     NW_ASSERT(pW->stringTableIterateInit);
       
   185     NW_ASSERT(pW->stringTableIterateNext);
       
   186     s = (*(pW->stringTableIterateInit))(pW->pStringTableObject,
       
   187                                         &strTableIterator);
       
   188     if (NW_STAT_IS_FAILURE(s)) {
       
   189       return s;
       
   190     }
       
   191     s = (*(pW->stringTableIterateNext))(&strTableIterator,
       
   192                                         &byteCount, &pBuf);
       
   193     while (s == NW_STAT_WBXML_ITERATE_MORE){
       
   194       s = NW_WBXML_Writer_Memcpy(pW, pBuf, byteCount);
       
   195       if (s != NW_STAT_SUCCESS){
       
   196         return s;
       
   197       }
       
   198       s = (*(pW->stringTableIterateNext))(&strTableIterator,
       
   199                                           &byteCount, &pBuf);
       
   200     }
       
   201     if (s != NW_STAT_WBXML_ITERATE_DONE){
       
   202       return NW_STAT_FAILURE;
       
   203     }
       
   204   }
       
   205   return NW_STAT_SUCCESS;
       
   206 }
       
   207 
       
   208 /* if boolean "set" is 1 then "or" with mask, else "and" with ~mask */
       
   209 static
       
   210 NW_Status_t
       
   211 NW_WBXML_Writer_TagFlagOp(NW_WBXML_Writer_t* pW, NW_Uint32 index,
       
   212                           NW_Uint8 mask, NW_Bool set)
       
   213 {
       
   214   NW_Status_t s = NW_STAT_SUCCESS;
       
   215   if (!pW->sizing) {
       
   216     if (index < pW->byteCount) {
       
   217       if (set) {
       
   218         (pW->pBuf)[index] |= mask;
       
   219       } else {
       
   220         (pW->pBuf)[index] &= ~mask;
       
   221       }
       
   222     } else {
       
   223       s = NW_STAT_FAILURE;
       
   224     }
       
   225   }
       
   226   return s;
       
   227 }
       
   228 
       
   229 EXPORT_C
       
   230 NW_Status_t
       
   231 NW_WBXML_Writer_TagSetContentFlag(NW_WBXML_Writer_t* pW, NW_Uint32 index)
       
   232 {
       
   233   return NW_WBXML_Writer_TagFlagOp(pW, index, NW_WBXML_FLAGS_CONTENT, 1);
       
   234 }
       
   235 
       
   236 EXPORT_C
       
   237 NW_Status_t
       
   238 NW_WBXML_Writer_TagClearContentFlag(NW_WBXML_Writer_t* pW, NW_Uint32 index)
       
   239 {
       
   240   return NW_WBXML_Writer_TagFlagOp(pW, index, NW_WBXML_FLAGS_CONTENT, 0);
       
   241 }
       
   242 
       
   243 EXPORT_C
       
   244 NW_Status_t
       
   245 NW_WBXML_Writer_TagSetAttributesFlag(NW_WBXML_Writer_t* pW, NW_Uint32 index)
       
   246 {
       
   247   return NW_WBXML_Writer_TagFlagOp(pW, index, NW_WBXML_FLAGS_ATTRIBUTES, 1);
       
   248 }
       
   249 
       
   250 NW_Status_t
       
   251 NW_WBXML_Writer_TagClearAttributesFlag(NW_WBXML_Writer_t* pW, NW_Uint32 index)
       
   252 {
       
   253   return NW_WBXML_Writer_TagFlagOp(pW, index, NW_WBXML_FLAGS_ATTRIBUTES, 0);
       
   254 }
       
   255 
       
   256 NW_Status_t
       
   257 NW_WBXML_Writer_TagToken(NW_WBXML_Writer_t* pW, NW_Uint16 fqToken,
       
   258                     NW_Uint32* pTagIndex)
       
   259 {
       
   260   NW_Status_t s;
       
   261   NW_Uint8 token;
       
   262   NW_Uint8 page;
       
   263   NW_Bool  switched = NW_FALSE;
       
   264 
       
   265   token = NW_WBXML_Dictionary_extractToken(fqToken);
       
   266   page =  NW_WBXML_Dictionary_extractPage(fqToken);
       
   267 
       
   268   s = NW_WBXML_Writer_MaybeSwitchPage(pW, page, NW_WBXML_TAG, &switched);
       
   269   if (NW_STAT_IS_FAILURE(s)) {
       
   270     return s;
       
   271   }
       
   272   *pTagIndex = pW->index;
       
   273   return NW_WBXML_Writer_Memcpy(pW, &token, 1); /* tag token */
       
   274   }
       
   275 
       
   276 static
       
   277 NW_Status_t
       
   278 NW_WBXML_Writer_Literal(NW_WBXML_Writer_t* pW, NW_Uint32 stringTableIndex)
       
   279   {
       
   280   NW_Status_t s;
       
   281 
       
   282   /* global in WBXML spec, so on all code pages */
       
   283   static const NW_Uint8 literalToken = NW_WBXML_LITERAL;
       
   284 
       
   285   s = NW_WBXML_Writer_Memcpy(pW, &literalToken, 1);
       
   286     if (NW_STAT_IS_FAILURE(s)) {
       
   287       return s;
       
   288     }
       
   289   return NW_WBXML_Writer_Multibyte(pW, stringTableIndex);
       
   290   }
       
   291 
       
   292 /* This function will write to the extension string Table. The buffer
       
   293  * "pBuf" is not NULL terminated. This can handle any type of encoding.
       
   294  */
       
   295 
       
   296 
       
   297 static
       
   298 NW_Status_t
       
   299 NW_WBXML_Writer_StringTableLiteral2(NW_WBXML_Writer_t* pW,
       
   300                                    NW_Uint32 charCount,
       
   301                                    const NW_Uint8* pBuf,
       
   302                                    NW_Uint32 encoding)
       
   303 {
       
   304  NW_Uint32 byteCount = 0;
       
   305  NW_Uint32 totalByteCount = 0;
       
   306  NW_Ucs2 c;
       
   307  NW_Uint32 numbytes;
       
   308  NW_Uint8* literalName = NULL;
       
   309  NW_Status_t s = NW_STAT_SUCCESS;
       
   310  NW_Uint32 i =0;
       
   311  NW_Uint32 tableIndex = 0;
       
   312 
       
   313  if(pBuf == NULL)
       
   314  {
       
   315   return NW_STAT_BAD_INPUT_PARAM;
       
   316  }
       
   317 
       
   318  if (pW->addToStringTable != NULL) 
       
   319    {
       
   320 
       
   321    /*
       
   322     * pBuf is not NULL terminated. So, need to use the following method.
       
   323     */
       
   324 
       
   325     numbytes = NW_String_readChar( (NW_Byte*) pBuf,&c,encoding);
       
   326 
       
   327    /* Calculate the length of string. Also add the number of characters 
       
   328     * required for the NULL termination.
       
   329     */
       
   330 
       
   331     byteCount = (numbytes * charCount) ;
       
   332         
       
   333     totalByteCount = byteCount + numbytes;
       
   334 
       
   335 
       
   336     literalName = (NW_Uint8*) NW_Mem_Malloc(totalByteCount);
       
   337 
       
   338     if (literalName != NULL) 
       
   339      {
       
   340       (void)NW_Mem_memcpy(literalName, pBuf, byteCount );
       
   341 
       
   342 
       
   343        for(i=0; i < numbytes; i++)
       
   344        {
       
   345         literalName[byteCount+i] = '\0';
       
   346        }
       
   347 
       
   348 
       
   349        /* During the PASS -1, the Literal is also added to the string table
       
   350         * so the correct index of Literal can be found. The index of the literal
       
   351         * is written in the WBXML buffer. The index is UINT 32 so (index = 01) and
       
   352         * (index == 0x80) is encoded differently in the WBXML integer encoding. So, 
       
   353         * string table function calculates the correct index. So, the calling function
       
   354         * should free the string table after PASS-1. Currently, PASS-1 and PASS-2 is 
       
   355         * used in the XML parser only.
       
   356         */
       
   357 
       
   358 
       
   359        s = (*pW->addToStringTable)(pW->pStringTableObject,
       
   360                                     totalByteCount, literalName,
       
   361                                     &tableIndex);
       
   362       if (NW_STAT_IS_SUCCESS(s))
       
   363       {
       
   364        s = NW_WBXML_Writer_Literal(pW,tableIndex);
       
   365        if(literalName != NULL)
       
   366        {
       
   367         NW_Mem_Free(literalName);
       
   368        }
       
   369       }
       
   370      }/*end if (literalName != NULL) */
       
   371      else
       
   372      {
       
   373       s = NW_STAT_OUT_OF_MEMORY;
       
   374      }
       
   375  } /*end if(pW->addToStringTable != NULL)*/
       
   376 
       
   377 return s;
       
   378 }/* NW_WBXML_Writer_StringTableLiteral2(..) */
       
   379 
       
   380 /* Examine the out parameter *pFound to see if the string was found in
       
   381 the string table.  If it wasn't found, then it can't be written as a literal
       
   382 in WBXML.  A failure return code means something else went wrong. The key
       
   383 part of this function is that it just queries the string table and doesn't
       
   384 try to force the string to be added to the string table. */
       
   385 static
       
   386 NW_Status_t
       
   387 NW_WBXML_Writer_StringTableLiteral(NW_WBXML_Writer_t* pW,
       
   388                                    NW_Uint32 byteCount,
       
   389                                    const NW_Uint8* pBuf,
       
   390                                    NW_Bool* pFound)
       
   391 {
       
   392   NW_Status_t s;
       
   393   NW_Uint32 tableIndex = 0;
       
   394 
       
   395   *pFound = 0;
       
   396   if (pW->getStringTableOffset) {
       
   397     s = (*pW->getStringTableOffset)(pW->pStringTableObject,
       
   398                                     byteCount, pBuf,
       
   399                                     pFound, &tableIndex);
       
   400     if (NW_STAT_IS_FAILURE(s)) {
       
   401       return s;
       
   402     }
       
   403   }
       
   404   if (*pFound) {
       
   405     /* global, so on all code pages */
       
   406     static const NW_Uint8 tableRefToken = NW_WBXML_STR_T;
       
   407 
       
   408     s = NW_WBXML_Writer_Memcpy(pW, &tableRefToken, 1);
       
   409     if (NW_STAT_IS_FAILURE(s)) {
       
   410       return s;
       
   411     }
       
   412     return NW_WBXML_Writer_Multibyte(pW, tableIndex);
       
   413   }
       
   414   /* *pFound indicates whether the string table entry was found so
       
   415      we return success */
       
   416   return NW_STAT_SUCCESS;
       
   417 }
       
   418 
       
   419 /* charCount should not include null termination character if any exists */
       
   420 EXPORT_C
       
   421 NW_Status_t
       
   422 NW_WBXML_Writer_TagString(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
       
   423                           NW_Uint32 charCount, NW_Uint32 byteCount,
       
   424                           NW_Uint8* pBuf, NW_Uint32* pTagIndex)
       
   425 {
       
   426   NW_Status_t s;
       
   427   NW_Uint16 fqToken;
       
   428 
       
   429   (void) byteCount;
       
   430 
       
   431   /* try token */
       
   432   s = NW_WBXML_Dictionary_getTagToken2(pW->pTagDictionary, encoding,
       
   433                                        charCount, pBuf, &fqToken);
       
   434   if (NW_STAT_IS_SUCCESS(s)) {
       
   435     return NW_WBXML_Writer_TagToken(pW, fqToken, pTagIndex);
       
   436   }
       
   437 
       
   438   /* try string table reference */
       
   439   if (pW->addToStringTable != NULL)
       
   440   {
       
   441     *pTagIndex = pW->index;
       
   442     s = NW_WBXML_Writer_StringTableLiteral2(pW, charCount, pBuf, encoding);
       
   443     // Return on success or failure (out of memory, etc.) except
       
   444     // NW_STAT_STR_TBL_OVERFLOW.
       
   445     if (s != NW_STAT_STR_TBL_OVERFLOW)
       
   446     {
       
   447       return s;
       
   448     }
       
   449   }
       
   450   
       
   451   /* no token, not in string table...try to encode as the unknown tag */
       
   452   s = NW_WBXML_Dictionary_getTagToken2(pW->pTagDictionary, zzzunknownEncoding,
       
   453                                        zzzunknownCharCount,
       
   454                                        (NW_Uint8*)&zzzunknown[0],
       
   455                                        &fqToken);
       
   456   if (NW_STAT_IS_SUCCESS(s)) 
       
   457   {
       
   458    return NW_WBXML_Writer_TagToken(pW, fqToken, pTagIndex);
       
   459   }
       
   460 
       
   461   /* getting here means no token, no string table entry
       
   462   and the reserved unknown tag is missing from the dictionary */
       
   463   NW_ASSERT(s == NW_STAT_SUCCESS); /* force error to be caught here */
       
   464   return s;
       
   465 }
       
   466 
       
   467 static
       
   468 NW_Status_t
       
   469 NW_WBXML_Writer_InlineString(NW_WBXML_Writer_t* pW,
       
   470                              NW_Uint32 encoding,
       
   471                              NW_Uint32 byteCount,
       
   472                              const NW_Uint8* pTextIn)
       
   473 {
       
   474   NW_Uint8* pTextOut = (NW_Uint8*)pTextIn; /* default */
       
   475   NW_Status_t s;
       
   476   NW_Bool nullTerminated;
       
   477   NW_Uint8 token = NW_WBXML_STR_I; /* global so on all code pages */
       
   478 
       
   479   nullTerminated = NW_FALSE;
       
   480 
       
   481   s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   482   if (NW_STAT_IS_FAILURE(s)) {
       
   483     if (pTextOut != pTextIn) {
       
   484       NW_Mem_Free(pTextOut);
       
   485     }
       
   486     return s;
       
   487   }
       
   488   s = NW_WBXML_Writer_Memcpy(pW, pTextOut, byteCount);
       
   489   if (NW_STAT_IS_FAILURE(s)) {
       
   490     if (pTextOut != pTextIn) {
       
   491       NW_Mem_Free(pTextOut);
       
   492     }
       
   493     return s;
       
   494   }
       
   495   if (pTextOut != pTextIn) {
       
   496     NW_Mem_Free(pTextOut);
       
   497   }
       
   498 
       
   499   /* test string to see if written bytes are already null terminated */
       
   500   /* FUTURE MISSING UTILITY SUPPORT
       
   501   this char encoding API isn't implemented yet
       
   502   NW_Char_SimpleString_t n;
       
   503   s = NW_CharEncoding_nullTermination(encoding, &n);
       
   504   if (NW_STAT_IS_FAILURE(s)) {
       
   505     return s;
       
   506   }
       
   507   test if null termination already written and if not...
       
   508   s = NW_WBXML_Writer_Memcpy(pW, n.buf, n.byteCount);
       
   509   if (NW_STAT_IS_FAILURE(s)) {
       
   510     return s;
       
   511   }
       
   512   */
       
   513   /* BUG HACK BEGIN
       
   514   Should not assume null termination missing but this works
       
   515   with the XMLP client.  Remove this when char encoding
       
   516   null termination utility support is available */
       
   517 
       
   518   if (encoding == HTTP_iso_10646_ucs_2){
       
   519     /* just look for any 1 bits in the UCS2 char */
       
   520     NW_Uint8 lastChar = (pTextIn + byteCount)[-1];
       
   521     lastChar |= (pTextIn + byteCount)[-2];
       
   522     if (lastChar == 0){
       
   523       nullTerminated = NW_TRUE;
       
   524     }
       
   525   }
       
   526   else if ((encoding == HTTP_iso_8859_1) ||
       
   527             (encoding == HTTP_utf_8) ||
       
   528             (encoding == HTTP_us_ascii))
       
   529   {
       
   530     NW_Uint8 lastChar = (pTextIn + byteCount)[-1];
       
   531     if (lastChar == 0){
       
   532       nullTerminated = NW_TRUE;
       
   533     }
       
   534   }
       
   535   else{
       
   536     NW_ASSERT(0);
       
   537   }
       
   538   if (!nullTerminated)
       
   539   {
       
   540   token = 0;
       
   541   s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   542   if (NW_STAT_IS_FAILURE(s)) {
       
   543     return s;
       
   544   }
       
   545   if (encoding == HTTP_iso_10646_ucs_2) {
       
   546     s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   547     if (NW_STAT_IS_FAILURE(s)) {
       
   548       return s;
       
   549     }
       
   550   }
       
   551   }
       
   552   /* BUG HACK END */
       
   553   return NW_STAT_SUCCESS;
       
   554 }
       
   555 
       
   556 /*
       
   557 1. charCount should not include null termination character if any exists
       
   558 2. if there is an attribute name but no value use valueCharCount==0,
       
   559    valueByteCount==0 and pValue==NULL
       
   560 */
       
   561 EXPORT_C
       
   562 NW_Status_t
       
   563 NW_WBXML_Writer_AttributeAndValue2(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
       
   564                                   NW_Uint32 nameCharCount, NW_Uint8* pName,
       
   565                                   NW_Uint32 valueCharCount, NW_Uint32 valueByteCount,
       
   566                                   NW_Uint8* pValue,
       
   567                                   NW_Uint32* cp_count)
       
   568 {
       
   569   /*
       
   570   Note: According to the WBXML specification, attribute codes (tokens) may
       
   571   encode all or a prefix of the attribute value as well as the attribute name.
       
   572   The implementation here is simpler, it assumes that attribute names are
       
   573   encoded separately from attribute values.
       
   574   */
       
   575   NW_Status_t s;
       
   576   NW_Uint16 fqToken;
       
   577   NW_Uint8 token;
       
   578   NW_Uint8 page;
       
   579   NW_Bool switched = NW_FALSE;
       
   580   NW_Bool extStrTbl = NW_FALSE;
       
   581 
       
   582   *cp_count = 0;
       
   583   /* Note: This dictionary lookup function is insufficient to look up
       
   584   combined attribute and value.  To do that we must be able to pass both
       
   585   the name and value and get both a return token and a character count
       
   586   of the value characters represented by the token so we can tell if there
       
   587   are remaing value characters to write. */
       
   588   s = NW_WBXML_Dictionary_getAttributeNameToken(pW->pAttributeDictionary,
       
   589                                                 encoding,
       
   590                                                 nameCharCount, pName, &fqToken);
       
   591   if (NW_STAT_IS_FAILURE(s)) {
       
   592     /* failure here means that we should encode as the reserved unknown
       
   593     name, so force that */
       
   594     fqToken = NW_WBXML_LITERAL;
       
   595   }
       
   596   token = NW_WBXML_Dictionary_extractToken(fqToken);
       
   597   page =  NW_WBXML_Dictionary_extractPage(fqToken);
       
   598 
       
   599 
       
   600   if ((token & NW_WBXML_MASK_TAG_ID) == NW_WBXML_LITERAL)
       
   601   {
       
   602    
       
   603    /* If strig table is supported then the attribute name not found 
       
   604     * in the dictionary is stored in string table a LITRAL otherwise
       
   605     * the workaround is to encode the name as a reserved unknown. 
       
   606    */
       
   607 
       
   608      if (pW->getStringTableOffset)
       
   609      {
       
   610       s = NW_WBXML_Writer_StringTableLiteral2(pW,nameCharCount,pName, encoding);
       
   611 
       
   612       if (NW_STAT_IS_FAILURE(s)) 
       
   613       {
       
   614        return s;
       
   615       }
       
   616       extStrTbl = NW_TRUE;
       
   617      }//end if(pW->getStringTableOffset)
       
   618      else
       
   619      {
       
   620 
       
   621        s = NW_WBXML_Dictionary_getAttributeNameToken(pW->pAttributeDictionary,
       
   622                                                   zzzunknownEncoding,
       
   623                                                   zzzunknownCharCount,
       
   624                                                   (NW_Uint8*)&zzzunknown[0],
       
   625                                                   &fqToken);
       
   626        if (NW_STAT_IS_FAILURE(s)) 
       
   627        {
       
   628            /* failure here means the reserved unknown name is missing from
       
   629            the dictionary */
       
   630           NW_ASSERT(s==NW_STAT_SUCCESS);/*force error to be caught here*/
       
   631           return s;
       
   632        }
       
   633         token = NW_WBXML_Dictionary_extractToken(fqToken);
       
   634         page =  NW_WBXML_Dictionary_extractPage(fqToken);
       
   635      }//end else
       
   636   }//end if ((token & NW_WBXML_MASK_TAG_ID) == NW_WBXML_LITERAL)
       
   637 
       
   638      //
       
   639      //If attribute name is found in the dictionary only then check for the
       
   640      // Page switching.
       
   641      //
       
   642 
       
   643      if(!extStrTbl)
       
   644      {
       
   645 
       
   646         s = NW_WBXML_Writer_MaybeSwitchPage(pW, page, NW_WBXML_ATTRIBUTE, &switched);
       
   647         if (NW_STAT_IS_FAILURE(s)) {
       
   648             return s;
       
   649          }
       
   650         if (switched)
       
   651             *cp_count = *cp_count + 1 ;
       
   652         s = NW_WBXML_Writer_Memcpy(pW, &token, 1); /* attribute name token */
       
   653         if (NW_STAT_IS_FAILURE(s)) {
       
   654            return s;
       
   655          }
       
   656      }//end if(!extStrTbl)   
       
   657 
       
   658 
       
   659   if ((valueCharCount == 0) && (pValue != NULL))
       
   660   {
       
   661     token = NW_WBXML_STR_I; /* global so on all code pages */
       
   662 
       
   663     s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   664     if (NW_STAT_IS_FAILURE(s)) {
       
   665       return s;
       
   666     }
       
   667     token = 0;
       
   668     s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   669     if (NW_STAT_IS_FAILURE(s)) {
       
   670       return s;
       
   671     }
       
   672     if (encoding == HTTP_iso_10646_ucs_2) {
       
   673       s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   674       if (NW_STAT_IS_FAILURE(s)) {
       
   675         return s;
       
   676       }
       
   677     }
       
   678   }
       
   679   else
       
   680   {
       
   681     if ((valueCharCount != 0) && (pValue != NULL))
       
   682     {
       
   683       s = NW_WBXML_Dictionary_getAttributeValueToken(pW->pAttributeDictionary,
       
   684                                                     encoding,
       
   685                                                     valueCharCount, pValue,
       
   686                                                     &fqToken);
       
   687       if (NW_STAT_IS_FAILURE(s)) {
       
   688         /* failure means couldn't find a token, force to literal */
       
   689         fqToken = NW_WBXML_LITERAL; /* page is irrelevant here */
       
   690       }
       
   691       token = NW_WBXML_Dictionary_extractToken(fqToken);
       
   692       page =  NW_WBXML_Dictionary_extractPage(fqToken);
       
   693       if ((token & NW_WBXML_MASK_TAG_ID) == NW_WBXML_LITERAL)
       
   694       {
       
   695         s = NW_WBXML_Writer_InlineString(pW, encoding,
       
   696                                         valueByteCount, pValue);
       
   697         if (NW_STAT_IS_FAILURE(s)) {
       
   698           return s;
       
   699         }
       
   700       } else {
       
   701         s = NW_WBXML_Writer_MaybeSwitchPage(pW, page,
       
   702                                             NW_WBXML_ATTRIBUTE, &switched);
       
   703         if (NW_STAT_IS_FAILURE(s)) {
       
   704           return s;
       
   705         }
       
   706         if (switched)
       
   707           *cp_count = *cp_count + 1 ;
       
   708         s = NW_WBXML_Writer_Memcpy(pW, &token, 1);/*attr value token*/
       
   709         if (NW_STAT_IS_FAILURE(s)) {
       
   710           return s;
       
   711         }
       
   712       }
       
   713     }
       
   714   }
       
   715   return NW_STAT_SUCCESS;
       
   716 }
       
   717 
       
   718 EXPORT_C
       
   719 NW_Status_t
       
   720 NW_WBXML_Writer_AttributeAndValue(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
       
   721                                   NW_Uint32 nameCharCount, NW_Uint8* pName,
       
   722                                   NW_Uint32 valueCharCount, NW_Uint32 valueByteCount,
       
   723                                   NW_Uint8* pValue)
       
   724 {
       
   725   NW_Uint32 cp_cnt = 0;
       
   726   return NW_WBXML_Writer_AttributeAndValue2(pW, encoding, nameCharCount, pName, valueCharCount, 
       
   727                                   valueByteCount, pValue, &cp_cnt);
       
   728 
       
   729 }
       
   730 
       
   731 NW_Status_t
       
   732 NW_WBXML_Writer_AttributeNameString(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
       
   733                                     NW_Uint32 nameCharCount,
       
   734                                     NW_Uint32 nameByteCount, NW_Uint8* pName)
       
   735 {
       
   736   NW_Status_t s;
       
   737   NW_Uint16 fqToken;
       
   738 
       
   739   (void) nameByteCount;
       
   740 
       
   741   /* try token */
       
   742   s = NW_WBXML_Dictionary_getAttributeToken2(pW->pAttributeDictionary,
       
   743                                              encoding, nameCharCount,
       
   744                                              pName, &fqToken,
       
   745                                              NW_TRUE /* isName */);
       
   746   if (NW_STAT_IS_SUCCESS(s)) {
       
   747     return NW_WBXML_Writer_AttributeToken(pW, fqToken);
       
   748   }
       
   749 
       
   750   /* try string table */
       
   751   if (pW->addToStringTable != NULL) {
       
   752     s = NW_WBXML_Writer_StringTableLiteral2(pW, nameCharCount, pName, encoding);
       
   753     return s;
       
   754     
       
   755   }
       
   756   /* no token, no string table so try unknown token */
       
   757   s = NW_WBXML_Dictionary_getAttributeToken2(pW->pAttributeDictionary,
       
   758                                              zzzunknownEncoding,
       
   759                                              zzzunknownCharCount,
       
   760                                              (NW_Uint8*)&zzzunknown[0],
       
   761                                              &fqToken,
       
   762                                              NW_TRUE /* isName */);
       
   763   if (NW_STAT_IS_SUCCESS(s)) {
       
   764     return NW_WBXML_Writer_AttributeToken(pW, fqToken);
       
   765   }
       
   766   NW_ASSERT(NW_STAT_IS_SUCCESS(s)); /* force debug to stop here */
       
   767   return NW_STAT_FAILURE;
       
   768 }
       
   769 
       
   770 NW_Status_t
       
   771 NW_WBXML_Writer_AttributeToken(NW_WBXML_Writer_t* pW,
       
   772                                NW_Uint16 fqToken)
       
   773 
       
   774 {
       
   775   NW_Status_t s;
       
   776   NW_Uint8 token;
       
   777   NW_Uint8 page;
       
   778   NW_Bool switched = NW_FALSE;
       
   779 
       
   780   token = NW_WBXML_Dictionary_extractToken(fqToken);
       
   781   page =  NW_WBXML_Dictionary_extractPage(fqToken);
       
   782 
       
   783   s = NW_WBXML_Writer_MaybeSwitchPage(pW, page, NW_WBXML_ATTRIBUTE, &switched);
       
   784   if (NW_STAT_IS_FAILURE(s)) {
       
   785     return s;
       
   786   }
       
   787   return NW_WBXML_Writer_Memcpy(pW, &token, 1); /* attribute token */
       
   788 }
       
   789 
       
   790 NW_Status_t
       
   791 NW_WBXML_Writer_Entity(NW_WBXML_Writer_t* pW,
       
   792                        NW_Uint32 entity)
       
   793 {
       
   794   NW_Status_t s;
       
   795   static const NW_Uint8 entityToken = NW_WBXML_ENTITY;
       
   796 
       
   797   s = NW_WBXML_Writer_Memcpy(pW, &entityToken, 1);
       
   798   if (NW_STAT_IS_FAILURE(s)) {
       
   799     return s;
       
   800   }
       
   801   return NW_WBXML_Writer_Multibyte(pW, entity);
       
   802 }
       
   803 
       
   804 /*
       
   805 This is a helper function for the EXT_T_[0,1,2] forms for these extensions.
       
   806 */
       
   807 NW_Status_t
       
   808 NW_WBXML_Writer_ExtensionUseStringTable(NW_WBXML_Writer_t* pW,
       
   809                                         NW_Uint16 fqToken,
       
   810                                         NW_Uint32 byteCount,
       
   811                                         NW_Uint8* pBuf)
       
   812 {
       
   813   NW_Uint32 tableIndex;
       
   814   NW_Status_t s;
       
   815 
       
   816   if (pW->addToStringTable != NULL) {
       
   817     s = (*pW->addToStringTable)(pW->pStringTableObject,
       
   818                                 byteCount, pBuf, &tableIndex);
       
   819     if (NW_STAT_IS_SUCCESS(s)) {
       
   820       return NW_WBXML_Writer_Extension(pW, fqToken, tableIndex, 0, NULL);
       
   821     }
       
   822   }
       
   823   return NW_STAT_FAILURE;
       
   824 }
       
   825 
       
   826 /*
       
   827 There are three type of extensions:
       
   828 
       
   829 1. one of three possible single byte tokens
       
   830      NW_WBXML_EXT_[0,1,2]
       
   831 2. an extension token followed by a multibyte encoded NW_Uint32 value
       
   832      NW_WBXML_EXT_T_[0,1,2] multibyte(anonymousValue)
       
   833 3. an extension token followed by an in-line string
       
   834      NW_WBXML_EXT_I_[0,1,2] null-terminated-string
       
   835 
       
   836 This function handles all three cases so you have to pass the appropriate
       
   837 arguments for each case:
       
   838 
       
   839 1. fqToken should be one of NW_WBXML_EXT_[0,1,2] (with any page value)
       
   840    and anonymousValue, byteCount and pBuf should be 0 or NULL
       
   841 
       
   842 2. fqToken should be one of NW_WBXML_EXT_T_[0,1,2] (with any page value),
       
   843    anonymousValue should be the value to multibyte encode
       
   844    and byteCount and pBuf should be 0 and NULL
       
   845 
       
   846 3. fqToken should be one of NW_WBXML_EXT_I_[0,1,2] (with any page value),
       
   847    byteCount should be the byte length of the null terminated string
       
   848    pointed to by pBuf
       
   849    and anonymousValue is ignored
       
   850 */
       
   851 NW_Status_t
       
   852 NW_WBXML_Writer_Extension(NW_WBXML_Writer_t* pW,
       
   853                           NW_Uint16 fqToken,
       
   854                           NW_Uint32 anonymousValue,
       
   855                           NW_Uint32 byteCount,
       
   856                           NW_Uint8* pBuf)
       
   857 {
       
   858   NW_Status_t s;
       
   859   NW_Uint8 token = (NW_Uint8)(fqToken & NW_WBXML_MASK_TOKEN);
       
   860 
       
   861   s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   862   if (NW_STAT_IS_FAILURE(s)) {
       
   863     return s;
       
   864   }
       
   865 
       
   866   switch (token) {
       
   867   case NW_WBXML_EXT_0:
       
   868   case NW_WBXML_EXT_1:
       
   869   case NW_WBXML_EXT_2:
       
   870     NW_ASSERT(byteCount == 0);
       
   871     NW_ASSERT(pBuf == NULL);
       
   872     break;
       
   873   case NW_WBXML_EXT_T_0:
       
   874   case NW_WBXML_EXT_T_1:
       
   875   case NW_WBXML_EXT_T_2:
       
   876     NW_ASSERT(byteCount == 0);
       
   877     NW_ASSERT(pBuf == NULL);
       
   878     s = NW_WBXML_Writer_Multibyte(pW, anonymousValue);
       
   879     break;
       
   880   case NW_WBXML_EXT_I_0:
       
   881   case NW_WBXML_EXT_I_1:
       
   882   case NW_WBXML_EXT_I_2:
       
   883     NW_ASSERT(byteCount > 0);
       
   884     NW_ASSERT(pBuf != NULL);
       
   885     s = NW_WBXML_Writer_Memcpy(pW, pBuf, byteCount);
       
   886     break;
       
   887   default:
       
   888     NW_ASSERT(!"wrong token");
       
   889     return NW_STAT_FAILURE;
       
   890   }
       
   891   return s;
       
   892 }
       
   893 
       
   894 EXPORT_C
       
   895 NW_Status_t
       
   896 NW_WBXML_Writer_Opaque(NW_WBXML_Writer_t* pW, NW_Uint32 byteCount,
       
   897                        NW_Uint8* pBuf)
       
   898 {
       
   899   NW_Status_t s;
       
   900   NW_Uint8 token = NW_WBXML_OPAQUE; /* global so on all code pages */
       
   901   s = NW_WBXML_Writer_Memcpy(pW, &token, 1);
       
   902   if (NW_STAT_IS_FAILURE(s)) {
       
   903     return s;
       
   904   }
       
   905   s = NW_WBXML_Writer_Multibyte(pW, byteCount);
       
   906   if (NW_STAT_IS_FAILURE(s)) {
       
   907     return s;
       
   908   }
       
   909   s = NW_WBXML_Writer_Memcpy(pW, pBuf, byteCount);
       
   910   return s;
       
   911 }
       
   912 
       
   913 EXPORT_C
       
   914 NW_Status_t
       
   915 NW_WBXML_Writer_Text(NW_WBXML_Writer_t* pW, NW_Uint32 encoding,
       
   916                      NW_Uint32 byteCount, const NW_Uint8* pText)
       
   917 {
       
   918   NW_Status_t s;
       
   919   NW_Bool found = 0;
       
   920 
       
   921   /* try string table */
       
   922   s = NW_WBXML_Writer_StringTableLiteral(pW, byteCount, pText, &found);
       
   923   if (NW_STAT_IS_FAILURE(s) || found) {
       
   924     return s;
       
   925   }
       
   926   /* back off to inline string */
       
   927   return NW_WBXML_Writer_InlineString(pW, encoding, byteCount, pText);
       
   928 }
       
   929 
       
   930 EXPORT_C
       
   931 NW_Status_t
       
   932 NW_WBXML_Writer_PI(NW_WBXML_Writer_t* pW)
       
   933 {
       
   934   NW_Uint8 piToken = 0x43; /* global, so on all code pages */
       
   935   return NW_WBXML_Writer_Memcpy(pW, &piToken, 1);
       
   936 }
       
   937 
       
   938 
       
   939 EXPORT_C
       
   940 NW_Status_t
       
   941 NW_WBXML_Writer_End(NW_WBXML_Writer_t* pW)
       
   942 {
       
   943   NW_Uint8 endToken = NW_WBXML_END; /* global, so on all code pages */
       
   944   return NW_WBXML_Writer_Memcpy(pW, &endToken, 1);
       
   945 }
       
   946 
       
   947 EXPORT_C
       
   948 void
       
   949 NW_WBXML_Writer_Initialize(NW_WBXML_Writer_t* pW,
       
   950                            NW_Uint32 byteCount, NW_Uint8* pBuf,
       
   951                            NW_WBXML_Writer_GrowBuf_t growBufCallback,
       
   952                            NW_WBXML_Dictionary_t* pTagDictionary,
       
   953                            NW_WBXML_Dictionary_t* pAttributeDictionary,
       
   954                            NW_WBXML_Writer_GetStringTableOffset_t getStringTableOffset,
       
   955                            NW_WBXML_Writer_AddToStringTable_t addToStringTable,
       
   956                            void* pStringTableObject,
       
   957                            NW_WBXML_Writer_StringTableIterateInit_t stringTableIterateInit,
       
   958                            NW_WBXML_Writer_StringTableIterateNext_t stringTableIterateNext,
       
   959                            NW_Bool sizing)
       
   960 {
       
   961   pW->index = 0;
       
   962   pW->byteCount = byteCount;
       
   963   pW->pBuf = pBuf;
       
   964   pW->growBufCallback = growBufCallback;
       
   965   pW->pTagDictionary = pTagDictionary;
       
   966   pW->pAttributeDictionary = pAttributeDictionary;
       
   967   pW->getStringTableOffset = getStringTableOffset;
       
   968   pW->addToStringTable = addToStringTable;
       
   969   pW->pStringTableObject = pStringTableObject;
       
   970   pW->stringTableIterateInit = stringTableIterateInit;
       
   971   pW->stringTableIterateNext = stringTableIterateNext;
       
   972   pW->tagCodePage = 0;
       
   973   pW->attributeCodePage = 0;
       
   974   pW->sizing = sizing;
       
   975   //WLIU_DEBUG: pW->cp_count = 0;
       
   976 }
       
   977 
       
   978 void
       
   979 NW_WBXML_Writer_SetToSizing(NW_WBXML_Writer_t* pW)
       
   980 {
       
   981   pW->index = 0;
       
   982   pW->tagCodePage = 0;  /* TBD BUG ? will this give correct code pages */
       
   983   pW->attributeCodePage = 0;/* TBD BUG ? will this give correct code pages */
       
   984   pW->sizing = 1;
       
   985   // WLIU_DEBUG: pW->cp_count = 0;
       
   986 }
       
   987 
       
   988 
       
   989 void
       
   990 NW_WBXML_Writer_SetToWrite(NW_WBXML_Writer_t* pW, NW_Uint32 byteCount, NW_Uint8* pBuf)
       
   991 {
       
   992   pW->index = 0;
       
   993   pW->byteCount = byteCount;
       
   994   pW->pBuf = pBuf;
       
   995   pW->tagCodePage = 0;  /* TBD BUG ? will this give correct code pages */
       
   996   pW->attributeCodePage = 0;/* TBD BUG ? will this give correct code pages */
       
   997   pW->sizing = 0;
       
   998   // WLIU_DEBUG: pW->cp_count = 0;
       
   999 }