xml/cxmllibrary/src/tinydom/src/tiny_dom.c
branchRCL_3
changeset 21 604ca70b6235
parent 20 889504eac4fb
equal deleted inserted replaced
20:889504eac4fb 21:604ca70b6235
     1 /*
       
     2 * Copyright (c) 2009 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 #include "cxml_internal.h"
       
    18 #include <xml/cxml/nw_tinydom.h>
       
    19 #include <xml/cxml/nw_wbxml_parse.h>
       
    20 #include <xml/cxml/nw_wbxml_reader.h>
       
    21 #include <xml/cxml/nw_wbxml_event.h>
       
    22 #include "nw_wbxml_parsei.h"
       
    23 
       
    24 /*Parser flags */
       
    25 
       
    26 /* Top four bits are pass state */
       
    27 #define T_PARSE_PASS_MASK      0xF0000000
       
    28 #define T_PARSE_PASS_1         0x00000000
       
    29 #define T_PARSE_PASS_2         0x10000000
       
    30 #define T_PARSE_PASS_3         0x20000000
       
    31 
       
    32 /* Next 8 bits are for parser states */
       
    33 #define T_PARSE_S_MASK         0x07F00000
       
    34 #define T_PARSE_S_TAG_START    0x00000000
       
    35 #define T_PARSE_S_ATTR_START   0x00100000
       
    36 #define T_PARSE_S_ATTR_VALS    0x00200000
       
    37 #define T_PARSE_S_CONTENT      0x00300000
       
    38 #define T_PARSE_F_EXT          0x08000000 /* Extension substate flag */
       
    39 
       
    40   /* Remaining 20 bits are flags */
       
    41 #define T_PARSE_FLAG_TEXT      0x00000001
       
    42 #define T_PARSE_FLAG_ATTR      0x00000002
       
    43 
       
    44 /*
       
    45 * Implements the tiny dom parser. This includes the methods to build a
       
    46 * tiny dom tree, and the underlying support routines to access the
       
    47 * "virtual elements" of the tree. The only thing that currently gets
       
    48 * in the way of a clean parser interface are several references to the
       
    49 * underlying parser state here. The underlying parser needs to be
       
    50 * fixed so it is never necessary to pass this. Several TODOs in this
       
    51 * file indicate places where references to parser state should be
       
    52 * removed.  
       
    53 */
       
    54 
       
    55 static
       
    56 NW_Uint32
       
    57 GET_PASS(NW_TinyDom_Parser_t* parser){
       
    58   return parser->state & T_PARSE_PASS_MASK;
       
    59 }
       
    60 
       
    61 static
       
    62 void 
       
    63 SET_PASS(NW_TinyDom_Parser_t* parser, NW_Uint32 pass){
       
    64   parser->state &= ~T_PARSE_PASS_MASK;
       
    65   parser->state |= pass;
       
    66 }
       
    67 
       
    68 static
       
    69 NW_Uint32
       
    70 GET_STATE(NW_TinyDom_Parser_t* parser){
       
    71   return parser->state & T_PARSE_S_MASK;
       
    72 }
       
    73 
       
    74 static
       
    75 void 
       
    76 SET_STATE(NW_TinyDom_Parser_t* parser, NW_Uint32 state){
       
    77   parser->state &= ~T_PARSE_S_MASK;
       
    78   parser->state |= state;
       
    79 }
       
    80 
       
    81 /* Callbacks to handle parsing passes: 
       
    82 *
       
    83 * Tiny dom uses multiple passes to implement the tree lazily. The
       
    84 * first two build the tree. Later, lazy deserialization invokes
       
    85 * further passes over parts of the source.
       
    86 * 
       
    87 * Pass 1 counts nodes and allocates space, pass 2 builds the
       
    88 * tree. However, there is much common behavior for both passes, since
       
    89 * accurate counting of nodes requires running the parser state
       
    90 * machine. Common behavior is implemented in common callbacks, while
       
    91 * pass-specific behavior is mostly implemented in pass-specific
       
    92 * callbacks.
       
    93 *
       
    94 * The tree built by passes 1 & 2 contains a node for every tag. If a tag
       
    95 * has attributes, the tree contains a node for the first attribute,
       
    96 * attached as the first child of the node. For text content, the tree
       
    97 * contains a node for the first text element in each sequence of text
       
    98 * elements. The goal of the tree design is to make it easy to find
       
    99 * elements for deserialization while using the minimum amount of
       
   100 * storage.
       
   101 * 
       
   102 * The deserialization API invokes parser methods that know how to
       
   103 * parse one of the node types stored in the tree (tags, attributes,
       
   104 * text). The API sets the parser offset using the node offset,
       
   105 * identifies the node type using the node type flags, and then calls
       
   106 * the appropriate parser method to parse a section of the source.
       
   107 * 
       
   108 * When called for deserialization the parser generates events as usual:
       
   109 * these are handled by the pass 3 handlers which build the appropriate
       
   110 * data structures for the API to return.
       
   111 * 
       
   112 * This may seem like a rather byzantine mechanism for
       
   113 * deserialization, but the goal is to use exactly the same parsing
       
   114 * code for all operations on the source. This makes it easy to change
       
   115 * or replace parsing code.  Also, all of the parsing logic is kept in
       
   116 * the parser module: the dom module (this one) has no knowledge of
       
   117 * parsing. This makes it easy to attach the dom module to different
       
   118 * parsers (one for wbxml, one for xml).  
       
   119 *
       
   120 * A note on buffer usage: tiny trees use segmented expandable buffers
       
   121 * (ebuffers) so that the tree can be read and written in minimum memory.
       
   122 * When building a tree from an existing buffer (passes 1 & 2), the whole
       
   123 * buffer is contained in the ebuffer segment 0. This means that the 
       
   124 * offsets we store in the tree nodes (which are indexes into the ebuffer)
       
   125 * are the same as the parser offsets in the buffer. However, for 
       
   126 * deserialization (pass 3), we may be reading a tree that was constructed
       
   127 * or modified via the dom api. This may have multiple segments and a given
       
   128 * node offset may refer to an address in any segment. Therefore, when setting
       
   129 * the parser offset from a node source offset, we first need to translate
       
   130 * the node source offset into a segment + offset form, and use this to set
       
   131 * the parser.   
       
   132 */
       
   133 
       
   134 
       
   135 static 
       
   136 NW_Status_t 
       
   137 Pass_1_StartDocument_CB (NW_WBXML_Parser_t *parser, 
       
   138                          NW_WBXML_Document_t *doc, 
       
   139                          void *context)
       
   140 {
       
   141 
       
   142   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   143 
       
   144   NW_REQUIRED_PARAM(parser);
       
   145   NW_REQUIRED_PARAM(doc);
       
   146 
       
   147   SET_STATE(tiny_parser, T_PARSE_S_CONTENT);
       
   148   tiny_parser->state &= ~T_PARSE_FLAG_TEXT; /* prepare for text */
       
   149   tiny_parser->node_count = 1;
       
   150   return NW_STAT_SUCCESS;
       
   151 
       
   152 }
       
   153 
       
   154 static 
       
   155 NW_Status_t 
       
   156 Pass_2_StartDocument_CB (NW_WBXML_Parser_t *parser, 
       
   157                          NW_WBXML_Document_t *doc, 
       
   158                          void *context)
       
   159 {
       
   160   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   161 
       
   162   NW_REQUIRED_PARAM(parser);
       
   163   NW_REQUIRED_PARAM(doc);
       
   164 
       
   165   tiny_parser->dom_tree->root_node = NW_TinyTree_setRoot(&(tiny_parser->dom_tree->tree), 0);
       
   166 
       
   167   if (tiny_parser->dom_tree->root_node != NULL){
       
   168     tiny_parser->current_node = tiny_parser->dom_tree->root_node;
       
   169     NW_TinyTree_Node_setUserFlags(tiny_parser->current_node, T_DOM_NODE_DOC);
       
   170     SET_STATE(tiny_parser, T_PARSE_S_CONTENT);
       
   171     tiny_parser->state &= ~T_PARSE_FLAG_TEXT; /* prepare for text */
       
   172     return NW_STAT_SUCCESS;
       
   173   }
       
   174   else{
       
   175     return NW_STAT_OUT_OF_MEMORY;
       
   176   }  
       
   177 }
       
   178 
       
   179 /* Private utility function to do NW_Byte reordering of ucs2 strings */
       
   180 /* TODO:  move this to our string library */
       
   181 
       
   182 static 
       
   183 void
       
   184 NW_String_Ucs2_ntoh(NW_String_t *string){
       
   185   NW_Uint32 i;
       
   186   NW_Ucs2 character;
       
   187 
       
   188   for(i = 0; i < string->length; i+=2){
       
   189     character = (NW_Ucs2)((string->storage[i] << 8) | string->storage[i+1]);
       
   190     (void) NW_Mem_memcpy (&string->storage[i], &character, sizeof (character));
       
   191   }
       
   192 }
       
   193 
       
   194 /* 
       
   195  * This callback sets the parser pass and takes care of any NW_Byte reordering 
       
   196  * that needs to be done on the string table. For some encodings (such as ucs2)
       
   197  * this allows applications to reference strings from the original storage.
       
   198  */
       
   199 
       
   200 /* TODO:  TODO: Add a flag to document to check if this has already been done 
       
   201   (in case the same buffer is parsed over again from the beginning.)
       
   202  */
       
   203 
       
   204 
       
   205 static 
       
   206 NW_Status_t 
       
   207 Pass_1_EndDocument_CB (NW_WBXML_Parser_t *parser, 
       
   208                        void *context)
       
   209 {
       
   210 
       
   211   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   212   //NW_String_t string;
       
   213   //NW_WBXML_Document_t *doc = tiny_parser->dom_tree->doc;
       
   214 
       
   215   NW_REQUIRED_PARAM(parser);
       
   216 
       
   217   // WLIU: all byte order conversions are moved to pass 2.
       
   218   //if(doc->charset == HTTP_iso_10646_ucs_2){
       
   219     /* TODO:  redefine string table as an NW_String_t ?? */
       
   220     //string.storage = doc->strtbl.data;
       
   221     //string.length = doc->strtbl.length;
       
   222     //NW_String_Ucs2_ntoh(&string);
       
   223   //}
       
   224   SET_PASS(tiny_parser, T_PARSE_PASS_2);
       
   225   return NW_STAT_SUCCESS;  
       
   226 }
       
   227 
       
   228 
       
   229 static 
       
   230 NW_Status_t 
       
   231 Pass_2_EndDocument_CB (NW_WBXML_Parser_t *parser, 
       
   232                        void *context)
       
   233 {
       
   234 
       
   235   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   236 
       
   237   NW_REQUIRED_PARAM(parser);
       
   238 
       
   239   SET_PASS(tiny_parser, T_PARSE_PASS_3);
       
   240   return NW_STAT_SUCCESS;  
       
   241 }
       
   242 
       
   243 static 
       
   244 NW_Status_t 
       
   245 Pass_1_Tag_Start_CB (NW_WBXML_Parser_t *parser, 
       
   246                      void *context)
       
   247 {
       
   248 
       
   249   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   250 
       
   251   NW_REQUIRED_PARAM(parser);
       
   252 
       
   253   tiny_parser->node_count++;
       
   254   return NW_STAT_SUCCESS;
       
   255 }
       
   256 
       
   257 
       
   258 static 
       
   259 NW_Status_t 
       
   260 Pass_2_Tag_Start_CB (NW_WBXML_Parser_t *parser, 
       
   261                      void *context)
       
   262 {
       
   263   NW_Status_t status = NW_STAT_SUCCESS;
       
   264   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   265 
       
   266   //Atleast there should be root node, before any tag
       
   267 
       
   268   if(tiny_parser->current_node != NULL)
       
   269   {
       
   270    tiny_parser->current_node = 
       
   271      NW_TinyTree_createChild(&(tiny_parser->dom_tree->tree), 
       
   272                             tiny_parser->current_node, 
       
   273                             (NW_TinyTree_Offset_t)parser->offset);
       
   274 
       
   275    if (tiny_parser->current_node != NULL)
       
   276    {
       
   277      NW_TinyTree_Node_setUserFlags(tiny_parser->current_node, T_DOM_NODE_TAG);
       
   278      status = NW_STAT_SUCCESS;
       
   279    }
       
   280    else
       
   281    {
       
   282     status =  NW_STAT_FAILURE;
       
   283    }  
       
   284   }//endif(tiny_parser->current_node != NULL)
       
   285   else
       
   286   {
       
   287    status =  NW_STAT_FAILURE;
       
   288   }
       
   289 
       
   290   return status;
       
   291 }//end Pass_2_Tag_Start_CB(..)
       
   292 
       
   293 
       
   294 static 
       
   295 NW_Status_t 
       
   296 Tag_Start_CB (NW_WBXML_Parser_t *parser, 
       
   297               void *context)
       
   298 
       
   299 {
       
   300   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   301   NW_Status_t s = NW_STAT_FAILURE;
       
   302 
       
   303   switch(GET_PASS(tiny_parser)){
       
   304   case T_PARSE_PASS_1:
       
   305     s = Pass_1_Tag_Start_CB(parser, context);
       
   306     break;
       
   307   case T_PARSE_PASS_2:
       
   308     s = Pass_2_Tag_Start_CB(parser, context);
       
   309     break;
       
   310   default:
       
   311     NW_ASSERT(NW_FALSE);
       
   312   }
       
   313   SET_STATE(tiny_parser, T_PARSE_S_TAG_START);
       
   314   tiny_parser->state &= ~T_PARSE_FLAG_TEXT; /* No longer accumulating text */
       
   315   tiny_parser->state &= ~T_PARSE_FLAG_ATTR; /* Turn off attribute flag */
       
   316   return s;
       
   317 }
       
   318 
       
   319 static
       
   320 NW_Status_t
       
   321 Pass_2_Pi_CB (NW_WBXML_Parser_t *parser, 
       
   322               void *context)
       
   323 {
       
   324   /* This is exactly like pass 2 tag start except for the node user flag. */
       
   325   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   326   NW_Status_t s = Tag_Start_CB(parser, context);
       
   327 
       
   328   if (s == NW_STAT_SUCCESS) {
       
   329     NW_TinyTree_Node_setUserFlags(tiny_parser->current_node, T_DOM_NODE_PI);
       
   330   }
       
   331   return s;
       
   332 }
       
   333 
       
   334 static 
       
   335 NW_Status_t 
       
   336 Tag_End_CB (NW_WBXML_Parser_t *parser, 
       
   337             void *context)
       
   338 {
       
   339   NW_Status_t status = NW_STAT_SUCCESS;
       
   340   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   341   NW_Int32 lastvalid;
       
   342   NW_REQUIRED_PARAM(parser);
       
   343 
       
   344   lastvalid = NW_TinyDom_getLastValid(tiny_parser->dom_tree);
       
   345   if(GET_PASS(tiny_parser)== T_PARSE_PASS_2)
       
   346   {
       
   347     /* for the dom tree appending, we won't handle close tag which is beyond last valid mark */
       
   348     if (lastvalid == -1 || (NW_Int32)parser->offset <= lastvalid)
       
   349 	{
       
   350       if(tiny_parser->current_node != NULL)
       
   351 	  {
       
   352       tiny_parser->current_node = NW_TinyTree_findParent(tiny_parser->current_node);
       
   353 	  }
       
   354 	  else
       
   355 	  {
       
   356 	   status = NW_STAT_FAILURE;
       
   357 	  }
       
   358 	}
       
   359   }
       
   360 
       
   361   if(status == NW_STAT_SUCCESS)
       
   362   {
       
   363    SET_STATE(tiny_parser, T_PARSE_S_CONTENT);
       
   364    tiny_parser->state &= ~T_PARSE_FLAG_TEXT; /* No longer accumulating text */
       
   365   }
       
   366   return status;
       
   367 }//end Tag_End_CB (..)
       
   368 
       
   369 /* 
       
   370 * The first attribute is added as (first) child of the current node.
       
   371 * This makes it easy to find attributes for later deserialization
       
   372 */
       
   373 
       
   374 static 
       
   375 NW_Status_t 
       
   376 Attr_Start_CB (NW_WBXML_Parser_t *parser, 
       
   377                void *context)
       
   378 {
       
   379   NW_Status_t status = NW_STAT_SUCCESS;
       
   380   
       
   381   NW_TinyTree_Node_t* attr_node;
       
   382   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   383 
       
   384   switch(GET_STATE(tiny_parser)){
       
   385   case T_PARSE_S_TAG_START:
       
   386   case T_PARSE_S_ATTR_START:
       
   387   case T_PARSE_S_ATTR_VALS:
       
   388     if((tiny_parser->state & T_PARSE_FLAG_ATTR) != T_PARSE_FLAG_ATTR){
       
   389       tiny_parser->state |= T_PARSE_FLAG_ATTR;
       
   390       switch (GET_PASS(tiny_parser)){
       
   391       case T_PARSE_PASS_1:
       
   392         tiny_parser->node_count++;
       
   393         break;
       
   394       case T_PARSE_PASS_2:
       
   395         attr_node = NW_TinyTree_createChild(&(tiny_parser->dom_tree->tree), 
       
   396                                             tiny_parser->current_node, 
       
   397                                             (NW_TinyTree_Offset_t)parser->offset);
       
   398         if (attr_node != NULL){
       
   399           NW_TinyTree_Node_setUserFlags(attr_node, T_DOM_NODE_ATTR);
       
   400         }
       
   401         else{
       
   402           status = NW_STAT_OUT_OF_MEMORY;
       
   403         }                    
       
   404         break;
       
   405       default:
       
   406         NW_ASSERT(NW_FALSE);
       
   407         status = NW_STAT_FAILURE;
       
   408       }
       
   409     }
       
   410     SET_STATE(tiny_parser, T_PARSE_S_ATTR_START);
       
   411     break;
       
   412   default:
       
   413     status = NW_STAT_FAILURE;
       
   414   }
       
   415   return status;  
       
   416 }
       
   417 
       
   418 static 
       
   419 NW_Status_t 
       
   420 Attr_Val_CB (NW_WBXML_Parser_t *parser, 
       
   421              void *context)
       
   422 {
       
   423 
       
   424   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   425 
       
   426   NW_REQUIRED_PARAM(parser);
       
   427 
       
   428   switch(GET_STATE(tiny_parser)){
       
   429   case T_PARSE_S_ATTR_START:
       
   430   case T_PARSE_S_ATTR_VALS:
       
   431     SET_STATE(tiny_parser,T_PARSE_S_ATTR_VALS);
       
   432     return NW_STAT_SUCCESS;
       
   433   default:
       
   434     return NW_STAT_FAILURE;
       
   435   }
       
   436 }
       
   437 
       
   438 static 
       
   439 NW_Status_t 
       
   440 Content_CB (NW_WBXML_Parser_t *parser, 
       
   441             void *context)
       
   442 {
       
   443 
       
   444   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   445 
       
   446   SET_STATE(tiny_parser, T_PARSE_S_CONTENT);
       
   447   /* We need to save the current offset to use if we need a text node. Ugh! */
       
   448   tiny_parser->content_offset = (NW_TinyTree_Offset_t)parser->offset; 
       
   449   return NW_STAT_SUCCESS;
       
   450 }
       
   451 
       
   452 /* Count code page switches */
       
   453 
       
   454 static
       
   455 NW_Status_t 
       
   456 Pass_1_CodePage_CB (NW_WBXML_Parser_t *parser, 
       
   457                     void *context)
       
   458 {
       
   459   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   460 
       
   461   NW_REQUIRED_PARAM(parser);
       
   462 
       
   463   tiny_parser->cp_count++;
       
   464   return NW_STAT_SUCCESS;
       
   465 }
       
   466 
       
   467 
       
   468 /* 
       
   469 * The first text element in a series of text elements is added as
       
   470 * a child to the current element. This may be followed by several more
       
   471 * text elements in the source buffer.  
       
   472 */
       
   473 
       
   474 static 
       
   475 NW_Status_t
       
   476 Text_CB (NW_WBXML_Parser_t *parser, 
       
   477          NW_Uint32 val, 
       
   478          void *context)
       
   479 {
       
   480   NW_Status_t status = NW_STAT_SUCCESS;
       
   481   
       
   482   NW_TinyTree_Node_t* text_node;
       
   483   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)context;
       
   484 
       
   485   NW_REQUIRED_PARAM(parser);
       
   486   NW_REQUIRED_PARAM(val);
       
   487 
       
   488   /*We're getting content but aren't yet accumulating text */
       
   489   if((GET_STATE(tiny_parser)==T_PARSE_S_CONTENT)
       
   490      &&((tiny_parser->state & T_PARSE_FLAG_TEXT) != T_PARSE_FLAG_TEXT)){
       
   491 
       
   492     switch(GET_PASS(tiny_parser)){
       
   493     case T_PARSE_PASS_1:
       
   494       tiny_parser->node_count++;
       
   495       break;
       
   496     case T_PARSE_PASS_2:
       
   497       /* Attach text as child to current node. */
       
   498 
       
   499       if(tiny_parser->current_node != NULL)
       
   500       {
       
   501        text_node = NW_TinyTree_createChild(&(tiny_parser->dom_tree->tree), 
       
   502                                           tiny_parser->current_node, 
       
   503                                           tiny_parser->content_offset);
       
   504        if (text_node != NULL){
       
   505          NW_TinyTree_Node_setUserFlags(text_node, T_DOM_NODE_TEXT);
       
   506        }
       
   507        else{
       
   508          status = NW_STAT_FAILURE;
       
   509        }      
       
   510       }
       
   511       else
       
   512       {
       
   513        status = NW_STAT_FAILURE;
       
   514       }  
       
   515       break;
       
   516     default:
       
   517       NW_ASSERT(NW_FALSE);
       
   518       status = NW_STAT_FAILURE;
       
   519     }
       
   520     tiny_parser->state |= T_PARSE_FLAG_TEXT;
       
   521   }
       
   522   return status;
       
   523 }
       
   524 
       
   525 
       
   526 
       
   527 static 
       
   528 NW_Status_t 
       
   529 Pass_1_InlineString_CB (NW_WBXML_Parser_t *parser, 
       
   530                         NW_Uint32 len, 
       
   531                         void *context)
       
   532 {
       
   533 
       
   534   return Text_CB(parser, len, context);
       
   535   
       
   536 }
       
   537 
       
   538 /* 
       
   539  * Pass 2 text callback to adjust the NW_Byte ordering of inline strings if needed.
       
   540  * For some string encodings (such as ucs2) this allows the application to reference
       
   541  * them directly from the original storage //TODO: Add a flag to buffer
       
   542  */
       
   543 
       
   544 static 
       
   545 NW_Status_t 
       
   546 Pass_2_InlineString_CB (NW_WBXML_Parser_t *parser, 
       
   547                         NW_Uint32 len, 
       
   548                         void *context)
       
   549 {
       
   550 
       
   551   NW_String_t string;
       
   552   NW_TinyDom_Parser_t *tiny_parser = (NW_TinyDom_Parser_t*)parser->context;
       
   553 
       
   554   
       
   555   if(tiny_parser->dom_tree->doc->charset == HTTP_iso_10646_ucs_2)
       
   556     {
       
   557      NW_WBXML_Parser_getStringInline(parser, tiny_parser->dom_tree->doc, 
       
   558             &string);
       
   559      NW_String_Ucs2_ntoh(&string);
       
   560     }
       
   561   
       
   562   return Text_CB(parser, len, context);
       
   563 }
       
   564 
       
   565 
       
   566 
       
   567 static 
       
   568 NW_Status_t 
       
   569 Extension_CB (NW_WBXML_Parser_t *parser, 
       
   570               void *context){
       
   571 
       
   572   return Text_CB(parser, 0, context);
       
   573 
       
   574 }
       
   575 
       
   576 
       
   577 static const NW_WBXML_EventHandler_t Pass_1_Handler = {
       
   578   Pass_1_StartDocument_CB,
       
   579   Pass_1_EndDocument_CB,
       
   580   Tag_Start_CB, /* PI treated exactly like tag start in pass 1 */
       
   581   0,
       
   582   Tag_Start_CB,
       
   583   Tag_End_CB,
       
   584   Attr_Start_CB,
       
   585   Attr_Val_CB,
       
   586   Content_CB,
       
   587   Pass_1_CodePage_CB,
       
   588   Extension_CB,  
       
   589   0,
       
   590   0,
       
   591   Pass_1_InlineString_CB,
       
   592   Text_CB,
       
   593   Text_CB,
       
   594   Text_CB,
       
   595   Text_CB,
       
   596   0  /*TODO: Add exception callback */
       
   597 };
       
   598 
       
   599 static const NW_WBXML_EventHandler_t Pass_2_Handler = {
       
   600   Pass_2_StartDocument_CB,
       
   601   Pass_2_EndDocument_CB,
       
   602   Pass_2_Pi_CB,
       
   603   Tag_End_CB, /* PI end treated exactly like tag end in pass 2 */
       
   604   Tag_Start_CB,
       
   605   Tag_End_CB,
       
   606   Attr_Start_CB,
       
   607   Attr_Val_CB,
       
   608   Content_CB,
       
   609   0,
       
   610   Extension_CB,  
       
   611   0,
       
   612   0,
       
   613   Pass_2_InlineString_CB,
       
   614   Text_CB,
       
   615   Text_CB,
       
   616   Text_CB,
       
   617   Text_CB,
       
   618   0
       
   619 };
       
   620 
       
   621 void
       
   622 NW_TinyDom_Tree_construct(NW_TinyDom_Tree_t* dom_tree,
       
   623                           NW_WBXML_Parser_t* parser,
       
   624                           NW_WBXML_Document_t* doc,
       
   625                           NW_WBXML_Writer_t* writer)
       
   626 {
       
   627   NW_ASSERT(dom_tree != NULL);
       
   628   dom_tree->doc = doc;
       
   629   dom_tree->parser = parser;
       
   630   dom_tree->writer = writer;
       
   631   dom_tree->root_node = 0;
       
   632 /*  dom_tree->tree = 0;*/
       
   633 }
       
   634 
       
   635 void
       
   636 NW_TinyDom_Tree_destruct(NW_TinyDom_Tree_t* dom_tree)
       
   637 {
       
   638   if (dom_tree != NULL) {
       
   639     NW_TinyTree_destruct(&(dom_tree->tree));
       
   640   }
       
   641 }
       
   642 
       
   643 EXPORT_C void
       
   644 NW_TinyDom_Parser_construct(NW_TinyDom_Parser_t* dom_parser,
       
   645                             NW_TinyDom_Tree_t *dom_tree)
       
   646 {
       
   647   dom_parser->state = 0;
       
   648   dom_parser->node_count = 0;
       
   649   dom_parser->cp_count = 0;
       
   650   dom_parser->current_node = 0;
       
   651   dom_parser->content_offset = 0;
       
   652   dom_parser->dom_tree = dom_tree;
       
   653 }
       
   654 
       
   655 /* Build the tree by running pass 1 and pass 2. */
       
   656 
       
   657 /* TODO: ADD OUT OF MEMORY HANDLER!!!  */
       
   658 
       
   659 NW_Status_t
       
   660 NW_TinyDom_Parser_buildTree(NW_TinyDom_Parser_t *dom_parser, 
       
   661                             char *buffer, 
       
   662                             NW_Uint32 buffsize,
       
   663                             NW_Bool freeBuff)
       
   664 {
       
   665 
       
   666   NW_Status_t status;
       
   667   NW_WBXML_CP_Registry_Entry_t* registry;
       
   668   NW_WBXML_Dictionary_t* dictionary = NULL;
       
   669   NW_String_t string;
       
   670 
       
   671   /* Run pass 1 (count nodes and code page switches) */
       
   672 
       
   673   status = NW_WBXML_Parser_registerHandler(dom_parser->dom_tree->parser, 
       
   674                                            &Pass_1_Handler, 
       
   675                                            (void *) dom_parser);
       
   676   if (status != NW_STAT_SUCCESS){
       
   677     return status;
       
   678   }
       
   679   status = NW_WBXML_Parser_parseBuffer (dom_parser->dom_tree->parser, 
       
   680                                         dom_parser->dom_tree->doc, 
       
   681                                         (NW_Byte *) buffer, buffsize);
       
   682 
       
   683   if (status != NW_STAT_SUCCESS){
       
   684     return status;
       
   685   }
       
   686 
       
   687   /* Initialize the writer */
       
   688 
       
   689   /* First get the dictionary */
       
   690   dictionary = NW_WBXML_Dictionary_getByIndex(dom_parser->dom_tree->parser->dictionary);
       
   691   
       
   692   if(dictionary == NULL){
       
   693     return NW_STAT_FAILURE;
       
   694   }
       
   695   
       
   696   /* Initialize the writer */
       
   697 
       
   698   NW_WBXML_Writer_Initialize(dom_parser->dom_tree->writer,
       
   699                              0, NULL,
       
   700                              NULL,
       
   701                              dictionary,
       
   702                              dictionary,
       
   703                              NW_Encoder_StringTable_getStringTableOffset,
       
   704                              NW_Encoder_StringTable_addToStringTable,
       
   705                              dom_parser->dom_tree->doc->strtbl_extension,
       
   706                              NW_Encoder_StringTable_StringTableIterateInit,
       
   707                              NW_Encoder_StringTable_StringTableIterateNext,
       
   708                              NW_TRUE  /* sizing only pass */);
       
   709 
       
   710   /* Setup the tree and any code page registry */
       
   711 
       
   712   status = NW_TinyTree_construct(&(dom_parser->dom_tree->tree),
       
   713                         (CXML_Vector_Metric_t)(dom_parser->node_count/4 + 2),
       
   714                         buffer,
       
   715                         buffsize,
       
   716                         (void*)dom_parser,
       
   717                         freeBuff);
       
   718   if (status != NW_STAT_SUCCESS) {
       
   719     return status;
       
   720   }
       
   721 
       
   722   /* TODO: move all of this down into the wbxml parser itself */
       
   723   if(dom_parser->cp_count > 0){
       
   724     /* There are code page switches, so add a code page registry */
       
   725     registry = (NW_WBXML_CP_Registry_Entry_t*) 
       
   726       NW_Mem_Malloc((dom_parser->cp_count + 1) * sizeof (NW_WBXML_CP_Registry_Entry_t));
       
   727     if (registry == NULL){
       
   728       return NW_STAT_OUT_OF_MEMORY;
       
   729     }
       
   730 
       
   731     NW_Mem_memset(registry, 0, (dom_parser->cp_count + 1) * sizeof (NW_WBXML_CP_Registry_Entry_t) );
       
   732 
       
   733 
       
   734     status = NW_WBXML_Parser_addCPRegistry(dom_parser->dom_tree->parser, 
       
   735                                            registry, dom_parser->cp_count);
       
   736     if (status != NW_STAT_SUCCESS){
       
   737       return status;
       
   738     }
       
   739   }
       
   740   /* Run pass 2 (build tree and any code page registry) */
       
   741   NW_WBXML_Parser_reset (dom_parser->dom_tree->parser); 
       
   742   NW_WBXML_Parser_registerHandler (dom_parser->dom_tree->parser, 
       
   743                                    &Pass_2_Handler, 
       
   744                                    (void*) dom_parser);
       
   745   if(dom_parser->dom_tree->doc->charset == HTTP_iso_10646_ucs_2){
       
   746     string.storage = dom_parser->dom_tree->doc->strtbl.data;
       
   747     string.length = dom_parser->dom_tree->doc->strtbl.length;
       
   748 
       
   749     if (string.length)
       
   750       NW_String_Ucs2_ntoh(&string);
       
   751   }
       
   752   /* set last valid to undefined for non-appending dom tree parsing */
       
   753   NW_TinyDom_setLastValid(dom_parser->dom_tree, -1);
       
   754   status = NW_WBXML_Parser_parseBuffer(dom_parser->dom_tree->parser, 
       
   755                                        dom_parser->dom_tree->doc, 
       
   756                                        (NW_Byte *) buffer, 
       
   757                                        buffsize);
       
   758   if (status != NW_STAT_SUCCESS){
       
   759     return status;
       
   760   }
       
   761 
       
   762   return NW_STAT_SUCCESS;
       
   763 }
       
   764 
       
   765 /**********************************************************
       
   766 */
       
   767 NW_Status_t
       
   768 NW_TinyDom_Parser_incrementalBuildTree(
       
   769                                        NW_TinyDom_Parser_t *dom_parser, 
       
   770                                        char *buffer, 
       
   771                                        NW_Uint32 buffsize,
       
   772                                        NW_Bool freeBuff,
       
   773                                        NW_Int32 lastValid)
       
   774 {
       
   775   
       
   776   NW_Status_t status;
       
   777   NW_WBXML_CP_Registry_Entry_t *old_registry, *registry;
       
   778   NW_WBXML_Dictionary_t* dictionary = NULL;
       
   779   NW_Uint32 old_cp_offset = 0;
       
   780   NW_String_t string;
       
   781 
       
   782   if (dom_parser->dom_tree->tree.tree == NULL)
       
   783   {
       
   784     status = NW_TinyTree_construct(&(dom_parser->dom_tree->tree),
       
   785       (CXML_Vector_Metric_t)(10),/*todo: remove hardcode number */
       
   786       buffer,
       
   787       buffsize,
       
   788       (void*)dom_parser,
       
   789       freeBuff);
       
   790     if (status != NW_STAT_SUCCESS) {
       
   791       goto finish_ibuildtree;
       
   792     }
       
   793   }
       
   794   /* Initialize the writer */
       
   795   if (dom_parser->dom_tree->parser->dictionary == 0)
       
   796   {
       
   797     dom_parser->dom_tree->parser->p = (NW_Byte *)buffer;
       
   798     dom_parser->dom_tree->parser->left = buffsize;
       
   799     if ((status = NW_WBXML_Parser_docHeaderParse (dom_parser->dom_tree->parser, dom_parser->dom_tree->doc))
       
   800       != NW_STAT_SUCCESS)
       
   801       goto finish_ibuildtree;
       
   802     
       
   803     /* Now get the dictionary from the document */
       
   804     
       
   805     if (dom_parser->dom_tree->doc->publicid > 0){
       
   806       dom_parser->dom_tree->parser->dictionary =
       
   807         NW_WBXML_Dictionary_getIndexByPublicId (dom_parser->dom_tree->doc->publicid);
       
   808     }
       
   809     
       
   810     else if (dom_parser->dom_tree->doc->doc_type){
       
   811       dom_parser->dom_tree->parser->dictionary =
       
   812         NW_WBXML_Dictionary_getIndexByDocType (dom_parser->dom_tree->doc->doc_type, dom_parser->dom_tree->doc->charset);
       
   813     }
       
   814     
       
   815     /* If a dictionary could not be attained try using the default public id */
       
   816     if (dom_parser->dom_tree->parser->dictionary == 0){
       
   817       dom_parser->dom_tree->doc->publicid = dom_parser->dom_tree->doc->default_public_id;
       
   818       dom_parser->dom_tree->parser->dictionary =
       
   819         NW_WBXML_Dictionary_getIndexByPublicId (dom_parser->dom_tree->doc->publicid);
       
   820     }
       
   821     
       
   822     /* Make the StartDocument callback */
       
   823     /* Run pass 2 (build tree and any code page registry) */
       
   824     NW_WBXML_Parser_registerHandler (dom_parser->dom_tree->parser, 
       
   825       &Pass_2_Handler, 
       
   826       (void*) dom_parser);
       
   827     SET_PASS(dom_parser, T_PARSE_PASS_2);
       
   828     
       
   829     if (dom_parser->dom_tree->parser->handler && dom_parser->dom_tree->parser->handler->StartDocument_CB)
       
   830     {
       
   831       status = (*(dom_parser->dom_tree->parser->handler->StartDocument_CB)) (dom_parser->dom_tree->parser, 
       
   832         dom_parser->dom_tree->doc, dom_parser);
       
   833       if (status != NW_STAT_SUCCESS)
       
   834         goto finish_ibuildtree;
       
   835     }  
       
   836     
       
   837     /* Initialize the writer */
       
   838     NW_WBXML_Writer_Initialize(dom_parser->dom_tree->writer,
       
   839       0, NULL,
       
   840       NULL,
       
   841       dictionary,
       
   842       dictionary,
       
   843       NW_Encoder_StringTable_getStringTableOffset,
       
   844       NW_Encoder_StringTable_addToStringTable,
       
   845       dom_parser->dom_tree->doc->strtbl_extension,
       
   846       NW_Encoder_StringTable_StringTableIterateInit,
       
   847       NW_Encoder_StringTable_StringTableIterateNext,
       
   848       NW_TRUE  /* sizing only pass */);
       
   849   }
       
   850   else
       
   851   {
       
   852     dom_parser->dom_tree->parser->p = (NW_Byte *)buffer + dom_parser->dom_tree->parser->offset;
       
   853     dom_parser->dom_tree->parser->left = buffsize - dom_parser->dom_tree->parser->offset;
       
   854     
       
   855     // copy the previous Ebuffer to overwrite the previous part of wbxml buffer.
       
   856     // since the previous part has native endianess, the conversion of endianess 
       
   857     // (big endian to little endian) only occurs to new contents.
       
   858     (void)NW_Mem_memcpy( 
       
   859       buffer, dom_parser->dom_tree->tree.ebuffer->segmentList->storage,
       
   860       dom_parser->dom_tree->parser->offset);
       
   861 
       
   862   }
       
   863   /* First get the dictionary */
       
   864   dictionary = NW_WBXML_Dictionary_getByIndex(dom_parser->dom_tree->parser->dictionary);
       
   865   
       
   866   if(dictionary == NULL){
       
   867     status = NW_STAT_FAILURE;
       
   868     goto finish_ibuildtree;
       
   869   }
       
   870   
       
   871   /* Setup the tree and any code page registry */
       
   872   
       
   873   
       
   874   NW_TinyDom_setLastValid(dom_parser->dom_tree, lastValid);
       
   875   
       
   876   /* TODO: move all of this down into the wbxml parser itself */
       
   877   if(dom_parser->cp_count > 0){
       
   878     /* There are code page switches, so add a code page registry */
       
   879     old_registry = dom_parser->dom_tree->parser->cp_registry.storage;
       
   880     registry = (NW_WBXML_CP_Registry_Entry_t*)NW_Mem_Malloc((dom_parser->cp_count + 1) * sizeof (NW_WBXML_CP_Registry_Entry_t));
       
   881     if (registry == NULL){
       
   882       status = NW_STAT_OUT_OF_MEMORY;
       
   883       goto finish_ibuildtree;
       
   884     }
       
   885 
       
   886     NW_Mem_memset(registry, 0, ( (dom_parser->cp_count + 1) * sizeof (NW_WBXML_CP_Registry_Entry_t) ) );
       
   887     if (old_registry)
       
   888     {
       
   889       old_cp_offset = dom_parser->dom_tree->parser->cp_registry.current - dom_parser->dom_tree->parser->cp_registry.storage;
       
   890       NW_Mem_memcpy(registry, old_registry, 
       
   891         dom_parser->dom_tree->parser->cp_registry.count*sizeof(NW_WBXML_CP_Registry_Entry_t));
       
   892       NW_Mem_Free(old_registry);
       
   893     }
       
   894     status = NW_WBXML_Parser_addCPRegistry(dom_parser->dom_tree->parser, 
       
   895       registry, dom_parser->cp_count);
       
   896     if (status != NW_STAT_SUCCESS){
       
   897       goto finish_ibuildtree;
       
   898     }
       
   899     dom_parser->dom_tree->parser->cp_registry.current = registry + old_cp_offset;
       
   900     // WLIU_DEBUG: dom_parser->dom_tree->parser->cp_registry.realcount = old_cp_offset;
       
   901     /* Make sure flag is not set, so that new cp entry could be added to the registry */
       
   902     dom_parser->dom_tree->parser->flags &= ~NW_WBXML_REGISTRY_INIT; 
       
   903   }
       
   904   
       
   905   //NW_WBXML_Parser_reset (dom_parser->dom_tree->parser); 
       
   906   
       
   907   /* Run pass 2 (build tree and any code page registry) */
       
   908   NW_WBXML_Parser_registerHandler (dom_parser->dom_tree->parser, 
       
   909     &Pass_2_Handler, 
       
   910     (void*) dom_parser);
       
   911   SET_PASS(dom_parser, T_PARSE_PASS_2);
       
   912   SET_STATE(dom_parser, T_PARSE_S_CONTENT);
       
   913   dom_parser->state &= ~T_PARSE_FLAG_TEXT; /* prepare for text */
       
   914   
       
   915   // convert endianess if necessary
       
   916   if(dom_parser->dom_tree->doc->charset == HTTP_iso_10646_ucs_2){
       
   917     string.storage = dom_parser->dom_tree->doc->strtbl.data;
       
   918     string.length = dom_parser->dom_tree->doc->strtbl.length;
       
   919     if (string.length)
       
   920       NW_String_Ucs2_ntoh(&string);
       
   921   }
       
   922 
       
   923   NW_TinyTree_EBuffer_Destruct (dom_parser->dom_tree->tree.ebuffer );
       
   924   
       
   925   dom_parser->dom_tree->tree.ebuffer = NW_TinyTree_EBuffer_Construct((NW_Byte *)buffer, 
       
   926     buffsize, 
       
   927     NW_TINY_TREE_BLOCK_SIZE_DEFAULT,
       
   928     freeBuff);
       
   929   
       
   930   status = NW_WBXML_Parser_parseBuffer(dom_parser->dom_tree->parser, 
       
   931     dom_parser->dom_tree->doc, 
       
   932     (NW_Byte *) buffer, 
       
   933     buffsize);
       
   934   //WLIU_DEBUG: dom_parser->dom_tree->parser->lastValid = NW_TinyDom_getLastValid(dom_parser->dom_tree);
       
   935   if (status != NW_STAT_SUCCESS){
       
   936     goto finish_ibuildtree;
       
   937   }
       
   938   dom_parser->dom_tree->parser->offset = NW_TinyDom_getLastValid(dom_parser->dom_tree);
       
   939 finish_ibuildtree:
       
   940   return status;
       
   941 }
       
   942 
       
   943 /*****************************************************************************
       
   944 */
       
   945 /* Get a pointer to the dom parser from the tiny tree */
       
   946 
       
   947 EXPORT_C NW_TinyDom_Parser_t*
       
   948 NW_TinyDom_getParser(NW_TinyTree_t *tree)
       
   949 
       
   950 {
       
   951   return (NW_TinyDom_Parser_t*)NW_TinyTree_getContext(tree);
       
   952 }
       
   953 
       
   954 /* Get a pointer to the dom tree from a tiny tree */
       
   955 
       
   956 EXPORT_C NW_TinyDom_Tree_t*
       
   957 NW_TinyDom_getTree(NW_TinyTree_t *tree)
       
   958 
       
   959 {
       
   960 
       
   961   NW_TinyDom_Parser_t *dom_parser;
       
   962 
       
   963   dom_parser = NW_TinyDom_getParser(tree);
       
   964   if(dom_parser != NULL){
       
   965     return dom_parser->dom_tree;
       
   966   }
       
   967   return NULL;
       
   968 }
       
   969 
       
   970 /* Get the doc header from the tiny tree */
       
   971 
       
   972 NW_WBXML_Document_t *
       
   973 NW_TinyDom_getDocHeader(NW_TinyTree_t *tree)
       
   974 
       
   975 {
       
   976   NW_TinyDom_Tree_t *dom_tree = NW_TinyDom_getTree(tree);
       
   977 
       
   978   if(dom_tree != NULL){
       
   979     return dom_tree->doc;
       
   980   }
       
   981   return NULL;
       
   982 }
       
   983 
       
   984 /* Deserialization API */
       
   985 
       
   986 NW_Uint16
       
   987 NW_TinyDom_Node_getType(NW_TinyTree_Node_t* node){
       
   988   return (NW_Uint16)(NW_TinyTree_Node_getFlags(node) & TNODE_USR_FLAGS);
       
   989 }
       
   990 
       
   991 /* Deserialization callbacks */
       
   992 
       
   993 
       
   994 /* 
       
   995 * Tag callbacks 
       
   996 * TODO: Combine these with the rest of the pass 3 callbacks
       
   997 */
       
   998 
       
   999 static 
       
  1000 NW_Status_t 
       
  1001 T_Tag_Start_CB (NW_WBXML_Parser_t *parser, 
       
  1002                 void *context)
       
  1003 {
       
  1004   NW_TinyDom_Tag_t *tag = (NW_TinyDom_Tag_t*)context;
       
  1005   NW_TinyDom_Parser_t *tiny_parser = tag->tiny_parser;
       
  1006 
       
  1007   NW_REQUIRED_PARAM(parser);
       
  1008 
       
  1009   SET_STATE(tiny_parser, T_PARSE_S_TAG_START);
       
  1010   return NW_STAT_SUCCESS;
       
  1011 }
       
  1012 
       
  1013 static 
       
  1014 NW_Status_t 
       
  1015 T_FQToken_CB (NW_WBXML_Parser_t *parser, 
       
  1016               NW_Uint32 token, 
       
  1017               void *context){
       
  1018 
       
  1019   NW_TinyDom_Tag_t *tag = (NW_TinyDom_Tag_t*)context;
       
  1020   NW_TinyDom_Parser_t *tiny_parser = tag->tiny_parser;
       
  1021 
       
  1022   NW_REQUIRED_PARAM(parser);
       
  1023 
       
  1024   switch (GET_STATE(tiny_parser)){ 
       
  1025   case T_PARSE_S_TAG_START:
       
  1026     tag->fq_token = token;
       
  1027     break;
       
  1028   default:
       
  1029     return NW_STAT_SUCCESS;
       
  1030   }
       
  1031   return NW_STAT_SUCCESS;
       
  1032 }
       
  1033 
       
  1034 static 
       
  1035 NW_Status_t 
       
  1036 T_TableString_CB (NW_WBXML_Parser_t *parser, 
       
  1037                   NW_Uint32 index, 
       
  1038                   void *context)
       
  1039 {
       
  1040   NW_TinyDom_Tag_t *tag = (NW_TinyDom_Tag_t*)context;
       
  1041   NW_TinyDom_Parser_t *tiny_parser = tag->tiny_parser;
       
  1042 
       
  1043   NW_REQUIRED_PARAM(parser);
       
  1044 
       
  1045   switch (GET_STATE(tiny_parser)){ 
       
  1046   case T_PARSE_S_TAG_START:
       
  1047     tag->name_index = index;
       
  1048     break;
       
  1049   default:
       
  1050     return NW_STAT_SUCCESS;
       
  1051   }
       
  1052   return NW_STAT_SUCCESS;
       
  1053 }
       
  1054 
       
  1055 static const NW_WBXML_EventHandler_t Tag_Handler = {
       
  1056   0,
       
  1057   0,
       
  1058   0,
       
  1059   0,
       
  1060   T_Tag_Start_CB,
       
  1061   0,
       
  1062   0,
       
  1063   0,
       
  1064   0,
       
  1065   0,
       
  1066   0,  
       
  1067   0,
       
  1068   T_FQToken_CB,
       
  1069   0,
       
  1070   T_TableString_CB,
       
  1071   0,
       
  1072   0,
       
  1073   0,
       
  1074   0
       
  1075 };
       
  1076 
       
  1077 
       
  1078 /* 
       
  1079 * Pass 3 callbacks. These are called by the parser when deserializing
       
  1080 * text and attributes. Since text elements are just a subset of
       
  1081 * attribute elements, almost exactly the same callbacks can be used
       
  1082 * for both.
       
  1083 *
       
  1084 * Note that parser state between callbacks is only meaningful if the
       
  1085 * callbacks are part of an atomic sequence. Such sequences always
       
  1086 * start with an Attr_Start, Attr_Val or Content callback, followed by
       
  1087 * one of the data type callbacks. Any attempt to use the parser state
       
  1088 * machine in another way is not reentrant.  
       
  1089 */
       
  1090 
       
  1091 static 
       
  1092 NW_Status_t 
       
  1093 Pass_3_Attr_Start_CB (NW_WBXML_Parser_t *parser, 
       
  1094                       void *context)
       
  1095 {
       
  1096   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1097   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1098 
       
  1099   NW_REQUIRED_PARAM(parser);
       
  1100 
       
  1101   SET_STATE(tiny_parser, T_PARSE_S_ATTR_START);
       
  1102   return NW_STAT_SUCCESS;
       
  1103 }
       
  1104 
       
  1105 static 
       
  1106 NW_Status_t 
       
  1107 Pass_3_Attr_Val_CB (NW_WBXML_Parser_t *parser, 
       
  1108                     void *context)
       
  1109 {
       
  1110   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1111   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1112 
       
  1113   NW_REQUIRED_PARAM(parser);
       
  1114 
       
  1115   SET_STATE(tiny_parser, T_PARSE_S_ATTR_VALS);
       
  1116   return NW_STAT_SUCCESS;
       
  1117 }
       
  1118 
       
  1119 static 
       
  1120 NW_Status_t 
       
  1121 Pass_3_Content_CB (NW_WBXML_Parser_t *parser, 
       
  1122                    void *context)
       
  1123 {
       
  1124   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1125   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1126 
       
  1127   NW_REQUIRED_PARAM(parser);
       
  1128 
       
  1129   SET_STATE(tiny_parser, T_PARSE_S_CONTENT);
       
  1130   return NW_STAT_SUCCESS;
       
  1131 }
       
  1132 
       
  1133 
       
  1134 static 
       
  1135 NW_Status_t 
       
  1136 Pass_3_Extension_CB (NW_WBXML_Parser_t *parser, 
       
  1137                      void *context)
       
  1138 {
       
  1139   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1140   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1141 
       
  1142   NW_REQUIRED_PARAM(parser);
       
  1143 
       
  1144   /* Set the extension substate flag */
       
  1145   tiny_parser->state |= T_PARSE_F_EXT;
       
  1146   return NW_STAT_SUCCESS;
       
  1147 }
       
  1148 
       
  1149 
       
  1150 static 
       
  1151 NW_Status_t 
       
  1152 Pass_3_FQToken_CB (NW_WBXML_Parser_t *parser, 
       
  1153                    NW_Uint32 token, 
       
  1154                    void *context)
       
  1155 {
       
  1156   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1157   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1158   NW_TinyDom_AttrVal_t* attr_val = (NW_TinyDom_AttrVal_t*)(handle->value);
       
  1159 
       
  1160   NW_REQUIRED_PARAM(parser);
       
  1161 
       
  1162   switch (GET_STATE(tiny_parser)){ 
       
  1163   case T_PARSE_S_ATTR_START:
       
  1164     handle->fq_token = token;
       
  1165     break;
       
  1166   case T_PARSE_S_ATTR_VALS:
       
  1167   case T_PARSE_S_CONTENT:
       
  1168     if((tiny_parser->state & T_PARSE_F_EXT) == T_PARSE_F_EXT){
       
  1169       attr_val->type = NW_WBXML_ATTR_COMPONENT_EXT;
       
  1170       attr_val->component.ext.type
       
  1171         = (NW_Uint8)((tiny_parser->dom_tree->parser->ext_t_not_table_index) ?
       
  1172            NW_TINYDOM_EXTENSION_TYPE_EXT_T_INTEGER
       
  1173            : NW_TINYDOM_EXTENSION_TYPE_NORMAL);
       
  1174       attr_val->component.ext.token = token;
       
  1175       attr_val->component.ext.value.string.length = 0;
       
  1176       attr_val->component.ext.value.string.storage = NULL;
       
  1177     }
       
  1178     else{ /*TODO: NW_ASSERT that this is not called with T_PARSE_S_ATTR_CONTENT? */
       
  1179       attr_val->type = NW_WBXML_ATTR_COMPONENT_TOKEN;
       
  1180       attr_val->component.value_token = token;
       
  1181     }
       
  1182     break;
       
  1183   default:
       
  1184     break;
       
  1185   }
       
  1186   return NW_STAT_SUCCESS;
       
  1187 }
       
  1188 
       
  1189 static 
       
  1190 NW_Status_t 
       
  1191 Pass_3_InlineString_CB (NW_WBXML_Parser_t *parser, 
       
  1192                         NW_Uint32 len, 
       
  1193                         void *context)
       
  1194 {
       
  1195   NW_Status_t status;
       
  1196   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1197   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1198   NW_TinyDom_AttrVal_t* attr_val = (NW_TinyDom_AttrVal_t*)(handle->value);
       
  1199 
       
  1200   NW_REQUIRED_PARAM(len);
       
  1201 
       
  1202   switch (GET_STATE(tiny_parser)){ 
       
  1203   case T_PARSE_S_ATTR_VALS:
       
  1204   case T_PARSE_S_CONTENT:
       
  1205     if((tiny_parser->state & T_PARSE_F_EXT) == T_PARSE_F_EXT){
       
  1206       status = NW_WBXML_Parser_getStringInline(parser, 
       
  1207                                                tiny_parser->dom_tree->doc, 
       
  1208                                                &(attr_val->component.ext.value.string));
       
  1209       if(status != NW_STAT_SUCCESS){
       
  1210         return status;
       
  1211       }
       
  1212       tiny_parser->state &= ~T_PARSE_F_EXT; /* Unset extension sub-state */
       
  1213     }
       
  1214     else{ 
       
  1215       attr_val->type = NW_WBXML_ATTR_COMPONENT_STRING;
       
  1216       status = NW_WBXML_Parser_getStringInline(parser, 
       
  1217                                                tiny_parser->dom_tree->doc, 
       
  1218                                                &(attr_val->component.string)); 
       
  1219       if(status != NW_STAT_SUCCESS){
       
  1220         return status;
       
  1221       }
       
  1222 
       
  1223     }
       
  1224     break;
       
  1225   default:
       
  1226     break;
       
  1227   }
       
  1228   return NW_STAT_SUCCESS;
       
  1229 }
       
  1230 
       
  1231 static 
       
  1232 NW_Status_t 
       
  1233 Pass_3_TableString_CB (NW_WBXML_Parser_t *parser, 
       
  1234                        NW_Uint32 index, 
       
  1235                        void *context)
       
  1236 {
       
  1237   NW_Status_t status;
       
  1238   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1239   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1240   NW_TinyDom_AttrVal_t* attr_val = (NW_TinyDom_AttrVal_t*)(handle->value);
       
  1241 
       
  1242   NW_REQUIRED_PARAM(parser);
       
  1243 
       
  1244   switch (GET_STATE(tiny_parser)){
       
  1245   case T_PARSE_S_ATTR_START:
       
  1246     handle->name_index = index;
       
  1247     break;
       
  1248   case T_PARSE_S_ATTR_VALS:
       
  1249   case T_PARSE_S_CONTENT:
       
  1250     if((tiny_parser->state & T_PARSE_F_EXT) == T_PARSE_F_EXT){
       
  1251       status = NW_WBXML_Document_getTableString(tiny_parser->dom_tree->doc, 
       
  1252                                                 index, 
       
  1253                                                 &(attr_val->component.ext.value.string));
       
  1254       if(status != NW_STAT_SUCCESS){
       
  1255         return status;
       
  1256       }
       
  1257       tiny_parser->state &= ~T_PARSE_F_EXT; /* Unset extension sub-state */
       
  1258     }
       
  1259     else{ 
       
  1260       attr_val->type = NW_WBXML_ATTR_COMPONENT_STRING;
       
  1261       status = NW_WBXML_Document_getTableString(tiny_parser->dom_tree->doc, 
       
  1262                                                 index, 
       
  1263                                                 &(attr_val->component.string));
       
  1264       if(status != NW_STAT_SUCCESS){
       
  1265         return status;
       
  1266       } 
       
  1267     }
       
  1268     break;
       
  1269   default:
       
  1270     break;
       
  1271   }
       
  1272   return NW_STAT_SUCCESS;
       
  1273 }
       
  1274 
       
  1275 
       
  1276 /* TODO: Fill in. This is to get inline integers */
       
  1277 
       
  1278 static 
       
  1279 NW_Status_t 
       
  1280 Pass_3_Binary_CB (NW_WBXML_Parser_t *parser, 
       
  1281                   NW_Uint32 x,
       
  1282                   void *context)
       
  1283 {
       
  1284   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1285   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1286 
       
  1287   NW_REQUIRED_PARAM(parser);
       
  1288 
       
  1289   if ((tiny_parser->state & T_PARSE_F_EXT) == T_PARSE_F_EXT) {
       
  1290     NW_TinyDom_AttrVal_t* attr_val = (NW_TinyDom_AttrVal_t*)(handle->value);
       
  1291     attr_val->component.ext.value.x = x;
       
  1292   }
       
  1293   tiny_parser->state &= ~T_PARSE_F_EXT; /* Unset extension sub-state */
       
  1294   return NW_STAT_SUCCESS;
       
  1295 }
       
  1296 
       
  1297 static 
       
  1298 NW_Status_t 
       
  1299 Pass_3_Opaque_CB (NW_WBXML_Parser_t *parser, 
       
  1300                   NW_Uint32 len, 
       
  1301                   void *context)
       
  1302 {
       
  1303   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;  
       
  1304   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1305   NW_TinyDom_AttrVal_t* attr_val = (NW_TinyDom_AttrVal_t*)(handle->value);
       
  1306 
       
  1307   switch (GET_STATE(tiny_parser)){ 
       
  1308   case T_PARSE_S_ATTR_VALS:
       
  1309   case T_PARSE_S_CONTENT:
       
  1310     attr_val->type = NW_WBXML_ATTR_COMPONENT_OPAQUE;
       
  1311     NW_WBXML_Parser_getOpaque(parser, len, &(attr_val->component.opaque)); 
       
  1312     break;
       
  1313   default:
       
  1314       break;
       
  1315   }
       
  1316   return NW_STAT_SUCCESS;
       
  1317 }
       
  1318 
       
  1319 static NW_Status_t 
       
  1320 Pass_3_Entity_CB (NW_WBXML_Parser_t *parser, 
       
  1321                   NW_Uint32 e, 
       
  1322                   void *context)
       
  1323 {
       
  1324   NW_TinyDom_AttributeHandle_t *handle = (NW_TinyDom_AttributeHandle_t*)context;
       
  1325   NW_TinyDom_Parser_t *tiny_parser = handle->tlit.tiny_parser;
       
  1326   NW_TinyDom_AttrVal_t* attr_val = (NW_TinyDom_AttrVal_t*)(handle->value);
       
  1327 
       
  1328   NW_REQUIRED_PARAM(parser);
       
  1329 
       
  1330   switch (GET_STATE(tiny_parser)){ 
       
  1331   case T_PARSE_S_ATTR_VALS:
       
  1332   case T_PARSE_S_CONTENT:
       
  1333     attr_val->type = NW_WBXML_ATTR_COMPONENT_ENTITY;
       
  1334     attr_val->component.entity = e;
       
  1335     break;
       
  1336   default:
       
  1337     break;
       
  1338   }
       
  1339   return NW_STAT_SUCCESS;
       
  1340 }
       
  1341 
       
  1342 
       
  1343 static const NW_WBXML_EventHandler_t Pass_3_Handler = {
       
  1344   0,
       
  1345   0,
       
  1346   0,
       
  1347   0,
       
  1348   0,
       
  1349   0,
       
  1350   Pass_3_Attr_Start_CB,
       
  1351   Pass_3_Attr_Val_CB,
       
  1352   Pass_3_Content_CB,
       
  1353   0,
       
  1354   Pass_3_Extension_CB,  
       
  1355   0,
       
  1356   Pass_3_FQToken_CB,
       
  1357   Pass_3_InlineString_CB,
       
  1358   Pass_3_TableString_CB,
       
  1359   Pass_3_Binary_CB,
       
  1360   Pass_3_Opaque_CB,
       
  1361   Pass_3_Entity_CB,
       
  1362   0
       
  1363 };
       
  1364 
       
  1365 
       
  1366 /*
       
  1367 * The tiny list iterator is a generic iterator that 
       
  1368 * can be used to invoke parser iterator methods.
       
  1369 */
       
  1370 
       
  1371 static void
       
  1372 TinyDom_ListIterator_init(NW_TinyDom_ListIterator_t *it, 
       
  1373                           NW_TinyDom_Parser_t *tiny_parser, 
       
  1374                           NW_TinyTree_Node_t *list_node, 
       
  1375                           void *context){
       
  1376   it->tiny_parser = tiny_parser;
       
  1377   NW_TinyTree_Node_GetSegmentAndOffset(&(tiny_parser->dom_tree->tree),list_node, (NW_Uint8**)&(it->segment), &(it->segSize), &(it->offset));
       
  1378   it->state = NW_STAT_WBXML_ITERATE_MORE;
       
  1379   it->context = context;
       
  1380 }
       
  1381 
       
  1382 /*
       
  1383 *
       
  1384 * This is a bit complicated: you pass in an iterator function (from
       
  1385 * the parser) that knows how to iterate the type you are interested
       
  1386 * in (e.g. attribute_iterate), and you pass in a handler that the
       
  1387 * parser iterator's callbacks will invoke.  When called, a handler
       
  1388 * receives the interator context field as the context arg.  The
       
  1389 * handler is used to select elements, gather data, etc.  
       
  1390 *
       
  1391 * This, NW_TinyDom_attribute_handle_init, and NW_TinyDom_tag_get, should
       
  1392 * not be called reentrantly (from a parser callback). This doesn't
       
  1393 * seem like a serious restriction. If this becomes a problem, the
       
  1394 * ParserSaveContext/ParserRestoreContext lines can be uncommented to
       
  1395 * make these reentrant.
       
  1396 */
       
  1397 
       
  1398 static 
       
  1399 NW_TinyTree_Offset_t
       
  1400 TinyDom_ListIterator_iterate(NW_TinyDom_ListIterator_t *it, 
       
  1401                              const NW_WBXML_EventHandler_t *handler, 
       
  1402                              NW_Status_t (*type_iterator) (NW_WBXML_Parser_t*))
       
  1403 {
       
  1404   NW_TinyTree_Offset_t startOffset;
       
  1405   NW_TinyTree_Offset_t sourceOffset;
       
  1406 
       
  1407   
       
  1408   if (it->state == NW_STAT_WBXML_ITERATE_MORE){
       
  1409    
       
  1410 
       
  1411     /* Set the parser buffer and buffer size to the values stored in the iterator */
       
  1412     NW_WBXML_Parser_resetBuffer(it->tiny_parser->dom_tree->parser, 
       
  1413                                 (NW_Byte*) it->segment, 
       
  1414                                 it->segSize);
       
  1415     
       
  1416     /* Register the callbacks */
       
  1417     NW_WBXML_Parser_registerHandler (it->tiny_parser->dom_tree->parser, 
       
  1418                                      handler, 
       
  1419                                      it->context);
       
  1420     startOffset = it->offset;
       
  1421     /* Now set the parser offset to the value stored in the iterator */
       
  1422     NW_WBXML_Parser_setOffset(it->tiny_parser->dom_tree->parser, it->offset);
       
  1423     /* Run the type iterator */
       
  1424     it->state = (NW_Uint32)(*(type_iterator))(it->tiny_parser->dom_tree->parser);
       
  1425     /* Set the new iterator offset (the segment should be unchanged)*/
       
  1426     it->offset = 
       
  1427       (NW_TinyTree_Offset_t)NW_WBXML_Parser_getOffset(it->tiny_parser->dom_tree->parser);
       
  1428 
       
  1429     if((it->tiny_parser->dom_tree->parser->status != NW_STAT_SUCCESS) ||
       
  1430        (it->offset == startOffset)){ /* Hack, hack . . The parser didn't advance. */
       
  1431         return 0;
       
  1432     }
       
  1433  
       
  1434     /* Convert the iterator offset into a source offset to return */
       
  1435 
       
  1436     NW_TinyTree_GetSourceOffset(&(it->tiny_parser->dom_tree->tree), 
       
  1437                                 (NW_Byte*) it->segment, startOffset, &sourceOffset);
       
  1438     return sourceOffset;
       
  1439   }
       
  1440   return 0;
       
  1441 }
       
  1442 
       
  1443 void
       
  1444 NW_TinyDom_AttrListHandle_init(NW_TinyDom_AttrListHandle_t *it, 
       
  1445                                NW_TinyDom_Parser_t *tiny_parser, 
       
  1446                                NW_TinyTree_Node_t *list_node)
       
  1447 {
       
  1448   TinyDom_ListIterator_init(it, tiny_parser, list_node, 0); 
       
  1449 }
       
  1450 
       
  1451 /* 
       
  1452 * Iterate through a list of attributes. There are
       
  1453 * no attribute list callbacks since we just want to iterate the
       
  1454 * attribute list, returning the start of each attribute.  
       
  1455 */
       
  1456 
       
  1457 NW_TinyTree_Offset_t
       
  1458 NW_TinyDom_AttrListHandle_iterate(NW_TinyDom_AttrListHandle_t *it){
       
  1459   /* Call list_iterate with a null handler.*/
       
  1460   return TinyDom_ListIterator_iterate(it, 0, NW_WBXML_Parser_attributeListIterate);
       
  1461 }
       
  1462 
       
  1463 /*
       
  1464 * Internal function to iterate the values of an attribute.
       
  1465 */
       
  1466 
       
  1467 NW_TinyTree_Offset_t
       
  1468 NW_TinyDom_AttributeHandle_valsIterate(NW_TinyDom_ListIterator_t *it)
       
  1469 {
       
  1470   return TinyDom_ListIterator_iterate(it, &Pass_3_Handler, NW_WBXML_Parser_attributeValsIterate);
       
  1471 }
       
  1472 
       
  1473 /*String indexes must be less than the largest offset */
       
  1474 #define ILLEGAL_STRING_INDEX ((NW_TinyTree_Offset_t)~0) 
       
  1475 
       
  1476 /*
       
  1477 * Initialize an attribute handle by parsing an attribute's start
       
  1478 * token and values, calling the attribute handlers.   
       
  1479 */
       
  1480 
       
  1481 void 
       
  1482 NW_TinyDom_AttributeHandle_init(NW_TinyDom_AttributeHandle_t *handle, 
       
  1483                                 NW_TinyDom_Parser_t *tiny_parser, 
       
  1484                                 NW_TinyTree_Offset_t offset)
       
  1485 {
       
  1486   /*lint --e{794} Conceivable use of null pointer */
       
  1487 
       
  1488   NW_TinyTree_Node_t dummy_node;
       
  1489   void *segment;
       
  1490   NW_TinyTree_Offset_t segSize;
       
  1491   NW_TinyTree_Offset_t segOffset;
       
  1492 
       
  1493   handle->fq_token = 0;
       
  1494   handle->name_index = ILLEGAL_STRING_INDEX;
       
  1495   handle->value = NULL;
       
  1496   /* Run parser once to get token, name */
       
  1497   handle->tlit.tiny_parser = tiny_parser;
       
  1498 
       
  1499   /* Fill in a dummy node with the supplied source offset */
       
  1500   dummy_node.source_offset = offset;
       
  1501 
       
  1502   /* Use this to initialize the parser */
       
  1503   NW_TinyTree_Node_GetSegmentAndOffset(&(tiny_parser->dom_tree->tree), 
       
  1504                                        &dummy_node, (NW_Uint8**)&segment, &segSize, &segOffset);
       
  1505 
       
  1506   NW_WBXML_Parser_resetBuffer(tiny_parser->dom_tree->parser, (NW_Byte*) segment, segSize);
       
  1507   
       
  1508   NW_WBXML_Parser_registerHandler (tiny_parser->dom_tree->parser, &Pass_3_Handler, handle);
       
  1509   NW_WBXML_Parser_setOffset(tiny_parser->dom_tree->parser, segOffset);
       
  1510   /* Run parser once to get past name */
       
  1511   NW_WBXML_Parser_attributeNameParse(tiny_parser->dom_tree->parser);
       
  1512 
       
  1513  /* Update the dummy node source offset to reflect the parser advance */
       
  1514   segOffset = 
       
  1515       (NW_TinyTree_Offset_t)NW_WBXML_Parser_getOffset(tiny_parser->dom_tree->parser);
       
  1516 
       
  1517   NW_TinyTree_GetSourceOffset(&(tiny_parser->dom_tree->tree), (NW_Byte*) segment, 
       
  1518                               segOffset, &(dummy_node.source_offset));
       
  1519 
       
  1520   TinyDom_ListIterator_init((NW_TinyDom_ListIterator_t*)&(handle->tlit), 
       
  1521                             tiny_parser, 
       
  1522                             &dummy_node, 
       
  1523                             handle);
       
  1524 }
       
  1525 
       
  1526 /* Get tag name and token */
       
  1527 
       
  1528 static 
       
  1529 void
       
  1530 NW_TinyDom_getTag(NW_TinyDom_Parser_t* tiny_parser, 
       
  1531                   NW_TinyTree_Node_t* node, 
       
  1532                   NW_TinyDom_Tag_t* tag)
       
  1533 {
       
  1534   NW_WBXML_Parser_t *parser = tiny_parser->dom_tree->parser;
       
  1535   void *segment;
       
  1536   NW_TinyTree_Offset_t segSize;
       
  1537   NW_TinyTree_Offset_t segOffset;
       
  1538 
       
  1539   /*NW_WBXML_Parser_t saved_context; */
       
  1540 
       
  1541   tag->tiny_parser = tiny_parser;
       
  1542   /*NW_WBXML_ParserSaveContext(parser, &saved_context); */
       
  1543   
       
  1544   /* Convert the node source offset to segment and offset form */
       
  1545   NW_TinyTree_Node_GetSegmentAndOffset(&(tiny_parser->dom_tree->tree), 
       
  1546                                        node, (NW_Uint8**)&segment, &segSize, &segOffset);
       
  1547 
       
  1548   /* Use these values to init the parser */
       
  1549   NW_WBXML_Parser_resetBuffer(tiny_parser->dom_tree->parser, (NW_Byte*) segment, segSize);
       
  1550   NW_WBXML_Parser_setOffset(parser, segOffset);
       
  1551   NW_WBXML_Parser_registerHandler (parser, &Tag_Handler, tag);
       
  1552   /* Parse the tag name */
       
  1553   NW_WBXML_Parser_tagNameParse(parser);
       
  1554   /*NW_WBXML_ParserRestoreContext(parser, &saved_context); */
       
  1555 }
       
  1556 
       
  1557 EXPORT_C NW_Uint32
       
  1558 NW_TinyDom_getTagToken(NW_TinyDom_Parser_t* tiny_parser, 
       
  1559                        NW_TinyTree_Node_t* node)
       
  1560 {
       
  1561   NW_TinyDom_Tag_t tag;
       
  1562   NW_TinyDom_getTag(tiny_parser, node, &tag);
       
  1563   return tag.fq_token;
       
  1564 }
       
  1565 
       
  1566 
       
  1567 NW_Status_t
       
  1568 NW_TinyDom_getTagName(NW_TinyDom_Parser_t* tiny_parser, 
       
  1569                       NW_TinyTree_Node_t* node, 
       
  1570                       NW_String_t* name)
       
  1571 {
       
  1572   NW_TinyDom_Tag_t tag;
       
  1573 
       
  1574   tag.name_index = ILLEGAL_STRING_INDEX;
       
  1575   NW_TinyDom_getTag(tiny_parser, node, &tag);
       
  1576   
       
  1577   if(tag.name_index != ILLEGAL_STRING_INDEX){
       
  1578     /*TODO: replace ??*/
       
  1579     return NW_WBXML_Document_getTableString(tiny_parser->dom_tree->doc, 
       
  1580                                             tag.name_index, 
       
  1581                                             name); 
       
  1582   }
       
  1583   return NW_STAT_WBXML_NO_NAME;
       
  1584 }
       
  1585 
       
  1586 NW_Uint32
       
  1587 NW_TinyDom_AttributeHandle_getToken(NW_TinyDom_AttributeHandle_t *handle)
       
  1588 {
       
  1589   return handle->fq_token;
       
  1590 }
       
  1591 
       
  1592 /* getName is going to return the entire "start token" which might
       
  1593    include a value prefix */
       
  1594 NW_Status_t
       
  1595 NW_TinyDom_AttributeHandle_getName(NW_TinyDom_AttributeHandle_t *handle,  
       
  1596                                    NW_String_t *name)
       
  1597 {
       
  1598   NW_TinyDom_Parser_t * tiny_parser = handle->tlit.tiny_parser;
       
  1599 
       
  1600   if(handle->name_index != ILLEGAL_STRING_INDEX){
       
  1601     /*TODO: replace?? */
       
  1602     return NW_WBXML_Document_getTableString(tiny_parser->dom_tree->doc, 
       
  1603                                             handle->name_index, 
       
  1604                                             name);
       
  1605   }
       
  1606   return NW_STAT_WBXML_NO_NAME;
       
  1607 }
       
  1608 
       
  1609 NW_TinyTree_Offset_t
       
  1610 NW_TinyDom_AttributeHandle_iterateValues(NW_TinyDom_AttributeHandle_t* handle, 
       
  1611                                          NW_TinyDom_AttrVal_t *value)
       
  1612 {
       
  1613   handle->value = value; /* Set up handle to receive value.*/
       
  1614   return NW_TinyDom_AttributeHandle_valsIterate((NW_TinyDom_ListIterator_t*)&(handle->tlit));
       
  1615 }
       
  1616 
       
  1617 
       
  1618 /* Init a text handle */ 
       
  1619 
       
  1620 void 
       
  1621 NW_TinyDom_TextHandle_init(NW_TinyDom_TextHandle_t* handle, 
       
  1622                            NW_TinyDom_Parser_t* tiny_parser, 
       
  1623                            NW_TinyTree_Offset_t offset)
       
  1624 {
       
  1625   NW_TinyTree_Node_t dummy_node;
       
  1626 
       
  1627   dummy_node.source_offset = offset; 
       
  1628   /* Initialize the iterator with this handle as the context */
       
  1629   TinyDom_ListIterator_init((NW_TinyDom_ListIterator_t *)&(handle->tlit), 
       
  1630                             tiny_parser, 
       
  1631                             &dummy_node, 
       
  1632                             handle);
       
  1633   handle->value = NULL;
       
  1634 }
       
  1635 
       
  1636 /* Iterate through the text items in a text element, calling the text handlers */
       
  1637 
       
  1638 NW_TinyTree_Offset_t
       
  1639 NW_TinyDom_TextHandle_iterate(NW_TinyDom_TextHandle_t *handle, 
       
  1640                               NW_TinyDom_Text_t *item)
       
  1641 {
       
  1642   handle->value = item;
       
  1643   return TinyDom_ListIterator_iterate(&(handle->tlit), 
       
  1644     &Pass_3_Handler, 
       
  1645     NW_WBXML_Parser_textIterate);
       
  1646 }
       
  1647 
       
  1648 void
       
  1649 NW_TinyDom_setLastValid(NW_TinyDom_Tree_t* dom_tree, NW_Int32 lastValid)
       
  1650 {
       
  1651   NW_ASSERT(dom_tree->tree.tree != NULL);
       
  1652   dom_tree->tree.tree->lastValid = lastValid;
       
  1653 }
       
  1654 
       
  1655 
       
  1656 NW_Int32
       
  1657 NW_TinyDom_getLastValid(NW_TinyDom_Tree_t* dom_tree)
       
  1658 {
       
  1659   if (dom_tree->tree.tree == NULL)
       
  1660     return 0;
       
  1661   return dom_tree->tree.tree->lastValid;
       
  1662 }
       
  1663 
       
  1664 
       
  1665 
       
  1666 
       
  1667 
       
  1668 
       
  1669 
       
  1670 
       
  1671 
       
  1672 
       
  1673