Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

wbxml_encoder.c

Go to the documentation of this file.
00001 /*
00002  * WBXML Lib, the WBXML Library.
00003  * Copyright (C) 2002-2003  Aymerick Jéhanne
00004  * 
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License (version 2.1) as published by the Free Software Foundation.
00008  * 
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  *
00018  * LGPL v2.1: http://www.gnu.org/licenses/lgpl.txt
00019  *
00020  * Author Contact: libwbxml@jehanne.org
00021  * WBXML Lib home: http://libwbxml.jehanne.org
00022  */
00023  
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include <ctype.h> /* For isdigit() */
00051 
00052 #include "wbxml.h"
00053 
00054 
00062 /* WBXML Header:    version     publicid    charset     length
00063  *                  u_int8      mb_u_int32  mb_u_int32  mb_u_int32
00064  *                  1 octet     5 octets    5 octets    5 octets   :  16 octets
00065  * mb_u_int32: 5 octets (to handle continuation bits)
00066  */
00067 #define WBXML_HEADER_MAX_LEN 16
00068 
00069 /* Memory management related defines */
00070 #define WBXML_ENCODER_XML_DOC_MALLOC_BLOCK 5000
00071 #define WBXML_ENCODER_WBXML_DOC_MALLOC_BLOCK 1000
00072 
00073 #define WBXML_ENCODER_XML_HEADER_MALLOC_BLOCK 250
00074 #define WBXML_ENCODER_WBXML_HEADER_MALLOC_BLOCK WBXML_HEADER_MAX_LEN
00075 
00076 /* WBXML Default Charset: UTF-8 (106) */
00077 #define WBXML_ENCODER_DEFAULT_CHARSET 0x6a
00078 
00079 /* String Terminating NULL Char */
00080 #define WBXML_STR_END '\0'
00081 
00082 /* Minimum String Size needed for String Table - @note Set to '3' for Prov 1.0 */
00083 #define WBXML_ENCODER_STRING_TABLE_MIN 3
00084 
00088 typedef enum WBXMLEncoderOutputType_e {
00089     WBXML_ENCODER_OUTPUT_WBXML = 0,
00090     WBXML_ENCODER_OUTPUT_XML
00091 } WBXMLEncoderOutputType;
00092 
00098 struct WBXMLEncoder_s {
00099     WBXMLTree *tree;                        
00100     WBXMLBuffer *output;                    
00101     const WBXMLTagEntry *current_tag;       
00102     const WBXMLAttrEntry *current_attr;     
00103     WB_UTINY tagCodePage;                   
00104     WB_UTINY attrCodePage;                  
00105     WB_BOOL ignore_empty_text;              
00106     WB_BOOL remove_text_blanks;             
00107     WBXMLEncoderOutputType output_type;     
00108     WBXMLEncoderXMLGenType xml_gen_type;    
00109     WB_UTINY indent_delta;                  
00110     WB_UTINY indent;                        
00111     WB_BOOL in_content;                     
00112 #if defined( WBXML_ENCODER_USE_STRTBL )
00113     WBXMLList *strstbl;                     
00114     WB_ULONG strstbl_len;                   
00115     WB_BOOL use_strtbl;                     
00116 #endif /* WBXML_ENCODER_USE_STRTBL */
00117     WB_BOOL xml_encode_header;              
00118     WBXMLVersion wbxml_version;             
00119 };
00120 
00121 #if defined( WBXML_ENCODER_USE_STRTBL )
00122 
00125 typedef struct WBXMLStringTableElement_t {
00126     WBXMLBuffer *string; 
00127     WB_ULONG offset;     
00128     WB_ULONG count;      
00129     WB_BOOL stat;        
00130 } WBXMLStringTableElement;
00131 #endif /* WBXML_ENCODER_USE_STRTBL */
00132 
00136 typedef enum WBXMLValueElementCtx_e {
00137     WBXML_VALUE_ELEMENT_CTX_CONTENT = 0,    
00138     WBXML_VALUE_ELEMENT_CTX_ATTR            
00139 } WBXMLValueElementCtx;
00140 
00144 typedef enum WBXMLValueElementType_e {
00145     WBXML_VALUE_ELEMENT_STRING = 0, 
00146     WBXML_VALUE_ELEMENT_EXTENSION,  
00147     WBXML_VALUE_ELEMENT_OPAQUE,     
00148     WBXML_VALUE_ELEMENT_ATTR_TOKEN 
00149 #if defined( WBXML_ENCODER_USE_STRTBL )
00150     , WBXML_VALUE_ELEMENT_TABLEREF   
00151 #endif /* WBXML_ENCODER_USE_STRTBL */
00152 } WBXMLValueElementType;
00153 
00157 typedef struct WBXMLValueElement_t {
00158     WBXMLValueElementType type;     
00159     union {
00160         WBXMLBuffer *str;                   
00161         const WBXMLExtValueEntry *ext;      
00162         WBXMLBuffer *buff;                  
00163         const WBXMLAttrValueEntry *attr;    
00164 #if defined( WBXML_ENCODER_USE_STRTBL )
00165         WB_ULONG    index;                  
00166 #endif /* WBXML_ENCODER_USE_STRTBL */
00167     } u;
00168 } WBXMLValueElement;
00169 
00170 
00171 /***************************************************
00172  *    Private Functions prototypes
00173  */
00174 
00175 /*******************************
00176  * Common Functions 
00177  */
00178 
00179 static WB_BOOL convert_char_to_ucs4(WB_UTINY ch, WB_ULONG *result);
00180 static WBXMLEncoder *wbxml_encoder_duplicate(WBXMLEncoder *encoder);
00181 
00182 
00183 /*******************************
00184  * WBXML Tree Parsing Functions 
00185  */
00186 
00187 static WBXMLError parse_node(WBXMLEncoder *encoder, WBXMLTreeNode *node);
00188 static WBXMLError parse_element(WBXMLEncoder *encoder, WBXMLTreeNode *node);
00189 static WBXMLError parse_attribute(WBXMLEncoder *encoder, WBXMLAttribute *attribute);
00190 static WBXMLError parse_text(WBXMLEncoder *encoder, WBXMLTreeNode *node);
00191 static WBXMLError parse_cdata(WBXMLEncoder *encoder, WBXMLTreeNode *node);
00192 static WBXMLError parse_pi(WBXMLEncoder *encoder, WBXMLTreeNode *node);
00193 static WBXMLError parse_tree(WBXMLEncoder *encoder, WBXMLTreeNode *node);
00194 
00195 
00196 /*******************************
00197  * WBXML Output Functions
00198  */
00199 
00200 /* Build WBXML Result */
00201 static WBXMLError wbxml_build_result(WBXMLEncoder *encoder, WB_UTINY **wbxml, WB_ULONG *wbxml_len);
00202 
00203 /* WBXML Encoding Functions */
00204 static WBXMLError wbxml_encode_end(WBXMLEncoder *encoder);
00205 
00206 static WBXMLError wbxml_encode_tag(WBXMLEncoder *encoer, WBXMLTreeNode *node);
00207 static WBXMLError wbxml_encode_tag_literal(WBXMLEncoder *encoder, WB_UTINY *tag, WB_UTINY mask);
00208 static WBXMLError wbxml_encode_tag_token(WBXMLEncoder *encoder, WB_UTINY token, WB_UTINY page);
00209 
00210 static WBXMLError wbxml_encode_attr(WBXMLEncoder *encoder, WBXMLAttribute *attribute);
00211 static WBXMLError wbxml_encode_attr_start(WBXMLEncoder *encoder, WBXMLAttribute *attribute, WB_UTINY **value);
00212 static WBXMLError wbxml_encode_value_element_buffer(WBXMLEncoder *encoder, WB_UTINY *value, WBXMLValueElementCtx ctx);
00213 static WBXMLError wbxml_encode_value_element_list(WBXMLEncoder *encoder, WBXMLList *list);
00214 static WBXMLError wbxml_encode_attr_start_literal(WBXMLEncoder *encoder, const WB_UTINY *attr);
00215 static WBXMLError wbxml_encode_attr_token(WBXMLEncoder *encoder, WB_UTINY token, WB_UTINY page);
00216 
00217 static WBXMLError wbxml_encode_inline_string(WBXMLEncoder *encoder, WBXMLBuffer *str);
00218 static WBXMLError wbxml_encode_inline_integer_extension_token(WBXMLEncoder *encoder, WB_UTINY ext, WB_UTINY value);
00219 static WBXMLError wbxml_encode_entity(WBXMLEncoder *encoder, WB_ULONG value);
00220 static WBXMLError wbxml_encode_opaque(WBXMLEncoder *encoder, WBXMLBuffer *buff);
00221 #if defined( WBXML_ENCODER_USE_STRTBL )
00222 static WBXMLError wbxml_encode_tableref(WBXMLEncoder *encoder, WB_ULONG offset);
00223 #endif /* WBXML_ENCODER_USE_STRTBL */
00224 
00225 static WBXMLValueElement *wbxml_value_element_create(void);
00226 static void wbxml_value_element_destroy(WBXMLValueElement *elt);
00227 static void wbxml_value_element_destroy_item(void *elt);
00228 
00229 static WBXMLError wbxml_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree);
00230 
00231 #if ( defined( WBXML_SUPPORT_SI ) || defined( WBXML_SUPPORT_EMN ) )
00232 static WBXMLError wbxml_encode_datetime(WBXMLEncoder *encoder, WB_UTINY *buffer);
00233 #endif /* WBXML_SUPPORT_SI || WBXML_SUPPORT_EMN */
00234 
00235 #if defined( WBXML_SUPPORT_WV )
00236 static WBXMLError wbxml_encode_wv_content(WBXMLEncoder *encoder, WB_UTINY *buffer);
00237 static WBXMLError wbxml_encode_wv_integer(WBXMLEncoder *encoder, WB_UTINY *buffer);
00238 static WBXMLError wbxml_encode_wv_datetime(WBXMLEncoder *encoder, WB_UTINY *buffer);
00239 #endif /* WBXML_SUPPORT_WV */
00240 
00241 #if defined( WBXML_SUPPORT_DRMREL )
00242 static WBXMLError wbxml_encode_drmrel_content(WBXMLEncoder *encoder, WB_UTINY *buffer);
00243 #endif /* WBXML_SUPPORT_DRMREL */
00244 
00245 #if defined( WBXML_ENCODER_USE_STRTBL )
00246 /* WBXML String Table Functions */
00247 static WBXMLStringTableElement *wbxml_strtbl_element_create(WBXMLBuffer *string, WB_BOOL is_stat);
00248 static void wbxml_strtbl_element_destroy(WBXMLStringTableElement *element);
00249 static void wbxml_strtbl_element_destroy_item(void *element);
00250 
00251 static WBXMLError wbxml_strtbl_initialize(WBXMLEncoder *encoder, WBXMLTreeNode *root);
00252 static void wbxml_strtbl_collect_strings(WBXMLEncoder *encoder, WBXMLTreeNode *node, WBXMLList *strings);
00253 static WBXMLError wbxml_strtbl_collect_words(WBXMLList *elements, WBXMLList **result);
00254 static void wbxml_strtbl_construct(WB_UTINY *buff, WBXMLList *strstbl);
00255 static WBXMLError wbxml_strtbl_check_references(WBXMLEncoder *encoder, WBXMLList **strings, WBXMLList **one_ref, WB_BOOL stat_buff);
00256 static WB_BOOL wbxml_strtbl_add_element(WBXMLEncoder *encoder, WBXMLStringTableElement *elt, WB_ULONG *index, WB_BOOL *added);
00257 #endif /* WBXML_ENCODER_USE_STRTBL */
00258 
00259 
00260 /*******************************
00261  * XML Output Functions
00262  */
00263 
00265 #define WBXML_ENCODER_XML_NEW_LINE ((WB_UTINY *)"\n")
00266 
00267 /* XML Header Macros */
00268 #define WBXML_ENCODER_XML_HEADER "<?xml version=\"1.0\"?>"
00269 #define WBXML_ENCODER_XML_DOCTYPE "<!DOCTYPE "
00270 #define WBXML_ENCODER_XML_PUBLIC " PUBLIC \""
00271 #define WBXML_ENCODER_XML_DTD "\" \""
00272 #define WBXML_ENCODER_XML_END_DTD "\">"
00273 
00274 /* Global vars for XML Normalization */
00275 const WB_UTINY xml_lt[5] = "&lt;";      
00276 const WB_UTINY xml_gt[5] = "&gt;";      
00277 const WB_UTINY xml_amp[6] = "&amp;";    
00278 const WB_UTINY xml_quot[7] = "&quot;";  
00279 const WB_UTINY xml_slashr[6] = "&#13;"; 
00280 const WB_UTINY xml_slashn[6] = "&#10;"; 
00281 const WB_UTINY xml_tab[5] = "&#9;";     
00283 /* Build XML Result */
00284 static WBXMLError xml_build_result(WBXMLEncoder *encoder, WB_UTINY **xml);
00285 static WB_BOOL xml_fill_header(WBXMLEncoder *encoder, WBXMLBuffer *header);
00286 
00287 /* XML Encoding Functions */
00288 static WBXMLError xml_encode_tag(WBXMLEncoder *encoer, WBXMLTreeNode *node);
00289 static WBXMLError xml_encode_end_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node);
00290 
00291 static WBXMLError xml_encode_attr(WBXMLEncoder *encoder, WBXMLAttribute *attribute);
00292 static WBXMLError xml_encode_end_attrs(WBXMLEncoder *encoder);
00293 
00294 static WBXMLError xml_encode_text(WBXMLEncoder *encoder, WBXMLBuffer *str);
00295 static WB_BOOL xml_encode_new_line(WBXMLBuffer *buff);
00296 static WB_BOOL xml_normalize(WBXMLBuffer *buff);
00297 
00298 static WBXMLError xml_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree);
00299 
00300 
00301 /***************************************************
00302  *    Public Functions
00303  */
00304 
00305 /* WBXMLEncoder Functions */
00306 
00307 WBXML_DECLARE(WBXMLEncoder *) wbxml_encoder_create_real(void)
00308 {
00309     WBXMLEncoder *encoder = NULL;
00310 
00311     encoder = (WBXMLEncoder *) wbxml_malloc(sizeof(WBXMLEncoder));
00312     if (encoder == NULL) {
00313         return NULL;
00314     }
00315 
00316 #if defined( WBXML_ENCODER_USE_STRTBL )
00317     if ((encoder->strstbl = wbxml_list_create()) == NULL) {
00318         wbxml_free(encoder);
00319         return NULL;
00320     }
00321     encoder->use_strtbl = TRUE;
00322     encoder->strstbl_len = 0;
00323 #endif /* WBXML_ENCODER_USE_STRTBL */
00324 
00325     encoder->tree = NULL;
00326     encoder->output = NULL;
00327 
00328     encoder->current_tag = NULL;
00329     encoder->current_attr = NULL;
00330 
00331     encoder->tagCodePage = 0;
00332     encoder->attrCodePage = 0;
00333 
00334     encoder->ignore_empty_text = FALSE;
00335     encoder->remove_text_blanks = FALSE;
00336 
00337     encoder->output_type = WBXML_ENCODER_OUTPUT_WBXML;
00338     encoder->xml_gen_type = WBXML_ENCODER_XML_GEN_COMPACT;
00339 
00340     encoder->indent_delta = 1;
00341     encoder->indent = 0;
00342     encoder->in_content = FALSE;
00343 
00344     encoder->xml_encode_header = TRUE;
00345     
00346     /* Default Version: WBXML 1.3 */
00347     encoder->wbxml_version = WBXML_VERSION_13;
00348 
00349     return encoder;
00350 }
00351 
00352 
00353 WBXML_DECLARE(void) wbxml_encoder_destroy(WBXMLEncoder *encoder)
00354 {
00355     if (encoder == NULL)
00356         return;
00357 
00358     wbxml_buffer_destroy(encoder->output);
00359 
00360 #if defined( WBXML_ENCODER_USE_STRTBL )
00361     wbxml_list_destroy(encoder->strstbl, wbxml_strtbl_element_destroy_item);
00362 #endif /* WBXML_ENCODER_USE_STRTBL */
00363    
00364     wbxml_free(encoder);
00365 }
00366 
00367 
00368 /* Possible options when generating WBXML or XML */
00369 
00370 WBXML_DECLARE(void) wbxml_encoder_set_ignore_empty_text(WBXMLEncoder *encoder, WB_BOOL set_ignore)
00371 {
00372     if (encoder == NULL)
00373         return;
00374 
00375     encoder->ignore_empty_text = set_ignore;
00376 }
00377 
00378 
00379 WBXML_DECLARE(void) wbxml_encoder_set_remove_text_blanks(WBXMLEncoder *encoder, WB_BOOL set_remove)
00380 {
00381     if (encoder == NULL)
00382         return;
00383 
00384     encoder->remove_text_blanks = set_remove;
00385 }
00386 
00387 
00388 /* Possible options when generating WBXML */
00389 
00390 WBXML_DECLARE(void) wbxml_encoder_set_use_strtbl(WBXMLEncoder *encoder, WB_BOOL use_strtbl)
00391 {
00392 #if defined( WBXML_ENCODER_USE_STRTBL )
00393     if (encoder == NULL)
00394         return;
00395 
00396     encoder->use_strtbl = use_strtbl;
00397 #endif /* WBXML_ENCODER_USE_STRTBL */
00398 }
00399 
00400 
00401 WBXML_DECLARE(void) wbxml_encoder_set_wbxml_version(WBXMLEncoder *encoder, WBXMLVersion version)
00402 {
00403     if (encoder == NULL)
00404         return;
00405     
00406     if (version != WBXML_VERSION_UNKNOWN)
00407         encoder->wbxml_version = version;
00408 }
00409 
00410 
00411 /* Possible options when generating XML */
00412 
00413 WBXML_DECLARE(void) wbxml_encoder_set_xml_gen_type(WBXMLEncoder *encoder, WBXMLEncoderXMLGenType gen_type)
00414 {
00415     if (encoder == NULL)
00416         return;
00417 
00418     encoder->xml_gen_type = gen_type;
00419 }
00420 
00421 
00422 WBXML_DECLARE(void) wbxml_encoder_set_indent(WBXMLEncoder *encoder, WB_UTINY indent)
00423 {
00424     if (encoder == NULL)
00425         return;
00426 
00427     encoder->indent_delta = indent;
00428 }
00429 
00430 
00431 /* Encoding Functions */
00432 
00433 WBXML_DECLARE(void) wbxml_encoder_set_tree(WBXMLEncoder *encoder, WBXMLTree *tree)
00434 {
00435     if (encoder == NULL)
00436         return;
00437 
00438     encoder->tree = tree;
00439 }
00440 
00441 
00442 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_to_wbxml(WBXMLEncoder *encoder, WB_UTINY **wbxml, WB_ULONG *wbxml_len)
00443 {
00444     WBXMLError ret = WBXML_OK;
00445 
00446     /* Check Parameters */
00447     if ((encoder == NULL) || (encoder->tree == NULL) || (encoder->tree->lang == NULL) || (wbxml == NULL) || (wbxml_len == NULL))
00448         return WBXML_ERROR_BAD_PARAMETER;
00449 
00450     /* We output WBXML */
00451     encoder->output_type = WBXML_ENCODER_OUTPUT_WBXML;
00452 
00453     /* Init ret values */
00454     *wbxml = NULL;
00455     *wbxml_len = 0;
00456      
00457     /* Init WBXML Output Buffer */
00458     encoder->output = wbxml_buffer_create("", 0, WBXML_ENCODER_WBXML_DOC_MALLOC_BLOCK);
00459     if (encoder->output == NULL) {
00460         wbxml_encoder_destroy(encoder);
00461         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00462     }
00463 
00464 #if defined( WBXML_ENCODER_USE_STRTBL )
00465 
00466     /* Choose if we will use String Table */
00467     switch (encoder->tree->lang->langID) 
00468     {
00469 #if defined( WBXML_SUPPORT_WV )
00470     /* Wireless-Village CSP 1.1 / 1.2: content can be tokenized, so we mustn't interfere with String Table stuff */
00471     case WBXML_LANG_WV_CSP11:
00472     case WBXML_LANG_WV_CSP12:
00473         encoder->use_strtbl = FALSE;
00474         break;
00475 #endif /* WBXML_SUPPORT_WV */
00476 
00477     default:
00478         /* Use Default Value */
00479         break;
00480     }
00481 
00482     /* Init String Table */
00483     if (encoder->use_strtbl) {
00484         if ((ret = wbxml_strtbl_initialize(encoder, encoder->tree->root)) != WBXML_OK)
00485             return ret;
00486     }
00487 
00488 #endif /* WBXML_ENCODER_USE_STRTBL */
00489 
00490     /* Let's begin WBXML Tree Parsing */
00491     if ((ret = parse_node(encoder, encoder->tree->root)) != WBXML_OK)
00492         return ret;
00493 
00494     /* Build result */
00495     return wbxml_build_result(encoder, wbxml, wbxml_len);
00496 }
00497 
00498 
00499 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_to_xml(WBXMLEncoder *encoder, WB_UTINY **xml)
00500 {
00501     WBXMLError ret = WBXML_OK;
00502 
00503     /* Check Parameters */
00504     if ((encoder == NULL) || (encoder->tree == NULL) || (encoder->tree->lang == NULL) || (xml == NULL))
00505         return WBXML_ERROR_BAD_PARAMETER;
00506 
00507     /* We output XML */
00508     encoder->output_type = WBXML_ENCODER_OUTPUT_XML;
00509 
00510     /* Init ret values */
00511     *xml = NULL;
00512      
00513     /* Init XML Output Buffer */
00514     encoder->output = wbxml_buffer_create("", 0, WBXML_ENCODER_XML_DOC_MALLOC_BLOCK);
00515     if (encoder->output == NULL) {
00516         wbxml_encoder_destroy(encoder);
00517         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00518     }
00519 
00520     /* Let's begin WBXML Tree Parsing */
00521     if ((ret = parse_node(encoder, encoder->tree->root)) != WBXML_OK)
00522         return ret;
00523 
00524     /* Build result */
00525     return xml_build_result(encoder, xml);
00526 }
00527 
00528 
00529 /***************************************************
00530  *    Private Functions
00531  */
00532 
00533 
00534 /****************************
00535  * Convertion Functions
00536  */
00537 
00544 static WB_BOOL convert_char_to_ucs4(WB_UTINY ch, WB_ULONG *result)
00545 {
00548     return FALSE;
00549 }
00550 
00551 
00558 static WBXMLEncoder *wbxml_encoder_duplicate(WBXMLEncoder *encoder)
00559 {
00560     WBXMLEncoder *result = NULL;
00561 
00562     if ((result = wbxml_encoder_create()) == NULL)
00563         return NULL;
00564 
00565     result->ignore_empty_text = encoder->ignore_empty_text;
00566     result->remove_text_blanks = encoder->remove_text_blanks;
00567 
00568     result->output_type = encoder->output_type;
00569     result->xml_gen_type = encoder->xml_gen_type;
00570 
00571     result->indent_delta = encoder->indent_delta;
00572     result->indent = encoder->indent;
00573 
00574     result->use_strtbl = encoder->use_strtbl;
00575 
00576     /* Do NOT generate XML Header */
00577     result->xml_encode_header = FALSE;
00578     
00579     result->wbxml_version = encoder->wbxml_version;
00580 
00581     return result;
00582 }
00583 
00584 
00585 /*********************************
00586  * WBXML Tree Parsing Functions
00587  */
00588 
00596 static WBXMLError parse_node(WBXMLEncoder *encoder, WBXMLTreeNode *node)
00597 {
00598     WBXMLError ret = WBXML_OK;
00599 
00600     /* Parse this node */
00601     switch (node->type) {
00602         case WBXML_TREE_ELEMENT_NODE:
00603             ret = parse_element(encoder, node);
00604                     break;
00605         case WBXML_TREE_TEXT_NODE:
00606                     ret = parse_text(encoder, node);
00607                     break;
00608         case WBXML_TREE_PI_NODE:
00609             ret = parse_pi(encoder, node);
00610             break;
00611         case WBXML_TREE_TREE_NODE:
00612             ret = parse_tree(encoder, node);
00613             break;
00614         default:
00615                 return WBXML_ERROR_XML_NODE_NOT_ALLOWED;
00616                     break;
00617     }
00618 
00619     if (ret != WBXML_OK)
00620         return ret;
00621 
00622     /* Check if node has children */
00623     if (node->children != NULL) {  
00624         /* Parse Child */
00625         if ((ret = parse_node(encoder, node->children)) != WBXML_OK)
00626             return ret;
00627                 
00628         /* Add a WBXML End tag */
00629         if (encoder->output_type == WBXML_ENCODER_OUTPUT_WBXML) {            
00630             if ((ret = wbxml_encode_end(encoder)) != WBXML_OK)
00631                 return ret;
00632 
00633             WBXML_DEBUG((WBXML_ENCODER, "End Element"));
00634         }
00635     }
00636 
00637     /* Reset Current Tag */
00638     encoder->current_tag = NULL;
00639 
00640     /* Always add an XML End Element tag */
00641     if ((encoder->output_type == WBXML_ENCODER_OUTPUT_XML) && 
00642         (node->type == WBXML_TREE_ELEMENT_NODE))
00643     {
00644         if ((ret = xml_encode_end_tag(encoder, node)) != WBXML_OK)
00645             return ret;
00646 
00647         WBXML_DEBUG((WBXML_ENCODER, "End Element"));
00648     }
00649 
00650     /* Parse next node */
00651     if (node->next != NULL)
00652         return parse_node(encoder, node->next);
00653     else
00654         return WBXML_OK;
00655 }
00656 
00657 
00664 static WBXMLError parse_element(WBXMLEncoder *encoder, WBXMLTreeNode *node)
00665 {   
00666     WBXMLTreeAttribute *attribute = NULL;
00667     WB_UTINY ret = WBXML_OK;
00668 
00669     WBXML_DEBUG((WBXML_ENCODER, "Element: <%s>", wbxml_tag_get_xml_name(node->name)));
00670 
00671     /* Encode: Element Name */
00672     switch (encoder->output_type) {
00673     case WBXML_ENCODER_OUTPUT_WBXML:
00674         if ((ret = wbxml_encode_tag(encoder, node)) != WBXML_OK)
00675             return ret;
00676         break;
00677     case WBXML_ENCODER_OUTPUT_XML:
00678         if ((ret = xml_encode_tag(encoder, node)) != WBXML_OK)
00679             return ret;
00680         break;
00681     default:
00682         return WBXML_ERROR_INTERNAL;
00683     }
00684 
00689     /* Parse: Attributes List */
00690     if ((attribute = node->attrs) != NULL) 
00691     {
00692                 while (attribute != NULL) {
00693             /* Parse: Attribute */
00694                         if ((ret = parse_attribute(encoder, attribute->attr)) != WBXML_OK)
00695                 return ret;
00696 
00697                         attribute = attribute->next;
00698                 }
00699     }
00700 
00701     /* Encode: End of attributes */
00702     switch (encoder->output_type) {
00703     case WBXML_ENCODER_OUTPUT_WBXML:
00707         if ((node->attrs != NULL) && (encoder->tree->lang->attrTable != NULL) ) {
00708             if ((ret = wbxml_encode_end(encoder)) != WBXML_OK)
00709                 return ret;
00710         }
00711         break;
00712     case WBXML_ENCODER_OUTPUT_XML:
00713         if ((ret = xml_encode_end_attrs(encoder)) != WBXML_OK)
00714             return ret;
00715         break;
00716     default:
00717         return WBXML_ERROR_INTERNAL;
00718     }
00719 
00720     return WBXML_OK;
00721 }
00722 
00723 
00730 static WBXMLError parse_attribute(WBXMLEncoder *encoder, WBXMLAttribute *attribute)
00731 {      
00732     if (encoder->tree->lang == NULL)
00733         return WBXML_ERROR_LANG_TABLE_UNDEFINED;
00734 
00735     if (encoder->tree->lang->attrTable == NULL)
00736         return WBXML_OK;
00737 
00738     /* Check that this attribute has a name */
00739     if (attribute->name == NULL)
00740         return WBXML_ERROR_XML_NULL_ATTR_NAME;
00741 
00742     WBXML_DEBUG((WBXML_ENCODER, "Attribute: %s = %s", wbxml_attribute_get_xml_name(attribute), wbxml_attribute_get_xml_value(attribute)));
00743    
00744     /* Encode: Attribute */
00745     switch (encoder->output_type) {
00746     case WBXML_ENCODER_OUTPUT_WBXML:
00747         return wbxml_encode_attr(encoder, attribute);
00748     case WBXML_ENCODER_OUTPUT_XML:
00749         return xml_encode_attr(encoder, attribute);
00750     default:
00751         return WBXML_ERROR_INTERNAL;
00752     }
00753 }
00754 
00755 
00762 static WBXMLError parse_text(WBXMLEncoder *encoder, WBXMLTreeNode *node)
00763 {
00764     /* If Canonical Form: "Ignorable white space is considered significant and is treated equivalently to data" */
00765     if (encoder->xml_gen_type != WBXML_ENCODER_XML_GEN_CANONICAL) {
00766         /* Ignore blank nodes */
00767         if ((encoder->ignore_empty_text) && (wbxml_buffer_contains_only_whitespaces(node->content)))
00768             return WBXML_OK;
00769 
00770         /* Strip Blanks */
00771         if (encoder->remove_text_blanks)
00772             wbxml_buffer_strip_blanks(node->content);
00773     }
00774 
00775     /* Encode Text */
00776     switch (encoder->output_type) {
00777     case WBXML_ENCODER_OUTPUT_WBXML:
00778         return wbxml_encode_value_element_buffer(encoder, wbxml_buffer_get_cstr(node->content), WBXML_VALUE_ELEMENT_CTX_CONTENT);
00779     case WBXML_ENCODER_OUTPUT_XML:
00780         return xml_encode_text(encoder, node->content);
00781     default:
00782         return WBXML_ERROR_INTERNAL;
00783     }
00784 
00785     return WBXML_OK;
00786 }
00787 
00788 
00795 static WBXMLError parse_cdata(WBXMLEncoder *encoder, WBXMLTreeNode *node)
00796 {
00799     return WBXML_ERROR_NOT_IMPLEMENTED;
00800 }
00801 
00802 
00809 static WBXMLError parse_pi(WBXMLEncoder *encoder, WBXMLTreeNode *node)
00810 {
00813     return WBXML_ERROR_NOT_IMPLEMENTED;
00814 }
00815 
00816 
00823 static WBXMLError parse_tree(WBXMLEncoder *encoder, WBXMLTreeNode *node)
00824 {
00825     switch (encoder->output_type) {
00826     case WBXML_ENCODER_OUTPUT_WBXML:
00827         return wbxml_encode_tree(encoder, node->tree);
00828     case WBXML_ENCODER_OUTPUT_XML:
00829         return xml_encode_tree(encoder, node->tree);
00830     default:
00831         return WBXML_ERROR_INTERNAL;
00832     }
00833 }
00834 
00835 
00836 /*****************************************
00837  *  WBXML Output Functions
00838  */
00839 
00840 
00841 /****************************
00842  * Build WBXML Result
00843  */
00844 
00853 static WBXMLError wbxml_build_result(WBXMLEncoder *encoder, WB_UTINY **wbxml, WB_ULONG *wbxml_len)
00854 {    
00855     WBXMLBuffer *header = NULL, *pid = NULL;
00856     WB_ULONG public_id, public_id_index, strstbl_len = 0;
00857     WB_BOOL pi_in_strtbl = FALSE, added = FALSE;
00858 
00859 #if defined( WBXML_ENCODER_USE_STRTBL )
00860     WBXMLStringTableElement *elt = NULL;
00861 
00862     strstbl_len = encoder->strstbl_len;
00863 #endif /* WBXML_ENCODER_USE_STRTBL */
00864 
00865     /* WBXML Public ID */
00866     public_id = encoder->tree->lang->publicID->wbxmlPublicID;
00867 
00868     /* Create WBXML Header buffer */
00869     header = wbxml_buffer_create("", 0, WBXML_ENCODER_WBXML_HEADER_MALLOC_BLOCK);
00870     if (header == NULL)
00871         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00872     
00873     /* Encode WBXML Version */
00874     if (!wbxml_buffer_append_char(header, (WB_UTINY) encoder->wbxml_version))
00875 
00876     {
00877         wbxml_buffer_destroy(header);
00878         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00879     }
00880 
00881     /* Encode Public ID */
00882     /* If WBXML Public Id is '0x01' (unknown), add the XML Public ID in the String Table */
00883     if (public_id == WBXML_PUBLIC_ID_UNKNOWN) 
00884     {
00885         if (encoder->tree->lang->publicID->xmlPublicID != NULL) 
00886         {
00887             if ((pid = wbxml_buffer_create(encoder->tree->lang->publicID->xmlPublicID, 
00888                                            WBXML_STRLEN(encoder->tree->lang->publicID->xmlPublicID),
00889                                            WBXML_STRLEN(encoder->tree->lang->publicID->xmlPublicID))) == NULL)
00890             {
00891                 wbxml_buffer_destroy(pid);
00892                 wbxml_buffer_destroy(header);
00893                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00894             }
00895 
00896 #if defined( WBXML_ENCODER_USE_STRTBL )
00897             if ((elt = wbxml_strtbl_element_create(pid, FALSE)) == NULL)
00898             {
00899                 wbxml_buffer_destroy(pid);
00900                 wbxml_buffer_destroy(header);
00901                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00902             }
00903 
00904             if (!wbxml_strtbl_add_element(encoder,
00905                                           elt,
00906                                           &public_id_index,
00907                                           &added))
00908             {
00909                 wbxml_buffer_destroy(header);
00910                 wbxml_strtbl_element_destroy(elt);
00911                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00912             }
00913 
00914             if (!added)
00915                 wbxml_strtbl_element_destroy(elt);
00916 
00917             strstbl_len = encoder->strstbl_len;
00918 #else
00919             /* Length of String Table is length of XML Public ID (including terminating NULL char) */
00920             strstbl_len = wbxml_buffer_len(pid) + 1;
00921 
00922             /* There is only the XML Public ID in String Table */
00923             public_id_index = 0;
00924 #endif /* WBXML_ENCODER_USE_STRTBL */
00925 
00926             pi_in_strtbl = TRUE;
00927         }
00928     }
00929     
00930     /* publicid = mb_u_int32 | ( zero index ) */
00931     if (pi_in_strtbl) {
00932         /* Encode XML Public ID String Table index */
00933         if (!wbxml_buffer_append_char(header, 0x00) ||
00934             !wbxml_buffer_append_mb_uint_32(header, public_id_index)) 
00935         {
00936             wbxml_buffer_destroy(header);
00937             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00938         }
00939     }
00940     else {
00941         /* Encode WBXML Public ID */
00942         if (!wbxml_buffer_append_mb_uint_32(header, public_id)) {
00943             wbxml_buffer_destroy(header);
00944             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00945         }
00946     }    
00947 
00948     /* Encode Charset (default: UTF-8) and String Table Length */
00950     if (!wbxml_buffer_append_mb_uint_32(header, WBXML_ENCODER_DEFAULT_CHARSET) || 
00951         !wbxml_buffer_append_mb_uint_32(header, strstbl_len))
00952     {
00953         wbxml_buffer_destroy(header);
00954         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00955     }
00956 
00957     /* Result Buffer Length */
00958     *wbxml_len = wbxml_buffer_len(header) + strstbl_len + wbxml_buffer_len(encoder->output);
00959 
00960     /* Create Result Buffer */
00961     *wbxml = (WB_UTINY *) wbxml_malloc(*wbxml_len * sizeof(WB_UTINY));
00962     if (*wbxml == NULL) {
00963         wbxml_buffer_destroy(header);
00964         *wbxml_len = 0;
00965         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00966     }
00967 
00968     /* Copy WBXML Header */
00969     memcpy(*wbxml, wbxml_buffer_get_cstr(header), wbxml_buffer_len(header));
00970 
00971     /* Copy WBXML String Table */
00972 #if defined( WBXML_ENCODER_USE_STRTBL )
00973     wbxml_strtbl_construct(*wbxml + wbxml_buffer_len(header), encoder->strstbl);
00974 #else
00975     /* The copy includes terminating NULL char */
00976     memcpy(*wbxml + wbxml_buffer_len(header), wbxml_buffer_get_cstr(pid), strstbl_len);
00977 
00978     wbxml_buffer_destroy(pid);
00979 #endif /* WBXML_ENCODER_USE_STRTBL */
00980 
00981     /* Copy WBXML Buffer */
00982     memcpy(*wbxml + wbxml_buffer_len(header) + strstbl_len, wbxml_buffer_get_cstr(encoder->output), wbxml_buffer_len(encoder->output));
00983       
00984     wbxml_buffer_destroy(header);
00985 
00986     return WBXML_OK;
00987 }
00988 
00989 
00990 /****************************
00991  * WBXML Encoding Functions
00992  */
00993 
00999 static WBXMLError wbxml_encode_end(WBXMLEncoder *encoder)
01000 {
01001     /* Append END */
01002     if (!wbxml_buffer_append_char(encoder->output, WBXML_END))
01003         return WBXML_ERROR_ENCODER_APPEND_DATA;
01004 
01005     return WBXML_OK;
01006 }
01007 
01008 
01015 static WBXMLError wbxml_encode_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node)
01016 {   
01017     const WBXMLTagEntry *tag = NULL;
01018     WB_UTINY token = 0x00, page = 0x00;
01019 
01020     if (node->name->type == WBXML_VALUE_TOKEN) {
01021         token = node->name->u.token->wbxmlToken;
01022         page = node->name->u.token->wbxmlCodePage;
01023 
01024         /* Current Tag */
01025         encoder->current_tag = node->name->u.token;
01026     }
01027     else {
01028         /* Search tag in Tags Table */
01029         if ((tag = wbxml_tables_get_tag_from_xml(encoder->tree->lang, wbxml_tag_get_xml_name(node->name))) != NULL) 
01030         {
01031             token = tag->wbxmlToken;
01032             page = tag->wbxmlCodePage;
01033 
01034             /* Current Tag */
01035             encoder->current_tag = tag;
01036         }
01037         else
01038             encoder->current_tag = NULL;
01039     }
01040 
01041     /* Check if this element has content */
01042     if (node->children != NULL)
01043         token |= WBXML_TOKEN_WITH_CONTENT;
01044 
01045     /* Check if this element has attributes */
01049     if ((node->attrs != NULL) && (encoder->tree->lang->attrTable != NULL) )
01050         token |= WBXML_TOKEN_WITH_ATTRS;
01051 
01052     /* Encode Token */
01053     if ((token & WBXML_TOKEN_MASK) == 0x00)
01054         return wbxml_encode_tag_literal(encoder, (WB_UTINY *) wbxml_tag_get_xml_name(node->name), token);
01055     else
01056         return wbxml_encode_tag_token(encoder, token, page);
01057 }
01058 
01059 
01070 static WBXMLError wbxml_encode_tag_literal(WBXMLEncoder *encoder, WB_UTINY *tag, WB_UTINY mask)
01071 {
01072 #if defined( WBXML_ENCODER_USE_STRTBL )
01073     WBXMLStringTableElement *elt = NULL;
01074     WBXMLBuffer *buff = NULL;
01075     WB_ULONG index = 0;
01076     WB_BOOL added = FALSE;
01077 
01078     /* If String Table generation is disabled, we can't generate this Literal Tag */
01079     if (!encoder->use_strtbl)
01080         return WBXML_ERROR_STRTBL_DISABLED;
01081 
01082     /* Add tag in String Table */
01083     if (((buff = wbxml_buffer_create(tag, WBXML_STRLEN(tag), WBXML_STRLEN(tag))) == NULL) ||
01084         ((elt = wbxml_strtbl_element_create(buff, FALSE)) == NULL) ||
01085         (!wbxml_strtbl_add_element(encoder, elt, &index, &added)))
01086     {
01087         wbxml_strtbl_element_destroy(elt);
01088         wbxml_buffer_destroy(buff);
01089         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01090     }
01091 
01092     /* If already exists in String Table: clean-up */
01093     if (!added)
01094         wbxml_strtbl_element_destroy(elt);    
01095 
01096     /* Encode literalTag index */
01097     if ((!wbxml_buffer_append_char(encoder->output, (WB_UTINY) (WBXML_LITERAL | mask))) ||
01098         (!wbxml_buffer_append_mb_uint_32(encoder->output, index)))
01099     {
01100         return WBXML_ERROR_ENCODER_APPEND_DATA;
01101     }
01102 
01103     return WBXML_OK;
01104 #else
01105     /* No String Table Support */
01106     return WBXML_ERROR_STRTBL_DISABLED;
01107 #endif /* WBXML_ENCODER_USE_STRTBL */
01108 }
01109 
01110 
01122 static WBXMLError wbxml_encode_tag_token(WBXMLEncoder *encoder, WB_UTINY token, WB_UTINY page)
01123 {
01124     /* Switch Page if needed */
01125     if (encoder->tagCodePage != page) 
01126     {
01127         if ((!wbxml_buffer_append_char(encoder->output, WBXML_SWITCH_PAGE)) ||
01128             (!wbxml_buffer_append_char(encoder->output, page)))
01129         {
01130             return WBXML_ERROR_ENCODER_APPEND_DATA;
01131         }
01132 
01133         encoder->tagCodePage = page;
01134     }
01135 
01136     /* Add Token */
01137     if (!wbxml_buffer_append_char(encoder->output, token))
01138         return WBXML_ERROR_ENCODER_APPEND_DATA;
01139 
01140     return WBXML_OK;
01141 }
01142 
01143 
01151 static WBXMLError wbxml_encode_attr(WBXMLEncoder *encoder, WBXMLAttribute *attribute)
01152 {
01153     WB_UTINY *value = NULL;
01154     WBXMLError ret = WBXML_OK;
01155 
01156     /* Encode Attribute Start */
01157     if ((ret = wbxml_encode_attr_start(encoder, attribute, &value)) != WBXML_OK)
01158         return ret;
01159 
01160     /* Encode Attribute Value */
01161     if (value != NULL) {
01162         if ((ret = wbxml_encode_value_element_buffer(encoder, value, WBXML_VALUE_ELEMENT_CTX_ATTR)) != WBXML_OK)
01163             return ret;
01164     }
01165 
01166     /* Reset Current Attribute */
01167     encoder->current_attr = NULL;
01168 
01169     return WBXML_OK;
01170 }
01171 
01172 
01187 static WBXMLError wbxml_encode_attr_start(WBXMLEncoder *encoder, WBXMLAttribute *attribute, WB_UTINY **value)
01188 {
01189     const WBXMLAttrEntry *attr = NULL;
01190     WB_UTINY *value_left = NULL;
01191     WB_UTINY token = 0x00, page = 0x00;
01192 
01193     *value = wbxml_buffer_get_cstr(attribute->value);
01194 
01195     if (attribute->name->type == WBXML_VALUE_TOKEN) {
01196         /* We already have Token / Page pair for this Attribute Start */
01197         token = attribute->name->u.token->wbxmlToken;
01198         page = attribute->name->u.token->wbxmlCodePage;
01199 
01200         /* Current Attribute */
01201         encoder->current_attr = attribute->name->u.token;
01202         
01203         /* If there is a Start Value associated to the Attribute Name token... */
01204         if (attribute->name->u.token->xmlValue != NULL) 
01205         {
01206             /* ... Check that we have it at start of full Attribute Value */
01207             if (WBXML_STRNCMP(wbxml_buffer_get_cstr(attribute->value), 
01208                               attribute->name->u.token->xmlValue,
01209                               WBXML_STRLEN(attribute->name->u.token->xmlValue)) == 0)
01210             {
01211                 /* Check if you have still a part in the Attribute Value to encode */
01212                 if (wbxml_buffer_len(attribute->value) > WBXML_STRLEN(attribute->name->u.token->xmlValue)) 
01213                 {
01214                     /* There is still a part in the Value to encode */
01215                     *value = wbxml_buffer_get_cstr(attribute->value) + WBXML_STRLEN(attribute->name->u.token->xmlValue);
01216                 }
01217                 else
01218                     *value = NULL;
01219             }
01220             else {
01222                 WBXML_WARNING((WBXML_ENCODER, "wbxml_encode_attr_start() => Attribute Value doesn't match Attribute Token"));
01223 
01224                 /* Current Attribute */
01225                 encoder->current_attr = NULL;
01226 
01227                 /* Encode Attribute Literal */
01228                 return wbxml_encode_attr_start_literal(encoder, wbxml_attribute_get_xml_name(attribute));
01229             }
01230         }
01231 
01232         /* Encode Attribute Token */
01233         return wbxml_encode_attr_token(encoder, token, page);
01234     }
01235     else {
01236         /* Search in Attribute table */
01237         if ((attr = wbxml_tables_get_attr_from_xml(encoder->tree->lang, 
01238                                                    (WB_UTINY *)attribute->name->u.token->xmlName, 
01239                                                    wbxml_buffer_get_cstr(attribute->value),
01240                                                    &value_left)) != NULL)
01241         {
01242             token = attr->wbxmlToken;
01243             page = attr->wbxmlCodePage;
01244 
01245             /* Current Attribute */
01246             encoder->current_attr = attr;
01247 
01248             /* If there is still a part in Attribute Value to encode */
01249             *value = value_left;
01250 
01251             /* Encode Attribute Token */
01252             return wbxml_encode_attr_token(encoder, token, page);
01253         }
01254         else {
01255             /* Current Attribute */
01256             encoder->current_attr = NULL;
01257 
01258             /* Encode Attribute Literal */
01259             return wbxml_encode_attr_start_literal(encoder, wbxml_attribute_get_xml_name(attribute));
01260         }
01261     }
01262 }
01263 
01264 
01277 static WBXMLError wbxml_encode_value_element_buffer(WBXMLEncoder *encoder, WB_UTINY *buffer, WBXMLValueElementCtx ctx)
01278 {
01279     WBXMLList *lresult = NULL;
01280     WBXMLBuffer *buff = NULL;
01281     WBXMLValueElement *elt = NULL, *new_elt = NULL;    
01282     WB_ULONG i = 0, j = 0, index = 0;
01283     WB_UTINY *the_buffer = buffer;
01284     WBXMLError ret = WBXML_OK;
01285 
01286 #if defined( WBXML_ENCODER_USE_STRTBL )
01287     WBXMLStringTableElement *strtbl_elt = NULL;
01288 #endif /* WBXML_ENCODER_USE_STRTBL */
01289 
01290     if ((buffer == NULL) || (*buffer == '\0'))
01291         return WBXML_OK;
01292 
01293 
01294     /*********************************************************
01295      *  Encoder Language Specific Attribute Values
01296      */
01297 
01298     if (ctx == WBXML_VALUE_ELEMENT_CTX_ATTR) {        
01299         switch (encoder->tree->lang->langID) {
01300 #if defined( WBXML_SUPPORT_SI )
01301         case WBXML_LANG_SI10:
01302             /* SI 1.0: Encode date for 'created' and 'si-expires' attributes */
01303             if ((encoder->current_attr->wbxmlCodePage == 0x00) && 
01304                 ((encoder->current_attr->wbxmlToken == 0x0a) || (encoder->current_attr->wbxmlToken == 0x10)))
01305             {
01306                 return wbxml_encode_datetime(encoder, buffer);
01307             }
01308             break;
01309 #endif /* WBXML_SUPPORT_SI */
01310 
01311 #if defined( WBXML_SUPPORT_EMN )
01312         case WBXML_LANG_EMN10:
01313             /* EMN 1.0: Encode date for 'timestamp' attribute */
01314             if ((encoder->current_attr->wbxmlCodePage == 0x00) && (encoder->current_attr->wbxmlToken == 0x05))
01315             {
01316                 return wbxml_encode_datetime(encoder, buffer);
01317             }
01318             break;
01319 #endif /* WBXML_SUPPORT_EMN */
01320 
01321         default:
01322             break;
01323         }
01324     }
01325 
01326 
01327     /*********************************************************
01328      *  Encoder Language Specific Content Text Values
01329      */
01330 
01331     /* If this is a Text Content */
01332     if (ctx == WBXML_VALUE_ELEMENT_CTX_CONTENT) 
01333     {
01334 #if defined( WBXML_SUPPORT_WV )
01335         /* If this is a Wireless-Village 1.1 / 1.2 document */
01336         if ((encoder->tree->lang->langID == WBXML_LANG_WV_CSP11) ||
01337             (encoder->tree->lang->langID == WBXML_LANG_WV_CSP12))
01338         {
01339             /* Here we try to encode Specific WV Content. If this buffer is not a WV Data Type buffer, or
01340              * if it can't be FULLY encoded as an Extension Token, then this function returns WBXML_NOT_ENCODED.
01341              * If so, the buffer will be encoded as String latter.
01342              */
01343             if ((ret = wbxml_encode_wv_content(encoder, buffer)) != WBXML_NOT_ENCODED)
01344                 return ret;
01345         }
01346 #endif /* WBXML_SUPPORT_WV */
01347 
01348 #if defined( WBXML_SUPPORT_DRMREL )
01349         /* If this is a DRMREL 1.0 document */
01350         if (encoder->tree->lang->langID == WBXML_LANG_DRMREL10)
01351         {
01352             /* Here we try to encode Specific DRMREL Content. If this buffer is not a DRMREL Data Type buffer
01353              * this function returns WBXML_NOT_ENCODED.
01354              * If so, the buffer will be encoded as String latter.
01355              */
01356             if ((ret = wbxml_encode_drmrel_content(encoder, buffer)) != WBXML_NOT_ENCODED)
01357                 return ret;
01358         }
01359 #endif /* WBXML_SUPPORT_DRMREL */
01360 
01361 #if defined( WBXML_SUPPORT_SYNCML )
01362         /* If this is a SyncML document ? */
01363         if ((encoder->tree->lang->langID == WBXML_LANG_SYNCML_SYNCML10) ||
01364             (encoder->tree->lang->langID == WBXML_LANG_SYNCML_SYNCML11))
01365         {
01368             /* Change text in <Type> from "application/vnd.syncml-devinf+xml" to "application/vnd.syncml-devinf+wbxml" */
01369             if (WBXML_STRCASECMP(buffer, "application/vnd.syncml-devinf+xml") == 0) {
01370                 the_buffer = (WB_UTINY*) "application/vnd.syncml-devinf+wbxml";
01371             }
01372         }
01373 #endif /* WBXML_SUPPORT_SYNCML */
01374     }
01375 
01376 
01377     /*********************************************************
01378      * @todo Search first for simple cases !
01379      */
01380 
01381 
01382     /*********************************************************
01383      *  We search the list of Value Elements that represents 
01384      *  this Value buffer
01385      */
01386 
01387     /* Create Result List */
01388     if ((lresult = wbxml_list_create()) == NULL)
01389         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01390 
01391     /* Create primary Buffer */
01392     if ((buff = wbxml_buffer_create_from_cstr(the_buffer)) == NULL) {
01393         wbxml_list_destroy(lresult, NULL);
01394         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01395     }
01396 
01397     /* Create Value Element for this buffer */
01398     if ((elt = wbxml_value_element_create()) == NULL) {
01399         wbxml_buffer_destroy(buff);
01400         wbxml_list_destroy(lresult, NULL);
01401         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01402     }
01403 
01404     elt->type = WBXML_VALUE_ELEMENT_STRING;
01405     elt->u.str = buff;
01406 
01407     /* Append this Buffer to Result List */
01408     if (!wbxml_list_append(lresult, elt)) {
01409         wbxml_value_element_destroy(elt);
01410         wbxml_list_destroy(lresult, NULL);
01411         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01412     }
01413 
01414     /* If this is an Attribute Value */
01415     if (ctx == WBXML_VALUE_ELEMENT_CTX_ATTR) 
01416     {
01417         /*********************************************************
01418          *  Search for Attribute Value Tokens
01419          */
01420 
01421         if (encoder->tree->lang->attrValueTable != NULL) {
01422             /* For each Attribute Value Token */
01423             j = 0;
01424             while (encoder->tree->lang->attrValueTable[j].xmlName != NULL)
01425             {
01426                 /* For each Value Element */
01427                 for (i = 0; i < wbxml_list_len(lresult); i++) {
01428                     if ((elt = (WBXMLValueElement *) wbxml_list_get(lresult, i)) == NULL)
01429                         continue;
01430 
01431                     if (elt->type != WBXML_VALUE_ELEMENT_STRING)
01432                         continue;
01433 
01434                     /* Is this Attribute Value contained in this Buffer ? */
01435                     if (wbxml_buffer_search_cstr(elt->u.str, (WB_UTINY *)encoder->tree->lang->attrValueTable[j].xmlName, 0, &index)) {
01436                         /* Create new Value Element */
01437                         if ((new_elt = wbxml_value_element_create()) == NULL) {
01438                             wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01439                             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01440                         }
01441 
01442                         new_elt->type = WBXML_VALUE_ELEMENT_ATTR_TOKEN;
01443                         new_elt->u.attr = &(encoder->tree->lang->attrValueTable[j]);
01444 
01445                         /* Insert new Value Element in List */
01446                         if (!wbxml_list_insert(lresult, (void *) new_elt, i + 1)) {
01447                             wbxml_value_element_destroy(new_elt);
01448                             wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01449                             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01450                         }
01451 
01452                         /* Check if there is still the end of the String to encode */
01453                         if (index + WBXML_STRLEN(encoder->tree->lang->attrValueTable[j].xmlName) < wbxml_buffer_len(elt->u.str)) {
01454                             /* Create new Value Element */
01455                             if ((new_elt = wbxml_value_element_create()) == NULL) {
01456                                 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01457                                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01458                             }
01459 
01460                             new_elt->type = WBXML_VALUE_ELEMENT_STRING;
01461                             new_elt->u.str = wbxml_buffer_create_from_cstr(wbxml_buffer_get_cstr(elt->u.str) + index + WBXML_STRLEN(encoder->tree->lang->attrValueTable[j].xmlName));
01462 
01463                             /* Insert new Value Element in List */
01464                             if ((new_elt->u.str == NULL) ||
01465                                 !wbxml_list_insert(lresult, (void *) new_elt, i + 2)) 
01466                             {
01467                                 wbxml_value_element_destroy(new_elt);
01468                                 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01469                                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01470                             }
01471                         }
01472 
01473                         /* Remove the Attribute Value found in Value Element */
01474                         wbxml_buffer_delete(elt->u.str, index, wbxml_buffer_len(elt->u.str) - index);
01475                     } /* if */
01476                 } /* for */
01477                 j++;
01478             } /* while */
01479         } /* if */
01480     }
01481 
01482     /* If this is a Text Content */
01483     if (ctx == WBXML_VALUE_ELEMENT_CTX_CONTENT) 
01484     {
01485         /*********************************************************
01486          *  Search for Extension Tokens
01487          */
01488 
01491         if (encoder->tree->lang->extValueTable != NULL) {
01492             /* For each Extension Token */
01493             j = 0;
01494             while (encoder->tree->lang->extValueTable[j].xmlName != NULL)
01495             {
01496                 /* For each Value Element */
01497                 for (i = 0; i < wbxml_list_len(lresult); i++) {
01498                     if ((elt = (WBXMLValueElement *) wbxml_list_get(lresult, i)) == NULL)
01499                         continue;
01500 
01501                     if (elt->type != WBXML_VALUE_ELEMENT_STRING)
01502                         continue;
01503 
01504                     /* Ignores the "1 char Extension Tokens" */
01505                     if (WBXML_STRLEN(encoder->tree->lang->extValueTable[j].xmlName) < 2)
01506                         continue;
01507 
01508                     /* Is this Extension Token contained in this Buffer ? */
01509                     if (wbxml_buffer_search_cstr(elt->u.str, (WB_UTINY *) encoder->tree->lang->extValueTable[j].xmlName, 0, &index)) 
01510                     {
01511                         /* Create new Value Element */
01512                         if ((new_elt = wbxml_value_element_create()) == NULL) {
01513                             wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01514                             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01515                         }
01516 
01517                         new_elt->type = WBXML_VALUE_ELEMENT_EXTENSION;
01518                         new_elt->u.ext = &(encoder->tree->lang->extValueTable[j]);
01519 
01520                         /* Insert new Value Element in List */
01521                         if (!wbxml_list_insert(lresult, (void *) new_elt, i + 1)) {
01522                             wbxml_value_element_destroy(new_elt);
01523                             wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01524                             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01525                         }
01526 
01527                         /* Check if there is still the end of the String to encode */
01528                         if (index + WBXML_STRLEN(encoder->tree->lang->extValueTable[j].xmlName) < wbxml_buffer_len(elt->u.str)) {
01529                             /* Create new Value Element */
01530                             if ((new_elt = wbxml_value_element_create()) == NULL) {
01531                                 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01532                                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01533                             }
01534 
01535                             new_elt->type = WBXML_VALUE_ELEMENT_STRING;
01536                             new_elt->u.str = wbxml_buffer_create_from_cstr(wbxml_buffer_get_cstr(elt->u.str) + index + WBXML_STRLEN(encoder->tree->lang->extValueTable[j].xmlName));
01537 
01538                             /* Insert new Value Element in List */
01539                             if ((new_elt->u.str == NULL) ||
01540                                 !wbxml_list_insert(lresult, (void *) new_elt, i + 2)) 
01541                             {
01542                                 wbxml_value_element_destroy(new_elt);
01543                                 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01544                                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01545                             }
01546                         }
01547 
01548                         /* Remove the Attribute Value found in Value Element */
01549                         wbxml_buffer_delete(elt->u.str, index, wbxml_buffer_len(elt->u.str) - index);
01550                     } /* if */
01551                 } /* for */
01552                 j++;
01553             } /* while */
01554         } /* if */
01555     }
01556 
01557 
01558 #if defined( WBXML_ENCODER_USE_STRTBL )
01559 
01560     /*********************************************************
01561      *  Search for String Table References
01562      */
01563 
01564     if (encoder->use_strtbl) {
01565         /* For each String Table Element */
01566         for (j = 0; j < wbxml_list_len(encoder->strstbl); j++) {
01567             if ((strtbl_elt = (WBXMLStringTableElement *) wbxml_list_get(encoder->strstbl, j)) == NULL)
01568                 continue;
01569 
01570             /* For each Value Element */
01571             for (i = 0; i < wbxml_list_len(lresult); i++) {
01572                 if ((elt = (WBXMLValueElement *) wbxml_list_get(lresult, i)) == NULL)
01573                     continue;
01574 
01575                 if (elt->type != WBXML_VALUE_ELEMENT_STRING)
01576                     continue;
01577 
01578                 /* Is the String Table Element contained in this Buffer ? */
01579                 if (wbxml_buffer_search(elt->u.str, strtbl_elt->string, 0, &index)) {
01580                     /* Create new Value Element */
01581                     if ((new_elt = wbxml_value_element_create()) == NULL) {
01582                         wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01583                         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01584                     }
01585 
01586                     new_elt->type = WBXML_VALUE_ELEMENT_TABLEREF;
01587                     new_elt->u.index = strtbl_elt->offset;
01588 
01589                     /* Insert new Value Element in List */
01590                     if (!wbxml_list_insert(lresult, (void *) new_elt, i + 1)) {
01591                         wbxml_value_element_destroy(new_elt);
01592                         wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01593                         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01594                     }
01595 
01596                     /* Check if there is still the end of the String to encode */
01597                     if (index + wbxml_buffer_len(strtbl_elt->string) < wbxml_buffer_len(elt->u.str)) {
01598                         /* Create new Value Element */
01599                         if ((new_elt = wbxml_value_element_create()) == NULL) {
01600                             wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01601                             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01602                         }
01603 
01604                         new_elt->type = WBXML_VALUE_ELEMENT_STRING;
01605                         new_elt->u.str = wbxml_buffer_create_from_cstr(wbxml_buffer_get_cstr(elt->u.str) + index + wbxml_buffer_len(strtbl_elt->string));
01606 
01607                         /* Insert new Value Element in List */
01608                         if ((new_elt->u.str == NULL) ||
01609                             !wbxml_list_insert(lresult, (void *) new_elt, i + 2)) 
01610                         {
01611                             wbxml_value_element_destroy(new_elt);
01612                             wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01613                             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01614                         }
01615                     }
01616 
01617                     /* Remove the Attribute Value found in Value Element */
01618                     wbxml_buffer_delete(elt->u.str, index, wbxml_buffer_len(elt->u.str) - index);
01619                 } /* if */
01620             } /* for */
01621         } /* for */
01622     } /* if */
01623 
01624 #endif /* WBXML_ENCODER_USE_STRTBL */
01625 
01626    
01627     /*********************************************************
01628      *  Encode Value Element Buffer
01629      */
01630 
01631     ret = wbxml_encode_value_element_list(encoder, lresult);
01632 
01633     /* Clean-up */
01634     wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
01635 
01636     return ret;
01637 }
01638 
01639 
01646 static WBXMLError wbxml_encode_value_element_list(WBXMLEncoder *encoder, WBXMLList *list)
01647 {
01648     WBXMLValueElement *elt = NULL;
01649     WB_ULONG i = 0;
01650     WBXMLError ret = WBXML_OK;
01651 
01652     if (encoder == NULL)
01653         return WBXML_ERROR_INTERNAL;
01654 
01655     if (list == NULL)
01656         return WBXML_OK;
01657 
01658     for (i = 0; i < wbxml_list_len(list); i++) {
01659         if ((elt = (WBXMLValueElement *) wbxml_list_get(list, i)) == NULL)
01660             continue;
01661 
01662         switch (elt->type) {
01663         case WBXML_VALUE_ELEMENT_STRING:
01664             /* Inline String */
01665             if (wbxml_buffer_len(elt->u.str) > 0) {
01666                 if ((ret = wbxml_encode_inline_string(encoder, elt->u.str)) != WBXML_OK)
01667                     return ret;
01668             }
01669             break;
01670 
01671 #if defined( WBXML_ENCODER_USE_STRTBL )
01672         case WBXML_VALUE_ELEMENT_TABLEREF:
01673             /* String Table Reference */
01674             if ((ret = wbxml_encode_tableref(encoder, elt->u.index)) != WBXML_OK)
01675                 return ret;
01676             break;
01677 #endif /* WBXML_ENCODER_USE_STRTBL */
01678 
01679         case WBXML_VALUE_ELEMENT_EXTENSION:
01680             /* Encode Extension Token */
01681             if ((ret = wbxml_encode_inline_integer_extension_token(encoder, WBXML_EXT_T_0, elt->u.ext->wbxmlToken)) != WBXML_OK)
01682                 return ret;
01683             break;
01684 
01685         case WBXML_VALUE_ELEMENT_OPAQUE:
01687             break;
01688 
01689         case WBXML_VALUE_ELEMENT_ATTR_TOKEN:
01690             /* Attribute Value Token */
01691             if ((ret = wbxml_encode_attr_token(encoder, elt->u.attr->wbxmlToken,  elt->u.attr->wbxmlCodePage)) != WBXML_OK)
01692                 return ret;
01693             break;
01694 
01695         default:
01696             return WBXML_ERROR_INTERNAL;
01697         }
01698     }
01699     
01700     return WBXML_OK;
01701 }
01702 
01703 
01712 static WBXMLError wbxml_encode_attr_start_literal(WBXMLEncoder *encoder, const WB_UTINY *attr)
01713 {
01714 #if defined( WBXML_ENCODER_USE_STRTBL )
01715     WBXMLStringTableElement *elt = NULL;
01716     WBXMLBuffer *buff = NULL;
01717     WB_ULONG index = 0;
01718     WB_BOOL added = FALSE;
01719 
01720     /* If String Table generation is disabled, we can't generate this Literal */
01721     if (!encoder->use_strtbl)
01722         return WBXML_ERROR_STRTBL_DISABLED;
01723 
01724     /* Add tag in String Table */
01725     if (((buff = wbxml_buffer_create(attr, WBXML_STRLEN(attr), WBXML_STRLEN(attr))) == NULL) ||
01726         ((elt = wbxml_strtbl_element_create(buff, FALSE)) == NULL) ||
01727         (!wbxml_strtbl_add_element(encoder, elt, &index, &added)))
01728     {
01729         wbxml_strtbl_element_destroy(elt);
01730         wbxml_buffer_destroy(buff);
01731         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01732     }
01733 
01734     /* If already exists in String Table: clean-up */
01735     if (!added)
01736         wbxml_strtbl_element_destroy(elt);    
01737 
01738     /* Encode LITERAL index */
01739     if ((!wbxml_buffer_append_char(encoder->output, WBXML_LITERAL)) ||
01740         (!wbxml_buffer_append_mb_uint_32(encoder->output, index)))
01741     {
01742         return WBXML_ERROR_ENCODER_APPEND_DATA;
01743     }
01744 
01745     return WBXML_OK;
01746 #else
01747     /* No String Table Support */
01748     return WBXML_ERROR_STRTBL_DISABLED;
01749 #endif /* WBXML_ENCODER_USE_STRTBL */
01750 }
01751 
01752 
01765 static WBXMLError wbxml_encode_attr_token(WBXMLEncoder *encoder, WB_UTINY token, WB_UTINY page)
01766 {
01767     /* Switch Page if needed */
01768     if (encoder->attrCodePage != page) 
01769     {
01770         if ((!wbxml_buffer_append_char(encoder->output, WBXML_SWITCH_PAGE)) ||
01771             (!wbxml_buffer_append_char(encoder->output, page)))
01772         {
01773             return WBXML_ERROR_ENCODER_APPEND_DATA;
01774         }
01775 
01776         encoder->attrCodePage = page;
01777     }
01778 
01779     /* Add Token */
01780     if (!wbxml_buffer_append_char(encoder->output, token))
01781         return WBXML_ERROR_ENCODER_APPEND_DATA;
01782 
01783     return WBXML_OK;
01784 }
01785 
01786 
01793 static WBXMLError wbxml_encode_inline_string(WBXMLEncoder *encoder, WBXMLBuffer *str)
01794 {
01795     /* Add STR_I */
01796     if (!wbxml_buffer_append_char(encoder->output, WBXML_STR_I))
01797         return WBXML_ERROR_ENCODER_APPEND_DATA;
01798 
01799     /* Add String */
01800     if (!wbxml_buffer_append(encoder->output, str))
01801         return WBXML_ERROR_ENCODER_APPEND_DATA;
01802 
01803     /* Add Null Termination */
01804     if (!wbxml_buffer_append_char(encoder->output, WBXML_STR_END))
01805         return WBXML_ERROR_ENCODER_APPEND_DATA;    
01806 
01807     return WBXML_OK;
01808 }
01809 
01810 
01819 static WBXMLError wbxml_encode_inline_integer_extension_token(WBXMLEncoder *encoder, WB_UTINY ext, WB_UTINY value)
01820 {
01821     /* Add EXT_T* */
01822     if (!wbxml_buffer_append_char(encoder->output, ext))
01823         return WBXML_ERROR_ENCODER_APPEND_DATA;
01824 
01825     /* Add Value */
01826     if (!wbxml_buffer_append_mb_uint_32(encoder->output, (WB_ULONG) value))
01827         return WBXML_ERROR_ENCODER_APPEND_DATA;
01828 
01829     return WBXML_OK;
01830 }
01831 
01832 
01841 static WBXMLError wbxml_encode_entity(WBXMLEncoder *encoder, WB_ULONG value)
01842 {
01843     /* Add ENTITY */
01844     if (!wbxml_buffer_append_char(encoder->output, WBXML_ENTITY))
01845         return WBXML_ERROR_ENCODER_APPEND_DATA;
01846 
01847     /* Add entcode */
01848     if (!wbxml_buffer_append_mb_uint_32(encoder->output, value))
01849         return WBXML_ERROR_ENCODER_APPEND_DATA;
01850 
01851     return WBXML_OK;
01852 }
01853 
01854 
01863 static WBXMLError wbxml_encode_opaque(WBXMLEncoder *encoder, WBXMLBuffer *buff)
01864 {
01865     /* Add WBXML_OPAQUE */
01866     if (!wbxml_buffer_append_char(encoder->output, WBXML_OPAQUE))
01867         return WBXML_ERROR_ENCODER_APPEND_DATA;
01868 
01869     /* Add Length */
01870     if (!wbxml_buffer_append_mb_uint_32(encoder->output, wbxml_buffer_len(buff)))
01871         return WBXML_ERROR_ENCODER_APPEND_DATA;
01872 
01873     /* Add Buffer */
01874     if (!wbxml_buffer_append(encoder->output, buff))
01875         return WBXML_ERROR_ENCODER_APPEND_DATA;
01876 
01877     return WBXML_OK;
01878 }
01879 
01880 
01881 #if defined( WBXML_ENCODER_USE_STRTBL )
01882 
01889 static WBXMLError wbxml_encode_tableref(WBXMLEncoder *encoder, WB_ULONG offset)
01890 {
01891     /* Add WBXML_STR_T */
01892     if (!wbxml_buffer_append_char(encoder->output, WBXML_STR_T))
01893         return WBXML_ERROR_ENCODER_APPEND_DATA;
01894 
01895     /* Add String */
01896     if (!wbxml_buffer_append_mb_uint_32(encoder->output, offset))
01897         return WBXML_ERROR_ENCODER_APPEND_DATA;
01898 
01899     return WBXML_OK;
01900 }
01901 #endif /* WBXML_ENCODER_USE_STRTBL */
01902 
01903 
01908 static WBXMLValueElement *wbxml_value_element_create(void)
01909 {
01910     WBXMLValueElement *elt = NULL;
01911 
01912     if ((elt = (WBXMLValueElement*) wbxml_malloc(sizeof(WBXMLValueElement))) == NULL)
01913         return NULL;
01914 
01915     elt->type = WBXML_VALUE_ELEMENT_STRING;
01916     elt->u.str = NULL;
01917 
01918     return elt;
01919 }
01920 
01921 
01926 static void wbxml_value_element_destroy(WBXMLValueElement *elt)
01927 {
01928     if (elt == NULL)
01929         return;
01930 
01931     switch (elt->type) {
01932     case WBXML_VALUE_ELEMENT_STRING:
01933         wbxml_buffer_destroy(elt->u.str);
01934         break;
01935     case WBXML_VALUE_ELEMENT_OPAQUE:
01936         wbxml_buffer_destroy(elt->u.buff);
01937         break;
01938     default:
01939         /* Nothing to destroy */
01940         break;    
01941     }
01942 
01943     wbxml_free((void*) elt);
01944 }
01945 
01946 
01951 static void wbxml_value_element_destroy_item(void *elt)
01952 {
01953     wbxml_value_element_destroy((WBXMLValueElement *) elt);
01954 }
01955 
01956 
01963 static WBXMLError wbxml_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree)
01964 {
01965     WBXMLEncoder *new_encoder = NULL;
01966     WB_UTINY *wbxml = NULL;
01967     WB_ULONG wbxml_len = 0;
01968     WBXMLError ret = WBXML_OK;
01969 
01970     if ((new_encoder = wbxml_encoder_duplicate(encoder)) == NULL)
01971         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01972 
01973     /* Set Tree */
01974     new_encoder->tree = tree;
01975 
01976     /* Encode to WBXML */
01977     if ((ret = wbxml_encoder_encode_to_wbxml(new_encoder, &wbxml, &wbxml_len)) != WBXML_OK) {
01978         wbxml_encoder_destroy(new_encoder);
01979         return ret;
01980     }
01981 
01982     /* Clean-up */
01983     wbxml_encoder_destroy(new_encoder);
01984 
01985     /* Add WBXML_OPAQUE */
01986     if (!wbxml_buffer_append_char(encoder->output, WBXML_OPAQUE)) {
01987         wbxml_free(wbxml);
01988         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01989     }
01990 
01991     /* Add Length */
01992     if (!wbxml_buffer_append_mb_uint_32(encoder->output, wbxml_len)) {
01993         wbxml_free(wbxml);
01994         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
01995     }
01996 
01997     /* Append wbxml to output */
01998     if (!wbxml_buffer_append_data(encoder->output, wbxml, wbxml_len)) {
01999         wbxml_free(wbxml);
02000         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02001     }
02002 
02003     /* Clean-up */
02004     wbxml_free(wbxml);
02005 
02006     return WBXML_OK;
02007 }
02008 
02009 
02010 /****************************************
02011  * Language Specific Encoding Functions
02012  */
02013 
02014 #if ( defined( WBXML_SUPPORT_SI ) || defined( WBXML_SUPPORT_EMN ) )
02015 
02016 /*******************
02017  * SI 1.0 / EMN 1.0
02018  */
02019 
02027 static WBXMLError wbxml_encode_datetime(WBXMLEncoder *encoder, WB_UTINY *buffer)
02028 {
02029     WBXMLBuffer *tmp = NULL;
02030     WB_ULONG i = 0;
02031     WB_UTINY ch = 0;
02032     WBXMLError ret = WBXML_OK;
02033 
02034 
02035     if ((tmp = wbxml_buffer_create_from_cstr(buffer)) == NULL)
02036         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02037 
02038     /* Remove non-digit characters */
02039     while (i < wbxml_buffer_len(tmp)) {
02040         /* Get char */
02041         if (!wbxml_buffer_get_char(tmp, i, &ch)) {
02042             wbxml_buffer_destroy(tmp);
02043             return WBXML_ERROR_INTERNAL;
02044         }
02045 
02046         if (!WBXML_ISDIGIT(ch)) {
02047             if ((ch != 'T') && (ch != 'Z') && (ch != '-') && (ch != ':')) {
02048                 wbxml_buffer_destroy(tmp);
02049                 return WBXML_ERROR_BAD_DATETIME;
02050             }
02051 
02052             /* Remove it */
02053             wbxml_buffer_delete(tmp, i, 1);
02054         }
02055         else
02056             i++;
02057     }
02058 
02059     /* Convert Ascii to Binary buffer */
02060     wbxml_buffer_hex_to_binary(tmp);
02061 
02062     /* Remove trailing zero */
02063     wbxml_buffer_remove_trailing_zeros(&tmp);
02064 
02065     /* Encode it to Opaque */
02066     ret = wbxml_encode_opaque(encoder, tmp);
02067 
02068     wbxml_buffer_destroy(tmp);
02069 
02070     return ret;
02071 }
02072 
02073 #endif /* WBXML_SUPPORT_SI || WBXML_SUPPORT_EMN */
02074 
02075 
02076 #if defined( WBXML_SUPPORT_WV )
02077 
02078 /*******************
02079  * WV 1.1 / WV 1.2
02080  */
02081 
02092 static WBXMLError wbxml_encode_wv_content(WBXMLEncoder *encoder, WB_UTINY *buffer)
02093 {
02094     const WBXMLExtValueEntry *ext = NULL;
02095     WBXMLWVDataType data_type = WBXML_WV_DATA_TYPE_STRING;
02096     /* WB_ULONG ucs4_ch = 0; */
02097 
02098     /* 
02099      *  Specific Data Type Elements:
02100      *
02101      *        Boolean:
02102      *            Acceptance (0x00 / 0x05)
02103      *            InUse (0x00 / 0x18)
02104      *            Poll (0x00 / 0x21)
02105      *            AllFunctionsRequest (0x01 / 0x06)
02106      *            CapabilityRequest (0x01 / 0x0B)
02107      *            CompletionFlag (0x01 / 0x34)
02108      *            ReceiveList (0x01 / 0x36) [WV 1.2]
02109      *            AnyContent (0x03 / 0x09)              
02110      *            DefaultList (0x04 / 0x0B)
02111      *            Auto-Subscribe (0x04 / 0x1E) [WV 1.2]
02112      *            DeliveryReport (0x06 / 0x08)
02113      *            JoinGroup (0x07 / 0x21)
02114      *            JoinedRequest (0x07 / 0x10)
02115      *            SubscribeNotification (0x07 / 0x22)
02116      *            CIR (0x09 / 0x05) [WV 1.2]
02117      *
02118      *        Integer:
02119      *            Code (0x00 / 0x0B)
02120      *            ContentSize (0x00 / 0x0F)
02121      *            MessageCount (0x00 / 0x1A)
02122      *            Validity (0x00 / 0x3C)
02123      *            KeepAliveTime (0x01 / 0x1C)
02124      *            SearchFindings (0x01 / 0x25)
02125      *            SearchID (0x01 / 0x26)
02126      *            SearchIndex (0x01 / 0x27)
02127      *            SearchLimit (0x01 / 0x28)
02128      *            TimeToLive (0x01 / 0x32)
02129      *            AcceptedCharSet (0x03 / 0x05)
02130      *            AcceptedContentLength (0x03 / 0x06)
02131      *            MultiTrans (0x03 / 0x0C)
02132      *            ParserSize (0x03 / 0x0D)
02133      *            ServerPollMin (0x03 / 0x0E)
02134      *            TCPPort (0x03 / 0x12)
02135      *            UDPPort (0x03 / 0x13)
02136      *            HistoryPeriod (0x09 / 0x08) [WV 1.2]
02137      *            MaxWatcherList (0x09 / 0x0A) [WV 1.2]
02138      *
02139      *        Date and Time:
02140      *            DateTime (0x00 / 0x11)
02141      *            DeliveryTime (0x06 / 0x1A)
02142      *
02143      *        Binary:
02144      *            ContentData (0x00 / 0x0D) (only if we have a: "<ContentEncoding>BASE64</ContentEncoding>" associated)
02145      */
02146 
02147     /****************************************
02148      * Get the Data Type of Current Element 
02149      */
02150 
02151     if (encoder->current_tag != NULL) 
02152     {
02153         switch (encoder->current_tag->wbxmlCodePage) {
02154         case 0x00:
02155             /* Code Page: 0x00 */
02156             switch (encoder->current_tag->wbxmlToken) {
02157             case 0x05: /* Acceptance */
02158             case 0x18: /* InUse */
02159             case 0x21: /* Poll */
02160                 /* BOOLEAN */
02161                 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
02162                 break;
02163             case 0x0B: /* Code */
02164             case 0x0F: /* ContentSize */
02165             case 0x1A: /* MessageCount */
02166             case 0x3C: /* Validity */
02167                 /* INTEGER */
02168                 data_type = WBXML_WV_DATA_TYPE_INTEGER;
02169                 break;
02170             case 0x11: /* DateTime */
02171                 /* DATE_AND_TIME */
02172                 data_type = WBXML_WV_DATA_TYPE_DATE_AND_TIME;
02173                 break;
02174             case 0x0D: /* ContentData */
02175                 /* BINARY */
02177                 /*
02178                 if (base64_encoded)
02179                     data_type = WBXML_WV_DATA_TYPE_BINARY;
02180                 else
02181                 */
02182                     data_type = WBXML_WV_DATA_TYPE_STRING;
02183                 break;
02184             default:
02185                 /* STRING */
02186                 data_type = WBXML_WV_DATA_TYPE_STRING;
02187                 break;
02188             }
02189             break;
02190         case 0x01:
02191             /* Code Page: 0x01 */
02192             switch (encoder->current_tag->wbxmlToken) {
02193             case 0x06: /* AllFunctionsRequest */
02194             case 0x0B: /* CapabilityRequest */
02195             case 0x34: /* CompletionFlag */
02196             case 0x36: /* ReceiveList */
02197                 /* BOOLEAN */
02198                 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
02199                 break;
02200             case 0x1C: /* KeepAliveTime */
02201             case 0x25: /* SearchFindings */
02202             case 0x26: /* SearchID */
02203             case 0x27: /* SearchIndex */
02204             case 0x28: /* SearchLimit */
02205             case 0x32: /* TimeToLive */
02206                 /* INTEGER */
02207                 data_type = WBXML_WV_DATA_TYPE_INTEGER;
02208                 break;
02209             default:
02210                 /* STRING */
02211                 data_type = WBXML_WV_DATA_TYPE_STRING;
02212                 break;
02213             }
02214             break;
02215         case 0x03:
02216             /* Code Page: 0x03 */
02217             switch (encoder->current_tag->wbxmlToken) {
02218             case 0x09: /* AnyContent */
02219                 /* BOOLEAN */
02220                 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
02221                 break;
02222             case 0x05: /* AcceptedCharSet */
02223             case 0x06: /* AcceptedContentLength */
02224             case 0x0C: /* MultiTrans */
02225             case 0x0D: /* ParserSize */
02226             case 0x0E: /* ServerPollMin */
02227             case 0x12: /* TCPPort */
02228             case 0x13: /* UDPPort */
02229                 /* INTEGER */
02230                 data_type = WBXML_WV_DATA_TYPE_INTEGER;
02231                 break;
02232             default:
02233                 /* STRING */
02234                 data_type = WBXML_WV_DATA_TYPE_STRING;
02235                 break;
02236             }
02237             break;
02238         case 0x04:
02239             /* Code Page: 0x04 */
02240             switch (encoder->current_tag->wbxmlToken) {
02241             case 0x0B: /* DefaultList */
02242             case 0x1E: /* Auto-Subscribe */
02243                 /* BOOLEAN */
02244                 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
02245                 break;
02246             default:
02247                 /* STRING */
02248                 data_type = WBXML_WV_DATA_TYPE_STRING;
02249                 break;
02250             }
02251             break;
02252         case 0x06:
02253             /* Code Page: 0x06 */
02254             switch (encoder->current_tag->wbxmlToken) {
02255             case 0x08: /* DeliveryReport */
02256                 /* BOOLEAN */
02257                 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
02258                 break;
02259             case 0x1A: /* DeliveryTime */
02260                 /* DATE AND TIME */
02261                 data_type = WBXML_WV_DATA_TYPE_DATE_AND_TIME;
02262                 break;
02263             default:
02264                 /* STRING */
02265                 data_type = WBXML_WV_DATA_TYPE_STRING;
02266                 break;
02267             }
02268             break;
02269         case 0x07:
02270             /* Code Page: 0x07 */
02271             switch (encoder->current_tag->wbxmlToken) {
02272             case 0x21: /* JoinGroup */
02273             case 0x10: /* JoinedRequest */
02274             case 0x22: /* SubscribeNotification */
02275                 /* BOOLEAN */
02276                 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
02277                 break;
02278             default:
02279                 /* STRING */
02280                 data_type = WBXML_WV_DATA_TYPE_STRING;
02281                 break;
02282             }
02283             break;
02284         case 0x09:
02285             /* Code Page: 0x09 */
02286             switch (encoder->current_tag->wbxmlToken) {
02287             case 0x05: /* CIR */
02288                 /* BOOLEAN */
02289                 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
02290                 break;
02291             case 0x08: /* HistoryPeriod */
02292             case 0x0A: /* MaxWatcherList */
02293                 /* INTEGER */
02294                 data_type = WBXML_WV_DATA_TYPE_INTEGER;
02295                 break;
02296             default:
02297                 /* STRING */
02298                 data_type = WBXML_WV_DATA_TYPE_STRING;
02299                 break;
02300             }
02301             break;
02302         default:
02303             data_type = WBXML_WV_DATA_TYPE_STRING;
02304             break;
02305         }
02306     }
02307 
02308 
02309     /****************************************
02310      * Encode, given the Data Type
02311      */
02312 
02313     switch (data_type) {
02314     case WBXML_WV_DATA_TYPE_INTEGER:
02315         /* Integer: Encode it */
02316         return wbxml_encode_wv_integer(encoder, buffer);
02317         break;
02318     case WBXML_WV_DATA_TYPE_DATE_AND_TIME:
02319         /* Date and time can be encoded as OPAQUE data or as a string as specified in [ISO8601]. For now we
02320          * keep the string... but if someone wants to code the Date and time encoding function :-)
02321          */
02322         /* return wbxml_encode_wv_datetime(encoder, buffer); */
02323         break;
02324     case WBXML_WV_DATA_TYPE_BINARY:
02326         break;
02327     case WBXML_WV_DATA_TYPE_BOOLEAN:
02328         /* Booleans are handled by the "T" and "F" extension tokens */
02329     case WBXML_WV_DATA_TYPE_STRING:
02330         /* Check if this buffer is an EXACT Extension Token */
02331         if ((ext = wbxml_tables_get_ext_from_xml(encoder->tree->lang, buffer)) != NULL)
02332             return wbxml_encode_inline_integer_extension_token(encoder, WBXML_EXT_T_0, ext->wbxmlToken);
02333         else {
02334             if (WBXML_STRLEN(buffer) == 1)
02335             {
02341                 /*
02342                 if (convert_char_to_ucs4(*buffer, &ucs4_ch))
02343                     return wbxml_encode_entity(encoder, ucs4_ch);
02344                 */
02345             }
02346 
02347             /* Else: noting encoded... this will be latter as an inline string */
02348         }
02349         break;
02350     default:
02351         /* Hu ? */
02352         break;
02353     }
02354        
02355     return WBXML_NOT_ENCODED;
02356 }
02357 
02358 
02365 static WBXMLError wbxml_encode_wv_integer(WBXMLEncoder *encoder, WB_UTINY *buffer)
02366 {
02367     WB_UTINY octets[4];
02368     WB_ULONG the_int = 0, i = 0, start = 0;
02369 
02370     if ((encoder == NULL) || (buffer == NULL))
02371         return WBXML_ERROR_INTERNAL;
02372 
02373     the_int = (WB_ULONG) atol((const WB_TINY *) buffer);
02374 
02375     for (i = 3; the_int > 0 && i >= 0; i--) {
02376         octets[i] = (WB_UTINY)(the_int & 0xff);
02377         the_int >>= 8;
02378     }
02379 
02380     start = i + 1;
02381     
02382     /* Add WBXML_OPAQUE */
02383     if (!wbxml_buffer_append_char(encoder->output, WBXML_OPAQUE))
02384         return WBXML_ERROR_ENCODER_APPEND_DATA;
02385 
02386     /* Add Integer Length */
02387     if (!wbxml_buffer_append_mb_uint_32(encoder->output, 4 - start))
02388         return WBXML_ERROR_ENCODER_APPEND_DATA;
02389 
02390     /* Add Integer */
02391     if (!wbxml_buffer_append_data(encoder->output, octets + start, (WB_UTINY)(4 - start)))
02392         return WBXML_ERROR_ENCODER_APPEND_DATA;
02393 
02394     return WBXML_OK;
02395 }
02396 
02397 
02422 static WBXMLError wbxml_encode_wv_datetime(WBXMLEncoder *encoder, WB_UTINY *buffer)
02423 {
02426     return WBXML_ERROR_NOT_IMPLEMENTED;
02427     
02428 #if 0
02429     WBXMLBuffer *tmp = NULL;
02430     WB_ULONG i = 0, len = 0;
02431     WB_UTINY ch = 0;
02432     WBXMLError ret = WBXML_OK;
02433     WB_BOOL is_utc = FALSE;
02434 
02435     len = WBXML_STRLEN(buffer);
02436 
02437     /* Check Length */
02438     if ((len != 15) && (len != 16))
02439         return WBXML_ERROR_WV_DATETIME_FORMAT;
02440 
02441     /* Check position of 'T' */
02442     if ((*buffer)[8] != 'T')
02443         return WBXML_ERROR_WV_DATETIME_FORMAT;
02444 
02445     /* Check position of 'Z' */
02446     if (len == 16) {
02447         if ((*buffer)[15] != 'Z')
02448             return WBXML_ERROR_WV_DATETIME_FORMAT;
02449 
02450         /* This is an UTC format */
02451         is_utc = TRUE;
02452     }
02453 
02454     /* Create temp Buffer */
02455     if ((tmp = wbxml_buffer_create_from_cstr(buffer)) == NULL)
02456         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02457 
02458     /* Delete 'T' and 'Z' */
02459     if (is_utc)
02460         wbxml_buffer_delete(tmp, 15, 1);
02461 
02462     wbxml_buffer_delete(tmp, 8, 1);
02463 
02464     /* Check if you have only digits characters */
02465     while (i < wbxml_buffer_len(tmp)) {
02466         /* Get char */
02467         if (!wbxml_buffer_get_char(tmp, i, &ch)) {
02468             wbxml_buffer_destroy(tmp);
02469             return WBXML_ERROR_INTERNAL;
02470         }
02471 
02472         if (!WBXML_ISDIGIT(ch)) {
02473             wbxml_buffer_destroy(tmp);
02474             return WBXML_ERROR_WV_DATETIME_FORMAT;
02475         }
02476         else
02477             i++;
02478     }
02479 
02480     /* Convert Ascii to Binary buffer */
02481     wbxml_buffer_hex_to_binary(tmp);
02482 
02483     /* Set Year */
02484 
02485     /* Set Month */
02486 
02487     /* Set Day */
02488 
02489     /* Set Hour */
02490 
02491     /* Set Minute */
02492 
02493     /* Set Second */
02494 
02495     /* Set Time Zone */    
02496 
02497     /* Encode it to Opaque */
02498     ret = wbxml_encode_opaque(encoder, tmp);
02499 
02500     wbxml_buffer_destroy(tmp);
02501 
02502     return ret;
02503 #endif /* 0 */
02504 }
02505 
02506 #endif /* WBXML_SUPPORT_WV */
02507 
02508 
02509 #if defined( WBXML_SUPPORT_DRMREL )
02510 
02511 /*******************
02512  * DRMREL 1.0
02513  */
02514 
02524 static WBXMLError wbxml_encode_drmrel_content(WBXMLEncoder *encoder, WB_UTINY *buffer)
02525 {
02526     WB_UTINY *data = NULL;
02527     WB_LONG data_len = 0;
02528 
02529     if (encoder->current_tag != NULL) 
02530     {
02531         if ((encoder->current_tag->wbxmlCodePage == 0x00) &&
02532             (encoder->current_tag->wbxmlToken == 0x0C))
02533         {
02534             /* <ds:KeyValue> content: "Encoded in binary format, i.e., no base64 encoding" */
02535 
02536             /* Decode Base64 */
02537             if ((data_len = wbxml_base64_decode(buffer, &data)) < 0)
02538                 return WBXML_NOT_ENCODED;
02539             
02540             /* Add WBXML_OPAQUE */
02541             if (!wbxml_buffer_append_char(encoder->output, WBXML_OPAQUE))
02542                 return WBXML_ERROR_ENCODER_APPEND_DATA;
02543 
02544             /* Add Data Length */
02545             if (!wbxml_buffer_append_mb_uint_32(encoder->output, (WB_ULONG) data_len))
02546                 return WBXML_ERROR_ENCODER_APPEND_DATA;
02547 
02548             /* Add Data */
02549             if (!wbxml_buffer_append_data(encoder->output, data, data_len))
02550                 return WBXML_ERROR_ENCODER_APPEND_DATA;
02551 
02552             /* Free Data */
02553             wbxml_free(data);
02554 
02555             return WBXML_OK;
02556         }
02557     }
02558 
02559     return WBXML_NOT_ENCODED;
02560 }
02561 
02562 #endif /* WBXML_SUPPORT_DRMREL */
02563 
02564 
02565 #if defined( WBXML_ENCODER_USE_STRTBL )
02566 
02567 /****************************
02568  * String Table Functions
02569  */
02570 
02577 static WBXMLStringTableElement *wbxml_strtbl_element_create(WBXMLBuffer *string, WB_BOOL is_stat)
02578 {
02579     WBXMLStringTableElement *elt = NULL;
02580 
02581     if ((elt = (WBXMLStringTableElement *) wbxml_malloc(sizeof(WBXMLStringTableElement))) == NULL)
02582         return NULL;
02583 
02584     elt->string = string;
02585     elt->offset = 0;
02586     elt->count = 0;
02587     elt->stat = is_stat;
02588 
02589     return elt;
02590 }
02591 
02592 
02597 static void wbxml_strtbl_element_destroy(WBXMLStringTableElement *element)
02598 {
02599     if (element == NULL)
02600         return;
02601 
02602     if (!element->stat)
02603         wbxml_buffer_destroy(element->string);
02604 
02605     wbxml_free(element);
02606 }
02607 
02608 
02613 static void wbxml_strtbl_element_destroy_item(void *element)
02614 {
02615     wbxml_strtbl_element_destroy((WBXMLStringTableElement *) element);
02616 }
02617 
02618 
02624 static WBXMLError wbxml_strtbl_initialize(WBXMLEncoder *encoder, WBXMLTreeNode *root)
02625 {
02626     WBXMLList *strings = NULL, *one_ref = NULL;
02627     WBXMLError ret;
02628 
02629     if ((strings = wbxml_list_create()) == NULL)
02630         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02631 
02632     /* Collect all Strings:
02633      * [out] 'strings' is the list of pointers to WBXMLBuffer. This Buffers must not be freed.
02634      */
02635     wbxml_strtbl_collect_strings(encoder, root, strings);
02636 
02637     /* Insert, in String Table, Strings that are referenced more than one time 
02638      * [out] 'strings' is NULL
02639      *       'one_ref' is the list of strings referenced only ONE time (list of WBXMLStringTableElement*)
02640      *       Strings referenced more than one time are added to String Table
02641      */
02642     if ((ret = wbxml_strtbl_check_references(encoder, &strings, &one_ref, TRUE)) != WBXML_OK) {
02643         wbxml_list_destroy(strings, NULL);
02644         return ret;
02645     }
02646 
02647     /* 'strings' is destroyed after call of wbxml_strtbl_check_references() */
02648 
02649     /* Split Strings refered only one time in Words 
02650      * [out] 'strings' is the list of words. This words (WBXMLBuffer) must be freed
02651      */
02652     if ((ret = wbxml_strtbl_collect_words(one_ref, &strings)) != WBXML_OK) {
02653         wbxml_list_destroy(one_ref, wbxml_strtbl_element_destroy_item);
02654         return ret;
02655     }
02656 
02657     /* Destroy References List */
02658     wbxml_list_destroy(one_ref, wbxml_strtbl_element_destroy_item);
02659     one_ref = NULL;
02660 
02661     /* Keep Strings referenced more than one time */
02662     if (strings != NULL)
02663             wbxml_strtbl_check_references(encoder, &strings, &one_ref, FALSE);
02664 
02665     /* 'strings' is destroyed after call of wbxml_strtbl_check_references() */
02666 
02667     /* Cleanup */
02668     wbxml_list_destroy(one_ref, wbxml_strtbl_element_destroy_item);
02669     
02670     return WBXML_OK;
02671 }
02672 
02673 
02680 static void wbxml_strtbl_collect_strings(WBXMLEncoder *encoder, WBXMLTreeNode *node, WBXMLList *strings)
02681 {
02682     WBXMLTreeAttribute *attribute = NULL;
02683     const WBXMLAttrEntry *attr_entry = NULL;
02684     WB_UTINY *value_left = NULL;
02685 
02686     switch (node->type)
02687     {
02688         case WBXML_TREE_TEXT_NODE:
02689             /* Ignore blank nodes */
02690             if (wbxml_buffer_contains_only_whitespaces(node->content))
02691                 break;
02692 
02695             /* Only add this string if it is big enought */
02696             if (wbxml_buffer_len(node->content) > WBXML_ENCODER_STRING_TABLE_MIN) {
02697                     wbxml_list_append(strings, node->content);
02698                 WBXML_DEBUG((WBXML_ENCODER, "Strtbl - Collecting String: %s", wbxml_buffer_get_cstr(node->content)));
02699             }
02700             break;
02701 
02702         case WBXML_TREE_ELEMENT_NODE:
02703             /* Collect strings in Attributes Values too */
02704                 attribute = node->attrs;
02705                 while (attribute != NULL) {
02706                 /* Only add this string if it is big enought */
02707                 if (wbxml_buffer_len(attribute->attr->value) > WBXML_ENCODER_STRING_TABLE_MIN) {
02708                     /* This mustn't be a tokenisable Attribute Start */
02709                     attr_entry = wbxml_tables_get_attr_from_xml(encoder->tree->lang, 
02710                                                        (WB_UTINY *) wbxml_attribute_get_xml_name(attribute->attr), 
02711                                                        (WB_UTINY *) wbxml_attribute_get_xml_value(attribute->attr),
02712                                                        &value_left);
02713 
02714                     /* - If attr_entry is NULL: no Attribute Start found
02715                      * - If attr_entry is not NULL: and Attribute Start is found, but it can be the one with
02716                      *   no Attribute Value associated. So just check that the 'value_left' is the same than
02717                      *   the attribute value we where searching for
02718                      */
02719                     if ((attr_entry == NULL) || ((attr_entry != NULL) && (value_left == (WB_UTINY *) wbxml_attribute_get_xml_value(attribute->attr))))
02720                     {
02721                         /* It mustn't contain a tokenisable Attribute Value */
02722                         if (!wbxml_tables_contains_attr_value_from_xml(encoder->tree->lang, 
02723                                                                        (WB_UTINY *) wbxml_attribute_get_xml_value(attribute->attr)))
02724                         {
02725                                 wbxml_list_append(strings, attribute->attr->value);
02726                             WBXML_DEBUG((WBXML_ENCODER, "Strtbl - Collecting String: %s", wbxml_buffer_get_cstr(attribute->attr->value)));
02727                         }
02728                     }
02729                 }
02730                 attribute = attribute->next;
02731                 }
02732                 break;
02733 
02734         default:
02735             /* NOOP */
02736             break;
02737     }
02738 
02739     if (node->children != NULL)
02740         wbxml_strtbl_collect_strings(encoder, node->children, strings);
02741 
02742     if (node->next != NULL)
02743             wbxml_strtbl_collect_strings(encoder, node->next, strings);
02744 }
02745 
02746 
02753 static WBXMLError wbxml_strtbl_collect_words(WBXMLList *elements, WBXMLList **result)
02754 {
02755     WBXMLStringTableElement *elt = NULL;
02756     WBXMLList *list = NULL, *temp_list = NULL;
02757     WBXMLBuffer *word = NULL;
02758     WB_ULONG i = 0;
02759 
02760     *result = NULL;
02761 
02762     for (i = 0; i < wbxml_list_len(elements); i++)
02763     {
02764             elt = (WBXMLStringTableElement *) wbxml_list_get(elements, i);
02765 
02766         if (list == NULL) {
02767             if ((list = wbxml_buffer_split_words(elt->string)) == NULL) {
02768                 wbxml_list_destroy(list, wbxml_buffer_destroy_item);
02769                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02770             }
02771         } else {
02772             if ((temp_list = wbxml_buffer_split_words(elt->string)) == NULL) {
02773                 wbxml_list_destroy(list, wbxml_buffer_destroy_item);
02774                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02775             }
02776     
02777             while ((word = wbxml_list_extract_first(temp_list)) != NULL) {
02778                 if (!wbxml_list_append(list, word)) {
02779                     wbxml_buffer_destroy(word);                    
02780                     wbxml_list_destroy(temp_list, wbxml_buffer_destroy_item);
02781                     wbxml_list_destroy(list, wbxml_buffer_destroy_item);
02782                     return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02783                 }
02784             }
02785     
02786             wbxml_list_destroy(temp_list, NULL);
02787         }
02788     }
02789 
02790     *result = list;
02791 
02792     return WBXML_OK;
02793 }
02794 
02795 
02801 static void wbxml_strtbl_construct(WB_UTINY *buff, WBXMLList *strstbl)
02802 {
02803     WBXMLStringTableElement *elt = NULL;
02804     WB_ULONG i = 0, buff_index = 0;
02805 
02806     if ((buff == NULL) || (strstbl == NULL))
02807         return;
02808 
02809     for (i = 0; i < wbxml_list_len(strstbl); i++) 
02810     {
02811         if ((elt = wbxml_list_get(strstbl, i)) == NULL)
02812             continue;
02813 
02814         memcpy(buff + buff_index, wbxml_buffer_get_cstr(elt->string), wbxml_buffer_len(elt->string));
02815         /* memcpy(buff + buff_index + wbxml_buffer_len(elt->string), WBXML_STR_END, 1); */
02816         buff[buff_index + wbxml_buffer_len(elt->string)] = WBXML_STR_END;
02817         buff_index += wbxml_buffer_len(elt->string) + 1;
02818     }
02819 }
02820 
02821 
02832 static WBXMLError wbxml_strtbl_check_references(WBXMLEncoder *encoder, WBXMLList **strings, WBXMLList **one_ref, WB_BOOL stat_buff)
02833 {
02834     WBXMLList *referenced = NULL, *result = NULL;
02835     WBXMLBuffer *string = NULL;
02836     WBXMLStringTableElement *ref = NULL;
02837     WB_ULONG j = 0;
02838     WB_BOOL added = FALSE;
02839 
02840     if ((strings == NULL) || (one_ref == NULL))
02841         return WBXML_ERROR_INTERNAL;
02842 
02843     *one_ref = NULL;
02844 
02845     /* Create list of String References */
02846     if ((referenced = wbxml_list_create()) == NULL)
02847         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02848 
02849 
02850     /*********************
02851      * Count References 
02852      */
02853 
02854     while (wbxml_list_len(*strings) > 0)
02855     {
02856         string = (WBXMLBuffer *) wbxml_list_extract_first(*strings);
02857         
02858         /* Check if we have already found this String */
02859         for (j = 0; j < wbxml_list_len(referenced); j++) 
02860         {
02861             ref = (WBXMLStringTableElement *) wbxml_list_get(referenced, j);
02862 
02863             if (wbxml_buffer_compare(ref->string, string) == 0) 
02864             {
02865                 if (!stat_buff)
02866                     wbxml_buffer_destroy(string);
02867 
02868                         string = NULL;
02869                         ref->count++;                
02870                         break;
02871             }
02872         }
02873         
02874         if (string != NULL) 
02875         {
02876             /* New Reference Element */
02877             if ((ref = wbxml_strtbl_element_create(string, stat_buff)) == NULL) 
02878             {
02879                 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
02880 
02881                 if (!stat_buff)
02882                     wbxml_list_destroy(*strings, wbxml_buffer_destroy_item);
02883                 else
02884                     wbxml_list_destroy(*strings, NULL);
02885 
02886                 *strings = NULL;                
02887                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02888             }
02889             
02890             ref->count++;
02891 
02892             if (!wbxml_list_append(referenced, (void *) ref)) 
02893             {
02894                 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
02895 
02896                 if (!stat_buff)                    
02897                     wbxml_list_destroy(*strings, wbxml_buffer_destroy_item);
02898                 else
02899                     wbxml_list_destroy(*strings, NULL);
02900 
02901                 *strings = NULL;                
02902                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02903             }
02904         }
02905     }
02906 
02907 
02908     wbxml_list_destroy(*strings, NULL);
02909     *strings = NULL;
02910 
02911 
02912     /***********************************************
02913      * Remove Strings that have only One reference
02914      */
02915 
02916     if ((result = wbxml_list_create()) == NULL) {
02917         wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
02918         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02919     }
02920 
02921     while (wbxml_list_len(referenced) > 0) 
02922     {
02923         ref = (WBXMLStringTableElement *) wbxml_list_extract_first(referenced);
02924         if ((ref->count > 1) && (wbxml_buffer_len(ref->string) > WBXML_ENCODER_STRING_TABLE_MIN)) {
02925             /* Add Element to String Table */
02926             if (!wbxml_strtbl_add_element(encoder, ref, NULL, &added)) {
02927                 wbxml_strtbl_element_destroy(ref);
02928                 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
02929                 wbxml_list_destroy(result, wbxml_strtbl_element_destroy_item);
02930                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02931             }
02932 
02933             if (!added) {
02934                 wbxml_strtbl_element_destroy(ref);
02935             }
02936         } 
02937         else {
02938             /* Add Element in resulting 'not added in String Table' list */
02939             if (!wbxml_list_append(result, (void *) ref)) {
02940                 wbxml_strtbl_element_destroy(ref);
02941                 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
02942                 wbxml_list_destroy(result, wbxml_strtbl_element_destroy_item);
02943                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
02944             }
02945         }
02946     }
02947 
02948     wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
02949 
02950     *one_ref = result;
02951 
02952     return WBXML_OK;
02953 }
02954 
02955 
02964 static WB_BOOL wbxml_strtbl_add_element(WBXMLEncoder *encoder, WBXMLStringTableElement *elt, WB_ULONG *index, WB_BOOL *added)
02965 {
02966     WBXMLStringTableElement *elt_tmp = NULL;
02967     WB_ULONG i = 0;
02968 
02969     if ((encoder == NULL) || (encoder->strstbl == NULL) || (elt == NULL) || (elt->string == NULL))
02970         return FALSE;
02971 
02972     *added = FALSE;
02973 
02974     /* Check if this element already exists in String Table */
02975     for (i = 0; i < wbxml_list_len(encoder->strstbl); i++) 
02976     {
02977         if ((elt_tmp = wbxml_list_get(encoder->strstbl, i)) == NULL)
02978             continue;
02979 
02980         if ((wbxml_buffer_len(elt_tmp->string) == wbxml_buffer_len(elt->string)) && 
02981             (wbxml_buffer_compare(elt_tmp->string, elt->string) == 0)) 
02982         {
02983             /* The String already exists in the String Table */
02984             if (index != NULL)
02985                 *index = elt_tmp->offset;
02986             return TRUE;
02987         }
02988     }
02989 
02990     /* Add this string to String Table */
02991     elt->offset = encoder->strstbl_len;
02992 
02993     if (!wbxml_list_append(encoder->strstbl, (void *) elt))
02994         return FALSE;
02995 
02996     /* Index in String Table */
02997     if (index != NULL)
02998         *index = encoder->strstbl_len;
02999 
03000     /* New String Table length */
03001     encoder->strstbl_len += wbxml_buffer_len(elt->string) + 1;
03002 
03003     *added = TRUE;
03004     
03005     return TRUE;
03006 }
03007 
03008 #endif /* WBXML_ENCODER_USE_STRTBL */
03009 
03010 
03011 /*****************************************
03012  *  XML Output Functions
03013  */
03014 
03015 
03016 /****************************
03017  * Build XML Result
03018  */
03019 
03026 static WBXMLError xml_build_result(WBXMLEncoder *encoder, WB_UTINY **xml)
03027 {
03028     WBXMLBuffer *header = NULL;
03029     WB_ULONG xml_len = 0;
03030 
03031     /* Create Header Buffer */
03032     if ((header = wbxml_buffer_create("", 0, WBXML_ENCODER_XML_HEADER_MALLOC_BLOCK)) == NULL)
03033         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03034 
03035     /* Fill Header Buffer */
03036     if (encoder->xml_encode_header) {
03037         if (!xml_fill_header(encoder, header)) {
03038             wbxml_buffer_destroy(header);
03039             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03040         }
03041     }
03042 
03043     /* Result Buffer Length */
03044     xml_len = wbxml_buffer_len(header) + wbxml_buffer_len(encoder->output);
03045 
03046     /* Create Result Buffer */
03047     *xml = (WB_UTINY *) wbxml_malloc((xml_len + 1) * sizeof(WB_UTINY));
03048     if (*xml == NULL) {
03049         wbxml_buffer_destroy(header);
03050         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03051     }
03052 
03053     /* Copy Header to Result */
03054     memcpy(*xml, wbxml_buffer_get_cstr(header), wbxml_buffer_len(header));
03055 
03056     /* Copy XML Document to Result */
03057     memcpy(*xml + wbxml_buffer_len(header), wbxml_buffer_get_cstr(encoder->output), wbxml_buffer_len(encoder->output));
03058 
03059     /* NULL Terminated Buffer */
03060     (*xml)[xml_len] = '\0';
03061    
03062     /* Clean-up */
03063     wbxml_buffer_destroy(header);
03064 
03065     return WBXML_OK;
03066 }
03067 
03068 
03075 static WB_BOOL xml_fill_header(WBXMLEncoder *encoder, WBXMLBuffer *header)
03076 {
03077     if ((encoder == NULL) || (header == NULL))
03078         return FALSE;
03079 
03080     /* <?xml version=\"1.0\"?> */
03081     if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_HEADER))
03082         return FALSE;
03083 
03084     /* New Line */
03085     if (encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_INDENT) {
03086         if (!xml_encode_new_line(header))
03087             return WBXML_ERROR_ENCODER_APPEND_DATA;        
03088     }
03089 
03090     /* <!DOCTYPE */
03091     if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_DOCTYPE))
03092         return FALSE;
03093 
03094     /* Root Element */
03095     if (!wbxml_buffer_append_cstr(header, encoder->tree->lang->publicID->xmlRootElt))
03096         return FALSE;
03097 
03098     /*  PUBLIC " */
03099     if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_PUBLIC))
03100         return FALSE;
03101 
03102     /* Public ID */
03103     if (!wbxml_buffer_append_cstr(header, encoder->tree->lang->publicID->xmlPublicID))
03104         return FALSE;
03105 
03106     /* DTD */
03107     if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_DTD))
03108         return FALSE;
03109 
03110     /* DTD */
03111     if (!wbxml_buffer_append_cstr(header, encoder->tree->lang->publicID->xmlDTD))
03112         return FALSE;
03113 
03114     /* "> */
03115     if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_END_DTD))
03116         return FALSE;
03117 
03118     /* New Line */
03119     if (encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_INDENT) {
03120         if (!xml_encode_new_line(header))
03121             return WBXML_ERROR_ENCODER_APPEND_DATA;        
03122     }
03123 
03124     return TRUE;
03125 }
03126 
03127 
03128 /****************************
03129  * XML Encoding Functions
03130  */
03131 
03138 static WBXMLError xml_encode_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node)
03139 {
03140     const WB_TINY *ns = NULL;
03141     WB_UTINY i;
03142 
03143     /* Set as current Tag */
03144     if (node->name->type == WBXML_VALUE_TOKEN)
03145         encoder->current_tag = node->name->u.token;
03146     else
03147         encoder->current_tag = NULL;
03148 
03149     /* Indent */
03150     if (encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_INDENT) {            
03151         for (i=0; i<(encoder->indent * encoder->indent_delta); i++) {
03152             if (!wbxml_buffer_append_char(encoder->output, ' '))
03153                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03154         }
03155     }
03156 
03157     /* Append < */
03158     if (!wbxml_buffer_append_char(encoder->output, '<'))
03159         return WBXML_ERROR_ENCODER_APPEND_DATA;
03160 
03161     /* Append Element Name */
03162     if (!wbxml_buffer_append_cstr(encoder->output, wbxml_tag_get_xml_name(node->name)))
03163         return WBXML_ERROR_ENCODER_APPEND_DATA;
03164 
03165     /* NameSpace handling: Check if Current Node Code Page is different than Parent Node Code Page */
03166     if ((encoder->tree->lang->nsTable != NULL) &&
03167         ((node->parent == NULL) ||
03168          ((node->parent->type == WBXML_TREE_ELEMENT_NODE) &&
03169           (node->parent->name->type == WBXML_VALUE_TOKEN) &&
03170           (node->type == WBXML_TREE_ELEMENT_NODE) &&
03171           (node->name->type == WBXML_VALUE_TOKEN) &&
03172           (node->parent->name->u.token->wbxmlCodePage != node->name->u.token->wbxmlCodePage))))
03173     {
03174         if ((ns = wbxml_tables_get_xmlns(encoder->tree->lang->nsTable, node->name->u.token->wbxmlCodePage)) != NULL)
03175         {
03176             /* Append xmlns=" */
03177             if (!wbxml_buffer_append_cstr(encoder->output, " xmlns=\""))
03178                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03179 
03180             /* Append NameSpace */
03181             if (!wbxml_buffer_append_cstr(encoder->output, ns))
03182                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03183 
03184             /* Append " */
03185             if (!wbxml_buffer_append_char(encoder->output, '"'))
03186                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03187         }
03188     }
03189 
03190     return WBXML_OK;
03191 }
03192 
03193 
03200 static WBXMLError xml_encode_end_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node)
03201 {
03202     WB_UTINY i;
03203 
03204     if (encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_INDENT) {
03205         /* Add a New Line if there were content in this element */
03206         if (encoder->in_content) {
03207             if (!xml_encode_new_line(encoder->output))
03208                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03209         }
03210 
03211         encoder->indent--;
03212 
03213         /* Indent End Element */
03214         for (i=0; i<(encoder->indent * encoder->indent_delta); i++) {
03215             if (!wbxml_buffer_append_char(encoder->output, ' '))
03216                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03217         }
03218     }
03219 
03220     /* Append </ */
03221     if (!wbxml_buffer_append_cstr(encoder->output, "</"))
03222         return WBXML_ERROR_ENCODER_APPEND_DATA;
03223 
03224     /* Append Element Name */
03225     if (!wbxml_buffer_append_cstr(encoder->output, wbxml_tag_get_xml_name(node->name)))
03226         return WBXML_ERROR_ENCODER_APPEND_DATA;
03227 
03228     /* Append > */
03229     if (!wbxml_buffer_append_char(encoder->output, '>'))
03230         return WBXML_ERROR_ENCODER_APPEND_DATA;
03231 
03232     /* New Line */
03233     if (encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_INDENT) {
03234         if (!xml_encode_new_line(encoder->output))
03235             return WBXML_ERROR_ENCODER_APPEND_DATA;        
03236     }
03237 
03238     /* Reset Current tag */
03239     encoder->current_tag = NULL;
03240 
03241     encoder->in_content = FALSE;
03242 
03243     return WBXML_OK;
03244 }
03245 
03246 
03253 static WBXMLError xml_encode_attr(WBXMLEncoder *encoder, WBXMLAttribute *attribute)
03254 {
03255     /* Append a space */
03256     if (!wbxml_buffer_append_char(encoder->output, ' '))
03257         return WBXML_ERROR_ENCODER_APPEND_DATA;
03258 
03259     /* Append Attribute Name */
03260     if (!wbxml_buffer_append_cstr(encoder->output, wbxml_attribute_get_xml_name(attribute)))
03261         return WBXML_ERROR_ENCODER_APPEND_DATA;
03262         
03263     /* Append =" */
03264     if (!wbxml_buffer_append_cstr(encoder->output, "=\""))
03265         return WBXML_ERROR_ENCODER_APPEND_DATA;
03266 
03267     if (wbxml_attribute_get_xml_value(attribute) != NULL) {
03268         /* Normalize Attribute Value */
03269         if (encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_CANONICAL) {
03270             WBXMLBuffer *tmp = NULL;
03271 
03272             /* Work with a temporary copy */
03273             if ((tmp = wbxml_buffer_create_from_cstr(wbxml_attribute_get_xml_value(attribute))) == NULL)
03274                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03275 
03276             /* Normalize */
03277             xml_normalize(tmp);
03278 
03279             /* Append Attribute Value */
03280             if (!wbxml_buffer_append(encoder->output, tmp)) {
03281                 wbxml_buffer_destroy(tmp);
03282                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03283             }
03284 
03285             wbxml_buffer_destroy(tmp);
03286         }
03287         else {     
03288             /* Append Attribute Value */
03289             if (!wbxml_buffer_append_cstr(encoder->output, wbxml_attribute_get_xml_value(attribute)))
03290                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03291         }
03292     }
03293 
03294     /* Append " */
03295     if (!wbxml_buffer_append_char(encoder->output, '"'))
03296         return WBXML_ERROR_ENCODER_APPEND_DATA;
03297 
03298     return WBXML_OK;
03299 }
03300 
03301 
03307 static WBXMLError xml_encode_end_attrs(WBXMLEncoder *encoder)
03308 {
03309     /* Append > */
03310     if (!wbxml_buffer_append_char(encoder->output, '>'))
03311         return WBXML_ERROR_ENCODER_APPEND_DATA;
03312 
03313     /* New Line */
03314     if (encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_INDENT) {
03315         if (!xml_encode_new_line(encoder->output))
03316             return WBXML_ERROR_ENCODER_APPEND_DATA;
03317 
03318         encoder->indent++;
03319     }       
03320 
03321     return WBXML_OK;
03322 }
03323 
03324 
03331 static WBXMLError xml_encode_text(WBXMLEncoder *encoder, WBXMLBuffer *str)
03332 {
03333     WBXMLBuffer *tmp = NULL;
03334     WB_UTINY i;
03335 
03336     /* Work with a temporary copy */
03337     if ((tmp = wbxml_buffer_duplicate(str)) == NULL)
03338         return WBXML_ERROR_NOT_ENOUGH_MEMORY;    
03339 
03340     /* Indent */
03341     if ((encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_INDENT) && 
03342         (!encoder->in_content)) 
03343     {
03344         /* Indent Content (only indent in first call to xml_encode_text()) */
03345         for (i=0; i<(encoder->indent * encoder->indent_delta); i++) {
03346             if (!wbxml_buffer_append_char(encoder->output, ' ')) {
03347                 wbxml_buffer_destroy(tmp);
03348                 return WBXML_ERROR_ENCODER_APPEND_DATA;
03349             }
03350         }
03351     }
03352 
03353 #if defined( WBXML_SUPPORT_SYNCML )
03354     /* Change text in <Type> from "application/vnd.syncml-devinf+wbxml" to "application/vnd.syncml-devinf+xml" */
03355     if (((encoder->tree->lang->langID == WBXML_LANG_SYNCML_SYNCML10) || 
03356          (encoder->tree->lang->langID == WBXML_LANG_SYNCML_SYNCML11)) &&
03357         (encoder->current_tag != NULL) &&
03358         (encoder->current_tag->wbxmlCodePage == 0x01 ) &&
03359         (encoder->current_tag->wbxmlToken == 0x13 ) &&
03360         (wbxml_buffer_compare_cstr(tmp, "application/vnd.syncml-devinf+wbxml") == 0))
03361     {
03362         wbxml_buffer_destroy(tmp);
03363 
03364         /* Change Content */
03365         if ((tmp = wbxml_buffer_create_from_cstr("application/vnd.syncml-devinf+xml")) == NULL)
03366             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03367     }
03368 #endif /* WBXML_SUPPORT_SYNCML */
03369 
03370     /* Normalize Text */
03371     if (encoder->xml_gen_type == WBXML_ENCODER_XML_GEN_CANONICAL)
03372         xml_normalize(tmp);       
03373 
03374     /* Append Text */
03375     if (!wbxml_buffer_append(encoder->output, tmp)) {
03376         wbxml_buffer_destroy(tmp);
03377         return WBXML_ERROR_ENCODER_APPEND_DATA;
03378     }
03379 
03380     encoder->in_content = TRUE;
03381 
03382     /* Clean-up */
03383     wbxml_buffer_destroy(tmp);
03384 
03385     return WBXML_OK;
03386 }
03387 
03388 
03394 static WB_BOOL xml_encode_new_line(WBXMLBuffer *buff)
03395 {
03396     if (buff == NULL)
03397         return FALSE;
03398 
03399     return wbxml_buffer_append_data(buff, WBXML_ENCODER_XML_NEW_LINE, WBXML_STRLEN(WBXML_ENCODER_XML_NEW_LINE));
03400 
03401 }
03402 
03403 
03409 static WB_BOOL xml_normalize(WBXMLBuffer *buff)
03410 {
03411         WB_ULONG i = 0;
03412     WB_UTINY ch;
03413 
03414         for (i = 0; i < wbxml_buffer_len(buff); i++) {
03415         if (!wbxml_buffer_get_char(buff, i, &ch))
03416             continue;
03417 
03418                 switch (ch) {
03419                 case '<':
03420             /* Remove it */
03421             wbxml_buffer_delete(buff, i, 1);
03422 
03423             /* Write "&lt;" */
03424             if (!wbxml_buffer_insert_cstr(buff, (WB_UTINY *) xml_lt, i))
03425                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03426 
03427                         break;
03428 
03429                 case '>':
03430             /* Remove it */
03431             wbxml_buffer_delete(buff, i, 1);
03432 
03433             /* Write "&gt;" */
03434             if (!wbxml_buffer_insert_cstr(buff, (WB_UTINY *) xml_gt, i))
03435                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03436 
03437                         break;
03438 
03439                 case '&':
03440             /* Remove it */
03441             wbxml_buffer_delete(buff, i, 1);
03442 
03443             /* Write "&amp;" */
03444             if (!wbxml_buffer_insert_cstr(buff, (WB_UTINY *) xml_amp, i))
03445                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03446 
03447                         break;
03448 
03449                 case '"':
03450             /* Remove it */
03451             wbxml_buffer_delete(buff, i, 1);
03452 
03453             /* Write "&quot;" */
03454             if (!wbxml_buffer_insert_cstr(buff, (WB_UTINY *) xml_quot, i))
03455                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03456 
03457                         break;
03458 
03459                 case '\r':
03460             /* Remove it */
03461             wbxml_buffer_delete(buff, i, 1);
03462 
03463             /* Write "&#13;" */
03464             if (!wbxml_buffer_insert_cstr(buff, (WB_UTINY *) xml_slashr, i))
03465                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03466 
03467                         break;
03468 
03469                 case '\n':
03470             /* Remove it */
03471             wbxml_buffer_delete(buff, i, 1);
03472 
03473             /* Write "&#10;" */
03474             if (!wbxml_buffer_insert_cstr(buff, (WB_UTINY *) xml_slashn, i))
03475                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03476 
03477                         break;
03478 
03479                 case '\t':
03480             /* Remove it */
03481             wbxml_buffer_delete(buff, i, 1);
03482 
03483             /* Write "&#9;" */
03484             if (!wbxml_buffer_insert_cstr(buff, (WB_UTINY *) xml_tab, i))
03485                 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03486 
03487                         break;
03488 
03489                 default:
03490             /* Do Nothing */
03491                         break;
03492                 }
03493         }
03494 
03495     return WBXML_OK;
03496 }
03497 
03498 
03505 static WBXMLError xml_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree)
03506 {
03507     WBXMLEncoder *new_encoder = NULL;
03508     WB_UTINY *xml = NULL;
03509     WBXMLError ret = WBXML_OK;
03510 
03511     if ((new_encoder = wbxml_encoder_duplicate(encoder)) == NULL)
03512         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03513 
03514     /* Set Tree */
03515     new_encoder->tree = tree;
03516 
03517     /* Encode to XML */
03518     if ((ret = wbxml_encoder_encode_to_xml(new_encoder, &xml)) != WBXML_OK) {
03519         wbxml_encoder_destroy(new_encoder);
03520         return ret;
03521     }
03522 
03523     /* Clean-up */
03524     wbxml_encoder_destroy(new_encoder);
03525 
03526     /* Append xml to output */
03527     if (!wbxml_buffer_append_cstr(encoder->output, xml)) {
03528         wbxml_free(xml);
03529         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
03530     }
03531 
03532     /* Clean-up */
03533     wbxml_free(xml);
03534 
03535     return WBXML_OK;
03536 }

Generated on Mon Nov 24 20:09:42 2003 for WBXML Library by doxygen1.3-rc1