xml/cxmllibrary/src/wbxmlp/src/parse_logic.cpp
branchRCL_3
changeset 32 889504eac4fb
equal deleted inserted replaced
31:6bcc0aa4be39 32:889504eac4fb
       
     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 /*****************************************************************
       
    20 **  File: wbxml_parse_logic.c
       
    21 **
       
    22 **  Description:
       
    23 *
       
    24 * Here is the main parser logic. None of these functions has
       
    25 * any knowlege of how wbxml is stored or read, so they should
       
    26 * work as well with a buffer, stream or file based parser. These
       
    27 * functions require some implementation of the "parser reader
       
    28 * interface" as defined in wbxml_reader.h.
       
    29 *
       
    30 *****************************************************************/
       
    31 
       
    32 #include "cxml_internal.h"
       
    33 #include <xml/cxml/nw_wbxml_token.h>
       
    34 #include <xml/cxml/nw_wbxml_dictionary.h>
       
    35 #include <xml/cxml/nw_wbxml_document.h>
       
    36 #include <xml/cxml/nw_wbxml_event.h>
       
    37 #include <xml/cxml/nw_wbxml_reader.h>
       
    38 #include "nw_wbxml_parsei.h"
       
    39 #include <xml/cxml/nw_string_char.h>
       
    40 
       
    41 #ifndef HTTP_utf_8
       
    42 #define HTTP_utf_8 0x6A
       
    43 #endif
       
    44 
       
    45 #define TOKEN_STATE_TAG         0
       
    46 #define TOKEN_STATE_ATTR        1
       
    47 
       
    48 #define WBXML_MAX_RECURSIVE_CALL_DEPTH 120  /* For parse element only */
       
    49 
       
    50 /* The parser tries to be very strict about errors caused by bad NW_Byte
       
    51  * code, lack of memory, etc. For example, the parser will not read
       
    52  * past the end of the buffer. Callbacks can also set error status to
       
    53  * stop parsing. These will be detected as soon as possible after the
       
    54  * callback returns.  The following method is called with the return
       
    55  * value (NW_Status_t) from the callback functions.  The status is
       
    56  * saved and if it is not NW_STAT_SUCCESS, then the parser's flags
       
    57  * field is updated so that the parser will know that a callback has
       
    58  * raised an exception/error condition. The parser will quit as soon
       
    59  * as it checks the flags.
       
    60  */
       
    61 
       
    62 static void
       
    63 NW_WBXML_Parser_setStatus (NW_WBXML_Parser_t * parser,
       
    64                            NW_Status_t status)
       
    65 {
       
    66   parser->status = status;
       
    67 
       
    68   switch (status)
       
    69   {
       
    70   case NW_STAT_SUCCESS:
       
    71     break;
       
    72   case NW_STAT_OUT_OF_MEMORY:
       
    73     parser->flags |= NW_WBXML_PARSER_NOMEMORY;
       
    74     break;
       
    75   case NW_STAT_WBXML_ERROR_BYTECODE:
       
    76     parser->flags |= NW_WBXML_PARSER_BYTECODEERROR;
       
    77     break;
       
    78   case NW_STAT_WBXML_ERROR_CHARSET_UNSUPPORTED:
       
    79     parser->flags |= NW_WBXML_PARSER_CHARSET_UNSUPPORTED;
       
    80     break;
       
    81   default:
       
    82     parser->flags |= NW_WBXML_PARSER_UNKNOWN_ERROR;
       
    83     break;
       
    84   }
       
    85   return;
       
    86 }
       
    87 
       
    88 /*
       
    89  * Convert the parser's flag status code to a NW_Status_t constant
       
    90  */
       
    91 
       
    92 static NW_Status_t
       
    93 NW_WBXML_Parser_flagToStatus (NW_WBXML_Parser_t * parser)
       
    94 {
       
    95   if (parser->flags & NW_WBXML_PARSER_NOMEMORY)
       
    96     return NW_STAT_OUT_OF_MEMORY;
       
    97 
       
    98   if (parser->flags & NW_WBXML_PARSER_BYTECODEERROR)
       
    99     return NW_STAT_WBXML_ERROR_BYTECODE;
       
   100 
       
   101   if (parser->flags & NW_WBXML_PARSER_CHARSET_UNSUPPORTED)
       
   102     return NW_STAT_WBXML_ERROR_CHARSET_UNSUPPORTED;
       
   103 
       
   104   return parser->status;
       
   105 }
       
   106 
       
   107 
       
   108 #define GET_STATE(parser) ((parser)->state & NW_WBXML_PARSER_S_MASK)
       
   109 #define SET_STATE(parser, st) \
       
   110   ((parser)->state = (~NW_WBXML_PARSER_S_MASK & parser->state) | (st))
       
   111 
       
   112 #define CHECK_PARSER_STATUS \
       
   113   if((parser->flags & NW_WBXML_PARSER_S_MASK) != NW_WBXML_PARSER_OK) \
       
   114     return NW_WBXML_Parser_flagToStatus(parser)
       
   115 
       
   116 
       
   117 /*
       
   118 * Create an uninitialized code page registry. As long as the registry is not
       
   119 * created, it will be ignored. Once it has been created, the parser will check
       
   120 * the REGISTRY_INIT flag. If this is not set, the registry will be initialized
       
   121 * as the parser runs. If this is set, then the registry will be consulted when
       
   122 * updating the offset.
       
   123 */
       
   124 
       
   125 NW_Status_t
       
   126 NW_WBXML_Parser_addCPRegistry(NW_WBXML_Parser_t* parser,
       
   127                               NW_WBXML_CP_Registry_Entry_t* storage,
       
   128                               NW_Int32 count)
       
   129 {
       
   130   NW_ASSERT(parser != NULL);
       
   131   NW_ASSERT(storage != NULL);
       
   132 
       
   133   parser->cp_registry.storage = storage;
       
   134   parser->cp_registry.current = storage;
       
   135   parser->cp_registry.count = count;
       
   136   // WLIU_DEBUG: parser->cp_registry.realcount = 0;
       
   137   parser->state &= ~NW_WBXML_REGISTRY_INIT; /* Make sure flag is not set */
       
   138   return NW_STAT_SUCCESS;
       
   139 }
       
   140 
       
   141 static void
       
   142 NW_WBXML_CPRegistry_addEntry(NW_WBXML_CP_Registry_t *registry ,
       
   143                              NW_Uint8 code_page,
       
   144                              NW_Uint32 offset, /* must point to switch_page token */
       
   145                              NW_Uint8 token_state)
       
   146 {
       
   147   NW_ASSERT(registry != NULL);
       
   148   NW_ASSERT(registry->current < (registry->storage + registry->count));
       
   149 
       
   150   /* ignoring page type (tag or attribute) check that registry is in
       
   151   increasing order of offset so that the algorith in
       
   152   NW_WBXML_CPRegistry_getCodePages() works */
       
   153   NW_ASSERT((registry->current > registry->storage) ?
       
   154             (offset > (registry->current - 1)->start_offset)
       
   155             : 1);
       
   156   /* Each entry must record if it is for tokens or attributes.  A
       
   157   trick to encode this without extra memory relies on the use of two
       
   158   bytes in WBXML to encode a page switch.  With two bytes one has an
       
   159   even offset and one an odd offset.  We pick the even if it is a tag
       
   160   page and the odd offset if it is an attribute page. */
       
   161   if (token_state == TOKEN_STATE_TAG) {
       
   162     if (offset & 1) { /* if it is odd, advance one to make it even */
       
   163       offset++;
       
   164     }
       
   165   } else {
       
   166     NW_ASSERT(token_state == TOKEN_STATE_ATTR);
       
   167     if ((offset & 1) == 0) { /* if it is even, advance one to make it odd */
       
   168       offset++;
       
   169     }
       
   170   }
       
   171   registry->current->start_offset = offset;
       
   172   registry->current->code_page = code_page;
       
   173 
       
   174   //if(registry->current < (registry->storage + registry->count - 1)){
       
   175     registry->current++;
       
   176     // WLIU_DEBUG: registry->realcount++;
       
   177   //
       
   178 }
       
   179 
       
   180 void
       
   181 NW_WBXML_CPRegistry_getCodePages(NW_WBXML_CP_Registry_t* registry,
       
   182                                  NW_Uint32 offset,
       
   183                                  NW_Uint8 *tag_code_page,
       
   184                                  NW_Uint8 *attribute_code_page)
       
   185 {
       
   186   NW_WBXML_CP_Registry_Entry_t* entry;
       
   187 
       
   188   NW_ASSERT(registry != NULL);
       
   189 
       
   190   *tag_code_page = 0;
       
   191   *attribute_code_page = 0;
       
   192   for (entry = registry->storage;
       
   193        entry < (registry->storage + registry->count);
       
   194        entry++){
       
   195     /* assume that the entries are in increasing offset order */
       
   196     NW_ASSERT((entry > registry->storage) ?
       
   197               (entry->start_offset > (entry - 1)->start_offset)
       
   198               : 1);
       
   199 
       
   200     if(offset > entry->start_offset) {
       
   201       if(entry->start_offset & 1) {
       
   202         /* odd offset indicates attributes */
       
   203         *attribute_code_page = entry->code_page;
       
   204       } else {
       
   205         /* even offset indicates tokens */
       
   206         *tag_code_page = entry->code_page;
       
   207       }
       
   208     } else {
       
   209       break; /* early out */
       
   210     }
       
   211   }
       
   212 }
       
   213 
       
   214 
       
   215 /*
       
   216   This function parses "version publicid charset strtbl" which is a
       
   217   sequence that comprises the "header" of a WBXML document.
       
   218 
       
   219   From specification WAP-192-WBXML-20010725-a, Version 1.3, 25 July 2001,
       
   220   section 5.3 BNF for Document Structure:
       
   221 
       
   222   start = version publicid charset strtbl body
       
   223   version = u_int8 // WBXML version number
       
   224   publicid = mb_u_int32 | ( zero index )
       
   225   charset = mb_u_int32
       
   226   strtbl = length *byte
       
   227   length = mb_u_int32
       
   228 
       
   229   The "version" specifies the WBXML specification version. The
       
   230   version byte contains the major version minus one in the upper
       
   231   four bits and the minor version in the lower four bits. For
       
   232   example, the version number 1.3 would be encoded as 0x03.
       
   233 
       
   234   The first form of publicid is a multi-byte positive integer value,
       
   235   greater than zero, representing a well-known XML document type given
       
   236   an assigned value.  See table at section 7.2.1 or try
       
   237   http://www.wapforum.org/wina/wbxml-public-docid.htm
       
   238   Note that 0x01 is used for "unknown or missing public identifier."
       
   239 
       
   240   The second form of publicid begins with a 0 byte followed by a
       
   241   string table index (note that these "index" values are all 0-based
       
   242   byte offsets from the start of the string table).  The entry in the
       
   243   string table encodes the XML document type string.
       
   244 
       
   245   The charset is the multi-byte encoding of the IANA charset MIBenum
       
   246   http://www.iana.org/assignments/character-sets
       
   247 
       
   248   The string table either has length 0, if empty, or the length is the
       
   249   byte count of the string table block not counting the length byte
       
   250   itself.
       
   251 
       
   252   This is what the specification says about "index" as an index into
       
   253   the string table:
       
   254 
       
   255   "Various tokens encode references to the contents of the string
       
   256   table. These references are encoded as scalar byte offsets from the
       
   257   first byte of the first string in the string table. For example, the
       
   258   offset of the first string is zero (0)."
       
   259 
       
   260   So, "index" is a 0-based byte offset from the first byte of the
       
   261   string table.  The first byte of the string table is the one after
       
   262   the multi-byte encoding of the string table length.
       
   263 
       
   264   This function returns one of:
       
   265 
       
   266   NW_STAT_SUCCESS
       
   267   NW_STAT_OUT_OF_MEMORY
       
   268   NW_STAT_WBXML_ERROR_BYTECODE
       
   269 */
       
   270 NW_Status_t
       
   271 NW_WBXML_Parser_docHeaderParse(NW_WBXML_Parser_t* pParser,
       
   272                                NW_WBXML_Document_t* pDoc)
       
   273 {
       
   274   NW_Int32 bytesRead;
       
   275   NW_Uint32 docTypeByteOffset = 0;
       
   276   NW_Status_t substatus;
       
   277   NW_Status_t status = NW_STAT_WBXML_ERROR_BYTECODE;
       
   278 
       
   279   /* this is an internal function where caller should guarantee these */
       
   280   NW_ASSERT(pParser != NULL);
       
   281   NW_ASSERT(pDoc != NULL);
       
   282   NW_ASSERT(GET_STATE(pParser) == NW_WBXML_PARSER_S_START);
       
   283 
       
   284   /* version */
       
   285   pDoc->version = NW_WBXML_Parser_readUint8(pParser);
       
   286   if (NW_WBXML_Parser_advance(pParser, 1) < 0) {
       
   287     goto errorExitHeaderParse;
       
   288   }
       
   289   /* publicid */
       
   290   bytesRead = NW_WBXML_Parser_readMbUint32(pParser, &(pDoc->publicid));
       
   291   if ((bytesRead < 0)
       
   292       || (NW_WBXML_Parser_advance(pParser, bytesRead) < 0)) {
       
   293     goto errorExitHeaderParse;
       
   294   }
       
   295   /* check for publicid second form referencing string table */
       
   296   if (pDoc->publicid == 0) {
       
   297     /* save doctype string table index for after string table is read */
       
   298     bytesRead = NW_WBXML_Parser_readMbUint32(pParser, &docTypeByteOffset);
       
   299     if ((bytesRead < 0)
       
   300         || (NW_WBXML_Parser_advance(pParser, bytesRead) < 0)) {
       
   301       goto errorExitHeaderParse;
       
   302     }
       
   303   }
       
   304 
       
   305  if(pDoc->publicid == 1) //As per WBXML spec, invalid public identifier
       
   306   {
       
   307     return NW_STAT_WMLBROWSER_BAD_CONTENT;
       
   308   }
       
   309 
       
   310   /* charset */
       
   311   if (pDoc->version != 0) {
       
   312     bytesRead = NW_WBXML_Parser_readMbUint32(pParser, &(pDoc->charset));
       
   313     if ((bytesRead < 0)
       
   314         || (NW_WBXML_Parser_advance(pParser, bytesRead) < 0)) {
       
   315       goto errorExitHeaderParse;
       
   316     }
       
   317   } else {
       
   318     /* For WBXML version 1.0, which did not have a charset field in
       
   319        the document header, we hardwire the charset to UTF-8.  This is
       
   320        against the spec which says that the charset should come as
       
   321        side info with the doc (e.g., get charset from the load
       
   322        response), but the API needs to change to support this so
       
   323        rather than reject all version 1.0 docs we accept the UTF-8
       
   324        (includes ASCII but not Latin-1) encoded ones. */
       
   325     pDoc->charset = HTTP_utf_8;
       
   326   }
       
   327   substatus = NW_String_charsetValid(pDoc->charset);
       
   328   if (substatus != NW_STAT_SUCCESS) {
       
   329     status = substatus;
       
   330     goto errorExitHeaderParse;
       
   331   }
       
   332   /* strtbl */
       
   333   substatus = NW_WBXML_Parser_readStringTable(pParser, pDoc,
       
   334                                               &(pDoc->strtbl.data));
       
   335   if (substatus != NW_STAT_SUCCESS) {
       
   336     status = substatus;
       
   337     goto errorExitHeaderParse;
       
   338   }
       
   339 
       
   340   /* record remainder of doc as the body length */
       
   341   pDoc->body_len = pParser->left;
       
   342 
       
   343   /* deal with doctype string, maybe from string table */
       
   344 
       
   345   if(pDoc->doc_type)
       
   346   {
       
   347    NW_String_delete(pDoc->doc_type);
       
   348   }
       
   349 
       
   350   pDoc->doc_type = NULL;
       
   351   if (pDoc->publicid == 0) {
       
   352     /* now that we have the string table, get the doctype string */
       
   353     if ((docTypeByteOffset >= pDoc->strtbl.length)
       
   354         || (!NW_String_valid(pDoc->strtbl.data + docTypeByteOffset,
       
   355                              pDoc->strtbl.length - docTypeByteOffset,
       
   356                              pDoc->charset))) {
       
   357       goto errorExitHeaderParse;
       
   358     }
       
   359     pDoc->doc_type = NW_String_new();
       
   360     if (pDoc->doc_type != NULL) {
       
   361       if (NW_String_initialize(pDoc->doc_type,
       
   362                                pDoc->strtbl.data + docTypeByteOffset,
       
   363                                pDoc->charset) != NW_STAT_SUCCESS) {
       
   364         NW_String_delete(pDoc->doc_type);
       
   365         pDoc->doc_type = NULL;
       
   366         goto errorExitHeaderParse;
       
   367       }
       
   368       /* TBD should now go back and try to fill in the internal "publicId"
       
   369          from the WBXML dictionary to match the docType. */
       
   370     } else {
       
   371       status = NW_STAT_OUT_OF_MEMORY;
       
   372       goto errorExitHeaderParse;
       
   373     }
       
   374   } else {
       
   375     /* doc came with publicid so now fill in the type string. */
       
   376     substatus
       
   377       = NW_WBXML_Dictionary_publicId_to_doctypeString(pDoc->publicid,
       
   378                                                       &(pDoc->doc_type));
       
   379     /* ignore any error other than OOM */
       
   380     if (substatus == NW_STAT_OUT_OF_MEMORY) {
       
   381       status = NW_STAT_OUT_OF_MEMORY;
       
   382       goto errorExitHeaderParse;
       
   383     }
       
   384   }
       
   385   SET_STATE(pParser, NW_WBXML_PARSER_S_HEADER);
       
   386   pParser->doc = pDoc;
       
   387   status = NW_STAT_SUCCESS;
       
   388  errorExitHeaderParse:
       
   389   return status;
       
   390 }
       
   391 
       
   392 /*
       
   393  * Save/restore context can be used if the parser is to be invoked
       
   394  * reentrantly (in a callback).  Normally this should be avoided since
       
   395  * the only really safe way to do this is to save the whole parser
       
   396  * object on the stack. This uses a lot of space!
       
   397  */
       
   398 
       
   399 NW_Status_t
       
   400 NW_WBXML_Parser_saveContext(NW_WBXML_Parser_t *parser,
       
   401                             NW_WBXML_Parser_t *context)
       
   402 {
       
   403   NW_ASSERT(parser != NULL);
       
   404   NW_ASSERT(context != NULL);
       
   405 
       
   406   NW_Mem_memcpy(context, parser, sizeof(*parser));
       
   407   return NW_STAT_SUCCESS;
       
   408 }
       
   409 
       
   410 NW_Status_t
       
   411 NW_WBXML_Parser_restoreContext(NW_WBXML_Parser_t *parser,
       
   412                                NW_WBXML_Parser_t *context)
       
   413 {
       
   414   NW_ASSERT(parser != NULL);
       
   415   NW_ASSERT(context != NULL);
       
   416 
       
   417   NW_Mem_memcpy(parser, context, sizeof(*parser));
       
   418   return NW_STAT_SUCCESS;
       
   419 }
       
   420 
       
   421 NW_Status_t
       
   422 NW_WBXML_Parser_setTagCodepage(NW_WBXML_Parser_t *parser,
       
   423                                NW_Uint8 page)
       
   424 {
       
   425   NW_ASSERT(parser != NULL);
       
   426 
       
   427   parser->tag_code_page = page;
       
   428   return NW_STAT_SUCCESS;
       
   429 }
       
   430 
       
   431 NW_Uint8
       
   432 NW_WBXML_Parser_getTagCodepage(NW_WBXML_Parser_t *parser)
       
   433 {
       
   434   NW_ASSERT(parser != NULL);
       
   435 
       
   436   return parser->tag_code_page;
       
   437 }
       
   438 
       
   439 NW_Status_t
       
   440 NW_WBXML_Parser_setAttrCodepage(NW_WBXML_Parser_t *parser,
       
   441                                 NW_Uint8 page)
       
   442 {
       
   443   NW_ASSERT(parser != NULL);
       
   444 
       
   445   parser->attribute_code_page = page;
       
   446   return NW_STAT_SUCCESS;
       
   447 }
       
   448 
       
   449 NW_Uint8
       
   450 NW_WBXML_Parser_getAttrCodepage(NW_WBXML_Parser_t *parser)
       
   451 {
       
   452   NW_ASSERT(parser != NULL);
       
   453 
       
   454   return parser->attribute_code_page;
       
   455 }
       
   456 
       
   457 /*
       
   458 * Turn an eight bit token into a fully qualified 32 bit token depending
       
   459 * on the parser state.
       
   460 */
       
   461 
       
   462 static
       
   463 NW_Uint32
       
   464 FqToken (NW_WBXML_Parser_t * parser,
       
   465          NW_Uint8 token,
       
   466          NW_Int32 token_state)
       
   467 {
       
   468   NW_Uint32 fq_token = token;
       
   469 
       
   470   NW_ASSERT(parser != NULL);
       
   471 
       
   472   fq_token |= (parser->dictionary << 16);
       
   473   if (token_state == TOKEN_STATE_ATTR) {
       
   474     fq_token |=
       
   475       ((parser->attribute_code_page << 8) | NW_WBXML_CP_STATE_ATTR);
       
   476   } else {
       
   477     fq_token |= ((parser->tag_code_page << 8) | NW_WBXML_CP_STATE_TAG);
       
   478   }
       
   479   return fq_token;
       
   480 }
       
   481 
       
   482 
       
   483 /* Invoke callbacks */
       
   484 
       
   485 /* The callback wrappers use the parser flags to implement an
       
   486  * "exception" mechanism. If a callback returns a non-OK status, the
       
   487  * parser will detect this as soon as possible and stop what
       
   488  * it is doing.
       
   489  */
       
   490 
       
   491 /* Handle state callbacks */
       
   492 
       
   493 static
       
   494 void
       
   495 Handle_Pi(NW_WBXML_Parser_t *parser)
       
   496 {
       
   497   NW_Status_t status;
       
   498   if ((parser->handler) && (parser->handler->Pi_CB)){
       
   499     status = (*(parser->handler->Pi_CB)) (parser, parser->context);
       
   500     NW_WBXML_Parser_setStatus (parser, status);
       
   501   }
       
   502 }
       
   503 
       
   504 static
       
   505 void
       
   506 Handle_Pi_End(NW_WBXML_Parser_t *parser)
       
   507 {
       
   508   NW_Status_t status;
       
   509   if ((parser->handler) && (parser->handler->Pi_End_CB)){
       
   510     status = (*(parser->handler->Pi_End_CB)) (parser, parser->context);
       
   511     NW_WBXML_Parser_setStatus (parser, status);
       
   512   }
       
   513 }
       
   514 
       
   515 static
       
   516 void
       
   517 Handle_Tag_Start(NW_WBXML_Parser_t *parser)
       
   518 {
       
   519   NW_Status_t status;
       
   520   if ((parser->handler) && (parser->handler->Tag_Start_CB)){
       
   521     status = (*(parser->handler->Tag_Start_CB)) (parser, parser->context);
       
   522     NW_WBXML_Parser_setStatus (parser, status);
       
   523   }
       
   524 }
       
   525 
       
   526 static
       
   527 void
       
   528 Handle_Tag_End(NW_WBXML_Parser_t *parser)
       
   529 {
       
   530   NW_Status_t status;
       
   531   if ((parser->handler) && (parser->handler->Tag_End_CB)){
       
   532     status = (*(parser->handler->Tag_End_CB)) (parser, parser->context);
       
   533     NW_WBXML_Parser_setStatus (parser, status);
       
   534   }
       
   535 }
       
   536 
       
   537 static
       
   538 void
       
   539 Handle_Attr_Start(NW_WBXML_Parser_t *parser)
       
   540 {
       
   541   NW_Status_t status;
       
   542   if ((parser->handler) && (parser->handler->Attr_Start_CB)){
       
   543     status = (*(parser->handler->Attr_Start_CB)) (parser, parser->context);
       
   544     NW_WBXML_Parser_setStatus (parser, status);
       
   545   }
       
   546 }
       
   547 
       
   548 static
       
   549 void
       
   550 Handle_Attr_Val(NW_WBXML_Parser_t *parser)
       
   551 {
       
   552   NW_Status_t status;
       
   553   if ((parser->handler) && (parser->handler->Attr_Val_CB)){
       
   554     status = (*(parser->handler->Attr_Val_CB)) (parser, parser->context);
       
   555     NW_WBXML_Parser_setStatus (parser, status);
       
   556   }
       
   557 }
       
   558 
       
   559 static
       
   560 void
       
   561 Handle_Content(NW_WBXML_Parser_t *parser)
       
   562 {
       
   563   NW_Status_t status;
       
   564   if ((parser->handler) && (parser->handler->Content_CB)){
       
   565     status = (*(parser->handler->Content_CB)) (parser, parser->context);
       
   566     NW_WBXML_Parser_setStatus (parser, status);
       
   567   }
       
   568 }
       
   569 
       
   570 static
       
   571 void
       
   572 Handle_Codepage(NW_WBXML_Parser_t *parser)
       
   573 {
       
   574   NW_Status_t status;
       
   575   if ((parser->handler) && (parser->handler->CodePage_CB)){
       
   576     status = (*(parser->handler->CodePage_CB)) (parser, parser->context);
       
   577     NW_WBXML_Parser_setStatus (parser, status);
       
   578   }
       
   579 }
       
   580 
       
   581 static
       
   582 void
       
   583 Handle_Extension(NW_WBXML_Parser_t *parser)
       
   584 {
       
   585   NW_Status_t status;
       
   586   if ((parser->handler) && (parser->handler->Extension_CB)){
       
   587     status = (*(parser->handler->Extension_CB)) (parser, parser->context);
       
   588     NW_WBXML_Parser_setStatus (parser, status);
       
   589   }
       
   590 }
       
   591 
       
   592 /* Handle data type callbacks */
       
   593 
       
   594 static
       
   595 void
       
   596 Handle_Fq_Token(NW_WBXML_Parser_t *parser,
       
   597                 NW_Uint32 token)
       
   598 {
       
   599   NW_Status_t status;
       
   600   if ((parser->handler) && (parser->handler->FQToken_CB)){
       
   601     status = (*(parser->handler->FQToken_CB)) (parser, token, parser->context);
       
   602     NW_WBXML_Parser_setStatus (parser, status);
       
   603   }
       
   604 }
       
   605 
       
   606 static
       
   607 void
       
   608 Handle_Inline_String(NW_WBXML_Parser_t *parser,
       
   609                      NW_Uint32 len)
       
   610 {
       
   611   NW_Status_t status;
       
   612   if ((parser->handler) && (parser->handler->InlineString_CB)){
       
   613     status = (*(parser->handler->InlineString_CB)) (parser, len,
       
   614                                                     parser->context);
       
   615     
       
   616         NW_WBXML_Parser_setStatus (parser, status);
       
   617  } 
       
   618 }
       
   619 
       
   620 static
       
   621 void
       
   622 Handle_Table_String(NW_WBXML_Parser_t *parser,
       
   623                     NW_Uint32 index)
       
   624 {
       
   625   NW_Status_t status;
       
   626   if ((parser->handler) && (parser->handler->TableString_CB)){
       
   627     status = (*(parser->handler->TableString_CB)) (parser, index,
       
   628                                                    parser->context);
       
   629     NW_WBXML_Parser_setStatus (parser, status);
       
   630   }
       
   631 }
       
   632 
       
   633 static
       
   634 void
       
   635 Handle_Binary(NW_WBXML_Parser_t *parser,
       
   636               NW_Uint32 value)
       
   637 {
       
   638   NW_Status_t status;
       
   639   if ((parser->handler) && (parser->handler->Binary_CB)){
       
   640     status = (*(parser->handler->Binary_CB)) (parser, value, parser->context);
       
   641     NW_WBXML_Parser_setStatus (parser, status);
       
   642   }
       
   643 }
       
   644 
       
   645 static
       
   646 void
       
   647 Handle_Opaque(NW_WBXML_Parser_t *parser,
       
   648               NW_Uint32 len)
       
   649 {
       
   650   NW_Status_t status;
       
   651   if ((parser->handler) && (parser->handler->Opaque_CB)){
       
   652     status = (*(parser->handler->Opaque_CB)) (parser, len, parser->context);
       
   653     NW_WBXML_Parser_setStatus (parser, status);
       
   654   }
       
   655 }
       
   656 
       
   657 static
       
   658 void
       
   659 Handle_Entity(NW_WBXML_Parser_t *parser,
       
   660               NW_Uint32 e)
       
   661 {
       
   662   NW_Status_t status;
       
   663   if ((parser->handler) && (parser->handler->Entity_CB)){
       
   664     status = (*(parser->handler->Entity_CB)) (parser, e, parser->context);
       
   665     NW_WBXML_Parser_setStatus (parser, status);
       
   666   }
       
   667 }
       
   668 
       
   669 /*
       
   670 * Safely get the next token, checking for switch pages along the way.
       
   671 * While this does advance past any switch pages, it DOES NOT advance
       
   672 * past the returned token.
       
   673 */
       
   674 
       
   675 static
       
   676 NW_Status_t
       
   677 NW_WBXML_Parser_getNextToken (NW_WBXML_Parser_t * parser,
       
   678                               NW_Uint8 * token,
       
   679                               NW_Int32 token_state)
       
   680 {
       
   681 
       
   682   NW_ASSERT(parser != NULL);
       
   683 
       
   684   if (!NW_WBXML_Parser_hasMoreBytecode (parser)) {
       
   685     return NW_STAT_WBXML_ERROR_BYTECODE;
       
   686   }
       
   687 
       
   688   while ((*token = NW_WBXML_Parser_readUint8 (parser)) ==
       
   689          NW_WBXML_SWITCH_PAGE)
       
   690   {
       
   691     if (NW_WBXML_Parser_advance (parser, 1) < 0){
       
   692       return NW_STAT_WBXML_ERROR_BYTECODE;
       
   693     }
       
   694     if (!NW_WBXML_Parser_hasMoreBytecode (parser)) {
       
   695       return NW_STAT_WBXML_ERROR_BYTECODE;
       
   696     }
       
   697 
       
   698     if (token_state == TOKEN_STATE_TAG){
       
   699       parser->tag_code_page = NW_WBXML_Parser_readUint8 (parser);
       
   700     } else {
       
   701       parser->attribute_code_page = NW_WBXML_Parser_readUint8 (parser);
       
   702     }
       
   703 
       
   704     if((parser->cp_registry.count > 0)
       
   705       && ((parser->flags & NW_WBXML_REGISTRY_INIT) != NW_WBXML_REGISTRY_INIT)){
       
   706       NW_ASSERT(parser->offset > 0);
       
   707       /* We have a registry but we haven't finished initing it yet */
       
   708       // WLIU_DEBUG: RFileLogger::WriteFormat(_L("Browser"), _L("cp_count.txt"), EFileLoggingModeAppend, _L("=== cp_count: %x, pW->index: %x \n"), parser->cp_registry.realcount +1, parser->offset - parser->lastValid);
       
   709       NW_WBXML_CPRegistry_addEntry(&(parser->cp_registry),
       
   710                                    NW_WBXML_Parser_readUint8(parser),
       
   711                                    /* must use switch page token position */
       
   712                                    parser->offset - 1,
       
   713                                    (NW_Uint8)token_state);
       
   714     }
       
   715 
       
   716     Handle_Codepage(parser);
       
   717 
       
   718     if (NW_WBXML_Parser_advance (parser, 1) < 0){
       
   719       return NW_STAT_WBXML_ERROR_BYTECODE;
       
   720     }
       
   721     if (!NW_WBXML_Parser_hasMoreBytecode (parser)) {
       
   722       return NW_STAT_WBXML_ERROR_BYTECODE;
       
   723     }
       
   724   }
       
   725   return NW_STAT_SUCCESS;
       
   726 }
       
   727 
       
   728 /*
       
   729  * Element parsing methods: The parser is made up of a set of methods
       
   730  * that know how to parse individual elements of the wbxml source. For
       
   731  * elements that repeat, these are implemented in iterators. Building
       
   732  * the parser from a set of element parsers and iterators makes it
       
   733  * simple to use the parser as a deserializer for wbxml elements.
       
   734  */
       
   735 
       
   736 #define HAS_CONTENT(t)    ((t)&NW_WBXML_FLAGS_CONTENT)
       
   737 #define HAS_ATTRIBUTES(t) ((t)&NW_WBXML_FLAGS_ATTRIBUTES)
       
   738 
       
   739 /*
       
   740 * Parse the token and name part of a tag. This generates a fully
       
   741 * qualified token.
       
   742 */
       
   743 
       
   744 NW_Status_t
       
   745 NW_WBXML_Parser_tagNameParse(NW_WBXML_Parser_t *parser)
       
   746 {
       
   747   NW_Uint8 token;
       
   748   NW_Int32 ilen;
       
   749   NW_Uint32 index;
       
   750   NW_Uint32 fq_token;
       
   751   NW_Status_t status;
       
   752 
       
   753   NW_ASSERT(parser != NULL);
       
   754 
       
   755   Handle_Tag_Start(parser);
       
   756 
       
   757   CHECK_PARSER_STATUS;
       
   758 
       
   759   status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_TAG);
       
   760   if(status != NW_STAT_SUCCESS){
       
   761     return status;
       
   762   }
       
   763 
       
   764   fq_token = FqToken (parser, token, TOKEN_STATE_TAG);
       
   765   Handle_Fq_Token(parser, fq_token);
       
   766 
       
   767   if (HAS_CONTENT(fq_token) || HAS_ATTRIBUTES(fq_token) ||
       
   768       (NW_WBXML_Parser_hasMoreBytecode (parser)))
       
   769   {
       
   770     if (NW_WBXML_Parser_advance (parser, 1) < 0){
       
   771         return NW_STAT_WBXML_ERROR_BYTECODE;
       
   772     }
       
   773   }
       
   774 
       
   775   /*
       
   776    * Note that while the spec defines tokens for literal tags with
       
   777    * and without attributes and content, they are just
       
   778    * NW_WBXML_LITERAL with the content and/or attributes flags
       
   779    * set. So ...
       
   780    */
       
   781 
       
   782   if ((token & NW_WBXML_MASK_TAG_ID) == NW_WBXML_LITERAL){
       
   783 
       
   784   /*
       
   785    * TODO:  Should check for another global token
       
   786    * and return an error?
       
   787    */
       
   788 
       
   789     ilen = NW_WBXML_Parser_readMbUint32 (parser, &index);
       
   790     if(ilen < 0){
       
   791       return NW_STAT_WBXML_ERROR_BYTECODE;
       
   792     }
       
   793 
       
   794     Handle_Table_String(parser, index);
       
   795 
       
   796     if(NW_WBXML_Parser_advance(parser, ilen) < 0){
       
   797       return NW_STAT_WBXML_ERROR_BYTECODE;
       
   798     }
       
   799   }
       
   800 
       
   801   if (HAS_ATTRIBUTES (fq_token)){   /* Has attributes, possibly content */
       
   802     status = NW_STAT_WBXML_HAS_ATTRIBUTES;
       
   803     if (HAS_CONTENT (fq_token)){
       
   804       status = NW_STAT_WBXML_HAS_ATTR_CONTENT;
       
   805     }
       
   806   }
       
   807 
       
   808   else if (HAS_CONTENT (fq_token)){ /* Has content, no attributes */
       
   809     status = NW_STAT_WBXML_HAS_CONTENT;
       
   810   }
       
   811 
       
   812   else{                             /* No attributes, no content */
       
   813     status = NW_STAT_SUCCESS;
       
   814     Handle_Tag_End(parser);
       
   815   }
       
   816 
       
   817   return status;
       
   818 }
       
   819 
       
   820 /* Parse an attribute list */
       
   821 
       
   822 NW_Status_t
       
   823 NW_WBXML_Parser_attributeListIterate(NW_WBXML_Parser_t *parser)
       
   824 {
       
   825   NW_Uint8 token;
       
   826   NW_Status_t status;
       
   827 
       
   828   NW_ASSERT(parser != NULL);
       
   829 
       
   830   status = NW_WBXML_Parser_attributeParse (parser);
       
   831   if(status != NW_STAT_SUCCESS){
       
   832     return status;
       
   833   }
       
   834 
       
   835   status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_ATTR);
       
   836   if(status != NW_STAT_SUCCESS){
       
   837     return status;
       
   838   }
       
   839 
       
   840   if (token == NW_WBXML_END){
       
   841     return NW_STAT_WBXML_ITERATE_DONE;
       
   842   }
       
   843   return NW_STAT_WBXML_ITERATE_MORE;
       
   844 }
       
   845 
       
   846 static
       
   847 NW_Status_t
       
   848 NW_WBXML_Parser_attributeListParse(NW_WBXML_Parser_t *parser)
       
   849 {
       
   850   NW_Status_t status;
       
   851 
       
   852   /* Run the attribute list iterator till it completes */
       
   853 
       
   854   while ((parser->flags & NW_WBXML_PARSER_S_MASK) == NW_WBXML_PARSER_OK){
       
   855     status = NW_WBXML_Parser_attributeListIterate(parser);
       
   856     if(status == NW_STAT_WBXML_ITERATE_DONE){
       
   857       return NW_STAT_SUCCESS;
       
   858     }
       
   859     if(status != NW_STAT_WBXML_ITERATE_MORE){
       
   860       return status;
       
   861     }
       
   862   }
       
   863   return NW_WBXML_Parser_flagToStatus(parser);
       
   864 }
       
   865 
       
   866 /*
       
   867 * Parse a processing instruction
       
   868 */
       
   869 static
       
   870 NW_Status_t
       
   871 NW_WBXML_Parser_piParse (NW_WBXML_Parser_t * parser,
       
   872                          NW_Int32 token_state)
       
   873 {
       
   874 
       
   875   NW_Uint8 token;
       
   876   NW_Status_t status;
       
   877 
       
   878   status = NW_WBXML_Parser_getNextToken (parser, &token, token_state);
       
   879   if(status != NW_STAT_SUCCESS){
       
   880     return status;
       
   881   }
       
   882 
       
   883   switch (token){
       
   884   case NW_WBXML_PI:
       
   885     Handle_Pi(parser);
       
   886     /*
       
   887     * Advance past the PI token and then get the PI's
       
   888     * target and value
       
   889     */
       
   890     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
   891       return NW_STAT_WBXML_ERROR_BYTECODE;
       
   892     }
       
   893     status = NW_WBXML_Parser_attributeParse (parser);
       
   894     if(status != NW_STAT_SUCCESS){
       
   895       return status;
       
   896     }
       
   897     /* Advance past the PI's end token */
       
   898     status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_ATTR);
       
   899     if(status != NW_STAT_SUCCESS){
       
   900       return status;
       
   901     }
       
   902     if (token == NW_WBXML_END){
       
   903       Handle_Pi_End(parser);
       
   904       /*
       
   905        * Must advance the reader past the end token but since this
       
   906        * PI may be the last NW_Byte in the bytecode, first check to see
       
   907        * if there is any bytecode left.
       
   908        */
       
   909       if (NW_WBXML_Parser_hasMoreBytecode (parser)){
       
   910         NW_WBXML_Parser_advance (parser, 1);
       
   911       }
       
   912     }
       
   913     else
       
   914       return NW_STAT_WBXML_ERROR_BYTECODE;
       
   915     break;
       
   916   default:
       
   917     return NW_STAT_WBXML_ERROR_BYTECODE;
       
   918   }
       
   919   return NW_STAT_SUCCESS;
       
   920 }
       
   921 
       
   922 /* Parse an element, recursively parsing content */
       
   923 
       
   924 static
       
   925 NW_Status_t
       
   926 NW_WBXML_Parser_elementParse (NW_WBXML_Parser_t * parser)
       
   927 {
       
   928   NW_Status_t tag_status = NW_STAT_SUCCESS;
       
   929   NW_Status_t status     = NW_STAT_WBXML_ERROR_BYTECODE;
       
   930 
       
   931   if (++(parser->recursiveCallCnt) >= WBXML_MAX_RECURSIVE_CALL_DEPTH) {
       
   932     goto FuncExit;
       
   933   }
       
   934 
       
   935   /* The while loop checks parser status after each case. */
       
   936   while ((parser->flags & NW_WBXML_PARSER_S_MASK) == NW_WBXML_PARSER_OK){
       
   937     if (tag_status == NW_STAT_SUCCESS){
       
   938       tag_status = NW_WBXML_Parser_tagNameParse(parser);
       
   939       if(tag_status == NW_STAT_SUCCESS){
       
   940         status = NW_STAT_SUCCESS; /* Normal return */
       
   941         goto FuncExit;
       
   942       }
       
   943     }
       
   944 
       
   945     else if((tag_status == NW_STAT_WBXML_HAS_ATTRIBUTES) ||
       
   946             (tag_status == NW_STAT_WBXML_HAS_ATTR_CONTENT)) {
       
   947 
       
   948       status = NW_WBXML_Parser_attributeListParse (parser);
       
   949       if(status != NW_STAT_SUCCESS){
       
   950         goto FuncExit;
       
   951       }
       
   952 
       
   953       if (NW_WBXML_Parser_hasMoreBytecode (parser)){
       
   954         if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
   955           status = NW_STAT_WBXML_ERROR_BYTECODE;
       
   956           goto FuncExit;
       
   957         }
       
   958       }
       
   959 
       
   960       if(tag_status == NW_STAT_WBXML_HAS_ATTR_CONTENT) {
       
   961         tag_status = NW_STAT_WBXML_HAS_CONTENT;
       
   962       }
       
   963       else {
       
   964         Handle_Tag_End(parser);
       
   965         status = NW_STAT_SUCCESS;       /* Normal return */
       
   966         goto FuncExit;
       
   967       }
       
   968 
       
   969       /*  TODO:  else check for error (token >= 128) */
       
   970     }
       
   971 
       
   972     else if((tag_status == NW_STAT_WBXML_HAS_CONTENT) ||
       
   973             (tag_status == NW_STAT_WBXML_HAS_ATTR_CONTENT)) {
       
   974 
       
   975       status = NW_WBXML_Parser_contentParse(parser);
       
   976       if(status != NW_STAT_SUCCESS){
       
   977         goto FuncExit;
       
   978       }
       
   979 
       
   980       Handle_Tag_End(parser);
       
   981       status = NW_STAT_SUCCESS; /* Normal return */
       
   982       goto FuncExit;
       
   983     }
       
   984     else{
       
   985       /* Unexpected NW_Byte code */
       
   986       status = NW_STAT_WBXML_ERROR_BYTECODE;
       
   987       goto FuncExit;
       
   988     }
       
   989   }
       
   990   status = NW_STAT_WBXML_ERROR_BYTECODE; /* Bad parser status */
       
   991 
       
   992   FuncExit:
       
   993   --(parser->recursiveCallCnt);
       
   994   return status;
       
   995 }
       
   996 
       
   997 
       
   998 /* Parse a sequence of text components until a non-text component is reached */
       
   999 
       
  1000 
       
  1001 static
       
  1002 NW_Uint32
       
  1003 isTextToken(NW_Uint8 token){
       
  1004   if((token == NW_WBXML_STR_I)
       
  1005     ||(token == NW_WBXML_STR_T)
       
  1006     ||(token == NW_WBXML_OPAQUE)
       
  1007     ||(token == NW_WBXML_ENTITY)
       
  1008     ||(token == NW_WBXML_EXT_I_0)
       
  1009     || (token == NW_WBXML_EXT_I_1)
       
  1010     || (token == NW_WBXML_EXT_I_2)
       
  1011     || (token == NW_WBXML_EXT_T_0)
       
  1012     || (token == NW_WBXML_EXT_T_1)
       
  1013     || (token == NW_WBXML_EXT_T_2)
       
  1014     || (token == NW_WBXML_EXT_0)
       
  1015     || (token == NW_WBXML_EXT_1)
       
  1016     || (token == NW_WBXML_EXT_2)){
       
  1017     return 1;
       
  1018   }
       
  1019   return 0;
       
  1020 }
       
  1021 
       
  1022 
       
  1023 NW_Status_t
       
  1024 NW_WBXML_Parser_textIterate(NW_WBXML_Parser_t * parser){
       
  1025 
       
  1026   NW_Uint8 token;
       
  1027   NW_Int32 ilen = 0;
       
  1028   NW_Uint32 index;
       
  1029   NW_Uint32 e;
       
  1030   NW_Status_t status;
       
  1031 
       
  1032   status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_TAG);
       
  1033   if(status != NW_STAT_SUCCESS){
       
  1034     return status;
       
  1035   }
       
  1036 
       
  1037   switch (token){
       
  1038   case NW_WBXML_STR_I:
       
  1039     Handle_Content(parser);
       
  1040     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1041       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1042     }
       
  1043     ilen = NW_WBXML_Parser_getInlineStrLen(parser, parser->doc);
       
  1044     if(ilen < 0){
       
  1045       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1046     }
       
  1047     Handle_Inline_String(parser, (NW_Uint32)ilen);
       
  1048     if(NW_WBXML_Parser_advance(parser, ilen) < 0){
       
  1049       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1050     }
       
  1051     break;
       
  1052   case NW_WBXML_STR_T:
       
  1053     Handle_Content(parser);
       
  1054     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1055       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1056     }
       
  1057     ilen = NW_WBXML_Parser_readMbUint32 (parser, &index);
       
  1058     if ((ilen < 0) || (index >= parser->doc->strtbl.length)) {
       
  1059       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1060     }
       
  1061     if (!NW_String_valid(parser->doc->strtbl.data + index,
       
  1062                          parser->doc->strtbl.length - index,
       
  1063                          parser->doc->charset)) {
       
  1064       return  NW_STAT_WBXML_ERROR_BYTECODE;
       
  1065     }
       
  1066     Handle_Table_String(parser, index);
       
  1067     if(NW_WBXML_Parser_advance(parser, ilen)< 0){
       
  1068       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1069     }
       
  1070     break;
       
  1071   case NW_WBXML_ENTITY:
       
  1072     Handle_Content(parser);
       
  1073     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1074       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1075     }
       
  1076     ilen = NW_WBXML_Parser_readMbUint32 (parser, &e);
       
  1077     if(ilen < 0){
       
  1078       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1079     }
       
  1080     if(NW_WBXML_Parser_advance (parser, ilen) < 0){
       
  1081       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1082     }
       
  1083     Handle_Entity(parser, e);
       
  1084     break;
       
  1085   case NW_WBXML_EXT_I_0:
       
  1086   case NW_WBXML_EXT_I_1:
       
  1087   case NW_WBXML_EXT_I_2:
       
  1088   case NW_WBXML_EXT_T_0:
       
  1089   case NW_WBXML_EXT_T_1:
       
  1090   case NW_WBXML_EXT_T_2:
       
  1091   case NW_WBXML_EXT_0:
       
  1092   case NW_WBXML_EXT_1:
       
  1093   case NW_WBXML_EXT_2:
       
  1094     Handle_Content(parser);
       
  1095     status = NW_WBXML_Parser_extensionParse (parser, TOKEN_STATE_TAG);
       
  1096     if(status != NW_STAT_SUCCESS){
       
  1097       return status;
       
  1098     }
       
  1099     break;
       
  1100   case NW_WBXML_OPAQUE:
       
  1101     Handle_Content(parser);
       
  1102     status = NW_WBXML_Parser_opaqueParse (parser, TOKEN_STATE_TAG);
       
  1103     if(status != NW_STAT_SUCCESS){
       
  1104       return status;
       
  1105     }
       
  1106     break;
       
  1107   case NW_WBXML_PI:
       
  1108     status = NW_WBXML_Parser_piParse (parser, TOKEN_STATE_TAG);
       
  1109     if (status != NW_STAT_SUCCESS){
       
  1110       return status;
       
  1111     }
       
  1112     break;
       
  1113   default:
       
  1114     return NW_STAT_FAILURE;
       
  1115   }
       
  1116   if (NW_WBXML_Parser_hasMoreBytecode (parser)) {
       
  1117     status = NW_WBXML_Parser_getNextToken(parser, &token, TOKEN_STATE_TAG);
       
  1118     if(status != NW_STAT_SUCCESS){
       
  1119       return status;
       
  1120     }
       
  1121     if(isTextToken(token))
       
  1122       return NW_STAT_WBXML_ITERATE_MORE;
       
  1123   }
       
  1124   return NW_STAT_WBXML_ITERATE_DONE;
       
  1125 }
       
  1126 
       
  1127 static
       
  1128 NW_Status_t
       
  1129 NW_WBXML_Parser_textParse(NW_WBXML_Parser_t * parser){
       
  1130 
       
  1131   NW_Status_t status;
       
  1132 
       
  1133   /* Run the text iterator till it completes */
       
  1134 
       
  1135   while ((parser->flags & NW_WBXML_PARSER_S_MASK) == NW_WBXML_PARSER_OK){
       
  1136     status = NW_WBXML_Parser_textIterate(parser);
       
  1137     if(status == NW_STAT_WBXML_ITERATE_DONE){
       
  1138       return NW_STAT_SUCCESS;
       
  1139     }
       
  1140     if(status != NW_STAT_WBXML_ITERATE_MORE){
       
  1141       return status;
       
  1142     }
       
  1143   }
       
  1144   return NW_WBXML_Parser_flagToStatus(parser);
       
  1145 }
       
  1146 
       
  1147 
       
  1148 /* Parse tag content */
       
  1149 
       
  1150 NW_Status_t
       
  1151 NW_WBXML_Parser_contentParse (NW_WBXML_Parser_t * parser){
       
  1152 
       
  1153   NW_Uint8 token;
       
  1154   NW_Status_t status;
       
  1155 
       
  1156   while ((parser->flags & NW_WBXML_PARSER_S_MASK) == NW_WBXML_PARSER_OK){
       
  1157 
       
  1158     status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_TAG);
       
  1159     if(status != NW_STAT_SUCCESS){
       
  1160       return status;
       
  1161     }
       
  1162 
       
  1163     switch (token){
       
  1164     case NW_WBXML_END:
       
  1165       if (NW_WBXML_Parser_hasMoreBytecode (parser)){
       
  1166         NW_WBXML_Parser_advance (parser, 1);
       
  1167       }
       
  1168       return NW_STAT_SUCCESS;             /* Normal return */
       
  1169 
       
  1170     case NW_WBXML_STR_I:
       
  1171     case NW_WBXML_STR_T:
       
  1172     case NW_WBXML_ENTITY:
       
  1173     case NW_WBXML_PI:
       
  1174     case NW_WBXML_EXT_I_0:
       
  1175     case NW_WBXML_EXT_I_1:
       
  1176     case NW_WBXML_EXT_I_2:
       
  1177     case NW_WBXML_EXT_T_0:
       
  1178     case NW_WBXML_EXT_T_1:
       
  1179     case NW_WBXML_EXT_T_2:
       
  1180     case NW_WBXML_EXT_0:
       
  1181     case NW_WBXML_EXT_1:
       
  1182     case NW_WBXML_EXT_2:
       
  1183     case NW_WBXML_OPAQUE:
       
  1184       status = NW_WBXML_Parser_textParse(parser);
       
  1185       if(status != NW_STAT_SUCCESS){
       
  1186         return status;
       
  1187       }
       
  1188       break;
       
  1189     case NW_WBXML_LITERAL:
       
  1190     case NW_WBXML_LITERAL_A:
       
  1191     case NW_WBXML_LITERAL_C:
       
  1192     case NW_WBXML_LITERAL_AC:
       
  1193     default:
       
  1194       Handle_Content(parser);
       
  1195       status = NW_WBXML_Parser_elementParse (parser);
       
  1196       if(status != NW_STAT_SUCCESS){
       
  1197         return status;
       
  1198       }
       
  1199       break;
       
  1200     }
       
  1201   }
       
  1202   return NW_WBXML_Parser_flagToStatus(parser);
       
  1203 }
       
  1204 
       
  1205 /* Parse an extension */
       
  1206 
       
  1207 NW_Status_t
       
  1208 NW_WBXML_Parser_extensionParse (NW_WBXML_Parser_t * parser,
       
  1209                                 NW_Int32 token_state)
       
  1210 {
       
  1211   NW_Uint8 token = 0;
       
  1212   NW_Uint32 fq_token;
       
  1213   int ilen;
       
  1214   NW_Uint32 value;
       
  1215   NW_Status_t status;
       
  1216 
       
  1217   /*  if (token_state == TOKEN_STATE_TAG)
       
  1218   * handler = parser->handler; TODO: deal with this
       
  1219   */
       
  1220 
       
  1221   Handle_Extension(parser);
       
  1222 
       
  1223   status = NW_WBXML_Parser_getNextToken (parser, &token, token_state);
       
  1224   if(status != NW_STAT_SUCCESS){
       
  1225     return status;
       
  1226   }
       
  1227 
       
  1228   fq_token = FqToken (parser, token, token_state);
       
  1229   Handle_Fq_Token(parser, fq_token);
       
  1230 
       
  1231   switch (token){
       
  1232   case NW_WBXML_EXT_I_0:
       
  1233   case NW_WBXML_EXT_I_1:
       
  1234   case NW_WBXML_EXT_I_2:
       
  1235     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1236       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1237     }
       
  1238 
       
  1239     ilen = NW_WBXML_Parser_getInlineStrLen(parser, parser->doc);
       
  1240     if(ilen < 0){
       
  1241       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1242     }
       
  1243 
       
  1244     Handle_Inline_String(parser, (NW_Uint32)ilen);
       
  1245 
       
  1246     if(NW_WBXML_Parser_advance(parser, ilen)<0){
       
  1247       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1248     }
       
  1249     break;
       
  1250   case NW_WBXML_EXT_T_0:
       
  1251   case NW_WBXML_EXT_T_1:
       
  1252   case NW_WBXML_EXT_T_2:
       
  1253 
       
  1254     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1255       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1256     }
       
  1257 
       
  1258     ilen = NW_WBXML_Parser_readMbUint32 (parser, &value);
       
  1259 
       
  1260     if(ilen < 0){
       
  1261       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1262     }
       
  1263 
       
  1264     if (parser->ext_t_not_table_index == 0) {
       
  1265       Handle_Table_String(parser, value);
       
  1266     } else {
       
  1267       Handle_Binary(parser, value); /* handle ext_t anonymous int */
       
  1268     }
       
  1269     if(NW_WBXML_Parser_advance (parser, ilen) < 0){
       
  1270       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1271     }
       
  1272     break;
       
  1273   case NW_WBXML_EXT_0:
       
  1274   case NW_WBXML_EXT_1:
       
  1275   case NW_WBXML_EXT_2:
       
  1276     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1277       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1278     }
       
  1279     /* Note - For an extension token without other parameters the
       
  1280      second parameter to Handle_Binary is bogus.  The callback is here
       
  1281      so that the parser client can manage its internal state. */
       
  1282     Handle_Binary(parser, 0);
       
  1283     break;
       
  1284   default:
       
  1285     NW_ASSERT(NW_FALSE);
       
  1286     return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1287   }
       
  1288   return NW_STAT_SUCCESS;
       
  1289 }
       
  1290 
       
  1291 
       
  1292 /*
       
  1293 * Parse an attribute
       
  1294 */
       
  1295 
       
  1296 
       
  1297 
       
  1298 NW_Status_t
       
  1299 NW_WBXML_Parser_attributeNameParse (NW_WBXML_Parser_t * parser){
       
  1300 
       
  1301   NW_Uint8 token;
       
  1302   NW_Uint32 fq_token;
       
  1303   NW_Uint32 index;
       
  1304   NW_Int32 ilen;
       
  1305   NW_Status_t status;
       
  1306 
       
  1307   if (!NW_WBXML_Parser_hasMoreBytecode(parser)) {
       
  1308     return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1309   }
       
  1310 
       
  1311   status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_ATTR);
       
  1312   if(status != NW_STAT_SUCCESS){
       
  1313     return status;
       
  1314   }
       
  1315 
       
  1316   if (token < 128){
       
  1317     Handle_Attr_Start(parser);
       
  1318     if (parser->status == NW_STAT_OUT_OF_MEMORY) {
       
  1319       return parser->status;
       
  1320     }
       
  1321     if(NW_WBXML_Parser_advance (parser, 1)<0){
       
  1322       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1323     }
       
  1324 
       
  1325     fq_token = FqToken (parser, token, TOKEN_STATE_ATTR);
       
  1326 
       
  1327     Handle_Fq_Token(parser, fq_token);
       
  1328   }
       
  1329 
       
  1330   else{
       
  1331     return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1332   }
       
  1333 
       
  1334   if (token == NW_WBXML_LITERAL){
       
  1335     /*  TODO:  Should check for another global token and return an error? */
       
  1336     ilen = NW_WBXML_Parser_readMbUint32 (parser, &index);
       
  1337     if(ilen < 0){
       
  1338       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1339     }
       
  1340     Handle_Table_String(parser, index);
       
  1341     if(NW_WBXML_Parser_advance(parser, ilen) < 0){
       
  1342       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1343     }
       
  1344   }
       
  1345   return NW_STAT_SUCCESS;
       
  1346 }
       
  1347 
       
  1348 
       
  1349 NW_Status_t
       
  1350 NW_WBXML_Parser_attributeValsIterate (NW_WBXML_Parser_t * parser)
       
  1351 {
       
  1352   NW_Uint8 token;
       
  1353   NW_Uint32 fq_token;
       
  1354   NW_Uint32 index;
       
  1355   NW_Uint32 e;
       
  1356   NW_Int32 ilen;
       
  1357   NW_Status_t status;
       
  1358 
       
  1359   status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_ATTR);
       
  1360   if(status != NW_STAT_SUCCESS){
       
  1361     return status;
       
  1362   }
       
  1363 
       
  1364   if (token == NW_WBXML_STR_I){
       
  1365     /* NW_WBXML_ATTR_COMPONENT_STRING; */
       
  1366     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1367       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1368     }
       
  1369     ilen = NW_WBXML_Parser_getInlineStrLen(parser, parser->doc);
       
  1370     if(ilen < 0){
       
  1371       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1372     }
       
  1373     Handle_Attr_Val(parser);
       
  1374     Handle_Inline_String(parser, (NW_Uint32) ilen);
       
  1375     if(NW_WBXML_Parser_advance(parser, ilen) < 0){
       
  1376       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1377     }
       
  1378   }
       
  1379   else if (token == NW_WBXML_STR_T){
       
  1380     /* NW_WBXML_ATTR_COMPONENT_STRING; */
       
  1381     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1382       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1383     }
       
  1384     ilen = NW_WBXML_Parser_readMbUint32 (parser, &index);
       
  1385     if(ilen < 0){
       
  1386       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1387     }
       
  1388     Handle_Attr_Val(parser);
       
  1389     Handle_Table_String(parser, index);
       
  1390     if(NW_WBXML_Parser_advance(parser, ilen)<0){
       
  1391       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1392     }
       
  1393   }
       
  1394   else if (token == NW_WBXML_OPAQUE){
       
  1395     /* NW_WBXML_ATTR_COMPONENT_OPAQUE; */
       
  1396     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1397       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1398     }
       
  1399     ilen = NW_WBXML_Parser_readMbUint32 (parser, &index);
       
  1400     if(ilen < 0){
       
  1401       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1402     }
       
  1403     /* Move past the length NW_Byte(s) */
       
  1404     if(NW_WBXML_Parser_advance (parser, ilen) < 0){
       
  1405       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1406     }
       
  1407     Handle_Attr_Val(parser);
       
  1408     Handle_Opaque(parser, index);
       
  1409     if(NW_WBXML_Parser_advance (parser, (NW_Int32)index) < 0){
       
  1410       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1411     }
       
  1412   }
       
  1413   else if (token == NW_WBXML_ENTITY){
       
  1414     /*NW_WBXML_ATTR_COMPONENT_ENTITY; */
       
  1415     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1416       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1417     }
       
  1418     ilen = NW_WBXML_Parser_readMbUint32 (parser,&e);
       
  1419     if(ilen < 0){
       
  1420       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1421     }
       
  1422     Handle_Entity(parser, e);
       
  1423     if(NW_WBXML_Parser_advance (parser, ilen) < 0){
       
  1424       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1425     }
       
  1426   }
       
  1427   else if ((token == NW_WBXML_EXT_I_0)
       
  1428            || (token == NW_WBXML_EXT_I_1)
       
  1429            || (token == NW_WBXML_EXT_I_2)
       
  1430            || (token == NW_WBXML_EXT_T_0)
       
  1431            || (token == NW_WBXML_EXT_T_1)
       
  1432            || (token == NW_WBXML_EXT_T_2)
       
  1433            || (token == NW_WBXML_EXT_0)
       
  1434            || (token == NW_WBXML_EXT_1)
       
  1435            || (token == NW_WBXML_EXT_2)){
       
  1436 
       
  1437     /* NW_WBXML_ATTR_COMPONENT_EXT; */
       
  1438     Handle_Attr_Val(parser);
       
  1439     status = NW_WBXML_Parser_extensionParse (parser, TOKEN_STATE_ATTR);
       
  1440     if(status != NW_STAT_SUCCESS){
       
  1441       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1442     }
       
  1443   }
       
  1444   else if (token >= 128){
       
  1445     /*NW_WBXML_ATTR_COMPONENT_TOKEN; */
       
  1446     fq_token = FqToken(parser, token, TOKEN_STATE_ATTR);
       
  1447     Handle_Attr_Val(parser);
       
  1448     Handle_Fq_Token(parser, fq_token);
       
  1449     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1450       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1451     }
       
  1452   }
       
  1453 
       
  1454   status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_ATTR);
       
  1455   if(status != NW_STAT_SUCCESS){
       
  1456     return status;
       
  1457   }
       
  1458 
       
  1459   /*
       
  1460   * Attribute tokens are either text tokens or
       
  1461   * dictionary-defined tokens > 128
       
  1462   */
       
  1463   if(isTextToken(token) || (token >=128)){
       
  1464 
       
  1465     return NW_STAT_WBXML_ITERATE_MORE;          /* Normal exit */
       
  1466   }
       
  1467   else /*if ((token < 128) || (token == NW_WBXML_END)
       
  1468     || (token == NW_WBXML_LITERAL))*/{
       
  1469     /*parser->state &= ~NW_WBXML_PARSER_S_ATTR_VAL; */
       
  1470     /* Don't advance parser */
       
  1471     return NW_STAT_WBXML_ITERATE_DONE;      /* Normal exit */
       
  1472   }
       
  1473 }
       
  1474 
       
  1475 NW_Status_t
       
  1476 NW_WBXML_Parser_attributeParse(NW_WBXML_Parser_t *parser)
       
  1477 {
       
  1478   NW_Status_t status;
       
  1479 
       
  1480   status = NW_WBXML_Parser_attributeNameParse(parser);
       
  1481   if(status != NW_STAT_SUCCESS){
       
  1482     return status;
       
  1483   }
       
  1484   while ((parser->flags & NW_WBXML_PARSER_S_MASK) == NW_WBXML_PARSER_OK){
       
  1485     status = NW_WBXML_Parser_attributeValsIterate(parser);
       
  1486     if(status == NW_STAT_WBXML_ITERATE_DONE){
       
  1487       return NW_STAT_SUCCESS;
       
  1488     }
       
  1489     if(status != NW_STAT_WBXML_ITERATE_MORE){
       
  1490       return status;
       
  1491     }
       
  1492   }
       
  1493   return NW_WBXML_Parser_flagToStatus(parser);
       
  1494 }
       
  1495 
       
  1496 
       
  1497 /*
       
  1498 * Parse opaque data
       
  1499 */
       
  1500 
       
  1501 NW_Status_t
       
  1502 NW_WBXML_Parser_opaqueParse (NW_WBXML_Parser_t * parser,
       
  1503                              NW_Int32 token_state)
       
  1504 {
       
  1505 
       
  1506   NW_Uint32 index;
       
  1507   NW_Int32 ilen = 0;
       
  1508   NW_Uint8 token;
       
  1509   NW_Status_t status;
       
  1510 
       
  1511   status = NW_WBXML_Parser_getNextToken (parser, &token, token_state);
       
  1512   if(status != NW_STAT_SUCCESS){
       
  1513     return status;
       
  1514   }
       
  1515 
       
  1516   switch (token){
       
  1517   case NW_WBXML_OPAQUE:
       
  1518     if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1519       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1520     }
       
  1521     ilen = NW_WBXML_Parser_readMbUint32 (parser, &index);
       
  1522     if(ilen < 0){
       
  1523       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1524     }
       
  1525     if(NW_WBXML_Parser_advance (parser, ilen) < 0){
       
  1526       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1527     }
       
  1528     Handle_Opaque(parser,index);
       
  1529     if(NW_WBXML_Parser_advance (parser, (NW_Int32)index) < 0){
       
  1530       return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1531     }
       
  1532     break;
       
  1533   default:
       
  1534     /* return NW_STAT_WBXML_ERROR_BYTECODE;*/
       
  1535     NW_ASSERT(NW_FALSE); /* Never reached */
       
  1536   }
       
  1537   return NW_STAT_SUCCESS;
       
  1538 }
       
  1539 
       
  1540 
       
  1541 /*
       
  1542 * Parse the body of a document
       
  1543 *
       
  1544 * RETURN NW_STAT_SUCCESS
       
  1545 *        NW_STAT_OUT_OF_MEMORY
       
  1546 *        NW_STAT_BAD_INPUT_PARAM
       
  1547 *        NW_STAT_WBXML_ERROR_BYTECODE
       
  1548 *        NW_STAT_WBXML_ERROR_CHARSET_UNSUPPORTED
       
  1549 */
       
  1550 
       
  1551 NW_Status_t
       
  1552 NW_WBXML_Parser_bodyParse (NW_WBXML_Parser_t * parser)
       
  1553 {
       
  1554   NW_Status_t status;
       
  1555   NW_Uint8 token;
       
  1556 
       
  1557   NW_ASSERT(parser != NULL);
       
  1558   // WLIU_DEBUG: RFileLogger::WriteFormat(_L("Browser"), _L("cp_count.txt"), EFileLoggingModeAppend, _L("====== body parse starts =====\n"));
       
  1559 
       
  1560   /* This is not quite the WBXML grammar because we want to permit
       
  1561      loose HTML docs where there is no one document node. */
       
  1562   while (((parser->flags & NW_WBXML_PARSER_S_MASK) == NW_WBXML_PARSER_OK)
       
  1563          && NW_WBXML_Parser_hasMoreBytecode (parser)) {
       
  1564 
       
  1565     status = NW_WBXML_Parser_getNextToken (parser, &token, TOKEN_STATE_TAG);
       
  1566     if(status != NW_STAT_SUCCESS){
       
  1567       return status;
       
  1568     }
       
  1569 
       
  1570     switch (token){
       
  1571     case NW_WBXML_END:
       
  1572       if (NW_WBXML_Parser_hasMoreBytecode (parser)) {
       
  1573         if(NW_WBXML_Parser_advance (parser, 1) < 0){
       
  1574           return NW_STAT_WBXML_ERROR_BYTECODE;
       
  1575         }
       
  1576         Handle_Tag_End(parser);
       
  1577       }
       
  1578       break;
       
  1579 
       
  1580     case NW_WBXML_STR_I:
       
  1581     case NW_WBXML_STR_T:
       
  1582     case NW_WBXML_ENTITY:
       
  1583     case NW_WBXML_PI:
       
  1584     case NW_WBXML_EXT_I_0:
       
  1585     case NW_WBXML_EXT_I_1:
       
  1586     case NW_WBXML_EXT_I_2:
       
  1587     case NW_WBXML_EXT_T_0:
       
  1588     case NW_WBXML_EXT_T_1:
       
  1589     case NW_WBXML_EXT_T_2:
       
  1590     case NW_WBXML_EXT_0:
       
  1591     case NW_WBXML_EXT_1:
       
  1592     case NW_WBXML_EXT_2:
       
  1593     case NW_WBXML_OPAQUE:
       
  1594       status = NW_WBXML_Parser_textParse(parser);
       
  1595       if(status != NW_STAT_SUCCESS){
       
  1596         return status;
       
  1597       }
       
  1598       break;
       
  1599 
       
  1600     case NW_WBXML_LITERAL:
       
  1601     case NW_WBXML_LITERAL_A:
       
  1602     case NW_WBXML_LITERAL_C:
       
  1603     case NW_WBXML_LITERAL_AC:
       
  1604     default:
       
  1605       status = NW_WBXML_Parser_elementParse (parser);
       
  1606       if(status != NW_STAT_SUCCESS){
       
  1607         return status;
       
  1608       }
       
  1609       break;
       
  1610     }
       
  1611   }
       
  1612   CHECK_PARSER_STATUS;
       
  1613 
       
  1614   /*
       
  1615   * If we have a registry then it must be inited at this point, so
       
  1616   * set the init flag.
       
  1617   */
       
  1618 
       
  1619   if((parser->cp_registry.count > 0)
       
  1620     && ((parser->flags & NW_WBXML_REGISTRY_INIT) != NW_WBXML_REGISTRY_INIT)){
       
  1621     parser->flags |= NW_WBXML_REGISTRY_INIT;
       
  1622   }
       
  1623 
       
  1624   // WLIU_DEBUG: RFileLogger::WriteFormat(_L("Browser"), _L("cp_count.txt"), EFileLoggingModeAppend, _L("====== body parse ends =====\n"));
       
  1625 
       
  1626   if (parser->handler && parser->handler->EndDocument_CB){
       
  1627     return (*(parser->handler->EndDocument_CB)) (parser, parser->context);
       
  1628   }
       
  1629   return NW_STAT_SUCCESS;
       
  1630 }
       
  1631 
       
  1632 
       
  1633 /*
       
  1634 * Cache the parser's event handler and context
       
  1635 *
       
  1636 * RETURN: NW_STAT_SUCCESS
       
  1637 */
       
  1638 
       
  1639 EXPORT_C NW_Status_t
       
  1640 NW_WBXML_Parser_registerHandler (NW_WBXML_Parser_t * parser,
       
  1641                                  const struct NW_WBXML_EventHandler_s * handler,
       
  1642                                  void *context)
       
  1643 {
       
  1644 
       
  1645   NW_ASSERT(parser != NULL);
       
  1646 
       
  1647   parser->handler = handler;
       
  1648   parser->context = context;
       
  1649 
       
  1650   return NW_STAT_SUCCESS;
       
  1651 }