|
1 /* |
|
2 * Copyright (c) 2000 - 2001 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <string.h> |
|
19 #include "cxml_internal.h" |
|
20 #include <xml/cxml/nw_encoder_wbxmlwriter.h> |
|
21 #include <xml/cxml/nw_xmlp_xmlparser.h> |
|
22 #include <xml/cxml/nw_xmlp_xmlp2wbxml.h> |
|
23 #include <xml/cxml/nw_encoder_stringtable.h> |
|
24 #include "cxml_xmlp_entity.h" |
|
25 |
|
26 |
|
27 typedef struct CXML_Encoding_String_s { |
|
28 NW_Int8* charSetStr; |
|
29 NW_Uint32 encodingVal; |
|
30 }CXML_Encoding_String_t; |
|
31 |
|
32 /* Number of encoding string supported */ |
|
33 |
|
34 #define CXML_Encoding_Str_Num 5 |
|
35 |
|
36 static |
|
37 const CXML_Encoding_String_t CXML_EncodingStr_Array[] = |
|
38 { |
|
39 {(NW_Int8*) "utf-8", HTTP_utf_8 }, |
|
40 {(NW_Int8*) "us-ascii", HTTP_us_ascii }, |
|
41 {(NW_Int8*) "iso-10646-ucs-2", HTTP_iso_10646_ucs_2 }, |
|
42 {(NW_Int8*) "iso-8859-1", HTTP_iso_8859_1 }, |
|
43 {(NW_Int8*) "utf-8", HTTP_utf_16} |
|
44 }; |
|
45 |
|
46 typedef struct NW_XML_XmlpWbxmlEncoder_s |
|
47 { |
|
48 NW_WBXML_Writer_t* pE; |
|
49 /* |
|
50 need access to last tag token to backpatch attribute and content flags |
|
51 */ |
|
52 NW_Uint32 lastTagTokenIndex; |
|
53 NW_Uint32 publicID; /* needed to pass to start callback */ |
|
54 NW_Uint32 encoding; /* needed to pass to start callback */ |
|
55 |
|
56 } NW_XML_XmlpWbxmlEncoder_t; |
|
57 |
|
58 /* The following function finds the encoding in the XML declaration statement (if any). |
|
59 * This function is called only when there is no BOM present and encoding is assumed |
|
60 * ASCII/Latine-1. |
|
61 * e.g. <?xml version="1.0" encoding="iso-8859-1"?>, here XML Declaration has the encoding |
|
62 * of "iso-8859-1" |
|
63 */ |
|
64 |
|
65 static NW_Bool NW_XML_FindEncoding(NW_Uint32 length, const unsigned char* pBuf, NW_Uint32* encodingVal) |
|
66 { |
|
67 |
|
68 NW_Bool s = NW_FALSE; |
|
69 NW_Uint8* sourceWalker = NULL; |
|
70 NW_Uint8* encodingStart = NULL; |
|
71 NW_Uint8* encodingValStart = NULL; |
|
72 NW_Uint8* endXMLDecl = NULL; |
|
73 NW_Uint32 xmlDeclLen = 0; |
|
74 NW_Uint32 encodingValLen = 0; |
|
75 NW_Uint32 i = 0; |
|
76 |
|
77 /* Look for end of the XML Declration statement */ |
|
78 |
|
79 endXMLDecl = (NW_Uint8*) strstr((char*) pBuf+2, "?>"); |
|
80 |
|
81 if(endXMLDecl) |
|
82 { |
|
83 xmlDeclLen = endXMLDecl - pBuf; |
|
84 |
|
85 |
|
86 if(xmlDeclLen < length) |
|
87 { |
|
88 encodingStart = (NW_Uint8*) strstr(( (char*)(pBuf+2) ),"encoding"); |
|
89 |
|
90 /*Move the pointer after the encoding */ |
|
91 |
|
92 |
|
93 if(encodingStart) |
|
94 { |
|
95 sourceWalker = encodingStart + 8; |
|
96 |
|
97 /*Skip any space */ |
|
98 while(CXML_Str_Isspace((NW_Ucs2)(*sourceWalker & 0xffff) ) ) |
|
99 { |
|
100 sourceWalker++; |
|
101 } |
|
102 |
|
103 if(*sourceWalker == '=') |
|
104 { |
|
105 sourceWalker++; |
|
106 while(CXML_Str_Isspace((NW_Ucs2)(*sourceWalker & 0xffff) ) ) |
|
107 { |
|
108 sourceWalker++; |
|
109 } |
|
110 } |
|
111 |
|
112 if( (*sourceWalker == '\'') || (*sourceWalker == '\"') ) |
|
113 { |
|
114 sourceWalker++; |
|
115 } |
|
116 |
|
117 encodingValStart = sourceWalker; |
|
118 |
|
119 /* End the Encoding value consume if one of following condition is reached: |
|
120 * 1) Closing quote has encounted. |
|
121 * 2) '>' closing tag has encountered |
|
122 * 3) Space had encounted |
|
123 * 4) '?' has encounded. |
|
124 * There is possibilty of some arguments after encoding like following: |
|
125 * <?xml version="1.0" encoding="iso-8859-1" standalone="no"?> |
|
126 */ |
|
127 |
|
128 while( (*sourceWalker != '\'') && (*sourceWalker != '\"') && |
|
129 (*sourceWalker != '>') && (*sourceWalker != '?') ) |
|
130 { |
|
131 encodingValLen++; |
|
132 sourceWalker++; |
|
133 } |
|
134 |
|
135 for(i=0; i < CXML_Encoding_Str_Num; i++) |
|
136 { |
|
137 if(!strncmp((char*) encodingValStart, (char*) CXML_EncodingStr_Array[i].charSetStr,encodingValLen)) |
|
138 { |
|
139 *encodingVal = CXML_EncodingStr_Array[i].encodingVal; |
|
140 s = NW_TRUE; |
|
141 break; |
|
142 } |
|
143 }/*end for() */ |
|
144 }/*end if(encodingStart)*/ |
|
145 }/*end if(xmlDeclLen < length)*/ |
|
146 }/*end if(endXMLDecl)*/ |
|
147 |
|
148 return s; |
|
149 }/*end NW_XML_FindEncoding()*/ |
|
150 |
|
151 NW_Status_t |
|
152 EXPORT_C |
|
153 NW_XML_ComputeEncoding(NW_Uint32 length, const unsigned char* pBuf, |
|
154 NW_Uint32* pEncoding, NW_Endianness_t* pEndianness) |
|
155 { |
|
156 NW_Uint32 c0, c1, c2, c3; |
|
157 if (length < 4) |
|
158 { |
|
159 return NW_STAT_FAILURE; |
|
160 } |
|
161 c0 = pBuf[0]; |
|
162 c1 = pBuf[1]; |
|
163 c2 = pBuf[2]; |
|
164 c3 = pBuf[3]; |
|
165 if (c0 == 0 && c1 == 0 && c2 == 0xfe && c3 == 0xff) |
|
166 { |
|
167 *pEncoding = 1001; /* ISO-10646-UCS-4 IANA MIBenum */ |
|
168 *pEndianness = NW_BIG_ENDIAN; |
|
169 } |
|
170 else if (c0 == 0 && c1 == 0 && c2 == 0 && c3 == 0x3c) |
|
171 { |
|
172 *pEncoding = 1001; /* ISO-10646-UCS-4 IANA MIBenum */ |
|
173 *pEndianness = NW_BIG_ENDIAN; |
|
174 } |
|
175 else if (c0 == 0xff && c1 == 0xfe && c2 == 0 && c3 == 0) |
|
176 { |
|
177 *pEncoding = 1001; /* ISO-10646-UCS-4 IANA MIBenum */ |
|
178 *pEndianness = NW_LITTLE_ENDIAN; |
|
179 } |
|
180 else if (c0 == 0x3c && c1 == 0 && c2 == 0 && c3 == 0) |
|
181 { |
|
182 *pEncoding = 1001; /* ISO-10646-UCS-4 IANA MIBenum */ |
|
183 *pEndianness = NW_LITTLE_ENDIAN; |
|
184 } |
|
185 else if (c0 == 0xfe && c1 == 0xff && !(c2 == 0 && c3 == 0)) |
|
186 { |
|
187 /* call it UCS-2 instead of UTF-16 IANA MIBenum, favor over |
|
188 UTF-16BE 1013 */ |
|
189 *pEncoding = 1000; |
|
190 *pEndianness = NW_BIG_ENDIAN; |
|
191 } |
|
192 else if (c0 == 0 && c1 == 0x3c && c2 == 0 && c3 == 0x3f) |
|
193 { |
|
194 /* could be UTF-16 but must read xml encoding decl to tell */ |
|
195 *pEncoding = 1000; /* UCS-2 IANA MIBenum */ |
|
196 *pEndianness = NW_BIG_ENDIAN; |
|
197 } |
|
198 else if (c0 == 0xff && c1 == 0xfe && !(c2 == 0 && c3 == 0)) |
|
199 { |
|
200 /* call it UCS-2 instead of UTF-16 IANA MIBenum, favor over |
|
201 UTF-16LE 1014 */ |
|
202 *pEncoding = 1000; |
|
203 *pEndianness = NW_LITTLE_ENDIAN; |
|
204 } |
|
205 else if (c0 == 0x3c && c1 == 0 && c2 == 0x3f && c3 == 0) |
|
206 { |
|
207 /* could be UTF-16 but must read xml encoding decl to tell */ |
|
208 *pEncoding = 1000; /* UCS-2 IANA MIBenum */ |
|
209 *pEndianness = NW_LITTLE_ENDIAN; |
|
210 } |
|
211 else if (c0 == 0x3c && c1 == 0x3f && c2 == 0x78 && c3 == 0x6d) |
|
212 { |
|
213 /* could be anything with anything with an ASCII subset, |
|
214 must read xml encoding decl to tell */ |
|
215 if( !NW_XML_FindEncoding (length,pBuf, pEncoding) ) |
|
216 { |
|
217 /*If encoding is not in the XML Declaration */ |
|
218 *pEncoding = 106; /* UTF-8 IANA MIBenum, no endianness */ |
|
219 } |
|
220 *pEndianness = NW_NATIVE_ENDIAN; |
|
221 } |
|
222 else if (c0 == 0xef && c1 == 0xbb && c2 == 0xbf) /* c3 ignored */ |
|
223 { |
|
224 *pEncoding = 106; /* UTF-8 IANA MIBenum, no endianness */ |
|
225 *pEndianness = NW_NATIVE_ENDIAN; /* Ha! */ |
|
226 } |
|
227 else |
|
228 { |
|
229 /* default to UTF-8 and let the parser barf if it isn't */ |
|
230 *pEncoding = 106; /* UTF-8 IANA MIBenum, no endianness */ |
|
231 *pEndianness = NW_NATIVE_ENDIAN; /* Ha! */ |
|
232 } |
|
233 return NW_STAT_SUCCESS; |
|
234 } |
|
235 |
|
236 |
|
237 |
|
238 /* When encoding is UCS-2, the parser has changed the byte order to |
|
239 native, however, the WBXML should be written in network (i.e., big |
|
240 endian) order. The way this is done is to change the byte order |
|
241 in-place to network order, write the WBXML, and then put the byte |
|
242 order back to native in-place. */ |
|
243 static |
|
244 void |
|
245 NW_XML_XmlpWbxmlEncoder_Ucs2NativeToNetworkByteOrder(NW_Uint32 byteCount, |
|
246 NW_Uint8* pBuf) |
|
247 { |
|
248 NW_Uint32 i; |
|
249 NW_Uint16 c_ucs2 = 1; |
|
250 |
|
251 if (((NW_Uint8*)&c_ucs2)[0] == 1) { /* test for little endian host */ |
|
252 for (i = 0; i < byteCount; i += 2) { |
|
253 (void)NW_Mem_memcpy(&c_ucs2, pBuf + i, sizeof(NW_Uint16)); |
|
254 pBuf[i] = (NW_Uint8)((c_ucs2 >> 8) & 0xff); |
|
255 pBuf[i+1] = (NW_Uint8)(c_ucs2 & 0xff); |
|
256 } |
|
257 } |
|
258 } |
|
259 |
|
260 static |
|
261 void |
|
262 NW_XML_XmlpWbxmlEncoder_Ucs2NetworkToNativeByteOrder(NW_Uint32 byteCount, |
|
263 NW_Uint8* pBuf) |
|
264 { |
|
265 NW_Uint32 i; |
|
266 NW_Uint16 c_ucs2 = 1; |
|
267 |
|
268 if (((NW_Uint8*)&c_ucs2)[0] == 1) { /* test for little endian host */ |
|
269 for (i = 0; i < byteCount; i += 2) { |
|
270 /* this is a clever trick: pick up bytes in big endian order, |
|
271 force the result to memory via taking address of result which |
|
272 will put the 16-bits into native byte order, then copy the |
|
273 result over the original bytes */ |
|
274 c_ucs2 = (NW_Uint16)((pBuf[i] << 8) | pBuf[i+1]); |
|
275 (void)NW_Mem_memcpy(pBuf + i, &c_ucs2, sizeof(NW_Uint16)); |
|
276 } |
|
277 } |
|
278 } |
|
279 |
|
280 /* end of line normalization replaces DOS or Mac style end of line |
|
281 with Unix style end of line. If no normalization is needed, then on |
|
282 return *ppTextOut == pTextIn (i.e., no malloc was done), otherwise you |
|
283 need to call NW_Mem_Free(*ppTextOut) when you are done with the output |
|
284 NOTE: only works for native byte order! |
|
285 */ |
|
286 static |
|
287 NW_Status_t |
|
288 NW_XML_XmlpWbxmlEncoder_EndOfLineNormalization(NW_Uint32 encoding, |
|
289 NW_Uint32* pCharCount, |
|
290 NW_Uint32* pByteCount, |
|
291 const NW_Uint8* pTextIn, |
|
292 NW_Uint8** ppTextOut) |
|
293 { |
|
294 NW_Uint32 i; |
|
295 NW_Uint32 j; |
|
296 NW_Uint32 elideCharCount; |
|
297 NW_Uint32 elideByteCount; |
|
298 NW_Int32 byteCount; |
|
299 NW_Ucs2 cUCS2; |
|
300 NW_Uint8 crHit; |
|
301 NW_Uint8 needsNormalization = 0; |
|
302 |
|
303 /* the output is the input unless it must be normalized */ |
|
304 *ppTextOut = (NW_Uint8*)pTextIn; |
|
305 |
|
306 /* scan to count #xD's that need translating */ |
|
307 elideCharCount = 0; |
|
308 elideByteCount = 0; |
|
309 crHit = 0; |
|
310 for (i = 0; i < *pByteCount; i += (NW_Uint32)byteCount) { |
|
311 byteCount = NW_String_readChar((NW_Uint8*)&(pTextIn[i]), &cUCS2, encoding); |
|
312 if (byteCount < 0) { |
|
313 return NW_STAT_FAILURE; |
|
314 } |
|
315 /* catch DOS 0xd 0xa eol */ |
|
316 if (crHit && (cUCS2 == 0xa)) { |
|
317 elideCharCount++; |
|
318 elideByteCount += (NW_Uint32)byteCount; |
|
319 } |
|
320 if (cUCS2 == 0xd) { |
|
321 needsNormalization = 1; |
|
322 crHit = 1; |
|
323 } else { |
|
324 crHit = 0; |
|
325 } |
|
326 } |
|
327 if (needsNormalization) { |
|
328 /* alloc a new string */ |
|
329 *ppTextOut = (NW_Uint8*) NW_Mem_Malloc(*pByteCount - elideByteCount); |
|
330 if (*ppTextOut == NULL) { |
|
331 *ppTextOut = (NW_Uint8*)pTextIn; |
|
332 return NW_STAT_OUT_OF_MEMORY; |
|
333 } |
|
334 |
|
335 /* make a normalized copy of input */ |
|
336 crHit = 0; |
|
337 j = 0; |
|
338 for (i = 0; i < *pByteCount; i += (NW_Uint32)byteCount) { |
|
339 byteCount = NW_String_readChar((NW_Uint8*)&(pTextIn[i]), &cUCS2, encoding); |
|
340 if (byteCount < 0) { |
|
341 NW_Mem_Free(*ppTextOut); |
|
342 *ppTextOut = (NW_Uint8*)pTextIn; |
|
343 return NW_STAT_FAILURE; |
|
344 } |
|
345 /* check that readChar isn't trying to read off end of buffer */ |
|
346 NW_ASSERT((i + byteCount - 1) < *pByteCount); |
|
347 if (cUCS2 == 0xd) { |
|
348 crHit = 1; |
|
349 if (byteCount == 1) { |
|
350 (*ppTextOut)[j++] = 0xa; |
|
351 } else if (byteCount == 2) { |
|
352 /* this looks odd but takes into account either endianess */ |
|
353 if (pTextIn[i] == 0xd) { |
|
354 (*ppTextOut)[j++] = (NW_Uint8)0xa; |
|
355 (*ppTextOut)[j++] = 0; |
|
356 } else { |
|
357 (*ppTextOut)[j++] = 0; |
|
358 (*ppTextOut)[j++] = (NW_Uint8)0xa; |
|
359 } |
|
360 } else { |
|
361 NW_ASSERT(byteCount <= 2); /* code bug, force debug stop here */ |
|
362 NW_Mem_Free(*ppTextOut); |
|
363 *ppTextOut = (NW_Uint8*)pTextIn; |
|
364 return NW_STAT_FAILURE; |
|
365 } |
|
366 } else { |
|
367 if (!(crHit && (cUCS2 == 0xa))) { |
|
368 (void)NW_Mem_memcpy(&((*ppTextOut)[j]), &(pTextIn[i]), (NW_Uint32)byteCount); |
|
369 j += (NW_Uint32)byteCount; |
|
370 } |
|
371 crHit = 0; |
|
372 } |
|
373 } |
|
374 *pByteCount -= elideByteCount; |
|
375 *pCharCount -= elideCharCount; |
|
376 } |
|
377 return NW_STAT_SUCCESS; |
|
378 } |
|
379 |
|
380 static |
|
381 NW_Status_t |
|
382 NW_XML_XmlpWbxmlEncoder_New(NW_Uint32 publicID, NW_Uint32 encoding, void** ppV) |
|
383 { |
|
384 NW_WBXML_Dictionary_t* pDictionary; |
|
385 NW_XML_XmlpWbxmlEncoder_t** ppTE = (NW_XML_XmlpWbxmlEncoder_t**)ppV; |
|
386 *ppTE = (NW_XML_XmlpWbxmlEncoder_t*) NW_Mem_Malloc(sizeof(NW_XML_XmlpWbxmlEncoder_t)); |
|
387 if (!*ppTE) { |
|
388 return NW_STAT_OUT_OF_MEMORY; |
|
389 } |
|
390 (*ppTE)->lastTagTokenIndex = 0; |
|
391 (*ppTE)->publicID = publicID; |
|
392 (*ppTE)->encoding = encoding; |
|
393 (*ppTE)->pE = (NW_WBXML_Writer_t*) NW_Mem_Malloc(sizeof(NW_WBXML_Writer_t)); |
|
394 if (!((*ppTE)->pE)) { |
|
395 return NW_STAT_OUT_OF_MEMORY; |
|
396 } |
|
397 /* Note that we only have access to one dictionary and we |
|
398 should really have two: one for tags and one for attributes. */ |
|
399 pDictionary = NW_WBXML_Dictionary_getByPublicId((*ppTE)->publicID); |
|
400 |
|
401 if( ( CXML_Additional_Feature_Supprted() & CXML_DTD_SUPPORT_ON) ) |
|
402 { |
|
403 NW_Encoder_StringTable_t* strTable = NW_Encoder_StringTable_new(); |
|
404 |
|
405 |
|
406 NW_WBXML_Writer_Initialize((*ppTE)->pE, |
|
407 0, NULL, NULL, /* no mem needed for sizing */ |
|
408 pDictionary, |
|
409 pDictionary, |
|
410 NW_Encoder_StringTable_getStringTableOffset, |
|
411 NW_Encoder_StringTable_addToStringTable, |
|
412 strTable, |
|
413 NW_Encoder_StringTable_StringTableIterateInit, |
|
414 NW_Encoder_StringTable_StringTableIterateNext, |
|
415 1 /* do sizing only */); |
|
416 } |
|
417 else |
|
418 { |
|
419 |
|
420 NW_WBXML_Writer_Initialize((*ppTE)->pE, |
|
421 0, NULL, NULL, /* no mem needed for sizing */ |
|
422 pDictionary, pDictionary, |
|
423 NULL, NULL, NULL, NULL, NULL, /* string table stuff */ |
|
424 1 /* do sizing only */); |
|
425 } |
|
426 return NW_STAT_SUCCESS; |
|
427 } |
|
428 |
|
429 static |
|
430 void |
|
431 NW_XML_XmlpWbxmlEncoder_SetToWrite(NW_XML_XmlpWbxmlEncoder_t* pTE, |
|
432 NW_Uint32 byteLength, NW_Uint8* pBuf, |
|
433 NW_WBXML_Writer_GrowBuf_t growBufCallback) |
|
434 { |
|
435 |
|
436 if( ( CXML_Additional_Feature_Supprted() & CXML_DTD_SUPPORT_ON) ) |
|
437 { |
|
438 NW_Encoder_StringTable_t* strTable = NW_Encoder_StringTable_new(); |
|
439 |
|
440 |
|
441 NW_WBXML_Writer_Initialize(pTE->pE, |
|
442 byteLength, pBuf, |
|
443 growBufCallback, |
|
444 pTE->pE->pTagDictionary, |
|
445 pTE->pE->pAttributeDictionary, |
|
446 NW_Encoder_StringTable_getStringTableOffset, |
|
447 NW_Encoder_StringTable_addToStringTable, |
|
448 strTable, |
|
449 NW_Encoder_StringTable_StringTableIterateInit, |
|
450 NW_Encoder_StringTable_StringTableIterateNext, |
|
451 0 /* don't do sizing, write */); |
|
452 } |
|
453 else |
|
454 { |
|
455 NW_WBXML_Writer_Initialize(pTE->pE, |
|
456 byteLength, pBuf, |
|
457 growBufCallback, |
|
458 pTE->pE->pTagDictionary, |
|
459 pTE->pE->pAttributeDictionary, |
|
460 NULL, NULL, NULL, NULL, NULL, /* string table stuff */ |
|
461 0 /* don't do sizing, write */); |
|
462 } |
|
463 } |
|
464 |
|
465 void |
|
466 NW_XML_XmlpWbxmlEncoder_Delete(void* pV) |
|
467 { |
|
468 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
469 NW_WBXML_Writer_t* pE = pTE->pE; |
|
470 NW_Mem_Free(pE); /* note that this doesn't free WBXML buf and string table. */ |
|
471 NW_Mem_Free(pTE); |
|
472 } |
|
473 |
|
474 static |
|
475 NW_Status_t |
|
476 NW_XML_XmlpWbxmlEncoder_StartDocument_CB(NW_XML_Reader_t* pT, void* pV) |
|
477 { |
|
478 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
479 NW_WBXML_Writer_t* pE = pTE->pE; |
|
480 |
|
481 NW_REQUIRED_PARAM(pT); |
|
482 |
|
483 /* Note: We do not build a string table because it isn't clear if |
|
484 it is worthwhile. */ |
|
485 |
|
486 return NW_WBXML_Writer_Header(pE, 3, pTE->publicID, pTE->encoding, 0); |
|
487 } |
|
488 |
|
489 static |
|
490 NW_Status_t |
|
491 NW_XML_XmlpWbxmlEncoder_Tag_Start_CB(NW_XML_Reader_t* pT, |
|
492 const NW_XML_Reader_Interval_t* pI_name, |
|
493 void* pV) |
|
494 { |
|
495 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
496 NW_WBXML_Writer_t* pE = pTE->pE; |
|
497 NW_Uint32 length; |
|
498 NW_Uint32 nameByteLength; |
|
499 NW_Uint8* pName; |
|
500 NW_Status_t s; |
|
501 if (!NW_XML_Reader_Interval_IsWellFormed(pI_name)) { |
|
502 return NW_STAT_FAILURE; |
|
503 } |
|
504 length = pI_name->stop - pI_name->start; |
|
505 nameByteLength = length; |
|
506 s = NW_XML_Reader_DataAddressFromBuffer(pT, pI_name->start, |
|
507 &nameByteLength, |
|
508 &pName); |
|
509 if (NW_STAT_IS_FAILURE(s)) { |
|
510 return s; |
|
511 } |
|
512 if (nameByteLength != length) { |
|
513 return NW_STAT_FAILURE; |
|
514 } |
|
515 length = pI_name->charStop - pI_name->charStart; |
|
516 s = NW_WBXML_Writer_TagString(pE, pTE->encoding, length, nameByteLength, |
|
517 pName, &(pTE->lastTagTokenIndex)); |
|
518 if (NW_STAT_IS_FAILURE(s)) { |
|
519 return s; |
|
520 } |
|
521 /* default to content but erase if see empty tag end */ |
|
522 return NW_WBXML_Writer_TagSetContentFlag(pE, pTE->lastTagTokenIndex); |
|
523 } |
|
524 |
|
525 static |
|
526 NW_Status_t |
|
527 NW_XML_XmlpWbxmlEncoder_Attr_Start_CB(NW_XML_Reader_t* pT, |
|
528 const NW_XML_Reader_Interval_t* pI_name, |
|
529 void* pV) |
|
530 { |
|
531 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
532 NW_WBXML_Writer_t* pE = pTE->pE; |
|
533 NW_REQUIRED_PARAM(pT); |
|
534 NW_REQUIRED_PARAM(pI_name); |
|
535 return NW_WBXML_Writer_TagSetAttributesFlag(pE, pTE->lastTagTokenIndex); |
|
536 } |
|
537 |
|
538 static |
|
539 NW_Status_t |
|
540 NW_XML_XmlpWbxmlEncoder_Attr_VarVal_CB(NW_XML_Reader_t* pT, |
|
541 const NW_XML_Reader_Interval_t* pI_name, |
|
542 const NW_XML_Reader_Interval_t* pI_value, |
|
543 void* pV) |
|
544 { |
|
545 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
546 NW_WBXML_Writer_t* pE = pTE->pE; |
|
547 NW_Uint32 length; |
|
548 NW_Uint32 nameLength; |
|
549 NW_Uint8* pName; |
|
550 NW_Uint32 valueByteLength; |
|
551 NW_Uint32 valueCharCount; |
|
552 NW_Uint8* pValue; |
|
553 NW_Status_t s; |
|
554 |
|
555 if (!NW_XML_Reader_Interval_IsWellFormed(pI_name)) { |
|
556 return NW_STAT_FAILURE; |
|
557 } |
|
558 |
|
559 /* var name setup */ |
|
560 length = pI_name->stop - pI_name->start; |
|
561 nameLength = length; /* byte length */ |
|
562 s = NW_XML_Reader_DataAddressFromBuffer(pT, pI_name->start, |
|
563 &nameLength, &pName); |
|
564 if (NW_STAT_IS_FAILURE(s)) { |
|
565 return s; |
|
566 } |
|
567 if (nameLength != length) { |
|
568 return NW_STAT_FAILURE; |
|
569 } |
|
570 nameLength = pI_name->charStop - pI_name->charStart; /* char count */ |
|
571 |
|
572 /* value setup */ |
|
573 length = pI_value->stop - pI_value->start; |
|
574 valueByteLength = length; |
|
575 s = NW_XML_Reader_DataAddressFromBuffer(pT, pI_value->start, |
|
576 &valueByteLength, &pValue); |
|
577 if (NW_STAT_IS_FAILURE(s)) { |
|
578 return s; |
|
579 } |
|
580 if (valueByteLength != length) { |
|
581 return NW_STAT_FAILURE; |
|
582 } |
|
583 valueCharCount = pI_value->charStop - pI_value->charStart; |
|
584 |
|
585 if (pT->encoding == HTTP_iso_10646_ucs_2) { |
|
586 NW_XML_XmlpWbxmlEncoder_Ucs2NativeToNetworkByteOrder(valueByteLength, |
|
587 pValue); |
|
588 } |
|
589 s = NW_WBXML_Writer_AttributeAndValue(pE, pTE->encoding, nameLength, |
|
590 pName, valueCharCount, |
|
591 valueByteLength, pValue); |
|
592 if (NW_STAT_IS_FAILURE(s)) { |
|
593 return s; |
|
594 } |
|
595 if (pT->encoding == HTTP_iso_10646_ucs_2) { |
|
596 NW_XML_XmlpWbxmlEncoder_Ucs2NetworkToNativeByteOrder(valueByteLength, |
|
597 pValue); |
|
598 } |
|
599 return NW_STAT_SUCCESS; |
|
600 } |
|
601 |
|
602 static |
|
603 NW_Status_t |
|
604 NW_XML_XmlpWbxmlEncoder_Attributes_End_CB(NW_XML_Reader_t* pT, |
|
605 NW_Uint32 attributeCount, void* pV) |
|
606 { |
|
607 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
608 NW_WBXML_Writer_t* pE = pTE->pE; |
|
609 NW_Status_t s; |
|
610 NW_REQUIRED_PARAM(pT); |
|
611 /* if there were any attributes, then must write end token */ |
|
612 if (attributeCount) { |
|
613 s = NW_WBXML_Writer_End(pE); |
|
614 if (NW_STAT_IS_FAILURE(s)) { |
|
615 return s; |
|
616 } |
|
617 } |
|
618 return NW_STAT_SUCCESS; |
|
619 } |
|
620 |
|
621 static |
|
622 NW_Status_t |
|
623 NW_XML_XmlpWbxmlEncoder_CoreTextHandler(NW_Uint32 encoding, |
|
624 NW_Uint32 charCount, |
|
625 NW_Uint32 byteLength, |
|
626 NW_Uint8* pText, |
|
627 NW_WBXML_Writer_t* pE) |
|
628 { |
|
629 NW_Uint8* pNormalizedText; |
|
630 NW_Status_t s; |
|
631 |
|
632 s = NW_XML_XmlpWbxmlEncoder_EndOfLineNormalization(encoding, |
|
633 &charCount, |
|
634 &byteLength, |
|
635 pText, |
|
636 &pNormalizedText); |
|
637 if (NW_STAT_IS_FAILURE(s)) { |
|
638 return s; |
|
639 } |
|
640 if (encoding == HTTP_iso_10646_ucs_2) { |
|
641 NW_XML_XmlpWbxmlEncoder_Ucs2NativeToNetworkByteOrder(byteLength, |
|
642 pNormalizedText); |
|
643 } |
|
644 s = NW_WBXML_Writer_Text(pE, encoding, byteLength, pNormalizedText); |
|
645 if (NW_STAT_IS_FAILURE(s)) { |
|
646 return s; |
|
647 } |
|
648 if (pText == pNormalizedText) { |
|
649 if (encoding == HTTP_iso_10646_ucs_2) { |
|
650 NW_XML_XmlpWbxmlEncoder_Ucs2NetworkToNativeByteOrder(byteLength, |
|
651 pNormalizedText); |
|
652 } |
|
653 } else { |
|
654 NW_Mem_Free(pNormalizedText); |
|
655 } |
|
656 return NW_STAT_SUCCESS; |
|
657 } |
|
658 |
|
659 |
|
660 static |
|
661 NW_Status_t |
|
662 NW_XML_XmlpWbxmlEncoder_Content_CB(NW_XML_Reader_t* pT, |
|
663 const NW_XML_Reader_Interval_t* pI_content, |
|
664 void* pV) |
|
665 { |
|
666 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
667 NW_WBXML_Writer_t* pE = pTE->pE; |
|
668 NW_Status_t s; |
|
669 NW_Uint32 length; |
|
670 NW_Uint32 byteLength; |
|
671 NW_Uint32 charCount; |
|
672 NW_Uint8* pContent; |
|
673 NW_Uint8* pNormalizedContent; |
|
674 |
|
675 if (!NW_XML_Reader_Interval_IsWellFormed(pI_content)) { |
|
676 return NW_STAT_FAILURE; |
|
677 } |
|
678 length = pI_content->stop - pI_content->start; |
|
679 byteLength = length; |
|
680 s = NW_XML_Reader_DataAddressFromBuffer(pT, pI_content->start, |
|
681 &byteLength, |
|
682 &pContent); |
|
683 if (NW_STAT_IS_FAILURE(s)) { |
|
684 return s; |
|
685 } |
|
686 if (byteLength != length) { |
|
687 return NW_STAT_FAILURE; |
|
688 } |
|
689 charCount = pI_content->charStop - pI_content->charStart; |
|
690 s = NW_XML_XmlpWbxmlEncoder_EndOfLineNormalization(pT->encoding, |
|
691 &charCount, |
|
692 &byteLength, |
|
693 pContent, |
|
694 &pNormalizedContent); |
|
695 if (NW_STAT_IS_FAILURE(s)) { |
|
696 return s; |
|
697 } |
|
698 if (pT->encoding == HTTP_iso_10646_ucs_2) { |
|
699 NW_XML_XmlpWbxmlEncoder_Ucs2NativeToNetworkByteOrder(byteLength, |
|
700 pNormalizedContent); |
|
701 } |
|
702 s = NW_WBXML_Writer_Text(pE, pT->encoding, byteLength, pNormalizedContent); |
|
703 if (NW_STAT_IS_FAILURE(s)) { |
|
704 return s; |
|
705 } |
|
706 if (pContent == pNormalizedContent) { |
|
707 if (pT->encoding == HTTP_iso_10646_ucs_2) { |
|
708 NW_XML_XmlpWbxmlEncoder_Ucs2NetworkToNativeByteOrder(byteLength, |
|
709 pNormalizedContent); |
|
710 } |
|
711 } else { |
|
712 NW_Mem_Free(pNormalizedContent); |
|
713 } |
|
714 return NW_STAT_SUCCESS; |
|
715 } |
|
716 |
|
717 static |
|
718 NW_Status_t |
|
719 NW_XML_XmlpWbxmlEncoder_Tag_End_CB(NW_XML_Reader_t* pT, |
|
720 const NW_XML_Reader_Interval_t* pI_name, |
|
721 NW_Uint32 emptyTagFlag, void* pV) |
|
722 { |
|
723 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
724 NW_WBXML_Writer_t* pE = pTE->pE; |
|
725 NW_Status_t s; |
|
726 NW_REQUIRED_PARAM(pT); |
|
727 NW_REQUIRED_PARAM(pI_name); |
|
728 if (emptyTagFlag) { |
|
729 s = NW_WBXML_Writer_TagClearContentFlag(pE, pTE->lastTagTokenIndex); |
|
730 } else { |
|
731 s = NW_WBXML_Writer_End(pE); |
|
732 } |
|
733 if (NW_STAT_IS_FAILURE(s)) { |
|
734 return s; |
|
735 } |
|
736 return s; |
|
737 } |
|
738 |
|
739 static |
|
740 NW_Status_t |
|
741 NW_XML_XmlpWbxmlEncoder_Cdata_CB(NW_XML_Reader_t* pT, |
|
742 const NW_XML_Reader_Interval_t* pI_cdata, |
|
743 void* pV) |
|
744 { |
|
745 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
746 NW_WBXML_Writer_t* pE = pTE->pE; |
|
747 NW_Uint8* pText; |
|
748 NW_Uint8* pQuotedText; |
|
749 NW_Uint8* pSrc; |
|
750 NW_Uint8* pDest; |
|
751 NW_Uint32 encoding = pT->encoding; |
|
752 NW_Uint32 length; |
|
753 NW_Uint32 byteLength; |
|
754 NW_Uint32 charCount; |
|
755 NW_Uint32 ampCount; |
|
756 NW_Uint32 i, j; |
|
757 NW_Ucs2 cUCS2; |
|
758 NW_Status_t s; |
|
759 |
|
760 /* code only supports the following charset values */ |
|
761 NW_ASSERT((encoding == HTTP_us_ascii) |
|
762 || (encoding == HTTP_iso_8859_1) |
|
763 || (encoding == HTTP_utf_8) |
|
764 || (encoding == HTTP_iso_10646_ucs_2)); |
|
765 |
|
766 charCount = pI_cdata->charStop - pI_cdata->charStart; |
|
767 length = pI_cdata->stop - pI_cdata->start; |
|
768 if (length < 1) { |
|
769 return NW_STAT_SUCCESS; |
|
770 } |
|
771 byteLength = length; |
|
772 s = NW_XML_Reader_DataAddressFromBuffer(pT, pI_cdata->start, |
|
773 &byteLength, |
|
774 &pText); |
|
775 if (NW_STAT_IS_FAILURE(s)) { |
|
776 return s; |
|
777 } |
|
778 if (byteLength != length) { |
|
779 return NW_STAT_FAILURE; |
|
780 } |
|
781 |
|
782 /* Cdata is not supposed to have any entity expansion done on it. |
|
783 Since we don't alter the original document text in general, we |
|
784 have done the entity expansion outside of cXML. Therefore, we |
|
785 must quote any ampersands in the Cdata to prevent later entity |
|
786 expansion. */ |
|
787 |
|
788 /* count ampersands */ |
|
789 pSrc = pText; |
|
790 ampCount = 0; |
|
791 for (i = 0; i < charCount; i++) { |
|
792 j = NW_String_readChar(pSrc, &cUCS2, pT->encoding); |
|
793 pSrc += j; |
|
794 /* don't need to check j < 1, text has already been validated */ |
|
795 if (cUCS2 == '&') { |
|
796 ampCount++; |
|
797 } |
|
798 } |
|
799 |
|
800 pQuotedText = pText; |
|
801 if (ampCount) { |
|
802 /* allocate a new buffer |
|
803 |
|
804 need incremental length for: & => & |
|
805 start with single byte charset value */ |
|
806 ampCount *= 4; |
|
807 /* double for ucs2 */ |
|
808 if (pT->encoding == HTTP_iso_10646_ucs_2) { |
|
809 ampCount *= 2; |
|
810 } |
|
811 pQuotedText = (NW_Uint8*)NW_Mem_Malloc(byteLength + ampCount); |
|
812 if (pQuotedText == NULL) { |
|
813 return NW_STAT_OUT_OF_MEMORY; |
|
814 } |
|
815 |
|
816 /* copy and quote ampersands */ |
|
817 pSrc = pText; |
|
818 pDest = pQuotedText; |
|
819 for (i = 0; i < charCount; i++) { |
|
820 j = NW_String_readChar(pSrc, &cUCS2, encoding); |
|
821 /* don't need to check for byteCount < 1, text has already been |
|
822 validated */ |
|
823 NW_Mem_memcpy(pDest, pSrc, j); |
|
824 pSrc += j; |
|
825 pDest += j; |
|
826 if (cUCS2 == '&') { |
|
827 if (encoding == HTTP_iso_10646_ucs_2) { |
|
828 /* double byte */ |
|
829 *((NW_Uint16*)pDest) = 'a'; |
|
830 *((NW_Uint16*)(pDest + 2)) = 'm'; |
|
831 *((NW_Uint16*)(pDest + 4)) = 'p'; |
|
832 *((NW_Uint16*)(pDest + 6)) = ';'; |
|
833 pDest += 8; |
|
834 } else { |
|
835 /* single byte encodings */ |
|
836 NW_Mem_memcpy(pDest, "amp;", 4); |
|
837 pDest += 4; |
|
838 } |
|
839 } |
|
840 } |
|
841 byteLength += ampCount; |
|
842 if (pT->encoding == HTTP_iso_10646_ucs_2) { |
|
843 charCount += (ampCount / 2); |
|
844 } else { |
|
845 charCount = byteLength; |
|
846 } |
|
847 } |
|
848 |
|
849 /* output the text */ |
|
850 s = NW_XML_XmlpWbxmlEncoder_CoreTextHandler(pT->encoding, |
|
851 charCount, |
|
852 byteLength, |
|
853 pQuotedText, |
|
854 pE); |
|
855 if (pQuotedText != pText) { |
|
856 NW_Mem_Free(pQuotedText); |
|
857 } |
|
858 return s; |
|
859 } |
|
860 |
|
861 static |
|
862 NW_Status_t |
|
863 NW_XML_XmlpWbxmlEncoder_EndDocument_CB(NW_XML_Reader_t* pT, void* pV) |
|
864 { |
|
865 /* When debugging, this func provides a place to capture the final WBXML. */ |
|
866 NW_REQUIRED_PARAM(pT); |
|
867 NW_REQUIRED_PARAM(pV); |
|
868 return NW_STAT_SUCCESS; |
|
869 } |
|
870 |
|
871 |
|
872 /* Function to check the string table of encoder process. If the string table is |
|
873 * found and supported then keep a copy of this so that WBXML parser can populate |
|
874 * its string table from this. |
|
875 */ |
|
876 static |
|
877 void NW_XML_StrTbl(struct NW_XML_Parser_EventCallbacks_s* eventCBs, |
|
878 void** WBXMLEncStrTbl) |
|
879 { |
|
880 //Keep the copy of the WBXML string table, so that it can be added to the |
|
881 //DOM later. |
|
882 if( (NW_Bool) (CXML_Additional_Feature_Supprted() & CXML_DTD_SUPPORT_ON) ) |
|
883 { |
|
884 NW_Uint32 stringTableByteCount = 0; |
|
885 NW_Encoder_StringTable_t* strTable = (NW_Encoder_StringTable_t*) |
|
886 ((NW_XML_XmlpWbxmlEncoder_t*)eventCBs->pClientPointer)->pE->pStringTableObject; |
|
887 if(strTable) |
|
888 { |
|
889 stringTableByteCount = NW_Encoder_StringTable_getTotalBytes(strTable); |
|
890 if( (stringTableByteCount == 0) || (WBXMLEncStrTbl == NULL) ) |
|
891 { |
|
892 //Empty Table |
|
893 NW_Encoder_StringTable_delete(strTable); |
|
894 if(WBXMLEncStrTbl) |
|
895 { |
|
896 *WBXMLEncStrTbl = NULL; |
|
897 } |
|
898 } |
|
899 else |
|
900 { |
|
901 if(WBXMLEncStrTbl) |
|
902 { |
|
903 *WBXMLEncStrTbl = (void*) strTable; |
|
904 } |
|
905 }//end else |
|
906 }//end if(strTable) |
|
907 else |
|
908 { |
|
909 if(WBXMLEncStrTbl) |
|
910 { |
|
911 *WBXMLEncStrTbl = NULL; |
|
912 } |
|
913 } |
|
914 }//end if((NW_Bool) CXML_Additional_Feature_Supprted() ) |
|
915 else |
|
916 { |
|
917 if(WBXMLEncStrTbl) |
|
918 { |
|
919 *WBXMLEncStrTbl = NULL; |
|
920 } |
|
921 } |
|
922 return; |
|
923 }/*NW_XML_StrTbl()*/ |
|
924 |
|
925 |
|
926 //Write the entity content now. There are two possibilities for |
|
927 //entities. |
|
928 // |
|
929 // 1) If it is character or decimal or predefined entities. |
|
930 // In this case, intEntityValStr = NULL. |
|
931 // |
|
932 // 2) If it is "Internal Entity" then intEntityValStr != NULL. |
|
933 // So, this is directly written to WBXML encoder as inline string. |
|
934 // In this case, entityVal = 0; |
|
935 |
|
936 static |
|
937 NW_Status_t |
|
938 NW_XML_XmlpWbxmlEncoder_Entity_CB(NW_XML_Reader_t* pT,NW_Uint32 numEntity, |
|
939 void* pV, CXML_Uint8* intEntityValStr) |
|
940 { |
|
941 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
942 NW_WBXML_Writer_t* pW = pTE->pE; |
|
943 NW_Status_t s = NW_STAT_FAILURE; |
|
944 |
|
945 NW_REQUIRED_PARAM(pT); |
|
946 NW_REQUIRED_PARAM(pV); |
|
947 |
|
948 if(intEntityValStr == NULL) |
|
949 { |
|
950 s = NW_WBXML_Writer_Entity(pW,numEntity); |
|
951 } |
|
952 else if( (intEntityValStr != NULL) && (numEntity == 0) ) |
|
953 { |
|
954 NW_Uint32 valBufByteCnt = 0; |
|
955 NW_Int32 valBufLen = NW_String_charBuffGetLength( (void*)intEntityValStr, |
|
956 pT->encoding, |
|
957 &valBufByteCnt); |
|
958 |
|
959 /* Write internal entity as Inline string */ |
|
960 |
|
961 s = NW_WBXML_Writer_Text( pW, pT->encoding, valBufByteCnt, intEntityValStr); |
|
962 |
|
963 }/*end else if*/ |
|
964 |
|
965 return s; |
|
966 }/*end NW_XML_XmlpWbxmlEncoder_Entity_CB() */ |
|
967 |
|
968 /* This is used for if Entity is there in the Attribute value */ |
|
969 |
|
970 static |
|
971 NW_Status_t |
|
972 NW_XML_XmlpWbxmlEncoder_Entity_Attr_VarVal_CB(NW_XML_Reader_t* pT, |
|
973 const NW_XML_Reader_Interval_t* pI_name, |
|
974 NW_Uint8* pValue, |
|
975 NW_Uint32 valueByteLength, |
|
976 void* pV) |
|
977 { |
|
978 NW_XML_XmlpWbxmlEncoder_t* pTE = (NW_XML_XmlpWbxmlEncoder_t*)pV; |
|
979 NW_WBXML_Writer_t* pE = pTE->pE; |
|
980 NW_Uint32 length; |
|
981 NW_Uint32 nameLength; |
|
982 NW_Uint32 valueCharCount; |
|
983 NW_Uint8* pName; |
|
984 NW_Status_t s; |
|
985 |
|
986 if (!NW_XML_Reader_Interval_IsWellFormed(pI_name)) { |
|
987 return NW_STAT_FAILURE; |
|
988 } |
|
989 |
|
990 /* var name setup */ |
|
991 length = pI_name->stop - pI_name->start; |
|
992 nameLength = length; /* byte length */ |
|
993 s = NW_XML_Reader_DataAddressFromBuffer(pT, pI_name->start, |
|
994 &nameLength, &pName); |
|
995 if (NW_STAT_IS_FAILURE(s)) { |
|
996 return s; |
|
997 } |
|
998 if (nameLength != length) { |
|
999 return NW_STAT_FAILURE; |
|
1000 } |
|
1001 nameLength = pI_name->charStop - pI_name->charStart; /* char count */ |
|
1002 |
|
1003 /* value setup */ |
|
1004 valueCharCount = valueByteLength; |
|
1005 |
|
1006 |
|
1007 if (pT->encoding == HTTP_iso_10646_ucs_2) { |
|
1008 NW_XML_XmlpWbxmlEncoder_Ucs2NativeToNetworkByteOrder(valueByteLength, |
|
1009 pValue); |
|
1010 } |
|
1011 s = NW_WBXML_Writer_AttributeAndValue(pE, pTE->encoding, nameLength, |
|
1012 pName, valueCharCount, |
|
1013 valueByteLength, pValue); |
|
1014 if (NW_STAT_IS_FAILURE(s)) { |
|
1015 return s; |
|
1016 } |
|
1017 if (pT->encoding == HTTP_iso_10646_ucs_2) { |
|
1018 NW_XML_XmlpWbxmlEncoder_Ucs2NetworkToNativeByteOrder(valueByteLength, |
|
1019 pValue); |
|
1020 } |
|
1021 return NW_STAT_SUCCESS; |
|
1022 }/*end NW_XML_XmlpWbxmlEncoder_Entity_Attr_VarVal_CB(..)*/ |
|
1023 |
|
1024 |
|
1025 |
|
1026 |
|
1027 |
|
1028 NW_Status_t |
|
1029 NW_XML_XmlToWbxml(NW_Buffer_t* pInBuf, NW_Uint32 encoding, |
|
1030 NW_Buffer_t** ppOutBuf, NW_Uint32* line, |
|
1031 NW_Uint32 publicID, void** WBXMLEncStrTbl) |
|
1032 { |
|
1033 NW_Status_t s; |
|
1034 NW_XML_Reader_t t; |
|
1035 NW_Uint8* pWbxmlBuf; |
|
1036 NW_Uint8* docStartAddress; |
|
1037 NW_Uint32 docByteLength; |
|
1038 NW_Uint32 wbxmlBufLength; |
|
1039 struct NW_XML_Parser_EventCallbacks_s wbxmlEncodeCallbacks; |
|
1040 NW_XML_XmlpWbxmlEncoder_t* ppTE = NULL; |
|
1041 NW_WBXML_Writer_t* pW = NULL; |
|
1042 |
|
1043 NW_ASSERT( pInBuf != NULL ); |
|
1044 NW_ASSERT( ppOutBuf != NULL ); |
|
1045 NW_ASSERT( line != NULL ); |
|
1046 |
|
1047 *line = 0; |
|
1048 if (pInBuf->length == 0 || pInBuf->data == NULL) { |
|
1049 return NW_STAT_FAILURE; |
|
1050 } |
|
1051 /* For UTF-8 and UCS-2 handle BOM (byte order mark). Also, for |
|
1052 UCS-2 handle network (big) to native byte order conversion. */ |
|
1053 docByteLength = pInBuf->length; |
|
1054 docStartAddress = pInBuf->data; |
|
1055 if (encoding == HTTP_utf_8) { |
|
1056 /* look for BOM and remove if found */ |
|
1057 if (docByteLength >= 3) { |
|
1058 if ((docStartAddress[0] == 0xef) |
|
1059 && (docStartAddress[1] == 0xbb) |
|
1060 && (docStartAddress[2] == 0xbf)) { |
|
1061 docByteLength -= 3; |
|
1062 docStartAddress += 3; |
|
1063 } |
|
1064 } |
|
1065 } |
|
1066 if (encoding == HTTP_iso_10646_ucs_2) { |
|
1067 /* WARNING: we are assuming network byte order (i.e., big) for |
|
1068 the input document */ |
|
1069 /* verify the doc has an even number of bytes, check LSB != 1 */ |
|
1070 if ((docByteLength & 1) == 1) { |
|
1071 return NW_STAT_FAILURE; |
|
1072 } |
|
1073 |
|
1074 /* make a pass over the doc, forcing byte order to native byte order */ |
|
1075 NW_XML_XmlpWbxmlEncoder_Ucs2NetworkToNativeByteOrder(docByteLength, |
|
1076 docStartAddress); |
|
1077 /* now look for BOM and remove if found */ |
|
1078 if (docByteLength >= 2) { |
|
1079 if (((docStartAddress[0] == 0xfe) && (docStartAddress[1] == 0xff)) |
|
1080 || ((docStartAddress[0] == 0xff) && (docStartAddress[1] == 0xfe))) { |
|
1081 docByteLength -= 2; |
|
1082 docStartAddress += 2; |
|
1083 } |
|
1084 } |
|
1085 } |
|
1086 /* verify there is some doc remaining after BOM processing */ |
|
1087 if (docByteLength == 0) { |
|
1088 return NW_STAT_FAILURE; |
|
1089 } |
|
1090 |
|
1091 /* malloc the output buffer */ |
|
1092 *ppOutBuf = (NW_Buffer_t*) NW_Mem_Malloc(sizeof(NW_Buffer_t)); |
|
1093 if (!*ppOutBuf) { |
|
1094 return NW_STAT_OUT_OF_MEMORY; |
|
1095 } |
|
1096 (*ppOutBuf)->length = 0; |
|
1097 (*ppOutBuf)->allocatedLength = 0; |
|
1098 (*ppOutBuf)->data = NULL; |
|
1099 |
|
1100 /* Null out all WBXML generation callback addresses. */ |
|
1101 NW_Mem_memset(&wbxmlEncodeCallbacks, 0, |
|
1102 sizeof(struct NW_XML_Parser_EventCallbacks_s)); |
|
1103 /* Add in-use WBXML generation callbacks. */ |
|
1104 wbxmlEncodeCallbacks.StartDocument_CB = NW_XML_XmlpWbxmlEncoder_StartDocument_CB; |
|
1105 wbxmlEncodeCallbacks.Tag_Start_CB = NW_XML_XmlpWbxmlEncoder_Tag_Start_CB; |
|
1106 wbxmlEncodeCallbacks.Attr_Start_CB = NW_XML_XmlpWbxmlEncoder_Attr_Start_CB; |
|
1107 wbxmlEncodeCallbacks.Attr_VarVal_CB = NW_XML_XmlpWbxmlEncoder_Attr_VarVal_CB; |
|
1108 wbxmlEncodeCallbacks.Attributes_End_CB = NW_XML_XmlpWbxmlEncoder_Attributes_End_CB; |
|
1109 wbxmlEncodeCallbacks.Tag_End_CB = NW_XML_XmlpWbxmlEncoder_Tag_End_CB; |
|
1110 wbxmlEncodeCallbacks.Content_CB = NW_XML_XmlpWbxmlEncoder_Content_CB; |
|
1111 wbxmlEncodeCallbacks.Cdata_CB = NW_XML_XmlpWbxmlEncoder_Cdata_CB; |
|
1112 wbxmlEncodeCallbacks.EndDocument_CB = NW_XML_XmlpWbxmlEncoder_EndDocument_CB; |
|
1113 |
|
1114 wbxmlEncodeCallbacks.Entity_CB = NW_XML_XmlpWbxmlEncoder_Entity_CB; |
|
1115 wbxmlEncodeCallbacks.Attr_Entity_VarVal_CB = NW_XML_XmlpWbxmlEncoder_Entity_Attr_VarVal_CB; |
|
1116 |
|
1117 |
|
1118 /* The encoder contains a WBXML_Writer that defaults to a sizing pass. */ |
|
1119 s = NW_XML_XmlpWbxmlEncoder_New(publicID, encoding, |
|
1120 &(wbxmlEncodeCallbacks.pClientPointer)); |
|
1121 if (NW_STAT_IS_FAILURE(s)) { |
|
1122 return s; |
|
1123 } |
|
1124 |
|
1125 ppTE = (NW_XML_XmlpWbxmlEncoder_t*)wbxmlEncodeCallbacks.pClientPointer; |
|
1126 pW = (NW_WBXML_Writer_t*) ppTE->pE; |
|
1127 |
|
1128 /* Hand the document text to the Reader in preparation for parsing. */ |
|
1129 s = NW_XML_Reader_InitFromBuffer(&t, docByteLength, docStartAddress); |
|
1130 if (NW_STAT_IS_FAILURE(s)) { |
|
1131 NW_XML_XmlpWbxmlEncoder_Delete(wbxmlEncodeCallbacks.pClientPointer); |
|
1132 if(pW->pStringTableObject) |
|
1133 { |
|
1134 NW_Encoder_StringTable_delete(pW->pStringTableObject); |
|
1135 } |
|
1136 return s; |
|
1137 } |
|
1138 NW_XML_Reader_SetEncoding(&t, encoding); |
|
1139 |
|
1140 /* Parse and do a sizing pass for the WBXML. */ |
|
1141 s = NW_XML_Parse(&t, &wbxmlEncodeCallbacks); |
|
1142 if (NW_STAT_IS_FAILURE(s)) { |
|
1143 NW_Uint32 column; |
|
1144 NW_XML_Reader_GetLineColumn(&t, line, &column); |
|
1145 if(pW->pStringTableObject) |
|
1146 { |
|
1147 NW_Encoder_StringTable_delete(pW->pStringTableObject); |
|
1148 } |
|
1149 NW_XML_XmlpWbxmlEncoder_Delete(wbxmlEncodeCallbacks.pClientPointer); |
|
1150 return s; |
|
1151 } |
|
1152 |
|
1153 /* If there is any string table data then free it after PASS-1 as |
|
1154 * PASS-2 will again store the data in this. The PASS-1 only calulate |
|
1155 * size of the WBXML buffer. |
|
1156 */ |
|
1157 |
|
1158 NW_Encoder_StringTable_delete((NW_Encoder_StringTable_t*) |
|
1159 ((NW_XML_XmlpWbxmlEncoder_t*)wbxmlEncodeCallbacks.pClientPointer)->pE->pStringTableObject); |
|
1160 |
|
1161 |
|
1162 /* Allocate buffer and reinitialize writer to write to buf. */ |
|
1163 wbxmlBufLength = (((NW_XML_XmlpWbxmlEncoder_t*) |
|
1164 wbxmlEncodeCallbacks.pClientPointer)->pE->index); |
|
1165 pWbxmlBuf = (NW_Uint8*) NW_Mem_Malloc(wbxmlBufLength); |
|
1166 if (!pWbxmlBuf) { |
|
1167 if(pW->pStringTableObject) |
|
1168 { |
|
1169 NW_Encoder_StringTable_delete(pW->pStringTableObject); |
|
1170 } |
|
1171 NW_XML_XmlpWbxmlEncoder_Delete(wbxmlEncodeCallbacks.pClientPointer); |
|
1172 return NW_STAT_OUT_OF_MEMORY; |
|
1173 } |
|
1174 NW_XML_XmlpWbxmlEncoder_SetToWrite((NW_XML_XmlpWbxmlEncoder_t*) |
|
1175 wbxmlEncodeCallbacks.pClientPointer, |
|
1176 wbxmlBufLength, pWbxmlBuf, |
|
1177 NULL /* no growth callback */); |
|
1178 /* Reregister the document text with the Reader in preparation for parsing. */ |
|
1179 s = NW_XML_Reader_InitFromBuffer(&t, docByteLength, docStartAddress); |
|
1180 if (NW_STAT_IS_FAILURE(s)) { |
|
1181 if(pW->pStringTableObject) |
|
1182 { |
|
1183 NW_Encoder_StringTable_delete(pW->pStringTableObject); |
|
1184 } |
|
1185 NW_XML_XmlpWbxmlEncoder_Delete(wbxmlEncodeCallbacks.pClientPointer); |
|
1186 return s; |
|
1187 } |
|
1188 NW_XML_Reader_SetEncoding(&t, encoding); |
|
1189 |
|
1190 /* Parse and generate WBXML. */ |
|
1191 s = NW_XML_Parse(&t, &wbxmlEncodeCallbacks); |
|
1192 if (NW_STAT_IS_FAILURE(s)) { |
|
1193 NW_Uint32 column; |
|
1194 NW_XML_Reader_GetLineColumn(&t, line, &column); |
|
1195 if(pW->pStringTableObject) |
|
1196 { |
|
1197 NW_Encoder_StringTable_delete(pW->pStringTableObject); |
|
1198 } |
|
1199 NW_XML_XmlpWbxmlEncoder_Delete(wbxmlEncodeCallbacks.pClientPointer); |
|
1200 return s; |
|
1201 } |
|
1202 |
|
1203 /* The string table support check and initialize parameter accordingly. */ |
|
1204 |
|
1205 |
|
1206 NW_XML_StrTbl(&wbxmlEncodeCallbacks,WBXMLEncStrTbl); |
|
1207 |
|
1208 NW_XML_XmlpWbxmlEncoder_Delete(wbxmlEncodeCallbacks.pClientPointer); |
|
1209 (*ppOutBuf)->length = wbxmlBufLength; |
|
1210 (*ppOutBuf)->allocatedLength = wbxmlBufLength; |
|
1211 (*ppOutBuf)->data = pWbxmlBuf; |
|
1212 return NW_STAT_SUCCESS; |
|
1213 } |
|
1214 |
|
1215 |