xml/cxmllibrary/src/string/src/string.c
branchRCL_3
changeset 21 604ca70b6235
parent 20 889504eac4fb
equal deleted inserted replaced
20:889504eac4fb 21:604ca70b6235
     1 /*
       
     2 * Copyright (c) 2000 - 2001 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 /*****************************************************************
       
    20 **  File: xml_string.c
       
    21 **
       
    22 **  Description:
       
    23  *
       
    24  * The following routines are an interface to raw strings stored in 
       
    25  * various encodings The implementation assumes a few things that 
       
    26  * are not necessarily generally true: 
       
    27  *  - every character read can be converted into a ucs_2 character
       
    28  *  - the string terminating character is a null character (not a null 
       
    29  *    NW_Byte)
       
    30  * 
       
    31 *****************************************************************/
       
    32 #include "cxml_internal.h"
       
    33 #include <xml/cxml/nw_string_string.h>
       
    34 #include <xml/cxml/nw_string_char.h>
       
    35 #include <xml/cxml/nw_wbxml_dictionary.h>
       
    36 
       
    37 static NW_Status_t
       
    38 StringUCS2Init(NW_String_UCS2String_t * string, void *storage)
       
    39 {
       
    40   NW_Status_t status = NW_STAT_SUCCESS;
       
    41   NW_Uint32 numBytes = 0;
       
    42 
       
    43   string->storage = (NW_Byte*) storage;
       
    44   if (string->storage){
       
    45     if (NW_String_charBuffGetLength(storage, HTTP_iso_10646_ucs_2, &numBytes) < 0) {
       
    46       numBytes = 0;
       
    47       status = NW_STAT_FAILURE;
       
    48     }
       
    49   }
       
    50   string->length = numBytes;
       
    51   return status;
       
    52 }
       
    53 
       
    54 
       
    55 /*  
       
    56  * TODO: The following functions need to have the allocator passed 
       
    57  * as an argument !!
       
    58  */
       
    59 
       
    60 /*
       
    61  * RETURN NULL if malloc fails
       
    62  */
       
    63 EXPORT_C NW_String_t *
       
    64 NW_String_new (void)
       
    65 {
       
    66   NW_String_t *str =
       
    67     (NW_String_t *) NW_Mem_Malloc (sizeof (NW_String_t));
       
    68   if (str == NULL)
       
    69     return NULL;
       
    70   str->length = 0;
       
    71   str->storage = NULL;
       
    72   return str;
       
    73 }
       
    74 
       
    75 EXPORT_C NW_Status_t 
       
    76 NW_String_initialize (NW_String_t *string, void *storage, NW_Uint32 encoding)
       
    77 {
       
    78   NW_Status_t status;
       
    79   NW_Uint32 numBytes = 0;
       
    80 
       
    81   NW_ASSERT(string != NULL);
       
    82 
       
    83   if (storage == NULL) {
       
    84     string->storage = NULL;
       
    85     string->length = 0;
       
    86 
       
    87     return NW_STAT_SUCCESS;
       
    88   }
       
    89 
       
    90   if ((status = NW_String_charsetValid (encoding)) != NW_STAT_SUCCESS)
       
    91     return status;
       
    92 
       
    93   string->storage = (NW_Byte*) storage;
       
    94 
       
    95   if (string->storage){
       
    96     if (NW_String_charBuffGetLength(storage, encoding, &numBytes) < 0) {
       
    97       return NW_STAT_FAILURE;
       
    98     }
       
    99   }
       
   100   string->length = numBytes;
       
   101 
       
   102   return NW_STAT_SUCCESS;
       
   103 }
       
   104 
       
   105 /*
       
   106  * Freeing a string might not free the storage!
       
   107  * String storage is complicated by the fact that
       
   108  * it can be allocated outside the bounds
       
   109  * of the parser. If so, it is not freed here.
       
   110  *
       
   111  */
       
   112 
       
   113 EXPORT_C void 
       
   114 NW_String_delete(NW_String_t *s)
       
   115 {
       
   116 
       
   117   NW_ASSERT(s != NULL);
       
   118 
       
   119   if (NW_String_getUserOwnsStorage(s)){
       
   120     NW_Mem_Free (s->storage);
       
   121   }
       
   122 
       
   123   NW_Mem_Free (s);
       
   124 }
       
   125 
       
   126 EXPORT_C NW_Status_t
       
   127 NW_String_deleteStorage(NW_String_t *s)
       
   128 {
       
   129 
       
   130   NW_ASSERT(s != NULL);
       
   131 
       
   132   if (NW_String_getUserOwnsStorage(s))
       
   133   {
       
   134     if (s->storage != NULL){
       
   135       NW_Mem_Free(s->storage);
       
   136     }
       
   137   }
       
   138   s->storage = NULL;
       
   139 	s->length = 0;
       
   140   return NW_STAT_SUCCESS;
       
   141 }
       
   142 /* 
       
   143  * Determine the length of the given string in characters (not
       
   144  * bytes).
       
   145  *
       
   146  * RETURN length in characters or 0 if s is NULL
       
   147  */
       
   148 
       
   149 EXPORT_C NW_Uint16
       
   150 NW_String_getCharCount(NW_String_t *s, NW_Uint32 encoding)
       
   151 {
       
   152   NW_Uint16 numChar = 0;
       
   153   NW_Uint32 getNumChar = NW_String_getCharCount32(s,encoding);
       
   154  
       
   155   if(getNumChar <= NW_UINT16_MAX)
       
   156   {
       
   157 	 numChar =(NW_Uint16) getNumChar;
       
   158   }
       
   159 
       
   160   return numChar;
       
   161 }
       
   162 /* 
       
   163  * The following function is a duplication of NW_String_getByteCount to
       
   164  * handle big files.  For not affecting the components other than
       
   165  * browser, this function is only called inside the browser.).
       
   166  *
       
   167  * INSTEAD OF CALLING NW_String_getByteCount, ALL THE BROWSER CODES SHOULD
       
   168  * CALL THIS DUPLICATE FUNCTION TO GET CHARACTER COUNTS.
       
   169  * 
       
   170  */
       
   171 
       
   172 EXPORT_C NW_Uint32
       
   173 NW_String_getCharCount32(NW_String_t *s, NW_Uint32 encoding)
       
   174 {
       
   175   NW_Int32 numChars;  
       
   176   NW_Uint32 byteCount;
       
   177 
       
   178   if (s == NULL)
       
   179     return 0;
       
   180  
       
   181   if (s->storage == NULL)
       
   182     return 0;
       
   183  
       
   184   numChars = NW_String_charBuffGetLength(s->storage, encoding, &byteCount);
       
   185 
       
   186   if ( numChars < 0 ) {
       
   187     numChars = 0;
       
   188   }
       
   189 
       
   190   return  NW_UINT32_CAST( numChars );  
       
   191 }
       
   192 
       
   193 EXPORT_C NW_Uint32
       
   194 NW_String_getByteCount (NW_String_t *s)
       
   195 {
       
   196   NW_Uint32 uint32Len;
       
   197 
       
   198   if (s == NULL)
       
   199     return 0;
       
   200 
       
   201   /* The MSB of NW_Byte length if set represents that the 
       
   202   string is from storage buffer, so BufferOwns String */
       
   203   uint32Len = (s->length) & 0x7FFFFFFF; 
       
   204   return uint32Len;
       
   205 }
       
   206 
       
   207 /*
       
   208  * Returns NULL or valid storage
       
   209  */
       
   210 EXPORT_C NW_Byte *
       
   211 NW_String_getStorage(NW_String_t *str)
       
   212 {
       
   213   if (str == NULL)
       
   214     return NULL;
       
   215 
       
   216   return str->storage;
       
   217 }
       
   218 
       
   219 /* 
       
   220  * Boolean comparison. This function assumes encodings to be
       
   221  * the same. It does not attempt to convert strings of different 
       
   222  * encodings for comparison, since we want to treat encoding as 
       
   223  * implicit for xml strings. 
       
   224  *
       
   225  * RETURN 1 if the strings are equal; 0 if the strings are not equal
       
   226  */
       
   227 
       
   228 EXPORT_C NW_Int32
       
   229 NW_String_equals(const NW_String_t *s1, const NW_String_t *s2)
       
   230 {
       
   231   if ( (s1 == NULL) || (s2 == NULL) )
       
   232     return 0;
       
   233 
       
   234   if (s1 == s2)
       
   235     return 1;
       
   236 
       
   237   if (NW_String_getByteCount((NW_String_t *) s1) != NW_String_getByteCount((NW_String_t *) s2))
       
   238     return 0;
       
   239   /* 
       
   240    * Assumes that strings are zero terminated, so a substring 
       
   241    * can't share storage with the super string
       
   242    */
       
   243   if (s1->storage == s2->storage)
       
   244     return 1;
       
   245 
       
   246   /* Same length, different storage, compare NW_Byte-by-NW_Byte */
       
   247 
       
   248   if (NW_Mem_memcmp (((NW_String_t *) s1)->storage, ((NW_String_t *) s2)->storage, 
       
   249       NW_String_getByteCount((NW_String_t *) s1)))
       
   250     return 0;
       
   251 
       
   252   return 1;
       
   253 }
       
   254 
       
   255 EXPORT_C NW_Bool
       
   256 NW_String_getUserOwnsStorage(NW_String_t * s)
       
   257 {
       
   258   NW_Uint32 i;
       
   259   if (s == NULL)
       
   260     return 0;
       
   261   
       
   262   /* The MSB of NW_Byte length if set represents that the 
       
   263   string is from storage buffer, so BufferOwns String */
       
   264   i = s->length & 0x80000000;
       
   265   if (i== 0)
       
   266     return NW_FALSE;
       
   267   return NW_TRUE;
       
   268 }
       
   269 
       
   270 
       
   271 EXPORT_C NW_Status_t
       
   272 NW_String_setUserOwnsStorage(NW_String_t * s)
       
   273 {
       
   274 
       
   275   NW_ASSERT(s != NULL);
       
   276   
       
   277   /* The MSB of NW_Byte length if set represents that the 
       
   278   string is from storage buffer, so BufferOwns String */
       
   279   s->length = s->length | 0x80000000;
       
   280   return NW_STAT_SUCCESS;
       
   281 }
       
   282 
       
   283 EXPORT_C NW_Status_t
       
   284 NW_String_clearUserOwnsStorage(NW_String_t * s)
       
   285 {
       
   286 
       
   287   NW_ASSERT(s != NULL);
       
   288   
       
   289   /* The MSB of NW_Byte length if set represents that the 
       
   290   string is from storage buffer, so BufferOwns String */
       
   291   s->length = s->length & 0x7fffffff;
       
   292   return NW_STAT_SUCCESS;
       
   293 }
       
   294 
       
   295 
       
   296 /*
       
   297  * Conversion routines 
       
   298  */
       
   299 
       
   300 /*
       
   301  * RETURN NW_STAT_SUCCESS
       
   302  *        NW_STAT_OUT_OF_MEMORY
       
   303  *
       
   304  * MODIFIED ret_string
       
   305  */
       
   306 NW_Status_t
       
   307 NW_String_stringToUCS2 (NW_String_UCS2String_t ** ret_string, NW_String_t * s, NW_Uint32 input_encoding)
       
   308 {
       
   309   NW_String_UCS2Buff_t *storage;
       
   310 
       
   311   if (*ret_string == NULL)
       
   312     *ret_string = NW_String_new();
       
   313 
       
   314   if (*ret_string == NULL)
       
   315     return NW_STAT_OUT_OF_MEMORY;
       
   316 
       
   317   if (input_encoding == HTTP_iso_10646_ucs_2)
       
   318     return NW_String_copy(*ret_string, s);
       
   319 
       
   320   if ((input_encoding == HTTP_utf_8) ||
       
   321       (input_encoding == HTTP_us_ascii) ||
       
   322       (input_encoding == HTTP_iso_8859_1))
       
   323   {
       
   324     NW_Status_t status;
       
   325     storage = NW_String_charToUCS2Buff (s->storage, input_encoding);
       
   326 
       
   327     if (storage == NULL){
       
   328       return NW_STAT_OUT_OF_MEMORY;
       
   329     }
       
   330 
       
   331     status = NW_String_initialize(*ret_string, (void *)storage, HTTP_iso_10646_ucs_2);
       
   332     if (status == NW_STAT_SUCCESS){
       
   333       return NW_String_setUserOwnsStorage(*ret_string);
       
   334     }
       
   335     else{
       
   336       NW_String_delete(*ret_string);
       
   337       NW_Mem_Free(storage);
       
   338       return status;
       
   339     }
       
   340   }
       
   341   NW_String_delete(*ret_string);
       
   342   return NW_STAT_WBXML_ERROR_CHARSET_UNSUPPORTED;
       
   343 }
       
   344 
       
   345 /*
       
   346  * RETURN NW_STAT_SUCCESS
       
   347  *        NW_STAT_OUT_OF_MEMORY
       
   348  *        NW_STAT_WBXML_ERROR_CHARSET_UNSUPPORTED
       
   349  *
       
   350  * MODIFIED ret_string
       
   351  */
       
   352 static
       
   353 NW_Status_t
       
   354 NW_String_stringFromUCS2 (NW_String_t ** ret_string, NW_String_UCS2String_t * s, NW_Uint32 output_encoding)
       
   355 {
       
   356   NW_Byte *storage;
       
   357   NW_String_UCS2Buff_t *ucs2Storage = (NW_String_UCS2Buff_t *) (s->storage);
       
   358   NW_Uint32 byteLength = NW_String_getByteCount(s);
       
   359   NW_Status_t status;
       
   360 
       
   361   if (*ret_string == NULL)
       
   362     *ret_string = NW_String_new();
       
   363 
       
   364   if (*ret_string == NULL)
       
   365     return NW_STAT_OUT_OF_MEMORY;
       
   366 
       
   367   if (output_encoding == HTTP_iso_10646_ucs_2)
       
   368     return NW_String_copy(*ret_string, s);
       
   369 
       
   370   if ( (output_encoding == HTTP_utf_8) || (output_encoding == HTTP_us_ascii) )
       
   371   {
       
   372     storage = NW_String_UCS2ToUTF8 (ucs2Storage, byteLength);
       
   373   }
       
   374   else if (output_encoding == HTTP_iso_8859_1)
       
   375   {
       
   376     storage = NW_String_UCS2ToISO88591 (ucs2Storage, byteLength);
       
   377   }
       
   378   else {
       
   379     NW_String_delete(*ret_string);
       
   380     return NW_STAT_WBXML_ERROR_CHARSET_UNSUPPORTED;
       
   381   }
       
   382   if (storage == NULL)
       
   383     return NW_STAT_OUT_OF_MEMORY;
       
   384   
       
   385   status =  NW_String_initialize(*ret_string, storage, output_encoding);
       
   386   if(status == NW_STAT_SUCCESS){
       
   387    return  NW_String_setUserOwnsStorage(*ret_string);
       
   388   }
       
   389   else{
       
   390     NW_String_delete(*ret_string);
       
   391     NW_Mem_Free(storage);
       
   392     return status;
       
   393   }
       
   394 }
       
   395 
       
   396 
       
   397 /*
       
   398  * Convert a NW_String_t (in any of the supported character 
       
   399  * set encodings) to a UCS2Buff string.
       
   400  *
       
   401  * NOTE: caller is responsible for freeing the pointer returned
       
   402  *   by this function
       
   403  *
       
   404  * NOTE: returned array is null-terminated.
       
   405  *
       
   406  * RETURN NULL if malloc fails
       
   407  */
       
   408 NW_String_UCS2Buff_t *
       
   409 NW_String_stringToUCS2Buff (NW_String_t * string, NW_Uint32 encoding)
       
   410 {
       
   411   NW_Byte *b = string->storage;
       
   412   if (!NW_String_charsetValid(encoding))
       
   413     return NULL;
       
   414 
       
   415   return NW_String_charToUCS2Buff(b, encoding);
       
   416 }
       
   417 
       
   418 /*
       
   419  * RETURN NW_STAT_SUCCESS
       
   420  *        NW_STAT_OUT_OF_MEMORY
       
   421  *        NW_WBXML_ERROR_CHARSET_UNSUPPORTED
       
   422  *
       
   423  * MODIFIED ret_string
       
   424  */
       
   425 EXPORT_C NW_Status_t 
       
   426 NW_String_UCS2BuffToString(NW_String_UCS2Buff_t *buff, NW_String_t *str, NW_Uint32 encoding)
       
   427 {
       
   428   NW_Status_t status;
       
   429   NW_String_UCS2String_t* ucs2String = NW_String_new();
       
   430 
       
   431   if (ucs2String == NULL) {
       
   432     return NW_STAT_OUT_OF_MEMORY;
       
   433   }
       
   434 
       
   435   status = StringUCS2Init(ucs2String, (void *)buff);
       
   436   if (status == NW_STAT_SUCCESS) {
       
   437     status = NW_String_stringFromUCS2 (&str, ucs2String, encoding);
       
   438   }
       
   439   /* Freeing only the NW_String_t and not the storage, since we
       
   440      used the input storage */
       
   441   NW_Mem_Free(ucs2String);
       
   442   return status;
       
   443 }
       
   444 
       
   445 
       
   446 /*
       
   447  * Returns
       
   448  * NW_STAT_WBXML_ERROR_CHARSET_UNSUPPORTED - If unsupported encoding
       
   449  * NW_STAT_OUT_OF_MEMORY - If memory for string storage could not be allocated
       
   450  * NW_STAT_WBXML_NO_NAME
       
   451  * NW_STAT_SUCCESS
       
   452  */
       
   453 EXPORT_C NW_Status_t 
       
   454 NW_String_ucs2CharToString(NW_String_t *string, NW_Ucs2 *u, NW_Uint32 encoding)
       
   455 {
       
   456   NW_Byte *storage;
       
   457   NW_String_t *ucs2_string = NW_String_new();
       
   458   NW_Status_t status;
       
   459   NW_Ucs2 *p = u;
       
   460   NW_Uint32 len = 0;
       
   461 
       
   462   NW_ASSERT(string != NULL);
       
   463   NW_ASSERT(u != NULL);
       
   464 
       
   465   if (ucs2_string == NULL){
       
   466     return NW_STAT_OUT_OF_MEMORY;
       
   467   }
       
   468 
       
   469   while (*p!= 0)
       
   470   {
       
   471     len++;
       
   472     p++;
       
   473   }
       
   474   
       
   475   if (NW_String_charsetValid(encoding) != NW_STAT_SUCCESS) {
       
   476     NW_String_delete(ucs2_string);
       
   477     return NW_STAT_WBXML_ERROR_CHARSET_UNSUPPORTED;
       
   478   }
       
   479   /* Create the storage and copy the bytes */
       
   480 
       
   481   if ((storage = (NW_Byte*) NW_Mem_Malloc ((len + 1) * sizeof(NW_String_UCS2Buff_t))) == NULL){
       
   482     return NW_STAT_OUT_OF_MEMORY;
       
   483   }
       
   484 
       
   485 #if 0
       
   486   {
       
   487     NW_Int32 index = 0;
       
   488 
       
   489     while(*u != 0)
       
   490     {
       
   491       storage[index++] = (NW_Byte)(*u >> 8);
       
   492       storage[index++] = (NW_Byte)(*u & 0x00ff);
       
   493       u++;
       
   494     }
       
   495 
       
   496     storage[index++] = (NW_Byte)0;
       
   497     storage[index] = (NW_Byte)0;
       
   498   }
       
   499 #else
       
   500     NW_Mem_memcpy(storage, u, (len + 1) * sizeof(NW_String_UCS2Buff_t));
       
   501 #endif
       
   502 
       
   503   status = NW_String_initialize(ucs2_string, storage, HTTP_iso_10646_ucs_2);
       
   504   if (status != NW_STAT_SUCCESS){
       
   505     NW_Mem_Free(storage);
       
   506     NW_String_delete(ucs2_string);
       
   507     return status;
       
   508   }
       
   509   NW_String_setUserOwnsStorage(ucs2_string);
       
   510 
       
   511   status = NW_String_stringFromUCS2(&string, ucs2_string, encoding);
       
   512   NW_String_delete(ucs2_string);
       
   513 
       
   514   return status;
       
   515 }
       
   516 
       
   517 /*
       
   518  * Conversion to string
       
   519  */
       
   520 EXPORT_C NW_Status_t 
       
   521 NW_String_entityToString(NW_Uint32 entity, NW_String_t *str, NW_Uint32 encoding)
       
   522 {
       
   523   NW_Status_t status;
       
   524   NW_Ucs2 *s;
       
   525   NW_Ucs2 e;
       
   526 
       
   527   if ((s = (NW_Ucs2*) NW_Mem_Malloc(2 * sizeof(NW_Ucs2))) == NULL)
       
   528     return NW_STAT_OUT_OF_MEMORY;
       
   529 
       
   530   e = (NW_Ucs2) entity;
       
   531   s[0] = e;
       
   532   s[1] = 0;
       
   533 
       
   534   status = NW_String_ucs2CharToString(str, s, encoding);
       
   535   NW_Mem_Free(s);
       
   536 
       
   537   return status;
       
   538 }
       
   539 
       
   540 
       
   541 NW_Status_t 
       
   542 NW_String_byteToString(NW_Byte *s, NW_String_t *str, NW_Uint32 encoding)
       
   543 {
       
   544   return NW_String_initialize(str, s, encoding);
       
   545 }
       
   546 
       
   547 EXPORT_C NW_Status_t 
       
   548 NW_String_tokenToString(NW_Uint32 token, NW_String_t *str, NW_Uint32 encoding)
       
   549 {
       
   550   NW_String_UCS2Buff_t *t;
       
   551 
       
   552   /* Get the tag from the dictionary */
       
   553   if ((t = NW_WBXML_Dictionary_getTagByFqToken (token)) == NULL)
       
   554     /* 
       
   555      * This can happen if the token is not defined or if the dictonary 
       
   556       for this token's codepage is not defined.  So, make a string 
       
   557      *from the token.
       
   558      */
       
   559     return NW_STAT_FAILURE;
       
   560 
       
   561   return NW_String_UCS2BuffToString(t, str, encoding);
       
   562 }
       
   563 
       
   564 
       
   565 /*
       
   566  * String manipulation functions
       
   567  */
       
   568 
       
   569 /* Duplicates storage 
       
   570  * Returns
       
   571  *  NW_STAT_BAD_INPUT_PARAM
       
   572  *  NW_STAT_OUT_OF_MEMORY
       
   573  *  NW_STAT_SUCCESS
       
   574  */
       
   575 NW_Status_t 
       
   576 NW_String_copy(NW_String_t *dest, NW_String_t *source)
       
   577 {
       
   578 
       
   579   NW_ASSERT(dest != NULL);
       
   580   NW_ASSERT(source != NULL);
       
   581 
       
   582   if (!NW_String_getUserOwnsStorage(source))
       
   583     return NW_String_shallowCopy(dest, source);
       
   584 
       
   585   return NW_String_deepCopy(dest, source);
       
   586 }
       
   587 
       
   588 EXPORT_C NW_Status_t
       
   589 NW_String_shallowCopy(NW_String_t *dest, NW_String_t *source)
       
   590 {
       
   591 
       
   592   NW_ASSERT(dest != NULL);
       
   593   NW_ASSERT(source != NULL);
       
   594 
       
   595   dest->storage = source->storage;
       
   596   dest->length = source->length;
       
   597   return NW_STAT_SUCCESS;
       
   598 }
       
   599 
       
   600 EXPORT_C NW_Status_t
       
   601 NW_String_deepCopy(NW_String_t *dest, NW_String_t *source)
       
   602 {
       
   603   NW_Uint32 len;
       
   604  
       
   605   NW_ASSERT(dest != NULL);
       
   606   NW_ASSERT(source != NULL);
       
   607 
       
   608   len = NW_String_getByteCount(source);
       
   609 
       
   610   dest->storage = (NW_Byte *) NW_Mem_Malloc (len);
       
   611 
       
   612   if (dest->storage == NULL){
       
   613     return NW_STAT_OUT_OF_MEMORY;
       
   614   }
       
   615   NW_Mem_memcpy(dest->storage, source->storage, len);
       
   616   dest->length = len;
       
   617   /* Since we allocated the new storage, we own it */
       
   618   NW_String_setUserOwnsStorage(dest);
       
   619   return NW_STAT_SUCCESS;
       
   620 }
       
   621 
       
   622 EXPORT_C NW_Status_t
       
   623 NW_String_concatenate(NW_String_t *dest, NW_String_t *source, NW_Uint32 encoding)
       
   624 {
       
   625   NW_Byte *storage = NULL;
       
   626   NW_Uint32 destLength = 0;
       
   627   NW_Uint32 sourceLength = 0;
       
   628  
       
   629   NW_ASSERT(dest != NULL);
       
   630   NW_ASSERT(source != NULL);
       
   631   NW_ASSERT(source->storage != NULL); 
       
   632   
       
   633   destLength = NW_String_getByteCount(dest);
       
   634   sourceLength = NW_String_getByteCount(source);
       
   635   NW_ASSERT(sourceLength != 0);
       
   636 
       
   637   /* get rid of the tailing NULL from dest string, in case of ucs2, 
       
   638      two bytes need to be removed. */
       
   639   if ( (encoding == HTTP_iso_10646_ucs_2) &&
       
   640       (destLength > 1) &&
       
   641       (dest->storage[(destLength-1)] == 0) && 
       
   642       (dest->storage[ (destLength-2) ] == 0) ) 
       
   643   {
       
   644     destLength--;
       
   645     destLength--;
       
   646   }
       
   647   else if ((encoding == HTTP_utf_8) ||
       
   648            (encoding == HTTP_us_ascii) ||
       
   649            (encoding == HTTP_iso_8859_1)) 
       
   650   {
       
   651     if ( (destLength > 0) && (dest->storage[destLength-1] == 0) ) {
       
   652       destLength--;
       
   653     }
       
   654   }
       
   655    
       
   656   storage = (NW_Byte*) NW_Mem_Malloc (destLength +sourceLength);
       
   657   if (storage == NULL)
       
   658     return NW_STAT_OUT_OF_MEMORY;
       
   659 
       
   660   if ((dest->storage != NULL) && (destLength > 0))
       
   661   {
       
   662     NW_Mem_memcpy(storage, dest->storage, destLength);
       
   663     NW_Mem_memcpy(storage + destLength, source->storage, sourceLength);
       
   664   }
       
   665   else
       
   666   {
       
   667     NW_Mem_memcpy(storage, source->storage, sourceLength);
       
   668   }
       
   669   NW_String_deleteStorage(dest);
       
   670   dest->storage = storage;
       
   671   dest->length = destLength +sourceLength;
       
   672   /* Since we allocated the new storage, we own it */
       
   673   NW_String_setUserOwnsStorage(dest);
       
   674   return NW_STAT_SUCCESS;
       
   675 }
       
   676 
       
   677 NW_Byte *
       
   678 NW_String_findChar(NW_String_t *string, NW_Int32 character, NW_Uint32 encoding)
       
   679 {
       
   680   NW_Byte *storage;
       
   681   NW_Uint32 length;
       
   682   NW_Uint32 index, numbytes;
       
   683   NW_Ucs2 c;
       
   684 
       
   685   if (string == NULL)
       
   686     return NULL;
       
   687 
       
   688   length  = NW_String_getCharCount(string, encoding);
       
   689   storage = string->storage;
       
   690 
       
   691   for (index= 0; index<length; index++)
       
   692   {
       
   693     /* read UCS2 character and advance pointer */
       
   694     numbytes = NW_String_readChar(storage, &c, encoding);
       
   695     if (c == character) {
       
   696       return storage;
       
   697     }
       
   698     storage += numbytes;
       
   699   }
       
   700 
       
   701   return NULL;  
       
   702 }
       
   703 
       
   704 
       
   705 /*
       
   706  * Functions
       
   707  */
       
   708 
       
   709 /*
       
   710 * IN - No of characters 
       
   711 */
       
   712 NW_Status_t 
       
   713 NW_String_ucs2CharInit(NW_Ucs2 **data, NW_Uint32 length)
       
   714 {
       
   715   NW_ASSERT(data != NULL);
       
   716 
       
   717   if ((*data = (NW_Ucs2*) NW_Mem_Malloc (length *sizeof(NW_Ucs2))) == NULL) {
       
   718     return NW_STAT_OUT_OF_MEMORY;  
       
   719   }
       
   720 
       
   721   return NW_STAT_SUCCESS;
       
   722 }
       
   723 
       
   724 EXPORT_C NW_Int32 
       
   725 NW_String_ucs2CharLength (NW_Ucs2 *data)
       
   726 {
       
   727   NW_Int32 length = 0;
       
   728 
       
   729   if (data == NULL)
       
   730     return -1;
       
   731 
       
   732   while(*data != 0)
       
   733   {
       
   734     length++;
       
   735     data++;
       
   736   }
       
   737   return length;
       
   738 }
       
   739 /*
       
   740  * Given an arbitrary NW_Byte array with no known character encoding, 
       
   741  * convert it to a NW_Ucs2 string.
       
   742  * 
       
   743  */
       
   744 EXPORT_C NW_Status_t
       
   745 NW_String_byteToUCS2Char (NW_Byte * b, NW_Uint32 length, NW_Ucs2 **data)
       
   746 {
       
   747   NW_Status_t status;
       
   748   NW_Byte *p = b;
       
   749   NW_Uint32 i = 0;
       
   750 
       
   751   NW_ASSERT(length != 0);
       
   752   NW_ASSERT(b != NULL);
       
   753 
       
   754   /*Need an extra NW_Byte for the null-terminator */
       
   755   status = NW_String_ucs2CharInit(data, length + 1);
       
   756   if (status != NW_STAT_SUCCESS)
       
   757     return status;
       
   758 
       
   759   for (i = 0; i < length; i++, p++)
       
   760   {
       
   761     (*data)[i] = *p;
       
   762   }
       
   763 
       
   764   /* Null-terminate the string */
       
   765   (*data)[length] = '\000';
       
   766 
       
   767   return NW_STAT_SUCCESS;
       
   768 }
       
   769 
       
   770 
       
   771 EXPORT_C NW_Status_t
       
   772 NW_String_entityToUCS2Char(NW_Uint32 entity, NW_Ucs2 **data)
       
   773 {
       
   774   NW_Status_t status;
       
   775 
       
   776   NW_ASSERT(data != NULL);
       
   777 
       
   778   status = NW_String_ucs2CharInit(data, 2);
       
   779   if (status != NW_STAT_SUCCESS)
       
   780     return status;
       
   781 
       
   782   (*data)[0] = (NW_Ucs2)entity;
       
   783   (*data)[1] = 0;
       
   784 
       
   785   return NW_STAT_SUCCESS;
       
   786 }
       
   787 
       
   788 /*
       
   789 NW_Status_t 
       
   790 NW_String_tokenToUCS2Char(NW_Uint32 token, NW_Ucs2 **data)
       
   791 {
       
   792   NW_String_UCS2Buff_t *t;
       
   793 
       
   794   // Get the tag from the dictionary 
       
   795   if ((t = NW_WBXML_Dictionary_getTagByFqToken (token)) == NULL)
       
   796      
       
   797      // This can happen if the token is not defined or if the dictonary 
       
   798      //for this token's codepage is not defined.  So, make a string 
       
   799      //from the token.
       
   800      //
       
   801     return NW_STAT_FAILURE;
       
   802 
       
   803   return NW_String_UCS2BuffToUCS2Char(t, data);
       
   804 }
       
   805 */
       
   806 
       
   807 EXPORT_C NW_Status_t 
       
   808 NW_String_stringToUCS2Char(const NW_String_t* string, 
       
   809                            NW_Uint32 encoding, 
       
   810                            NW_Ucs2 **data)
       
   811 {
       
   812   NW_Uint32 i;
       
   813   NW_Int32 numChars;
       
   814   NW_Ucs2 c = 1;
       
   815   NW_Uint32 count = 0;
       
   816   NW_Byte *b = string->storage;
       
   817   NW_Status_t status;
       
   818   NW_Int32 retval = 0;
       
   819   NW_Uint32 numBytes = 0;
       
   820 
       
   821   if (b == NULL)
       
   822   {
       
   823     *data = NULL;
       
   824   }
       
   825   else
       
   826   {
       
   827     numChars = NW_String_charBuffGetLength(b, encoding, &numBytes);
       
   828     if(numChars < 0){
       
   829       return NW_STAT_FAILURE;
       
   830     }
       
   831 
       
   832     /* allocate the memory and point to it with *data */
       
   833     status = NW_String_ucs2CharInit(data, (NW_Uint32)numChars+1);
       
   834 
       
   835     if (status != NW_STAT_SUCCESS){
       
   836       return status;
       
   837     }
       
   838 
       
   839     /* copy the characters out of string->storage onto *data */
       
   840     for (i=0; c != 0; i++) {
       
   841       retval = NW_String_readChar((NW_Byte *) b + count, &c, encoding);
       
   842       if(retval < 0){
       
   843         NW_Mem_Free( *data );
       
   844 	*data = NULL;
       
   845         return NW_STAT_FAILURE;
       
   846       }
       
   847       count += (NW_Uint32)retval;
       
   848       (*data)[i] = c;
       
   849     }
       
   850 
       
   851     /* finally null terminate the string storage */
       
   852     (*data)[numChars] = 0;
       
   853   }
       
   854   return NW_STAT_SUCCESS;
       
   855 }
       
   856 /*
       
   857 NW_Status_t 
       
   858 NW_String_UCS2BuffToUCS2Char(NW_String_UCS2Buff_t *buff, NW_Ucs2 **data)
       
   859 {
       
   860   NW_Int32 numChars = 0;
       
   861   NW_Uint32 count;
       
   862   NW_Status_t status;
       
   863 
       
   864   NW_ASSERT(buff != NULL);  
       
   865   NW_ASSERT(data != NULL);
       
   866 
       
   867   numChars = NW_String_charBuffGetLength(buff, HTTP_iso_10646_ucs_2, &count);
       
   868   if (numChars < 0) {
       
   869     return NW_STAT_FAILURE;
       
   870   }
       
   871   // Create the storage and copy the bytes 
       
   872   status = NW_String_ucs2CharInit(data, (NW_Uint32)numChars+1);
       
   873   if (status != NW_STAT_SUCCESS) {
       
   874     return status;
       
   875   }
       
   876   (void)NW_Mem_memcpy(*data, buff, (NW_Uint32) numChars * sizeof(NW_Ucs2));
       
   877   (*data)[numChars] = 0;
       
   878 
       
   879   return NW_STAT_SUCCESS;
       
   880 }
       
   881 */