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 |
|