GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

GATString.c

Go to the documentation of this file.
00001 /** @file GATString.c
00002  * Source file for the GATString class.
00003  * 
00004  * A GATString represents a string of characters.
00005  * 
00006  * @date $Date: 2004/04/02 12:31:58 $
00007  * 
00008  * @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATString.c,v 1.22 2004/04/02 12:31:58 hartmutkaiser Exp $
00009  *
00010  *  Copyright (C) Kelly Davis
00011  *  This file is part of the GAT Engine.
00012  *  Contributed by Kelly Davis <kdavis@aei.mpg.de>.
00013  *
00014  *  Use, modification and distribution is subject to the Gridlab Software
00015  *  License. (See accompanying file GLlicense.txt or copy at
00016  *  http://www.gridlab.org/GLlicense.txt)
00017  */
00018  
00019  static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATString.c,v 1.22 2004/04/02 12:31:58 hartmutkaiser Exp $";
00020  
00021 /* System Header Files */
00022 
00023 #include <math.h>
00024 #include <stdio.h>
00025 #include <limits.h>
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include <errno.h>
00029 
00030 /* GAT Header Files */
00031 
00032 #include "GATType.h"
00033 #include "GATString.h"
00034 #include "GATErrors.h"
00035 #include "GATInternal.h"
00036 #include "GATXdsWrapper.h"
00037 
00038 /* Header Files of Libraries Shipped with GAT */
00039 
00040 #include <iconv.h>
00041 
00042 /* Macros */
00043 
00044 /* Length chosen at random */
00045 #define GATSTRING_BUFFER_LENGTH 1024
00046 
00047 /* See RFC 2278: IANA Charset  Registration Procedures. */
00048 #define GATSTRING_MAX_ENCODING_LENGTH 41
00049 
00050 /* Structures, unions and enums */
00051 
00052 /* define the vtable types */
00053 GATOBJECT_DEFINE_VTABLE(GATString);
00054 GATSERIALISABLE_DEFINE_VTABLE(GATString);
00055 
00056 /* Declare the converters to/from GATObject */
00057 GATOBJECT_DEFINE_CONVERTERS(GATString);
00058 
00059 struct GATString_S
00060 {  
00061   GATString_vtable *GATObject__vtable;
00062   GATString_ISerialisable_vtable *GATSerialisable__vtable;
00063   
00064   char *byteArray;
00065   GATuint32 lengthInBytes;
00066   char encoding[GATSTRING_MAX_ENCODING_LENGTH];
00067 };
00068 
00069 /* Static function prototypes */
00070 
00071 /* File scope variables */
00072 static GATString_vtable GATString__vtable = {
00073   GATString_GetType,
00074   GATString_Destroy,
00075   GATString_Equals,
00076   GATString_Clone,
00077   GATString_GetInterface,
00078   NULL
00079 };
00080 
00081 static GATString_ISerialisable_vtable GATString_ISerialisable__vtable = {
00082   GATString_Serialise,
00083   GATString_DeSerialise,
00084   GATString_GetIsDirty
00085 };
00086 
00087 /* External functions */
00088 
00089 /** GATString_Register_GATSerialisable
00090  *  The GATString_Register_GATSerialisable function registers the serialization
00091  *  vtable with the GAT engine to allow generic object creation.
00092  *  This function is called by the GAT engine, there is no need to use it 
00093  *  directly.
00094  */
00095 GATResult GATString_Register_GATSerialisable()
00096 {
00097   return GATObject_Register_GATSerialisable(GATType_GATString, 
00098     &GATString_ISerialisable__vtable);
00099 }
00100 
00101 /**
00102  * <p>
00103  * This function creates a new #GATString instance. This function constructs a new
00104  * #GATString by decoding the specified array of  bytes, @c byteArray, using the
00105  * specified encoding, @c encoding. The number of charaters in the new #GATString 
00106  * is a function of the encoding, and hence may not be equal to the length of the 
00107  * byte array, @c byteArray.
00108  * </p>
00109  * <p>
00110  * The @c encoding passed to this function is a array of bytes which represents
00111  * the name of the encoding in which the byte array @c byteArray is encoded. The
00112  * encoding itself is encoded using the encoding @c ASCII. The supported encodings
00113  * are as follows:
00114  * </p>
00115  * <p>
00116  * @htmlonly
00117  * <table width="100%" border=0 rules="none" frame="void"
00118  *        cols="2" cellspacing="0" cellpadding="0">
00119  * <tr valign="top" align="left">
00120  * <td width="10%"></td><td width="90%">
00121  * European languages</td></table>
00122  * 
00123  * <table width="100%" border=0 rules="none" frame="void"
00124  *        cols="2" cellspacing="0" cellpadding="0">
00125  * <tr valign="top" align="left">
00126  * <td width="21%"></td><td width="79%">
00127  * ASCII, ISO-8859-{1,2,3,4,5,7,9,10,13,14,15,16}, KOI8-R,
00128  * KOI8-U, KOI8-RU, CP{1250,1251,1252,1253,1254,1257},
00129  * CP{850,866},
00130  * Mac{Roman,CentralEurope,Iceland,Croatian,Romania},
00131  * Mac{Cyrillic,Ukraine,Greek,Turkish}, Macintosh</td></table>
00132  * 
00133  * <table width="100%" border=0 rules="none" frame="void"
00134  *        cols="2" cellspacing="0" cellpadding="0">
00135  * <tr valign="top" align="left">
00136  * <td width="10%"></td><td width="90%">
00137  * Semitic languages</td></table>
00138  * 
00139  * <table width="100%" border=0 rules="none" frame="void"
00140  *        cols="2" cellspacing="0" cellpadding="0">
00141  * <tr valign="top" align="left">
00142  * <td width="21%"></td><td width="79%">
00143  * ISO-8859-{6,8}, CP{1255,1256}, CP862,
00144  * Mac{Hebrew,Arabic}</td></table>
00145  * 
00146  * <table width="100%" border=0 rules="none" frame="void"
00147  *        cols="2" cellspacing="0" cellpadding="0">
00148  * <tr valign="top" align="left">
00149  * <td width="10%"></td><td width="90%">
00150  * Japanese</td></table>
00151  * 
00152  * <table width="100%" border=0 rules="none" frame="void"
00153  *        cols="2" cellspacing="0" cellpadding="0">
00154  * <tr valign="top" align="left">
00155  * <td width="21%"></td><td width="79%">
00156  * EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP, ISO-2022-JP-2,
00157  * ISO-2022-JP-1</td></table>
00158  * 
00159  * <table width="100%" border=0 rules="none" frame="void"
00160  *        cols="2" cellspacing="0" cellpadding="0">
00161  * <tr valign="top" align="left">
00162  * <td width="10%"></td><td width="90%">
00163  * Chinese</td></table>
00164  * 
00165  * <table width="100%" border=0 rules="none" frame="void"
00166  *        cols="2" cellspacing="0" cellpadding="0">
00167  * <tr valign="top" align="left">
00168  * <td width="21%"></td><td width="79%">
00169  * EUC-CN, HZ, GBK, GB18030, EUC-TW, BIG5, CP950, BIG5-HKSCS,
00170  * ISO-2022-CN, ISO-2022-CN-EXT</td></table>
00171  * 
00172  * <table width="100%" border=0 rules="none" frame="void"
00173  *        cols="2" cellspacing="0" cellpadding="0">
00174  * <tr valign="top" align="left">
00175  * <td width="10%"></td><td width="90%">
00176  * Korean</td></table>
00177  * 
00178  * <table width="100%" border=0 rules="none" frame="void"
00179  *        cols="2" cellspacing="0" cellpadding="0">
00180  * <tr valign="top" align="left">
00181  * <td width="21%"></td><td width="79%">
00182  * EUC-KR, CP949, ISO-2022-KR, JOHAB</td></table>
00183  * 
00184  * <table width="100%" border=0 rules="none" frame="void"
00185  *        cols="2" cellspacing="0" cellpadding="0">
00186  * <tr valign="top" align="left">
00187  * <td width="10%"></td><td width="90%">
00188  * Armenian</td></table>
00189  * 
00190  * <table width="100%" border=0 rules="none" frame="void"
00191  *        cols="2" cellspacing="0" cellpadding="0">
00192  * <tr valign="top" align="left">
00193  * <td width="21%"></td><td width="79%">
00194  * ARMSCII-8</td></table>
00195  * 
00196  * <table width="100%" border=0 rules="none" frame="void"
00197  *        cols="2" cellspacing="0" cellpadding="0">
00198  * <tr valign="top" align="left">
00199  * <td width="10%"></td><td width="90%">
00200  * Georgian</td></table>
00201  * 
00202  * <table width="100%" border=0 rules="none" frame="void"
00203  *        cols="2" cellspacing="0" cellpadding="0">
00204  * <tr valign="top" align="left">
00205  * <td width="21%"></td><td width="79%">
00206  * Georgian-Academy, Georgian-PS</td></table>
00207  * 
00208  * <table width="100%" border=0 rules="none" frame="void"
00209  *        cols="2" cellspacing="0" cellpadding="0">
00210  * <tr valign="top" align="left">
00211  * <td width="10%"></td><td width="90%">
00212  * Tajik</td></table>
00213  * 
00214  * <table width="100%" border=0 rules="none" frame="void"
00215  *        cols="2" cellspacing="0" cellpadding="0">
00216  * <tr valign="top" align="left">
00217  * <td width="21%"></td><td width="79%">
00218  * KOI8-T</td></table>
00219  * 
00220  * <table width="100%" border=0 rules="none" frame="void"
00221  *        cols="2" cellspacing="0" cellpadding="0">
00222  * <tr valign="top" align="left">
00223  * <td width="10%"></td><td width="90%">
00224  * Thai</td></table>
00225  * 
00226  * <table width="100%" border=0 rules="none" frame="void"
00227  *        cols="2" cellspacing="0" cellpadding="0">
00228  * <tr valign="top" align="left">
00229  * <td width="21%"></td><td width="79%">
00230  * TIS-620, CP874, MacThai</td></table>
00231  * 
00232  * <table width="100%" border=0 rules="none" frame="void"
00233  *        cols="2" cellspacing="0" cellpadding="0">
00234  * <tr valign="top" align="left">
00235  * <td width="10%"></td><td width="90%">
00236  * Laotian</td></table>
00237  * 
00238  * <table width="100%" border=0 rules="none" frame="void"
00239  *        cols="2" cellspacing="0" cellpadding="0">
00240  * <tr valign="top" align="left">
00241  * <td width="21%"></td><td width="79%">
00242  * MuleLao-1, CP1133</td></table>
00243  * 
00244  * <table width="100%" border=0 rules="none" frame="void"
00245  *        cols="2" cellspacing="0" cellpadding="0">
00246  * <tr valign="top" align="left">
00247  * <td width="10%"></td><td width="90%">
00248  * Vietnamese</td></table>
00249  * 
00250  * <table width="100%" border=0 rules="none" frame="void"
00251  *        cols="2" cellspacing="0" cellpadding="0">
00252  * <tr valign="top" align="left">
00253  * <td width="21%"></td><td width="79%">
00254  * VISCII, TCVN, CP1258</td></table>
00255  * 
00256  * <table width="100%" border=0 rules="none" frame="void"
00257  *        cols="2" cellspacing="0" cellpadding="0">
00258  * <tr valign="top" align="left">
00259  * <td width="10%"></td><td width="90%">
00260  * Platform specifics</td></table>
00261  * 
00262  * <table width="100%" border=0 rules="none" frame="void"
00263  *        cols="2" cellspacing="0" cellpadding="0">
00264  * <tr valign="top" align="left">
00265  * <td width="21%"></td><td width="79%">
00266  * HP-ROMAN8, NEXTSTEP</td></table>
00267  * 
00268  * <table width="100%" border=0 rules="none" frame="void"
00269  *        cols="2" cellspacing="0" cellpadding="0">
00270  * <tr valign="top" align="left">
00271  * <td width="10%"></td><td width="90%">
00272  * Full Unicode</td></table>
00273  * 
00274  * <table width="100%" border=0 rules="none" frame="void"
00275  *        cols="2" cellspacing="0" cellpadding="0">
00276  * <tr valign="top" align="left">
00277  * <td width="21%"></td><td width="79%">
00278  * UTF-8</td></table>
00279  * 
00280  * <table width="100%" border=0 rules="none" frame="void"
00281  *        cols="2" cellspacing="0" cellpadding="0">
00282  * <tr valign="top" align="left">
00283  * <td width="21%"></td><td width="79%">
00284  * UCS-2, UCS-2BE, UCS-2LE</td></table>
00285  * 
00286  * <table width="100%" border=0 rules="none" frame="void"
00287  *        cols="2" cellspacing="0" cellpadding="0">
00288  * <tr valign="top" align="left">
00289  * <td width="21%"></td><td width="79%">
00290  * UCS-4, UCS-4BE, UCS-4LE</td></table>
00291  * 
00292  * <table width="100%" border=0 rules="none" frame="void"
00293  *        cols="2" cellspacing="0" cellpadding="0">
00294  * <tr valign="top" align="left">
00295  * <td width="21%"></td><td width="79%">
00296  * UTF-16, UTF-16BE, UTF-16LE</td></table>
00297  * 
00298  * <table width="100%" border=0 rules="none" frame="void"
00299  *        cols="2" cellspacing="0" cellpadding="0">
00300  * <tr valign="top" align="left">
00301  * <td width="21%"></td><td width="79%">
00302  * UTF-32, UTF-32BE, UTF-32LE</td></table>
00303  * 
00304  * <table width="100%" border=0 rules="none" frame="void"
00305  *        cols="2" cellspacing="0" cellpadding="0">
00306  * <tr valign="top" align="left">
00307  * <td width="21%"></td><td width="79%">
00308  * UTF-7</td></table>
00309  * 
00310  * <table width="100%" border=0 rules="none" frame="void"
00311  *        cols="2" cellspacing="0" cellpadding="0">
00312  * <tr valign="top" align="left">
00313  * <td width="21%"></td><td width="79%">
00314  * C99, JAVA</td></table>
00315  * @endhtmlonly
00316  * </p>
00317  * <p>
00318  * If the passed @c byteArray is not encoded properly in the passed encoding
00319  * or if there is a problem in allocating memory, this function returns the
00320  * value NULL.
00321  * </p>
00322  *
00323  * @param byteArray The array of bytes encoded using @c encoding.
00324  * @param lengthInBytes The number of bytes in the passed array of bytes
00325  * @param encoding The encoding used to encode the passed array of bytes
00326  * @return On success a new #GATString representing the passed data
00327  */
00328 GATString GATString_Create(const char *byteArray, GATuint32 lengthInBytes, const char *encoding)
00329 {
00330   GATString this;
00331   
00332   this = NULL;
00333   
00334   if( (NULL != byteArray) && (0 < lengthInBytes) && (NULL != encoding) )
00335   {
00336     this = (GATString) malloc( sizeof(*this) );
00337     if(NULL != this)
00338     {
00339       float charPerByte;
00340       char *tempByteArray;
00341       size_t lengthInChars;
00342       
00343       this->byteArray = NULL;
00344       this->GATObject__vtable = &GATString__vtable;
00345       this->GATSerialisable__vtable = &GATString_ISerialisable__vtable;
00346       this->lengthInBytes = lengthInBytes;
00347       
00348       strncpy( this->encoding, encoding, GATSTRING_MAX_ENCODING_LENGTH );
00349       (this->encoding)[GATSTRING_MAX_ENCODING_LENGTH - 1] = '\0'; /* Ensure encoding is null terminated */
00350       
00351       charPerByte = ( 8 / CHAR_BIT );
00352       lengthInChars = (size_t) ceil( lengthInBytes * charPerByte );
00353       tempByteArray = (char *) malloc( lengthInChars );
00354       if(NULL == tempByteArray)
00355       {
00356         GATString_Destroy( &this);
00357       }
00358       else
00359       {
00360         memcpy( (void *) tempByteArray, (const void *) byteArray, lengthInChars);
00361         this->byteArray = tempByteArray;
00362       }      
00363     }
00364   }
00365   
00366   return this;
00367 }
00368 
00369 /**
00370  * This fucntion returns the type, a #GATType, of the passed #GATString_const.
00371  * This function will always return #GATType_GATString.
00372  *
00373  * @param string The #GATString_const to query
00374  * @return The #GATType of the passed @c string
00375  */
00376 GATType GATString_GetType(GATString_const string)
00377 {
00378   GAT_UNUSED_PARAMETER(string);
00379   return GATType_GATString;
00380 }
00381 
00382 /**
00383  * <p>
00384  * This function determines if the two passed #GATString_const are equivalent.
00385  * Two #GATString_const instances are equivalent if they are both non-null and
00386  * represent the exact same sequence of characters.
00387  * </p>
00388  * <p>
00389  * If the two passed #GATString_const are equal and this function does not
00390  * encouter an error state of some sort, then the #GATBool pointed to by the
00391  * passed @c isequal parameter is set to #GATTrue. Otherwise this #GATBool
00392  * is set of #GATFalse. The completion status of this function is returned
00393  * through its return value.
00394  * </p>
00395  *
00396  * @param this The first #GATString_const to query
00397  * @param that The Second #GATString_const to query
00398  * @param isequal The query result
00399  * @return The completion status of this function
00400  */
00401 int GATString_Equals(GATString_const this, GATString_const that, GATBool *isequal)
00402 {
00403    int retval;
00404    GATuint32 count;
00405    GATString thisString;
00406    GATString thatString;
00407    GATuint32 thisArrayLength;
00408    GATuint32 thatArrayLength;
00409    
00410    retval = GAT_INVALID_PARAMETER;
00411    if( (NULL != this) && (NULL != that) && (NULL != isequal) )
00412    {
00413      (*isequal) = GATFalse;
00414      
00415      if( GAT_SUCCESS == (retval = GATString_Translate(this, "UTF-32BE", &thisString)) )
00416      {
00417        if( GAT_SUCCESS == (retval = GATString_Translate(that, "UTF-32BE", &thatString)) )
00418        {
00419          thisArrayLength = (GATuint32) (GATString_GetLengthInBytes(thisString) / 4); /* Always integral as in UTF-32BE */
00420          thatArrayLength = (GATuint32) (GATString_GetLengthInBytes(thatString) / 4); /* Always integral as in UTF-32BE */
00421          
00422          if( thisArrayLength == thatArrayLength )
00423          {
00424            GATBool equalFlag;
00425            const GATuint32 *thisArray;
00426            const GATuint32 *thatArray;
00427            
00428            equalFlag = GATTrue;
00429            thisArray = (const GATuint32 *) GATString_GetBuffer(thisString);
00430            thatArray = (const GATuint32 *) GATString_GetBuffer(thatString);
00431            
00432            for(count = 0; (count < thisArrayLength) && (GATTrue == equalFlag); count++)
00433            {
00434              if(thisArray[count] != thatArray[count])
00435              {
00436                equalFlag = GATFalse;
00437              }
00438            }
00439            
00440            if( GATTrue == equalFlag )
00441            {
00442              (*isequal) = GATTrue;
00443            }
00444          }
00445          GATString_Destroy(&thatString);
00446        }
00447        GATString_Destroy(&thisString);
00448      }
00449    }
00450    return retval;
00451 }
00452 
00453 /**
00454  * This function returns a "deep clone" of the passed #GATString_const @c string. 
00455  * This "deep clone" is returned in the variable @c stringClone. Furthermore, this 
00456  * function returns its completion status, through its return value.
00457  *
00458  * @param  string The #GATString_const to clone
00459  * @param stringClone The cloned #GATString_const
00460  * @return The completion status of this function
00461  */
00462 int GATString_Clone(GATString_const string, GATString *stringClone)
00463 {
00464   int retval;
00465   
00466   retval = GAT_INVALID_PARAMETER;
00467   if( (NULL != string) && (NULL != stringClone) )
00468   {
00469     GATuint32 length;
00470     const char *buffer;
00471     const char *encoding;
00472     
00473     (*stringClone) = NULL;
00474     
00475     retval = GAT_MEMORYFAILURE;
00476     
00477     buffer = GATString_GetBuffer(string);
00478     encoding = GATString_GetEncoding(string);
00479     length = GATString_GetLengthInBytes(string);
00480 
00481     (*stringClone) = GATString_Create(buffer, length, encoding);
00482     
00483     if( NULL != (*stringClone) )
00484     {
00485       retval = GAT_SUCCESS;
00486     }
00487   }
00488   
00489   return retval;
00490 }
00491 
00492 /**
00493  * Destroys the #GATString instance
00494  *
00495  * @param string The #GATString to destroy.
00496  */
00497 void GATString_Destroy(GATString *string)
00498 {
00499   if( (NULL !=  string) && (NULL != (*string)) )
00500   {
00501     free( (*string)->byteArray );
00502     
00503     free( (*string) );
00504     (*string) = NULL;
00505   }
00506 }
00507 
00508 /**
00509  * This function returns the length in bytes of the passed #GATString_const's encoded 
00510  * buffer.
00511  *
00512  * @param string The #GATString_const to query
00513  * @return The length in bytes of #GATString_const's encoded buffer, -1 upon NULL @c string
00514  */
00515 GATuint32 GATString_GetLengthInBytes(GATString_const string)
00516 {
00517   GATuint32 lengthInBytes;
00518   
00519   lengthInBytes = -1;
00520   
00521   if(NULL != string)
00522   {
00523     lengthInBytes = string->lengthInBytes;
00524   }
00525   
00526   return lengthInBytes;
00527 }
00528 
00529 /**
00530  * This function returns the passed #GATString_const's encoded buffer.
00531  *
00532  * @param string The #GATString_const to query
00533  * @return The passed #GATString_const's encoded buffer, NULL upon NULL @c string
00534  */
00535 const char * GATString_GetBuffer(GATString_const string)
00536 {
00537   const char *buffer;
00538   
00539   buffer = NULL;
00540   
00541   if(NULL != string)
00542   {
00543     buffer = string->byteArray;
00544   }
00545   
00546   return buffer;
00547 }
00548 
00549 /**
00550  * This fucntion return the passed #GATString_const's encoding, itself encoded in ASCII.
00551  *
00552  * @param string The #GATString_const to query
00553  * @return The passed #GATString_const's encoding, itself encoded in ASCII, NULL upon NULL @c string
00554  */
00555 const char * GATString_GetEncoding(GATString_const string)
00556 {
00557   const char *encoding;
00558   
00559   encoding = NULL;
00560   
00561   if(NULL != string)
00562   {
00563     encoding = string->encoding;
00564   }
00565   
00566   return encoding;
00567 }
00568 
00569 /**
00570  * <p> 
00571  * This function translates the passed #GATString_const, @c string, from its 
00572  * encoding to the encoding, @c encoding. The result is returned in @c result. 
00573  * </p>
00574  * <p>
00575  * The supported encoding which may be passed to this function are the same
00576  * set of encodings as specified by the documentation for the function
00577  * #GATString_Create. 
00578  * </p>
00579  * <p>
00580  * If an error occurs during translation, then @c result is set to NULL and
00581  * the error status is returned in this function's return value. Otherwise
00582  * the completion status of this function is returned through its return
00583  * value and @c result s set to point to the translated #GATString.
00584  * </p>
00585  *
00586  * @param string The #GATString_const to translate
00587  * @param encoding The target encoding
00588  * @param result The translated #GATString or NULL on failure
00589  * @return The completion status of this function
00590  */
00591 int GATString_Translate(GATString_const string, const char *newEncoding, GATString *result)
00592 {
00593   int retval;
00594   
00595   retval = GAT_INVALID_PARAMETER;
00596   
00597   if( (NULL != string) && (NULL != newEncoding) && (NULL != result) )
00598   {
00599     const char *oldEncoding;
00600     iconv_t conversionDescriptor;
00601     
00602     (*result) = NULL;
00603     retval = GAT_INVALID_ENCODING;
00604     oldEncoding = GATString_GetEncoding( string );
00605     conversionDescriptor = iconv_open(newEncoding, oldEncoding);
00606     if( (iconv_t)(-1) != conversionDescriptor)
00607     {
00608       GATBool isDone;
00609       char *newBuffer;
00610       char *tempNewBuffer;
00611       const char *oldBuffer;
00612       const char *tempOldBuffer;
00613       GATuint32 oldBufferLengthInBytes;
00614       GATuint32 newBufferLengthInBytes;
00615       GATuint32 tempOldBufferLengthInBytes;
00616       GATuint32 tempNewBufferLengthInBytes;
00617       
00618       isDone = GATFalse;
00619       
00620       retval = GAT_MEMORYFAILURE;
00621       
00622       oldBuffer = GATString_GetBuffer(string);
00623       oldBufferLengthInBytes = GATString_GetLengthInBytes(string);
00624       
00625       tempOldBuffer = oldBuffer;
00626       tempOldBufferLengthInBytes = oldBufferLengthInBytes;
00627       
00628       tempNewBuffer = NULL;
00629       tempNewBufferLengthInBytes = 0;
00630       
00631       newBufferLengthInBytes = (GATuint32) GATSTRING_BUFFER_LENGTH * (CHAR_BIT / 8);
00632       newBuffer = (char *) malloc( newBufferLengthInBytes * (8 / CHAR_BIT) );
00633       
00634       if(NULL != newBuffer)
00635       {
00636         size_t iconvRetVal;
00637         tempNewBuffer = newBuffer;
00638         tempNewBufferLengthInBytes = newBufferLengthInBytes;
00639         
00640         while(GATFalse == isDone)
00641         {
00642           newBuffer = tempNewBuffer;
00643           oldBuffer = tempOldBuffer;
00644           newBufferLengthInBytes = tempNewBufferLengthInBytes;
00645           oldBufferLengthInBytes = tempOldBufferLengthInBytes;
00646           
00647           iconvRetVal = (int) iconv(conversionDescriptor, &oldBuffer, (size_t *) &oldBufferLengthInBytes, &newBuffer, (size_t *) &newBufferLengthInBytes);
00648           
00649           if( ((size_t)(-1) == iconvRetVal) && (EILSEQ == errno) )
00650           {
00651             isDone = GATTrue;
00652             retval = GAT_INVALID_ENCODING;
00653           } else if( (size_t)(-1) != iconvRetVal )
00654           {
00655             isDone = GATTrue;
00656             retval = GAT_MEMORYFAILURE;
00657             (*result) = GATString_Create( tempNewBuffer, (tempNewBufferLengthInBytes - newBufferLengthInBytes), newEncoding );
00658             if( NULL != (*result) )
00659             {
00660               retval = GAT_SUCCESS;
00661             }
00662           } else if( ((size_t)(-1) == iconvRetVal) && (EINVAL == errno) )
00663           {
00664             isDone = GATTrue;
00665             retval = GAT_INCOMPLETE_ENCODING;
00666           } else if( ((size_t)(-1) == iconvRetVal) && (E2BIG == errno) )
00667           {
00668             tempNewBufferLengthInBytes = 2 * tempNewBufferLengthInBytes;
00669             if( NULL == (tempNewBuffer = (char *)realloc(tempNewBuffer, tempNewBufferLengthInBytes * (8 / CHAR_BIT))) )
00670             {
00671               isDone = GATTrue;
00672               retval = GAT_MEMORYFAILURE;
00673             }
00674           }
00675         }
00676       }
00677       
00678       free( tempNewBuffer );
00679     }
00680     
00681     iconv_close( conversionDescriptor );
00682   }
00683   
00684   return retval;
00685 }
00686 
00687 /**
00688  * <p> 
00689  * This function compares two strings lexicographically. The comparison is based
00690  * on the UTF-32BE value of each character in the strings. The character sequence
00691  * represented by @c this #GATString_const instance is compared lexicographically 
00692  * to the character sequence represented by the argument @c that #GATString_const. 
00693  * The result is a negative integer if @c this #GATString_const lexicographically 
00694  * precedes the argument @c that. The result is a  positive integer if @c this 
00695  * #GATString_const instance lexicographically follows the argument @c that. 
00696  * </p>
00697  * <p>
00698  * This is the definition of lexicographic ordering. If two strings are  different, 
00699  * then either they have different characters at some index that is a valid index 
00700  * for both strings, or their lengths are different, or both. If they have different 
00701  * characters at one or more index positions, let k be the smallest such index; then 
00702  * the string  whose character at position k has the smaller value, as  determined 
00703  * by using the < operator, lexicographically precedes the  other string. In this 
00704  * case, #GATString_CompareTo returns the  difference of the two character values at 
00705  * position k in  the two string.
00706  * </p>
00707  * <p>
00708  * If there is no index position at which they differ, then the shorter string 
00709  * lexicographically precedes the longer string. In this case, #GATString_CompareTo
00710  * returns the difference of number of bytes in the encoded lengths of the strings 
00711  * in the UTF-32BE encoding.
00712  * </p>
00713  * <p>
00714  * If any error occurs durring the processing of this function an appropriate
00715  * error code is returned through the return value of this function and the
00716  * value pointed to by @c comparrison is 0.
00717  * </p>
00718  *
00719  * @param this The first #GATString_const to compare
00720  * @param that The second #GATString_const to compare
00721  * @param comparrison The result of the comparrison or 0 on error
00722  * @return The completion status of this function
00723  */
00724 int GATString_CompareTo(GATString_const this, GATString_const that, int *comparrison)
00725 {
00726   int retval;
00727   
00728   retval = GAT_INVALID_PARAMETER;
00729   if( (NULL != this) && (NULL != that) && (NULL != comparrison) )
00730   {
00731     GATString thisString;
00732     GATString thatString;
00733     
00734     (*comparrison) = 0;
00735     if( GAT_SUCCESS == (retval = GATString_Translate(this, "UTF-32BE", &thisString)) )
00736     {
00737       if( GAT_SUCCESS == (retval = GATString_Translate(that, "UTF-32BE", &thatString)) )
00738       {
00739         GATuint32 thisLengthInBytes;
00740         GATuint32 thatLengthInBytes;
00741         
00742         retval = GAT_SUCCESS;
00743         thisLengthInBytes = GATString_GetLengthInBytes(thisString);
00744         thatLengthInBytes = GATString_GetLengthInBytes(thatString);
00745         if( thisLengthInBytes == thatLengthInBytes )
00746         {
00747           GATBool isDone;
00748           GATuint32 count;
00749           GATuint32 countMax;
00750           const GATuint32 *thisArray;
00751           const GATuint32 *thatArray;
00752           
00753           isDone = GATFalse;
00754           (*comparrison) = 0;
00755           thisArray = (const GATuint32 *) GATString_GetBuffer(thisString);
00756           thatArray = (const GATuint32 *) GATString_GetBuffer(thatString);
00757           countMax = (GATuint32) (thisLengthInBytes / 4); /* UTF-32BE implies this is an integer */
00758           for(count = 0; (count < countMax) && (GATFalse == isDone); count++)
00759           {
00760             if(thisArray[count] != thatArray[count])
00761             {
00762               isDone = GATTrue;
00763               (*comparrison) = (int) (thisArray[count] - thatArray[count]);
00764             }
00765           }
00766         }
00767         else
00768         {
00769           (*comparrison) = (int) (thisLengthInBytes - thatLengthInBytes);
00770         }
00771         
00772         GATString_Destroy( &thisString );
00773         GATString_Destroy( &thatString );
00774       }
00775       else
00776       {
00777         GATString_Destroy( &thisString );
00778       }
00779     }
00780   }
00781   
00782   return retval;
00783 }
00784 
00785 /**
00786  * <p> 
00787  * This function determines if the passed #GATString_const @c string ends with the
00788  * passed #GATString_const @c query. If it does and no error occurs, then the #GATBool 
00789  * pointed to by @c result is set to #GATTrue. If it does not and no error occurs,
00790  * then the #GATBool pointed to by @c result is set to #GATFalse.
00791  * </p>
00792  * <p>
00793  * If there is an error, then the #GATBool pointed to by @c result is set to GATFalse
00794  * and the error is returned in this function's return value.
00795  * </p>
00796  *
00797  * @param string The #GATString_const to query
00798  * @param query The #GATString_const query string
00799  * @param result The #GATBool result of the query, queryString on error
00800  * @return The completion status of this function
00801  */
00802 int GATString_EndsWith(GATString_const string, GATString_const query, GATBool *result)
00803 {
00804   int retval;
00805   
00806   retval = GAT_INVALID_PARAMETER;
00807   
00808   if( (NULL != string) && (NULL != query) && (NULL != result) )
00809   {
00810     GATString queryString;
00811     GATString stringString;
00812     
00813     (*result) = GATFalse;
00814     if( GAT_SUCCESS == (retval =GATString_Translate(string, "UTF-32BE", &stringString)) )
00815     {
00816       if( GAT_SUCCESS == (retval =GATString_Translate(query, "UTF-32BE", &queryString)) )
00817       {
00818         GATuint32 queryLength;
00819         GATuint32 stringLength;
00820         
00821         retval = GAT_SUCCESS;
00822         queryLength = (GATuint32) (GATString_GetLengthInBytes(queryString) / 4); /* UTF-32BE implies this is an integer */
00823         stringLength = (GATuint32) (GATString_GetLengthInBytes(stringString) / 4); /* UTF-32BE implies this is an integer */
00824         
00825         if( queryLength <= stringLength )
00826         {
00827           size_t charactersToCompare;
00828           const GATuint32 *queryArray;
00829           const GATuint32 *stringArray;
00830           const void *queryComparrisonStart;
00831           const void *stringComparrisonStart;
00832         
00833           queryArray = (const GATuint32 *) GATString_GetBuffer(queryString);
00834           stringArray = (const GATuint32 *) GATString_GetBuffer(stringString);
00835           
00836           queryComparrisonStart = (const void *) queryArray;
00837           charactersToCompare = (size_t) ( (queryLength * 4) * (8 / CHAR_BIT) );
00838           stringComparrisonStart = (const void *) &( stringArray[stringLength - queryLength] );
00839           
00840           if( 0 == memcmp(stringComparrisonStart, queryComparrisonStart,  charactersToCompare) )
00841           {
00842             (*result) = GATTrue;
00843           }
00844         }
00845         
00846         GATString_Destroy( &queryString );
00847         GATString_Destroy( &stringString );
00848       }
00849       else
00850       {
00851          GATString_Destroy( &stringString );
00852       }
00853     }
00854   }
00855   
00856   return retval;
00857 }
00858 
00859 /**
00860  * <p> 
00861  * This function determines if the passed #GATString_const @c string starts with the
00862  * passed #GATString_const @c query. If it does and no error occurs, then the #GATBool 
00863  * pointed to by @c result is set to #GATTrue. If it does not and no error occurs,
00864  * then the #GATBool pointed to by @c result is set to #GATFalse.
00865  * </p>
00866  * <p>
00867  * If there is an error, then the #GATBool pointed to by @c result is set to GATFalse
00868  * and the error is returned in this function's return value.
00869  * </p>
00870  *
00871  * @param string The #GATString_const to query
00872  * @param query The #GATString_const query string
00873  * @param result The #GATBool result of the query, GATFalse on error
00874  * @return The completion status of this function
00875  */
00876 int GATString_StartsWith(GATString_const string, GATString_const query, GATBool *result)
00877 {
00878   int retval;
00879   
00880   retval = GAT_INVALID_PARAMETER;
00881   
00882   if( (NULL != string) && (NULL != query) && (NULL != result) )
00883   {
00884     GATString queryString;
00885     GATString stringString;
00886     
00887     (*result) = GATFalse;
00888     if( GAT_SUCCESS == (retval = GATString_Translate(string, "UTF-32BE", &stringString)) )
00889     {
00890       if( GAT_SUCCESS == (retval = GATString_Translate(query, "UTF-32BE", &queryString)) )
00891       {
00892         GATuint32 queryLength;
00893         GATuint32 stringLength;
00894         
00895         retval = GAT_SUCCESS;
00896         queryLength = (GATuint32) (GATString_GetLengthInBytes(queryString) / 4); /* UTF-32BE implies this is an integer */
00897         stringLength = (GATuint32) (GATString_GetLengthInBytes(stringString) / 4); /* UTF-32BE implies this is an integer */
00898         
00899         if( queryLength <= stringLength )
00900         {
00901           size_t charactersToCompare;
00902           const GATuint32 *queryArray;
00903           const GATuint32 *stringArray;
00904           const void *queryComparrisonStart;
00905           const void *stringComparrisonStart;
00906         
00907           queryArray = (const GATuint32 *) GATString_GetBuffer(queryString);
00908           stringArray = (const GATuint32 *) GATString_GetBuffer(stringString);
00909           
00910           queryComparrisonStart = (const void *) queryArray;
00911           stringComparrisonStart = (const void *) stringArray;
00912           charactersToCompare = (size_t) ( ((queryLength - 1) * 4) * (8 / CHAR_BIT) );
00913           
00914           if( 0 == memcmp(stringComparrisonStart, queryComparrisonStart,  charactersToCompare) )
00915           {
00916             (*result) = GATTrue;
00917           }
00918         }
00919         
00920         GATString_Destroy( &queryString );
00921         GATString_Destroy( &stringString );
00922       }
00923       else
00924       {
00925          GATString_Destroy( &stringString );
00926       }
00927     }
00928   }
00929   
00930   return retval;
00931 }
00932 
00933 /**
00934  * <p>
00935  * This function concatenats the passed #GATString_const @c that to the right side
00936  * of the passed #GATString_const @c this and returns the resulting #GATString by
00937  * way of the pointer @c result.
00938  * </p>
00939  * <p>
00940  * If an error occurs durring processings @c result is set to point to NULL and
00941  * the error status is returned through this function's return value.
00942  * </p>
00943  *
00944  * @param this The first #GATString_const to concatenate
00945  * @param that The second #GATString_const to concatenate
00946  * @param result The concatenation of @c this and @c that or NULL on error
00947  * @return The completion status of this function
00948  */
00949 int GATString_Concatenate(GATString_const this, GATString_const that, GATString *result)
00950 {
00951   int retval ;
00952   
00953   retval = GAT_INVALID_PARAMETER;
00954   
00955   if( (NULL != this) && (NULL != that) && (NULL != result) )
00956   {
00957     GATString thisString;
00958     GATString thatString;
00959     
00960     (*result) = NULL;
00961     if( GAT_SUCCESS == (retval =GATString_Translate(this, "UTF-32BE", &thisString)) )
00962     {
00963       if( GAT_SUCCESS == (retval =GATString_Translate(that, "UTF-32BE", &thatString)) )
00964       {
00965         GATuint32 *resultBuffer;
00966         GATuint32 thisLengthInBytes;
00967         GATuint32 thatLengthInBytes;
00968         
00969         retval = GAT_MEMORYFAILURE;
00970         thisLengthInBytes = GATString_GetLengthInBytes( thisString );
00971         thatLengthInBytes = GATString_GetLengthInBytes( thatString );
00972         
00973         resultBuffer = (GATuint32 *) malloc( (thisLengthInBytes + thatLengthInBytes - 4) * (8 / CHAR_BIT) );
00974         
00975         if(NULL != resultBuffer)
00976         {
00977           const GATuint32 *thisArray;
00978           const GATuint32 *thatArray;
00979           
00980           thisArray = (const GATuint32 *) GATString_GetBuffer( thisString );
00981           thatArray = (const GATuint32 *) GATString_GetBuffer( thatString );
00982           
00983           memcpy( (void *) resultBuffer, (const void *) thisArray, (size_t) (thisLengthInBytes - 4) * (8 / CHAR_BIT) );
00984           memcpy( (void *) &(resultBuffer[(thisLengthInBytes - 4) / 4]), (const void *) thatArray, (size_t) (thatLengthInBytes) * (8 / CHAR_BIT) );
00985           
00986           (*result) = GATString_Create( (const char *) resultBuffer, (thisLengthInBytes + thatLengthInBytes - 4), "UTF-32BE" );
00987           
00988           if(NULL != (*result) )
00989           {
00990             retval = GAT_SUCCESS;
00991           }
00992         }
00993         
00994         free(resultBuffer);
00995         GATString_Destroy( &thisString );
00996         GATString_Destroy( &thatString );
00997       }
00998       else
00999       {
01000         GATString_Destroy( &thisString );
01001       }
01002     }
01003   }
01004   
01005   return retval;
01006 }
01007 
01008 /**
01009  * <p>
01010  * This function returns the last index @c index of the passed #GATString_const @c query
01011  * in the passed @GATString_const string. If the passed #GATString_const @c string does
01012  * not contain the passed #GATString_const @c query, then @c index is set to point to a
01013  * value -1.
01014  * </p>
01015  * <p>
01016  * If an error occurs durring processing, then @c index is set to point to (GATuint32)(-1)
01017  * and the error code is returned as the return value of this function.
01018  * </p>
01019  * 
01020  * @param string The #GATString_const to examine
01021  * @param query The #GATString_const to search for
01022  * @param queryIndex The last index of @query in @string or(GATuint32)(-1)
01023  * @return The completion status of this function
01024  */
01025 int GATString_LastIndexOf(GATString_const string, GATString_const query, GATuint32 *queryIndex)
01026 {
01027   int retval;
01028   
01029   retval = GAT_INVALID_PARAMETER;
01030   
01031   if( (NULL != string) && (NULL != query) && (NULL != queryIndex) )
01032   {
01033     GATString queryString;
01034     GATString stringString;
01035     
01036     (*queryIndex) = -1;
01037     if( GAT_SUCCESS == (retval =GATString_Translate(string, "UTF-32BE", &stringString)) )
01038     {
01039       if( GAT_SUCCESS == (retval =GATString_Translate(query, "UTF-32BE", &queryString)) )
01040       {
01041         GATuint32 queryLengthInBytes;
01042         GATuint32 stringLengthInBytes;
01043         
01044         retval = GAT_INVALID_PARAMETER;
01045         queryLengthInBytes = GATString_GetLengthInBytes( queryString );
01046         stringLengthInBytes = GATString_GetLengthInBytes( stringString );
01047         
01048         if( queryLengthInBytes <= stringLengthInBytes )
01049         {
01050           GATBool isDone;
01051           GATuint32 count;
01052           GATuint32 countMaximum;
01053           size_t charsToCompare;
01054           const char *queryArray;
01055           const char *stringArray;
01056           
01057           retval = GAT_SUCCESS;
01058           queryArray = GATString_GetBuffer(queryString);
01059           stringArray = GATString_GetBuffer(stringString);
01060           
01061           isDone = GATFalse;
01062           charsToCompare = (size_t) ( (queryLengthInBytes - 4) * (8 / CHAR_BIT) );
01063           countMaximum = (GATuint32) ( ((stringLengthInBytes - queryLengthInBytes) / 4) + 1 ); 
01064           
01065           count = countMaximum;
01066           while( GATFalse == isDone )
01067           {
01068             if( 0 == memcmp( (const void *) ( stringArray + (4 * count) - 4), (const void *) queryArray, charsToCompare ) )
01069             {
01070               isDone = GATTrue;
01071               (*queryIndex) = (count - 1);
01072             }
01073             
01074             if( 1 == count )
01075             {
01076               isDone = GATTrue;
01077             }
01078             else
01079             {
01080               count = count - 1;
01081             }
01082           }
01083         }
01084         
01085         GATString_Destroy( &queryString );
01086         GATString_Destroy( &stringString );
01087       }
01088       else
01089       {
01090         GATString_Destroy( &stringString );
01091       }
01092     }
01093   }
01094   
01095   return retval;
01096 }
01097 
01098 
01099 /**
01100  * <p>
01101  * This function returns the first index @c index of the passed #GATString_const @c query
01102  * in the passed @GATString_const string. If the passed #GATString_const @c string does
01103  * not contain the passed #GATString_const @c query, then @c index is set to point to a
01104  * value -1.
01105  * </p>
01106  * <p>
01107  * If an error occurs durring processing, then @c index is set to point to (GATuint32)(-1)
01108  * and the error code is returned as the return value of this function.
01109  * </p>
01110  * 
01111  * @param string The #GATString_const to examine
01112  * @param query The #GATString_const to search for
01113  * @param index The first queryIndex of @query in @string or (GATuint32)(-1)
01114  * @return The completion status of this function
01115  */
01116 int GATString_FirstIndexOf(GATString_const string, GATString_const query, GATuint32 *queryIndex)
01117 {
01118   int retval;
01119   
01120   retval = GAT_INVALID_PARAMETER;
01121   
01122   if( (NULL != string) && (NULL != query) && (NULL != queryIndex) )
01123   {
01124     GATString queryString;
01125     GATString stringString;
01126     
01127     (*queryIndex) = -1;
01128     if( GAT_SUCCESS == (retval =GATString_Translate(string, "UTF-32BE", &stringString)) )
01129     {
01130       if( GAT_SUCCESS == (retval =GATString_Translate(query, "UTF-32BE", &queryString)) )
01131       {
01132         GATuint32 queryLengthInBytes;
01133         GATuint32 stringLengthInBytes;
01134         
01135         retval = GAT_INVALID_PARAMETER;
01136         queryLengthInBytes = GATString_GetLengthInBytes( queryString );
01137         stringLengthInBytes = GATString_GetLengthInBytes( stringString );
01138         
01139         if( queryLengthInBytes <= stringLengthInBytes )
01140         {
01141           GATBool isDone;
01142           GATuint32 count;
01143           GATuint32 countMaximum;
01144           size_t charsToCompare;
01145           const char *queryArray;
01146           const char *stringArray;
01147           
01148           retval = GAT_SUCCESS;
01149           queryArray = GATString_GetBuffer(queryString);
01150           stringArray = GATString_GetBuffer(stringString);
01151           
01152           isDone = GATFalse;
01153           charsToCompare = (size_t) ( (queryLengthInBytes - 4) * (8 / CHAR_BIT) );
01154           countMaximum = (GATuint32) ( ((stringLengthInBytes - queryLengthInBytes) / 4) + 1 ); 
01155           
01156           count = 1;
01157           while( GATFalse == isDone )
01158           {
01159             if( 0 == memcmp( (const void *) ( stringArray + (4 * count) - 4), (const void *) queryArray, charsToCompare ) )
01160             {
01161               isDone = GATTrue;
01162               (*queryIndex) = (count - 1);
01163             }
01164             
01165             if( countMaximum == count)
01166             {
01167               isDone = GATTrue;
01168             }
01169             else
01170             {
01171               count = count + 1;
01172             }
01173           }
01174         }
01175         
01176         GATString_Destroy( &queryString );
01177         GATString_Destroy( &stringString );
01178       }
01179       else
01180       {
01181         GATString_Destroy( &stringString );
01182       }
01183     }
01184   }
01185   
01186   return retval;
01187 }
01188 
01189 /**
01190  * <p>
01191  * This function creates a new #GATString which is a substring of the passed #GATString_const
01192  * @c string. The first character in this substring is the @c start charcter in @c string. 
01193  * The last charater is the charcter <code>finish - 1</code> in @c string.
01194  * </p>
01195  * <p>
01196  * If an error occurs durring processing, then @substring is set to point not to a new 
01197  * #GATString but to NULL and the appropriate error code is returned through the return
01198  * value of this function.
01199  * </p>
01200  *
01201  * @param string The #GATString_const to query
01202  * @param start The starting index, inclusive
01203  * @param finish The finishing index, exclusive
01204  * @param substring The specified substring
01205  * @return The completion status of this function
01206  */
01207 int GATString_GetSubString(GATString_const string, GATuint32 start, GATuint32 end, GATString *substring)
01208 {
01209   int retval;
01210   
01211   retval = GAT_INVALID_PARAMETER;
01212   
01213   if( (NULL != string) && (start < end) && (NULL != substring) )
01214   {
01215     GATString stringString;
01216     
01217     (*substring) = NULL;
01218     if( GAT_SUCCESS == (retval =GATString_Translate(string, "UTF-32BE", &stringString)) )
01219     {
01220       GATuint32 stringLengthInChars;
01221       GATuint32 stringLengthInBytes;
01222       
01223       retval = GAT_INVALID_PARAMETER;
01224       stringLengthInBytes = GATString_GetLengthInBytes(stringString);
01225       stringLengthInChars = (GATuint32) (stringLengthInBytes / 4);
01226       
01227       if( (start <= stringLengthInChars) && (end <= (stringLengthInChars + 1)) )
01228       {
01229         const char *stringArray;
01230         GATuint32 *substringBuffer;
01231         size_t substringLengthInChar;
01232         GATuint32 substringLengthInBytes;
01233         size_t substringLengthInCharacters;
01234         
01235         retval = GAT_MEMORYFAILURE;
01236         substringLengthInCharacters = (end - start);
01237         substringLengthInBytes = (size_t) (substringLengthInCharacters * 4);
01238         stringArray = (const char *) GATString_GetBuffer(stringString);
01239         substringLengthInChar = (size_t) ( substringLengthInBytes * (8 / CHAR_BIT) );
01240         
01241         substringBuffer = (GATuint32 *) malloc( substringLengthInChar );
01242         if( NULL != substringBuffer )
01243         {
01244           memcpy( (void *) substringBuffer, (const void *) ( stringArray + (start * 4) ), substringLengthInChar );
01245           
01246           (*substring) = GATString_Create( (const char *) substringBuffer, substringLengthInBytes, "UTF-32BE");
01247           if( NULL != (*substring) )
01248           {
01249             retval = GAT_SUCCESS;
01250           }          
01251         }
01252         free(substringBuffer);
01253       }
01254       GATString_Destroy( &stringString );
01255     }
01256   }
01257   
01258   return retval;
01259 }
01260 
01261 /** int GATString_GetInterface(GATString_const file, GATInterface iftype, void const **ifp)
01262  *  @brief Get an interface supported by a GATObject
01263  *
01264  *  The function GATString_GetInterface allows to get a pointer to an 
01265  *  additional interface supported by this GATString.
01266  *
01267  *  @param object The object to be asked for the new interface.
01268  *  @param iftype The interface the object is to be asked for.
01269  *  @param ifp The pointer, through which the result is to be returned.
01270  *
01271  *  @return An error type.
01272  */
01273 int GATString_GetInterface(GATString_const string, GATInterface iftype, void const **ifp)
01274 {
01275   int retval = GAT_INVALID_PARAMETER;
01276 
01277   if (NULL != ifp)
01278   {
01279     *ifp = NULL;
01280     if (GATInterface_ISerialisable == iftype || 
01281         GATInterface_IAdvertisable == iftype)
01282     {
01283       *ifp = (void const *) &string->GATSerialisable__vtable;
01284       retval = GAT_SUCCESS;
01285     }
01286     else
01287     {
01288       retval = GAT_NO_INTERFACE;
01289     }
01290   }
01291   return retval;
01292 }
01293 
01294 /* GATAdvertiseable API */
01295 
01296 /** int GATString_Serialise(GATString file, GATObject stream, GATBool clear_dirty)
01297  *  @brief Serialise a GATString object
01298  *
01299  *  The function GATString_Serialise serialises the given GATString object into the
01300  *  given stream. 
01301  *
01302  *  @param string The GATString object to serialise.
01303  *  @param stream The stream interface to use for the serialisation.
01304  *  @param clear_dirty If the clear_dirty parameter is set to GATTrue, the 
01305  *        internal dirty flag of this object is to be reset (no used here)
01306  *
01307  *  @return An error code.
01308  */
01309 int 
01310 GATString_Serialise(GATString string, GATObject stream, GATBool clear_dirty)
01311 {
01312   int retval = GAT_INVALID_HANDLE;
01313   if (NULL != string)
01314   {
01315     retval = GATXds_SerialiseObject(GATString_ToGATObject(string), stream, 
01316       clear_dirty, 0, "uint32 octet string",
01317       GATSTRING_VERSION1, string->byteArray, string->lengthInBytes, 
01318       string->encoding);
01319   }
01320   return retval;
01321 }
01322 
01323 /** GATString_VersionCallback
01324  *
01325  *  The function GATString_VersionCallback is used as a callback 
01326  *  function during the de-serialisation of a GATString. It should be 
01327  *  provided to test, whether the de-serialised version matches the expected 
01328  *  version.
01329  *
01330  *  @param version The version number, which was de-serialised from the stream.
01331  *
01332  *  @return This function should return GATTrue, if the version matches the 
01333  *        expected value (version is valid), GATFalse otherwise.
01334  *
01335  *  @remark This function is called from the GAT engine, there is no need to 
01336  *        call it directly.
01337  */
01338 static GATBool
01339 GATString_VersionCallback(GATuint32 version)
01340 {
01341   GATBool retval = GATFalse;
01342   if ((version & ~GATSTRING_MINOR_MASK) <= GATSTRING_LASTVERSION)
01343   {
01344     retval = GATTrue;
01345   }
01346   return retval;
01347 }
01348 
01349 /** GATString_DeSerialiseCallback
01350  *
01351  *  The function GATString_DeSerialiseCallback is used as a callback 
01352  *  function during the de-serialisation of a GATString. It should be 
01353  *  provided for the instantiation of the new GATString object based on 
01354  *  the already de-serialised data items.
01355  *
01356  *  @param context The GAT context to be used for object construction.
01357  *  @param stream The stream interface to use for the serialisation.
01358  *  @param object The pointer to the variable, which should receive the newly 
01359  *        constructed object.
01360  *  @param version The version of the saved data read from the input stream.
01361  *  @param args This parameter is the pointer to the va_list containing 
01362  *        pointers to the already de-serialised data items accordingly to the
01363  *        format string, provided during the call to the 
01364  *        GATString_DeSerialise function.
01365  *
01366  *  @return An error code.
01367  *
01368  *  @remark This function is called from the GAT engine, there is no need to 
01369  *        call it directly.
01370  */
01371 static int
01372 GATString_DeSerialiseCallback(GATContext context, GATObject stream, 
01373   GATObject *object, GATuint32 version, va_list args)
01374 {
01375   int retval = GAT_FAIL;
01376   
01377   /* the version was eaten already */
01378   char **byte_array = va_arg(args, char **);
01379   GATuint32 *byte_array_size = va_arg(args, GATuint32 *);
01380   char const **encoding = va_arg(args, char const **);
01381   
01382   /* construct the new object */
01383   GATString string = (GATString) malloc(sizeof(struct GATString_S));
01384   if (NULL == string)
01385   {
01386     retval = GAT_MEMORYFAILURE;
01387   }
01388   else
01389   {
01390     string->GATObject__vtable = &GATString__vtable;
01391     string->GATSerialisable__vtable = &GATString_ISerialisable__vtable;
01392     string->byteArray = *byte_array;
01393     string->lengthInBytes = *byte_array_size;
01394 
01395     strncpy(string->encoding, *encoding, GATSTRING_MAX_ENCODING_LENGTH);
01396     /* Ensure encoding is null terminated */
01397     (string->encoding)[GATSTRING_MAX_ENCODING_LENGTH - 1] = '\0'; 
01398     
01399     retval = GAT_SUCCESS;
01400   }
01401   
01402   if (GAT_SUCCESS == retval)
01403   {
01404     if (NULL != object)
01405     {
01406       *object = GATString_ToGATObject(string);
01407     }
01408     else
01409     {
01410       GATString_Destroy(&string);
01411       retval = GAT_INVALID_PARAMETER;
01412     }
01413   }
01414   return retval;
01415 }
01416 
01417 /** GATString GATString_DeSerialise(GATContext context, GATObject stream, GATBool clear_dirty)
01418  *  @brief De-serialise a GATString object
01419  *
01420  *  The function GATString_DeSerialise de-serialises a streamed GATString object  
01421  *  from the given stream  It constructs a new instance of the de-serialised 
01422  *  object.
01423  *
01424  *  @param context The GAT context to be used for object construction.
01425  *  @param stream The stream interface to use for the serialisation.
01426  *  @param result The pointer to a variable, which receives the status code of
01427  *        the operation.
01428  *
01429  *  @return The newly constructed GATString object.
01430  */
01431 GATString 
01432 GATString_DeSerialise(GATContext context, GATObject stream, GATResult *result)
01433 {
01434   GATObject string = NULL;     /* the new object will be created here */
01435   
01436   /* we must provide all instance data items to be de-serialised for this
01437      GATFile object accordingly to the provided format string */
01438   GATuint32 version = 0;
01439   char *byte_array = NULL;
01440   GATuint32 byte_array_size = 0;
01441   char *encoding = NULL;
01442 
01443   /* read the data */
01444   int retval = GATXds_DeSerialiseObject(context, stream, 
01445     GATString_DeSerialiseCallback, GATString_VersionCallback, &string, 
01446     "uint32 octet string", &version, &byte_array, &byte_array_size, &encoding);
01447 
01448   /* on success the ownership of the byte array was transferred to the new 
01449      object */
01450   if (GAT_SUCCESS != retval)
01451   {
01452     free(byte_array);
01453   }
01454   free(encoding);
01455 
01456   /* FIXME: GATStatus(retval); */
01457   return GATObject_ToGATString(string);
01458 }
01459 
01460 /** GATString_GetIsDirty
01461  *  
01462  *  The function GATString_GetIsDirty retrieves the status of the dirty flag of 
01463  *  this GATString object.
01464  *
01465  *  @param file The GATString object to inspect for its dirty status.
01466  *  @param isdirty The pointer to a variable, which receives the dirty status.
01467  *
01468  *  @return An error code.
01469  */
01470 int GATString_GetIsDirty(GATString_const string, GATBool *isdirty)
01471 {
01472   int retval = GAT_INVALID_HANDLE;
01473   if (NULL != string)
01474   {
01475     if (NULL != isdirty)
01476     {
01477       *isdirty = GATFalse;    /* GATString's are never dirty */
01478       retval = GAT_SUCCESS;
01479     }
01480     else
01481     {
01482       retval = GAT_INVALID_PARAMETER;
01483     }
01484   }
01485   return retval;
01486 }