GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATTable.c

Go to the documentation of this file.
00001 /** @file GATTable.c
00002  * Main file for the GATTable class.
00003  * 
00004  * The GATTable is the object used for hash tables. 
00005  * It uses a table of elements, which is an array 
00006  * of linked lists. Keys must be strings.
00007  * 
00008  * @date Tue Sep 24 2003
00009  * 
00010  * @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATTable.c,v 1.53 2004/04/02 12:31:58 hartmutkaiser Exp $
00011  *
00012  *  Copyright (C) Gavin Powell
00013  *  This file is part of the GAT Engine.
00014  *  Contributed by Gavin Powell <powell@cs.cf.ac.uk>.
00015  *
00016  *  Use, modification and distribution is subject to the Gridlab Software
00017  *  License. (See accompanying file GLlicense.txt or copy at
00018  *  http://www.gridlab.org/GLlicense.txt)
00019  */
00020  
00021 #if defined(sccs) 
00022 static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATTable.c,v 1.53 2004/04/02 12:31:58 hartmutkaiser Exp $";
00023 #endif
00024 
00025 /* system header files */
00026 
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 
00031 /* GAT header files */
00032 #include "GATInternal.h"
00033 #include "GATType.h"
00034 #include "GATTable.h"
00035 #include "GATTableAnyKey.h"
00036 #include "GATErrors.h"
00037 #include "GATXdsWrapper.h"
00038 #include "GATUtil.h"
00039 
00040 /* macros */
00041 
00042 /* structures, unions and enums */
00043 
00044 typedef struct Hash_String_S
00045 {
00046   char *data;
00047 }
00048 *Hash_String;
00049 
00050 typedef struct Hash_float_S
00051 {
00052   float data;
00053 }
00054 *Hash_float;
00055 
00056 typedef struct Hash_int_S
00057 {
00058   int32_t data;
00059 }
00060 *Hash_int;
00061 
00062 typedef struct Hash_short_S
00063 {
00064   int16_t data;
00065 }
00066 *Hash_short;
00067 
00068 typedef struct Hash_double_S
00069 {
00070   double data;
00071 }
00072 *Hash_double;
00073 
00074 typedef struct Hash_GATObject_S
00075 {
00076   GATObject data;
00077 } 
00078 *Hash_GATObject;
00079 
00080 typedef struct Hash_Element_S
00081 {
00082   GATType type;
00083   void *value;
00084   char *key;
00085   unsigned long hash;
00086   struct Hash_Element_S *next;
00087 }*Hash_Element;
00088 
00089 /* define the internal GATTable data structure */
00090 GATOBJECT_DEFINE_VTABLE(GATTable);
00091 GATSERIALISABLE_DEFINE_VTABLE(GATTable);
00092 
00093 struct GATTable_S 
00094 {
00095   /* the GATObject vtable for table object */
00096   GATTable_vtable *GATObject__vtable;
00097   /* the GATSerialisable vtable for table object */
00098   GATTable_ISerialisable_vtable *GATSerialisable__vtable;  
00099   /* genericity support */
00100   GATTable_GetKeySizeProc get_key_size;
00101   GATTable_EqualKeysProc equal_keys;
00102   GATTable_CloneKeyProc clone_key;
00103   GATTable_GetHashProc get_hash;
00104   GATTable_DestroyKeyProc destroy_key;
00105   
00106   /* instance data */
00107   GATuint32 table_length;
00108   Hash_Element *table;
00109   GATuint32 element_count;
00110   GATuint32 load_limit;
00111   GATBool isdirty;              /* dirty status (changed since last write) */
00112 };
00113 
00114 /* Declare the converters to/from GATObject */
00115 GATOBJECT_DEFINE_CONVERTERS(GATTable)
00116 
00117 /* Static function prototypes */
00118 static GATBool 
00119   GATTable_Internal_Equal_Keys(GATTable_const table, void const *key1, 
00120     const void *key2);
00121 static unsigned long 
00122   GATTable_Internal_Hash_sdbm(GATTable_const table, void const *key);
00123 static GATuint32 
00124   GATTable_Internal_Get_KeySize(GATTable_const table, void const *key);
00125 static GATResult 
00126   GATTable_Internal_CloneKey(GATTable_const table, void const *src, void **dest);
00127 static void 
00128   GATTable_Internal_Destroy_Key(GATTable_const table, void **key);
00129 
00130 static GATuint32 
00131   GATTable_Internal_Index(GATuint32 table_length, unsigned long hash_value);
00132 static GATResult 
00133   GATTable_Internal_Expand(GATTable table);
00134 static GATResult 
00135   GATTable_Internal_Add(GATTable table, const void *key, void *value, 
00136   GATType type);
00137 
00138 
00139 static GATResult 
00140 GATTable_SerialiseItems(GATTable_const list, GATXds xds,
00141   GATXdsScope flag, void **buffer, size_t *buffer_size, GATBool clear_dirty);
00142 
00143 static GATResult 
00144 GATTable_DeSerialise_Create(GATXds xds, GATuint32 table_length, 
00145   GATuint32 element_count, GATTable *table);
00146 
00147 /* default callback functions for string keys */
00148 static GATBool 
00149   GATTable_Internal_Equal_Keys_String(GATTable_const table, void const *key1, 
00150     const void *key2);
00151 static GATuint32 
00152   GATTable_Internal_Get_KeySize_String(GATTable_const table, void const *key);
00153 static GATResult 
00154   GATTable_Internal_CloneKey_String(GATTable_const table, void const *src, 
00155     void **dest);
00156 
00157 /* compiler generated vtable */
00158 static GATTable_vtable GATTable__vtable = {
00159   GATTable_GetType, 
00160   GATTable_Destroy, 
00161   GATTable_Equals, 
00162   GATTable_Clone,
00163   GATTable_GetInterface,
00164   NULL
00165 };
00166 
00167 static GATTable_ISerialisable_vtable GATTable_ISerialisable__vtable = {
00168   GATTable_Serialise,
00169   GATTable_DeSerialise,
00170   GATTable_GetIsDirty
00171 };
00172 
00173                                
00174 /* External functions */
00175 
00176 /** GATTable_Register_GATSerialisable
00177  *  The GATTable_Register_GATSerialisable function registers the serialization
00178  *  vtable with the GAT engine to allow generic object creation.
00179  *  table function is called by the GAT engine, there is no need to use it 
00180  *  directly.
00181  */
00182 GATResult GATTable_Register_GATSerialisable()
00183 {
00184   return GATObject_Register_GATSerialisable(GATType_GATTable, 
00185     &GATTable_ISerialisable__vtable);
00186 }
00187 
00188 /** GATTable_Create
00189  *  Create the GATTable object.
00190  *  This is the method used by any application code to create the GATTable
00191  *  object.
00192  *  
00193  * @param void.
00194  *
00195  * @return The GATTable object
00196  */
00197 GATTable GATTable_Create(void)
00198 {
00199   return GATTable_CreateAnyKey(GATTable_Internal_Get_KeySize_String,
00200     GATTable_Internal_Equal_Keys_String, GATTable_Internal_CloneKey_String,
00201     GATTable_Default_Hash_sdbm, GATTable_Default_Destroy_Key);
00202 } 
00203  
00204 /** GATTable_CreateAnyKey
00205  *  @brief Create the GATTable object.
00206  *
00207  *  This is the method used by any application code to create a GATTable
00208  *  object, which used the provided callback functions.
00209  *
00210  *  Note though, that objects of this type may not be used for serialisation.
00211  *  
00212  *  @param get_keysize The callback function to calculate the size of a given 
00213  *        key. This parameter must be supplied.
00214  *  @param equalkeys The callback function to compare two keys for equality. If
00215  *        this param is 0 (zero) the default callback function will be used
00216  *        (GATTable_Default_Equal_Keys).
00217  *  @param get_hash The callback function to calculate the hash value for a 
00218  *        given key. If this param is 0 (zero) the default callback function 
00219  *        will be used used (GATTable_Default_Hash_sdbm).
00220  *  @param destroy_key The callback function to destroy a key (deallocate all 
00221  *        associated memory). If this parameter is 0 (zero), the default 
00222  *        callback function will be used (GATTable_Default_Destroy_Key).
00223  *
00224  *  @return The GATTable object
00225  */
00226 GATTable GATTable_CreateAnyKey(GATTable_GetKeySizeProc get_keysize, 
00227   GATTable_EqualKeysProc equalkeys, GATTable_CloneKeyProc copykey,
00228   GATTable_GetHashProc get_hash, GATTable_DestroyKeyProc destroy_key)
00229 {
00230   GATTable table;                      /* the hash structure */
00231   GATuint32 i;                        /* counter */
00232   GATuint32 size = 1u;                /* power of 2 sizing constraint */
00233   GATuint32 minsize = 16;             /* start size of table */
00234   float const maxloadfactor = 0.75f;  /* loading for table expand */
00235   
00236   /* Enforce size as power of 2 */
00237   while (size < minsize)
00238     size <<= 1;
00239 
00240   if ((table = (GATTable) malloc(sizeof (struct GATTable_S))) != NULL)
00241   {
00242     memset(table, 0, sizeof(struct GATTable_S));
00243     table->GATObject__vtable = &GATTable__vtable;
00244     table->GATSerialisable__vtable = &GATTable_ISerialisable__vtable;
00245 
00246     table->get_key_size = get_keysize;
00247     table->equal_keys = (NULL != equalkeys) ? equalkeys : GATTable_Default_Equal_Keys;
00248     table->clone_key = (NULL != copykey) ? copykey : GATTable_Default_Clone_Key;
00249     table->get_hash = (NULL != get_hash) ? get_hash : GATTable_Default_Hash_sdbm;
00250     table->destroy_key = (NULL != destroy_key) ? destroy_key : GATTable_Default_Destroy_Key;
00251  
00252     if ((table->table 
00253        = (Hash_Element *) malloc(sizeof (Hash_Element) * size)) == NULL)
00254     {
00255       free(table);
00256       table = NULL;
00257     }
00258     else
00259     {
00260     /* initiate the table pointers */
00261       for (i = 0; i < size; i++)
00262       {
00263         table->table[i] = NULL;      
00264       }
00265 
00266       table->table_length = size;
00267       table->element_count = 0;
00268 
00269       table->load_limit = (GATuint32) ((float) size * maxloadfactor);
00270     }
00271   }
00272   return table;
00273 }
00274 
00275 /** GATTable_GetType
00276  *  Return the type of the GATTable object.
00277  *  table is the method used by any 
00278  *  application code to return the type of a given GATTable 
00279  *  object.
00280  *  
00281  * @param GATTable The table to analyze.
00282  *
00283  * @return Always returns GATType_GATTable
00284  */
00285 GATType GATTable_GetType(GATTable_const table)
00286 {
00287   GAT_UNUSED_PARAMETER(table);
00288   return GATType_GATTable;
00289 }
00290 
00291 /** GATTable_Clone
00292  *  Clone the GATTable object.
00293  *  table is the method used by any 
00294  *  application code to clone a GATTable
00295  *  object.
00296  *  
00297  * @param GATTable The table to copy.
00298  *
00299  * @return The cloned GATTable object
00300  */
00301 
00302 GATResult GATTable_Clone(GATTable_const table, GATTable *new_table)
00303 {
00304   GATTable clone;              /* the cloned hash structure */
00305   GATuint32 i;             /* counter */
00306   Hash_Element element;       /* element to copy across */
00307   GATResult result;            /* error checking */
00308   
00309   result = GAT_SUCCESS;
00310   *new_table = NULL;
00311   
00312   if ((clone = (GATTable) malloc(sizeof (struct GATTable_S))) != NULL)    /* create the table */
00313   {
00314     memset(clone, 0, sizeof(struct GATTable_S));
00315     clone->GATObject__vtable = &GATTable__vtable;
00316     clone->GATSerialisable__vtable = &GATTable_ISerialisable__vtable;
00317     clone->equal_keys = table->equal_keys;
00318     clone->get_hash = table->get_hash;
00319     clone->clone_key = table->clone_key;
00320     clone->get_key_size = table->get_key_size;
00321     clone->destroy_key = table->destroy_key;
00322     
00323     if ((clone->table 
00324        = (Hash_Element *) malloc(sizeof (Hash_Element) * table->table_length)) != NULL)
00325     {
00326       memset(clone->table, 0, sizeof (Hash_Element) * table->table_length);
00327       clone->table_length = table->table_length;
00328       clone->element_count = 0;
00329       clone->load_limit = table->load_limit;
00330       
00331       for(i=0; i<table->table_length;i++)      /* copy data across */
00332       {
00333         for(element = table->table[i];;)
00334         {
00335           if(element == NULL)
00336           {
00337             break; 
00338           }
00339           else
00340           switch(element->type)
00341           {
00342             case GATType_GATint32:
00343               result = GATTable_Add_int(clone, element->key, ((Hash_int)element->value)->data);
00344               break;
00345             case GATType_GATint16:
00346               result = GATTable_Add_short(clone, element->key, ((Hash_short)element->value)->data);
00347               break;
00348             case GATType_GATdouble64:
00349               result = GATTable_Add_double(clone, element->key, ((Hash_double)element->value)->data);
00350               break;
00351             case GATType_String:
00352               result = GATTable_Add_String(clone, element->key, ((Hash_String)element->value)->data);
00353               break;
00354             case GATType_GATfloat32:
00355               result = GATTable_Add_float(clone, element->key, ((Hash_float)element->value)->data);
00356               break;
00357             default:
00358               if (GATType_GATObject & element->type)
00359               {
00360                 result = GATTable_Add_GATObject(clone, element->key, 
00361                   ((Hash_GATObject) element->value)->data);
00362               }
00363               else
00364               {
00365                 result = GAT_KEY_TYPE_ERROR;
00366               }
00367               break;
00368           }
00369           
00370           if(result != GAT_SUCCESS)
00371           {
00372             GATTable_Destroy(&clone);
00373             clone = NULL;
00374             break;
00375           }
00376           else
00377           {
00378             element = element->next;
00379           }
00380         }  
00381         
00382         if(result != GAT_SUCCESS)
00383         {
00384           break;
00385         }
00386       }
00387     }
00388   }
00389   
00390   if (GAT_SUCCESS == result)
00391   {
00392     *new_table = clone;
00393   }
00394   
00395   return result;
00396 }
00397 
00398 /** GATTable_Equals
00399  *  @brief Compares two tables
00400  *
00401  *  The function @c GATTable_Equals compares two tables @c GATTable, 
00402  *  which hold arbitrary data.
00403  *
00404  *  @param lhs The first table to compare
00405  *  @param rhs The second table to compare
00406  *
00407  *  @return GAT_SUCCESS on equality, and GAT_FALSE otherwise. May return other
00408  *        error codes too.
00409  */
00410 GATResult 
00411 GATTable_Equals(GATTable_const lhs, GATTable_const rhs, GATBool *isequal)
00412 {
00413   GATResult result = GAT_SUCCESS;
00414 
00415   *isequal = GATFalse;
00416   if (NULL == lhs || NULL == rhs || NULL == isequal)
00417   {
00418     /* one of the parameters is 0 (zero) */
00419     result = GAT_INVALID_HANDLE;
00420   }
00421   else
00422   {
00423     if (lhs->element_count != rhs->element_count ||
00424         lhs->table_length != rhs->table_length)
00425     {
00426       /* element count is different */
00427       result = GAT_SUCCESS;
00428     }
00429     else
00430     {
00431       GATuint32 i = 0;
00432       for(/**/; i < lhs->table_length; ++i)
00433       {
00434         Hash_Element lhs_e = lhs->table[i];
00435         Hash_Element rhs_e = rhs->table[i];
00436 
00437         *isequal = GATTrue;
00438         for(/**/; NULL != lhs_e; lhs_e = lhs_e->next, rhs_e = rhs_e->next)
00439         {
00440           if (NULL == rhs_e || lhs_e->type != rhs_e->type)
00441           {
00442             break;
00443           }
00444           
00445           switch(lhs_e->type)
00446           {
00447             case GATType_GATint16:
00448               *isequal = (((Hash_short) lhs_e->value)->data == 
00449                 ((Hash_short) rhs_e->value)->data) ? GATTrue : GATFalse;
00450               break;
00451 
00452             case GATType_GATint32:
00453               *isequal = (((Hash_int) lhs_e->value)->data == 
00454                 ((Hash_int) rhs_e->value)->data) ? GATTrue : GATFalse;
00455               break;
00456 
00457             case GATType_GATfloat32:
00458               *isequal = (((Hash_float) lhs_e->value)->data == 
00459                 ((Hash_float) rhs_e->value)->data) ? GATTrue : GATFalse;
00460               break;
00461 
00462             case GATType_GATdouble64:
00463               *isequal = (((Hash_double) lhs_e->value)->data == 
00464                 ((Hash_double) rhs_e->value)->data) ? GATTrue : GATFalse;
00465               break;
00466 
00467             case GATType_String:
00468               *isequal = GATTable_Internal_Equal_Keys(lhs,
00469                 ((Hash_String) lhs_e->value)->data, 
00470                 ((Hash_String) rhs_e->value)->data);
00471               break;
00472 
00473             default:
00474               if (GATType_GATObject & lhs_e->type)
00475               {
00476                 /* we have to compare two GATObject's */
00477                 result = GATObject_Equals(((Hash_GATObject) lhs_e->value)->data, 
00478                   ((Hash_GATObject) rhs_e->value)->data, isequal);
00479               }
00480               else
00481               {
00482                 result = GAT_KEY_TYPE_ERROR;
00483               }
00484               break;
00485           }
00486 
00487           if(result != GAT_SUCCESS || GATFalse == *isequal)
00488           {
00489             break;
00490           }
00491         } /* inner for() */
00492         
00493         if(result != GAT_SUCCESS || GATFalse == *isequal)
00494         {
00495           break;
00496         }
00497       } /* outer for */
00498     }
00499   }
00500   return result;
00501 }
00502 
00503 /** GATTable_Destroy
00504  *  Destroy a hash table and free all memory.
00505  *  
00506  * @param table Pointer to the hash table.
00507  *
00508  * @return void
00509  */
00510 void GATTable_Destroy(GATTable * table)
00511 {
00512   if (NULL != table && NULL != *table) 
00513   {
00514     GATuint32 i;
00515     Hash_Element e;    /* element to free */
00516     Hash_Element f;    /* remember last element to free */
00517     Hash_Element *t = (*table)->table;
00518 
00519     for (i = 0; i < (*table)->table_length; i++)
00520     {
00521       e = t[i];
00522       while (NULL != e)
00523       {
00524         f = e;                    /* copy pointer across */
00525         e = e->next;              /* iterate list */
00526         if (f->type == GATType_String)
00527         {
00528           free(((Hash_String) f->value)->data);
00529         }
00530         else if (f->type & GATType_GATObject)
00531         {
00532           GATObject_Destroy(&((Hash_GATObject) f->value)->data);
00533         }
00534         GATTable_Internal_Destroy_Key(*table, (void **) &f->key);
00535         free(f->value);
00536         free(f);
00537       }
00538     }
00539     free((*table)->table);
00540     free(*table);
00541     *table = NULL;
00542   }
00543 }
00544 
00545 /** int GATTable_GetInterface(GATTable_const table, GATInterface iftype, void const **ifp)
00546  *  @brief Get an interface supported by a GATTable
00547  *
00548  *  The function GATTable_GetInterface allows to get a pointer to an 
00549  *  additional interface supported by table GATTable.
00550  *
00551  *  @param object The object to be asked for the new interface.
00552  *  @param iftype The interface the object is to be asked for.
00553  *  @param ifp The pointer, through which the result is to be returned.
00554  *
00555  *  @return An error type.
00556  */
00557 GATResult 
00558 GATTable_GetInterface(GATTable_const table, GATInterface iftype, void const **ifp)
00559 {
00560   GATResult retval = GAT_INVALID_PARAMETER;
00561 
00562   if (NULL != ifp && NULL != table)
00563   {
00564     *ifp = NULL;
00565     if (GATInterface_ISerialisable == iftype)
00566     {
00567       *ifp = (void const *) &table->GATSerialisable__vtable;
00568       retval = GAT_SUCCESS;
00569     }
00570     else
00571     {
00572       retval = GAT_NO_INTERFACE;
00573     }
00574   }
00575   return retval;
00576 }
00577 
00578 
00579 /* GATTable API functions */
00580 
00581 /** GATTable_Remove
00582  *  Remove a key,value pair from the hash table.
00583  *  
00584  * @param table The hash table to remove from.
00585  * @param key The the key for the key,value pair to be removed
00586  *
00587  * @return GAT error code
00588  */
00589 
00590 GATResult GATTable_Remove(GATTable table, const void *key)
00591 {
00592   Hash_Element e;            /* element to remove */
00593   Hash_Element *pE;
00594   GATResult result;
00595 
00596   GATuint32 table_index = GATTable_Internal_Index(table->table_length,
00597         GATTable_Internal_Hash_sdbm(table, key));
00598 
00599   pE = &(table->table[table_index]);
00600   e = *pE;
00601 
00602   result = GAT_KEY_NOT_FOUND;
00603   
00604   while (NULL != e)
00605   {
00606     if (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key))
00607     {
00608       table->element_count--;
00609       table->isdirty = GATTrue;
00610       *pE = e->next;
00611       
00612       if (e->type == GATType_String)
00613       {
00614         free(((Hash_String) e->value)->data);
00615       }
00616       else if (e->type & GATType_GATObject)
00617       {
00618         GATObject_Destroy(&((Hash_GATObject) e->value)->data);
00619       }
00620       
00621       GATTable_Internal_Destroy_Key(table, (void **) &e->key);
00622       free(e->value);
00623       free(e);
00624       result = GAT_SUCCESS;
00625       break;
00626     }
00627     pE = &(e->next);            /* join the list back up */
00628     e = e->next;
00629   }
00630   return result;
00631 }
00632 
00633 /** GATTable_Add_Int
00634  *  Add a type int to the hash table.
00635  *  
00636  * @param table The hash table to add the data to.
00637  * @param key The key value to associate the data to.
00638  * @param data The int data to be added
00639  *
00640  * @return GAT error code
00641  */
00642 GATResult GATTable_Add_int(GATTable table, const void *key, GATint32 data)
00643 {
00644   Hash_int p_int;        /* pointer to Hash_int struct */
00645   GATResult result;
00646 
00647   if ((p_int = (Hash_int) malloc(sizeof (struct Hash_int_S))) != NULL)
00648   {
00649     p_int->data = data;       /* data to Add */  
00650     result = GATTable_Internal_Add(table, key, p_int, GATType_GATint32);
00651     if (GAT_SUCCESS != result)
00652     {
00653       free(p_int);
00654     }
00655   }
00656   else
00657   {
00658     result = GAT_MEMORYFAILURE;
00659   }
00660 
00661   return result;
00662 }
00663 
00664 
00665 /** GATTable_Add_Short
00666  *  Add a type short to the hash table.
00667  *  
00668  * @param table The hash table to add the data to.
00669  * @param key The key value to associate the data to.
00670  * @param data The short data to be added
00671  *
00672  * @return GAT error code
00673  */
00674 GATResult GATTable_Add_short(GATTable table, const void *key, GATint16 data)
00675 {
00676   Hash_short p_short;      /* pointer to gat short struct */
00677   GATResult result;
00678 
00679   if ((p_short 
00680        = (Hash_short) malloc(sizeof (struct Hash_short_S))) != NULL)
00681   {
00682     p_short->data = data;         /* data to Add */
00683 
00684     result = GATTable_Internal_Add(table, key, p_short, GATType_GATint16);
00685     if (GAT_SUCCESS != result)
00686     {
00687       free(p_short);
00688     }
00689   }
00690   else
00691   {
00692     result = GAT_MEMORYFAILURE;
00693   }
00694   
00695   return result;
00696 
00697   
00698 }
00699 
00700 
00701 /** GATTable_Add_Double
00702  *  Add a type double to the hash table.
00703  *  
00704  * @param table The hash table to add the data to.
00705  * @param key The key value to associate the data to.
00706  * @param data The double data to be added
00707  *
00708  * @return GAT error code
00709  */
00710 GATResult GATTable_Add_double(GATTable table, const void *key, GATdouble64 data)
00711 {
00712   Hash_double p_double;     /* pointer to gat double struct */
00713   GATResult result;
00714   
00715   if ((p_double 
00716        = (Hash_double) malloc(sizeof (struct Hash_double_S))) != NULL)
00717   {
00718     p_double->data = data;        /* data to Add */
00719 
00720     result = GATTable_Internal_Add(table, key, p_double, GATType_GATdouble64);  
00721     if (GAT_SUCCESS != result)
00722     {
00723       free(p_double);
00724     }
00725   }
00726   else
00727   {
00728     result = GAT_MEMORYFAILURE;
00729   }
00730   
00731   return result;
00732 }
00733 
00734 
00735 /** GATTable_Add_Float
00736  *  Add a type float to the hash table.
00737  *  
00738  * @param table The hash table to add the data to.
00739  * @param key The key value to associate the data to.
00740  * @param data The float data to be added
00741  *
00742  * @return GAT error code
00743  */
00744 GATResult GATTable_Add_float(GATTable table, const void *key, GATfloat32 data)
00745 {
00746   Hash_float p_float;      /* pointer to Hash_float struct */
00747   GATResult result;
00748   
00749   if ((p_float 
00750        = (Hash_float) malloc(sizeof (struct Hash_float_S))) != NULL)
00751   {
00752     p_float->data = data;         /* data to Add */
00753 
00754     result = GATTable_Internal_Add(table, key, p_float, GATType_GATfloat32);
00755     if (GAT_SUCCESS != result)
00756     {
00757       free(p_float);
00758     }
00759   }
00760   else
00761   {
00762     result = GAT_MEMORYFAILURE;
00763   }
00764 
00765   return result;
00766 }
00767 
00768 
00769 /** GATTable_Add_String
00770  *  Add a type string to the hash table.
00771  *  
00772  * @param table The hash table to add the data to.
00773  * @param key The key value to associate the data to.
00774  * @param data The string data to be added
00775  *
00776  * @return GAT error code
00777  */
00778 GATResult 
00779 GATTable_Add_String(GATTable table, const void *key, const char *data)
00780 {
00781   Hash_String p_string;     /* pointer to Hash_String struct */
00782   GATResult result;
00783   
00784   if ((p_string 
00785        = (Hash_String) malloc(sizeof (struct Hash_String_S))) == NULL)
00786   {
00787     result = GAT_MEMORYFAILURE;
00788   }
00789   else
00790   if ((p_string->data 
00791        = (char *) malloc(sizeof (char) * (strlen(data)+1))) == NULL)
00792   {
00793     free(p_string);
00794     result = GAT_MEMORYFAILURE;
00795   }
00796   else
00797   {
00798     strcpy(p_string->data, data);  /* data to Add */
00799 
00800     result = GATTable_Internal_Add(table, key, p_string, GATType_String);
00801     if (GAT_SUCCESS != result)
00802     {
00803       free(p_string->data);
00804       free(p_string);
00805     }
00806   }
00807   
00808   return result;
00809 }
00810 
00811 /** GATTable_Add_GATObject
00812  *  Add a type GATObject to the hash table.
00813  *  
00814  * @param table The hash table to add the data to.
00815  * @param key The key value to associate the data to.
00816  * @param data The float data to be added
00817  *
00818  * @return GAT error code
00819  */
00820 
00821 GATResult 
00822 GATTable_Add_GATObject(GATTable table, const void *key, GATObject_const data)
00823 {
00824   Hash_GATObject p_object;        /* pointer to Hash_GATObject struct */
00825   GATResult result;
00826   
00827   if ((p_object 
00828        = (Hash_GATObject) malloc(sizeof (struct Hash_GATObject_S))) != NULL)
00829   {
00830     result = GATObject_Clone(data, &p_object->data);        /* data to Add */
00831     if (GAT_SUCCESS == result)
00832     {
00833       result = GATTable_Internal_Add(table, key, p_object, GATType_GATObject);
00834       if (GAT_SUCCESS != result)
00835       {
00836         GATObject_Destroy(&p_object->data);
00837         free(p_object);
00838       }
00839     }
00840     else
00841     {
00842       free(p_object);
00843     }
00844   }
00845   else
00846   {
00847     result = GAT_MEMORYFAILURE;
00848   }
00849 
00850   return result;
00851 }
00852 
00853 /** GATTable_Get_ElementType
00854  *  Get the type associated with a key.
00855  *  
00856  * @param table The hash table to get the type from.
00857  * @param key The key value associated with the data type.
00858  *
00859  * @return GATType
00860  */
00861 GATType GATTable_Get_ElementType(GATTable_const table, const void *key)
00862 {
00863   Hash_Element e;            /* element to get type for */
00864   unsigned long hash_value;
00865   GATuint32 table_index;
00866   GATType result;
00867 
00868   hash_value = GATTable_Internal_Hash_sdbm(table, key);
00869 
00870   table_index = GATTable_Internal_Index(table->table_length, hash_value);
00871 
00872   e = table->table[table_index];
00873 
00874   result = GATType_NoType;
00875   
00876   while (NULL != e)
00877   {
00878     if ((hash_value == e->hash) 
00879         && (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key)))
00880     {
00881       result = e->type;
00882       break;
00883     }
00884 
00885     e = e->next;
00886   }
00887   return result;
00888 }
00889 
00890 
00891 /** GATTable_GetKeys
00892  *  Get a list of all the current keys in the hash table. The key list is 
00893  *  terminated by a NULL
00894  *  
00895  * @param table The hash table to get the keys from.
00896  *
00897  * @return the list of keys
00898  */
00899 void **GATTable_GetKeys(GATTable_const table)
00900 {
00901   void **list = NULL;        /* list of keys */
00902   GATuint32 i = 0;
00903   GATuint32 key_no = 0;   /* key found counter */
00904   int retval = GAT_SUCCESS;
00905   
00906   list = (void **)malloc(sizeof(void *) * (table->element_count+1));
00907   if (NULL != list)
00908   {
00909     memset(list, 0, sizeof(void *) * (table->element_count+1));
00910     for (/**/; i < table->table_length; ++i)
00911     {
00912       if (NULL != table->table[i])
00913       {
00914         Hash_Element hold = table->table[i];
00915         
00916         retval = GAT_SUCCESS;
00917         do 
00918         {
00919           retval = GATTable_Internal_CloneKey(table, hold->key, &list[key_no++]);
00920           if (GAT_SUCCESS != retval)
00921           {
00922             break;
00923           }
00924         }
00925         while (NULL != (hold = hold->next));
00926       }
00927     }
00928     list[key_no] = NULL;  /* list terminator */
00929   }
00930   else
00931   {
00932     retval = GAT_MEMORYFAILURE;
00933   }
00934 
00935   if (GAT_SUCCESS != retval)
00936   {
00937     /* on error all the allocated memory should be free'd */
00938     for (i = 0, key_no = 0; i < table->table_length; ++i)
00939     {
00940       free(list[key_no++]);
00941     }
00942     free(list);
00943     list = NULL;
00944   }
00945   return list;
00946 }
00947 
00948 /** 
00949  *
00950  *  
00951  */
00952 void 
00953 GATTable_ReleaseKeys(GATTable_const this, void ***keys)
00954 {
00955   GAT_UNUSED_PARAMETER(this);
00956   if (NULL != keys && NULL != *keys)
00957   {
00958     GATuint32 i = 0;
00959     for (/**/; NULL != (*keys)[i]; ++i)
00960     {
00961       free((*keys)[i]);
00962     }
00963     free(*keys);
00964     *keys = NULL;
00965   }
00966 }
00967 
00968 /** GATTable_Get_Int
00969  *  Get the int type data associated with a key.
00970  *  
00971  * @param table The hash table get the data from.
00972  * @param key The key value to associate the data to.
00973  * @param data The recovered int data
00974  *
00975  * @return GAT error code
00976  */
00977 GATResult 
00978 GATTable_Get_int(GATTable_const table, const void *key, GATint32 *data)
00979 {
00980   GATResult result = GAT_INVALID_HANDLE;
00981   if (NULL != table)
00982   {
00983     Hash_Element e;            /* element to add */
00984     unsigned long hash_value;   /* has value for key */
00985     GATuint32 table_index;        /* index of hash */
00986     
00987     hash_value = GATTable_Internal_Hash_sdbm(table, key);
00988 
00989     table_index = GATTable_Internal_Index(table->table_length, hash_value);
00990 
00991     e = table->table[table_index];
00992 
00993     result = GAT_KEY_NOT_FOUND;
00994     
00995     while (NULL != e)
00996     {
00997       if ((hash_value == e->hash) 
00998           && (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key)))
00999       {
01000         if (e->type == GATType_GATint32)
01001         {
01002           if (NULL != data)
01003           {
01004             *data = ((Hash_int) e->value)->data;
01005             result = GAT_SUCCESS;
01006           }
01007           else
01008           {
01009             result = GAT_INVALID_PARAMETER;
01010           }
01011           break;
01012         }
01013         else
01014         {
01015           result = GAT_KEY_TYPE_ERROR;
01016           break;
01017         }
01018       }
01019       e = e->next;
01020     }
01021   }  
01022   return result;
01023 }
01024 
01025 /** GATTable_Get_Short
01026  *  Get the short type data associated with a key.
01027  *  
01028  * @param table The hash table get the data from.
01029  * @param key The key value to associate the data to.
01030  * @param data The recovered short data
01031  *
01032  * @return GAT error code
01033  */
01034 GATResult 
01035 GATTable_Get_short(GATTable_const table, const void *key, GATint16 *data)
01036 {
01037   GATResult result = GAT_INVALID_HANDLE;
01038   if (NULL != table)
01039   {
01040     Hash_Element e;            /* element to add */
01041     unsigned long hash_value;   /* has value for key */
01042     GATuint32 table_index;        /* index of hash */
01043     
01044     hash_value = GATTable_Internal_Hash_sdbm(table, key);
01045 
01046     table_index = GATTable_Internal_Index(table->table_length, hash_value);
01047 
01048     e = table->table[table_index];
01049 
01050     result = GAT_KEY_NOT_FOUND;
01051     
01052     while (NULL != e)
01053     {
01054       if ((hash_value == e->hash) 
01055           && (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key)))
01056       {
01057         if (e->type == GATType_GATint16)
01058         {
01059           if (NULL != data)
01060           {
01061             *data = ((Hash_short) e->value)->data;
01062             result = GAT_SUCCESS;
01063           }
01064           else
01065           {
01066             result = GAT_INVALID_PARAMETER;
01067           }
01068           break;
01069         }
01070         else
01071         {
01072           result = GAT_KEY_TYPE_ERROR;
01073           break;
01074         }
01075       }
01076       e = e->next;
01077     }
01078   }
01079   return result;
01080 }
01081 
01082 /** GATTable_Get_Double
01083  *  Get the double type data associated with a key.
01084  *  
01085  * @param table The hash table get the data from.
01086  * @param key The key value to associate the data to.
01087  * @param data The recovered double data
01088  *
01089  * @return GAT error code
01090  */
01091 GATResult 
01092 GATTable_Get_double(GATTable_const table, const void *key, double *data)
01093 {
01094   GATResult result = GAT_INVALID_HANDLE;
01095   if (NULL != table)
01096   {
01097     Hash_Element e;            /* element to add */
01098     unsigned long hash_value;   /* has value for key */
01099     GATuint32 table_index;        /* index of hash */
01100     
01101     hash_value = GATTable_Internal_Hash_sdbm(table, key);
01102 
01103     table_index = GATTable_Internal_Index(table->table_length, hash_value);
01104 
01105     e = table->table[table_index];
01106 
01107     result = GAT_KEY_NOT_FOUND;
01108     
01109     while (NULL != e)
01110     {
01111       if ((hash_value == e->hash) 
01112           && (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key)))
01113       {
01114         if (e->type == GATType_GATdouble64)
01115         {
01116           if (NULL != data)
01117           {
01118             *data = ((Hash_double) e->value)->data;
01119             result = GAT_SUCCESS;
01120           }
01121           else
01122           {
01123             result = GAT_INVALID_PARAMETER;
01124           }
01125           break;
01126         }
01127         else
01128         {
01129           result = GAT_KEY_TYPE_ERROR;
01130           break;
01131         }
01132       }
01133       e = e->next;
01134     }
01135   }
01136   return result;
01137 }
01138 
01139 /** GATTable_Get_Float
01140  *  Get the float type data associated with a key.
01141  *  
01142  * @param table The hash table get the data from.
01143  * @param key The key value to associate the data to.
01144  * @param data The recovered float data
01145  *
01146  * @return GAT error code
01147  */
01148 GATResult
01149 GATTable_Get_float(GATTable_const table, const void *key, float *data)
01150 {
01151   GATResult result = GAT_INVALID_HANDLE;
01152   if (NULL != table)
01153   {
01154     Hash_Element e;            /* element to add */
01155     unsigned long hash_value;   /* has value for key */
01156     GATuint32 table_index;        /* index of hash */
01157     
01158     hash_value = GATTable_Internal_Hash_sdbm(table, key);
01159 
01160     table_index = GATTable_Internal_Index(table->table_length, hash_value);
01161 
01162     e = table->table[table_index];
01163 
01164     result = GAT_KEY_NOT_FOUND;
01165     
01166     while (NULL != e)
01167     {
01168       if ((hash_value == e->hash) 
01169           && (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key)))
01170       {
01171         if (e->type == GATType_GATfloat32)
01172         {
01173           if (NULL != data)
01174           {
01175             *data = ((Hash_float) e->value)->data;
01176             result = GAT_SUCCESS;
01177           }
01178           else
01179           {
01180             result = GAT_INVALID_PARAMETER;
01181           }
01182           break;
01183         }
01184         else
01185         {
01186           result = GAT_KEY_TYPE_ERROR;
01187           break;
01188         }
01189       }
01190       e = e->next;
01191     }
01192   }
01193   return result;
01194 }
01195 
01196 /** GATTable_Get_String
01197  *  Get the string type data associated with a key.  
01198  *
01199  * @param table The hash table get the data from.
01200  * @param key The key value to associate the data to.
01201  * @param data The recovered string data. If table parameter is 0 (zero), the 
01202  *        function does not try to recover the data but simply returns the
01203  *        required size of the buffer needed to recover the data.
01204  * @param length length of the string buffer arg data
01205  *
01206  * @return length of string found or error code
01207  */
01208 GATResult
01209 GATTable_Get_String(GATTable_const table, const void *key, char *data,
01210   GATuint32 length)
01211 {
01212   GATResult result = GAT_INVALID_HANDLE;
01213   if (NULL != table)
01214   {
01215     Hash_Element e;            /* element to add */
01216     unsigned long hash_value;   /* has value for key */
01217     GATuint32 table_index;        /* index of hash */
01218     GATuint32 element_length;
01219     
01220     hash_value = GATTable_Internal_Hash_sdbm(table, key);
01221 
01222     table_index = GATTable_Internal_Index(table->table_length, hash_value);
01223 
01224     e = table->table[table_index];
01225 
01226     result = GAT_KEY_NOT_FOUND;
01227     
01228     while (NULL != e)
01229     {
01230       if ((hash_value == e->hash) && 
01231           (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key)))
01232       {
01233         if (e->type == GATType_String)
01234         {
01235           element_length = strlen(((Hash_String) e->value)->data);
01236           
01237           if (NULL != data) 
01238           {
01239             if (element_length >= length)      /* remember the null char */
01240             {
01241               memcpy(data, 
01242                     ((Hash_String) e->value)->data, 
01243                     (sizeof (char) * (length-1)));
01244               data[length-1] = '\0';                      /* make sure! */
01245             }
01246             else
01247             {
01248               memcpy(data, ((Hash_String) e->value)->data,
01249                     (sizeof (char) * element_length));
01250               data[element_length] = '\0';
01251             }
01252           }
01253           
01254           result = element_length;
01255           break;
01256         }
01257         else
01258         {
01259           result = GAT_KEY_TYPE_ERROR;
01260           break;
01261         }
01262       }
01263       e = e->next;
01264     }
01265   }
01266   return result;
01267 }
01268 
01269 /** GATTable_Get_GATObject
01270  *  Get the GATObject type data associated with a key.
01271  *  
01272  * @param table The hash table get the data from.
01273  * @param key The key value to associate the data to.
01274  * @param data The recovered GATObject data
01275  *
01276  * @return GAT error code
01277  */
01278 GATResult GATTable_Get_GATObject(GATTable_const table, const void *key, 
01279   GATObject_const *data)
01280 {
01281   GATResult result = GAT_INVALID_HANDLE;
01282   if (NULL != table)
01283   {
01284     Hash_Element e;             /* element to add */
01285     unsigned long hash_value;   /* has value for key */
01286     GATuint32 table_index;      /* index of hash */
01287     
01288     hash_value = GATTable_Internal_Hash_sdbm(table, key);
01289 
01290     table_index = GATTable_Internal_Index(table->table_length, hash_value);
01291 
01292     e = table->table[table_index];
01293 
01294     result = GAT_KEY_NOT_FOUND;
01295     
01296     while (NULL != e)
01297     {
01298       if ((hash_value == e->hash) && 
01299           (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key)))
01300       {
01301         if (e->type == GATType_GATObject)
01302         {
01303           if (NULL != data)
01304           {
01305             *data = ((Hash_GATObject) e->value)->data;
01306             result = GAT_SUCCESS;
01307           }
01308           else
01309           {
01310             result = GAT_INVALID_PARAMETER;
01311           }
01312           break;
01313         }
01314         else
01315         {
01316           result = GAT_KEY_TYPE_ERROR;
01317           break;
01318         }
01319       }
01320       e = e->next;
01321     }
01322   }
01323   return result;
01324 }
01325 
01326 /*  GATTable_internal_Get_GATObjectRef
01327  *  
01328  *  The functions GATTable_internal_Get_GATObjectRef allows to access a 
01329  *  GATObject stored inside a GATTable without copying it.
01330  *
01331  *  @param table The hash table get the data from.
01332  *  @param key The key value to associate the data to.
01333  *  @param data The recovered reference to the GATObject data
01334  *
01335  *  @remark This is an internal function, do not use it directly.
01336  *
01337  *  @return An error code.
01338  */
01339 GATResult 
01340 GATTable_internal_Get_GATObjectRef(GATTable_const table, const void *key, 
01341   GATObject *object)
01342 {
01343   GATResult result = GAT_INVALID_HANDLE;;
01344   if (NULL != table) 
01345   {
01346     Hash_Element e;             /* element to add */
01347     unsigned long hash_value;   /* has value for key */
01348     GATuint32 table_index;      /* index of hash */
01349     
01350     hash_value = GATTable_Internal_Hash_sdbm(table, key);
01351     table_index = GATTable_Internal_Index(table->table_length, hash_value);
01352 
01353     e = table->table[table_index];
01354 
01355     result = GAT_KEY_NOT_FOUND;
01356     
01357     while (NULL != e)
01358     {
01359       if ((hash_value == e->hash) && 
01360           (GATTrue == GATTable_Internal_Equal_Keys(table, key, e->key)))
01361       {
01362         if (e->type == GATType_GATObject)
01363         {
01364           if (NULL != object)
01365           {
01366             *object = ((Hash_GATObject) e->value)->data;
01367             result = GAT_SUCCESS;
01368           }
01369           else
01370           {
01371             result = GAT_INVALID_PARAMETER;
01372           }
01373           break;
01374         }
01375         else
01376         {
01377           result = GAT_KEY_TYPE_ERROR;
01378           break;
01379         }
01380       }
01381       e = e->next;
01382     }
01383   }
01384   return result;
01385 }
01386 
01387 
01388 /* GATAdvertiseable API */
01389 
01390 /** int GATTable_Serialise(GATTable_const table, GATObject stream, GATBool clear_dirty)
01391  *  @brief Serialise a GATTable object
01392  *
01393  *  The function GATTable_Serialise serialises the given GATTable object into 
01394  *  the given stream. 
01395  *
01396  *  @param file The GATTable object to serialise.
01397  *  @param stream The stream interface to use for the serialisation.
01398  *  @param clear_dirty If the clear_dirty parameter is set to GATTrue, the 
01399  *        internal dirty flag of table object is to be reset (no used here)
01400  *
01401  *  @return An error code.
01402  */
01403 GATResult 
01404 GATTable_Serialise(GATTable table, GATObject stream, GATBool clear_dirty)
01405 {
01406   GATResult retval = GAT_INVALID_HANDLE;
01407   if (NULL != table)
01408   {
01409     GATXds xds = NULL;
01410     void *xds_buffer = NULL;
01411     GATuint32 xds_buffer_size = 0;
01412     void *xds_item_buffer = NULL;
01413     GATuint32 xds_item_buffer_size = 0;
01414     
01415     if (GAT_SUCCESS == (retval = GATXds_Init(&xds, GATXdsType_Encode)) &&
01416         GAT_SUCCESS == (retval = GATXds_Encode(xds, GATXdsScope_Gift, 
01417           &xds_buffer, (size_t *) &xds_buffer_size, "uint32 uint32 uint32", 
01418           GATTABLE_VERSION1, table->table_length, table->element_count)) &&
01419         GAT_SUCCESS == (retval = GATTable_SerialiseItems(table, xds,
01420           GATXdsScope_Gift, &xds_item_buffer, (size_t *) &xds_item_buffer_size, 
01421           clear_dirty)))
01422     {
01423       /* write the buffer len to ease de-serialisation */
01424       void *xds_size_buffer = NULL;
01425       GATuint32 xds_size_buffer_size = 0;
01426       
01427       if (GAT_SUCCESS == (retval = GATXds_Encode(xds, GATXdsScope_Gift,
01428             &xds_size_buffer, (size_t *) &xds_size_buffer_size, "uint32", 
01429             xds_buffer_size + xds_item_buffer_size)))
01430       {
01431         assert(NULL != xds_size_buffer);
01432         retval = GATStreamable_Write(stream, xds_size_buffer, 
01433           xds_size_buffer_size, 0);
01434         if (GAT_SUCCESS == retval)
01435         {
01436           /* write the GATTable instance data */
01437           assert(NULL != xds_buffer);
01438           retval = GATStreamable_Write(stream, xds_buffer, xds_buffer_size, 0);
01439         }
01440         
01441         if (GAT_SUCCESS == retval)
01442         {
01443           /* write the GATTable item data */
01444           retval = GATStreamable_Write(stream, xds_item_buffer, 
01445             xds_item_buffer_size, 0);
01446             
01447           if (GAT_SUCCESS == retval && clear_dirty)
01448           {
01449             table->isdirty = GATFalse;   /* clear the dirty flag of table table */
01450           }
01451         }
01452       }
01453       free(xds_size_buffer);
01454     }
01455     free(xds_item_buffer);
01456     free(xds_buffer);
01457     GATXds_Destroy(&xds);
01458   }
01459   return retval;
01460 }
01461 
01462 /** GATTable GATTable_DeSerialise(GATContext context, GATObject stream, GATBool clear_dirty)
01463  *  @brief De-serialise a GATTable object
01464  *
01465  *  The function GATTable_DeSerialise de-serialises a streamed GATTable object  
01466  *  from the given stream  It constructs a new instance of the de-serialised 
01467  *  object.
01468  *
01469  *  @param context The GAT context to be used for object construction.
01470  *  @param stream The stream interface to use for the serialisation.
01471  *  @param result The pointer to a variable, which receives the status code of
01472  *        the operation.
01473  *
01474  *  @return The newly constructed GATTable object.
01475  */
01476 GATTable GATTable_DeSerialise(GATContext context, GATObject stream, 
01477   GATResult *result)
01478 {
01479   GATTable table = NULL;
01480   char buffer[64];          /* seems to be sufficient for a GATuint32 value */
01481   GATuint32 xds_read_bytes = 0;
01482   int retval = GATStreamable_Read(stream, buffer, sizeof(buffer), 
01483     &xds_read_bytes);
01484   
01485   if (GAT_SUCCESS == retval)
01486   {
01487     GATXds xds = NULL;
01488 
01489     if (GAT_SUCCESS == (retval = GATXds_InitEx(&xds, GATXdsType_Decode, context)))
01490     {
01491       GATuint32 xds_buffer_size = 0;
01492       
01493       /* read the expected size of the stream for table object */
01494       retval = GATXds_Decode(xds, GATXdsScope_Loan, buffer, 
01495         sizeof(buffer), "uint32", &xds_buffer_size);
01496       if (GAT_SUCCESS == retval)
01497       {
01498         /* reposition the input stream to start with the real object data */
01499         retval = GATStreamable_Seek(stream, GATOrigin_Current, 
01500           GATXds_GetBufferLen(xds) - xds_read_bytes, 0);
01501           
01502         if (GAT_SUCCESS == retval)
01503         {
01504           /* read the object data itself */
01505           char *xds_buffer = (char *)malloc(xds_buffer_size);
01506           if (NULL == xds_buffer)
01507           {
01508             retval = GAT_MEMORYFAILURE;
01509           }
01510           else if (GAT_SUCCESS == (retval = GATStreamable_Read(stream, 
01511               xds_buffer, xds_buffer_size, 0)))
01512           {
01513             /* read the version */
01514             GATuint32 version = 0;
01515 
01516             retval = GATXds_Decode(xds, GATXdsScope_Gift, xds_buffer, 
01517               xds_buffer_size, "uint32", &version);
01518             if (GAT_SUCCESS != retval || 
01519                 (version & ~GATTABLE_MINOR_MASK) > GATTABLE_LASTVERSION)
01520             {
01521               retval = GAT_UNKNOWN_FORMAT;
01522             }
01523             else 
01524             {
01525               /* read the data */
01526               GATuint32 table_length = 0;
01527               GATuint32 element_count = 0;
01528               
01529               retval = GATXds_Decode(xds, (GATXdsScope)0, 0, 0, "uint32 uint32", 
01530                 &table_length, &element_count);
01531               if (GAT_SUCCESS == retval)
01532               {
01533                 /* construct the new object */
01534                 retval = GATTable_DeSerialise_Create(xds, table_length, 
01535                   element_count, &table);
01536               }
01537             }
01538           }
01539         }
01540       }
01541     }
01542     GATXds_Destroy(&xds);
01543 
01544     /* FIXME: GATStatus(retval); */
01545   }
01546   
01547   if (NULL != result)
01548   {
01549     *result = retval;
01550   }
01551   return table;
01552 }
01553 
01554 /** GATTable_GetIsDirty
01555  *  
01556  *  The function GATTable_GetIsDirty retrieves the status of the dirty flag of 
01557  *  table GATTable object.
01558  *
01559  *  @param file The GATTable object to inspect for its dirty status.
01560  *  @param isdirty The pointer to a variable, which receives the dirty status.
01561  *
01562  *  @return An error code.
01563  */
01564 GATResult GATTable_GetIsDirty(GATTable_const table, GATBool *isdirty)
01565 {
01566   GATResult retval = GAT_INVALID_HANDLE;
01567   if (NULL != table)
01568   {
01569     if (NULL != isdirty)
01570     {
01571       *isdirty = table->isdirty;
01572       retval = GAT_SUCCESS;
01573     }
01574     else
01575     {
01576       retval = GAT_INVALID_PARAMETER;
01577     }
01578   }
01579   return retval;
01580 }
01581   
01582 /** GATTable_Default_Hash_sdbm
01583  *
01584  *  The function GATTable_Default_Hash_sdbm is the default callback function 
01585  *  which is used to calculate the hash value for a given key. 
01586  *  This function calculates the hash value based on the plain memory 
01587  *  representation of the key.
01588  *  
01589  *  @param table The table, for which this hash value is to be calculated.
01590  *  @param key The key to create a hash from.
01591  *
01592  *  @return the hash value
01593  */
01594 unsigned long
01595 GATTable_Default_Hash_sdbm(GATTable_const table, void const *key)
01596 {
01597   GATuint32 key_size = GATTable_Internal_Get_KeySize(table, key);
01598   unsigned long hash = 0;
01599 /*int       c   = *((int8_t *) key)++; */
01600   int8_t*   tmp = (int8_t *) key;
01601   int8_t    c   = *tmp++;
01602   GATuint32 i   = 1;
01603   
01604   for (/**/; i < key_size; ++i)
01605   {
01606     hash = c + (hash << 6) + (hash << 16) - hash;
01607     if (i < key_size)
01608     {
01609       /* c = *((int8_t *) key)++; */
01610       c   = *tmp++;
01611     }
01612   }
01613   return hash;
01614 }
01615 
01616 /** GATTable_Default_Clone_Key
01617  *
01618  *  The function GATTable_Default_Clone_Key is the default callback function 
01619  *  which is used to copy a key to a new location. 
01620  *  This function calculates copies the key with the help of the function 
01621  *  memcpy.
01622  *  
01623  *  @param table The table, into which this key is to be inserted.
01624  *  @param src The source memory area, where the key is to be copied from.
01625  *  @param dest The destination area, which receives the new key. 
01626  *
01627  *  @return A GAT error code.
01628  */
01629 GATResult
01630 GATTable_Default_Clone_Key(GATTable_const table, void const *src, void **dest)
01631 {
01632   GATuint32 key_size = GATTable_Internal_Get_KeySize(table, src);
01633   *dest = GATUtil_memdup(src, key_size);
01634   return (NULL != *dest) ? GAT_SUCCESS : GAT_MEMORYFAILURE;
01635 }
01636 
01637 /** GATTable_Default_Equal_Keys
01638  *
01639  *  The function GATTable_Default_Equal_Keys is the default callback function 
01640  *  which is used to compare two different keys of a GATTableAnyKey for 
01641  *  equality.
01642  *  This function compares the keys with the help of the function memcmp.
01643  *
01644  *  @param table The table, for which these keys are to be used.
01645  *  @param key1 first key for comparison.
01646  *  @param key2 second key for comparison.
01647  *
01648  *  @return GATTrue for equal keys, GATFalse for non equal keys
01649  */
01650 GATBool 
01651 GATTable_Default_Equal_Keys(GATTable_const table, void const *key1, 
01652   void const *key2)
01653 {
01654   GATuint32 key_size1 = GATTable_Internal_Get_KeySize(table, key1);
01655   GATuint32 key_size2 = GATTable_Internal_Get_KeySize(table, key2);
01656   GATBool retval = GATFalse;
01657   
01658   if (key_size1 == key_size2)
01659   { 
01660     retval = (0 == memcmp(key1, key2, key_size1)) ? GATTrue : GATFalse;
01661   }
01662   return retval;
01663 }
01664 
01665 /** GATTable_Default_Destroy_Key
01666  *
01667  *  The function GATTable_Default_Destroy_Key is the default callback function 
01668  *  which is used to destroy a key (deallocate all associated memory).
01669  *  This function compares free's the key with the std function free().
01670  *
01671  *  @param table The table, for which these keys are to be used.
01672  *  @param key The pointer to the key to deallocate.
01673  */
01674 void 
01675 GATTable_Default_Destroy_Key(GATTable_const table, void **key)
01676 {
01677   GAT_UNUSED_PARAMETER(table);
01678   if (NULL != key && NULL != *key)
01679   {
01680     free(*key);
01681     *key = NULL;
01682   }
01683 }
01684 
01685 /** GATTable_Size
01686  *  @brief Return the number of elements stored inside a table
01687  *
01688  *  The function @c GATTable_Size returns the number of elements, currently
01689  *  stored inside the given table.
01690  *
01691  *  @param table The table to be queried for its number of elements
01692  *
01693  *  @return If successful, the function returns number of elements. If an error 
01694  *        occures, (size_t)(-1) is returned.
01695  */
01696 GATuint32 GATTable_Size(GATTable_const table)
01697 {
01698   GATuint32 retval = (GATuint32)(-1);
01699   if (NULL != table)
01700   {
01701     retval = table->element_count;
01702   }
01703   return retval;
01704 }
01705 
01706 /* Local functions */
01707 
01708 /** GATTable_Internal_Equal_keys
01709  *  Compare the values of two hash keys.
01710  *  
01711  *  @param table The table, for which these keys are to be used.
01712  *  @param key1 first key for comparison
01713  *  @param key2 second key for comparison
01714  *
01715  *  @return GATTrue for equal keys, GATFalse for non equal keys
01716  */
01717 static GATBool 
01718 GATTable_Internal_Equal_Keys(GATTable_const table, void const *key1, 
01719   void const *key2)
01720 {
01721   return table->equal_keys(table, key1, key2);
01722 }
01723 
01724 static GATBool 
01725 GATTable_Internal_Equal_Keys_String(GATTable_const table, void const *key1, 
01726   void const *key2)
01727 {
01728   GAT_UNUSED_PARAMETER(table);
01729   return (0 == strcmp((char const *) key1, (char const *) key2)) ?
01730     GATTrue : GATFalse;
01731 }
01732 
01733 /** GATTable_Internal_Hash_sdbm
01734  *  Creates a hash from a key using sdbm.
01735  *  
01736  *  @param table The table, for which this hash value is to be calculated.
01737  *  @param key The key to create a hash from.
01738  *
01739  *  @return the hash value
01740  */
01741 static unsigned long 
01742 GATTable_Internal_Hash_sdbm(GATTable_const table, void const *key)
01743 {
01744   return table->get_hash(table, key);
01745 }
01746 
01747 /** GATTable_Internal_Get_KeySize
01748  *
01749  *  The function GATTable_Internal_Get_KeySize returns the size to be allocated 
01750  *  for the given key.
01751  *
01752  *  @param table The table, into which this key is to be inserted.
01753  *  @param key The key to calculate the size for
01754  */
01755 static GATuint32 
01756 GATTable_Internal_Get_KeySize(GATTable_const table, void const *key)
01757 {
01758   return table->get_key_size(table, key);
01759 }
01760 
01761 static GATuint32 
01762 GATTable_Internal_Get_KeySize_String(GATTable_const table, void const *key)
01763 {
01764   GAT_UNUSED_PARAMETER(table);
01765   return strlen((char const *) key) + 1;
01766 }
01767 
01768 /** GATTable_Internal_CloneKey
01769  *
01770  *  The function GATTable_Internal_CloneKey is used to copy a key.
01771  *
01772  *  @param table The table, into which this key is to be inserted.
01773  *  @param dest The destination area, where the new key is to be constructed 
01774  *        (the memory was allocated already).
01775  *  @param src The source memory area, where the key is to be copied from.
01776  *
01777  *  @return A GAT error code.
01778  */
01779 static GATResult  
01780 GATTable_Internal_CloneKey(GATTable_const table, void const *src, void **dest)
01781 {
01782   return table->clone_key(table, src, dest);
01783 }
01784 
01785 static GATResult 
01786 GATTable_Internal_CloneKey_String(GATTable_const table, void const *src, 
01787   void **dest)
01788 {
01789   GAT_UNUSED_PARAMETER(table);
01790   *dest = GATUtil_strdup((char const *)src);
01791   return (NULL != *dest) ? GAT_SUCCESS : GAT_MEMORYFAILURE;
01792 }
01793 
01794 /** GATTable_Internal_Destroy_Key
01795  *
01796  *  The function GATTable_Default_Destroy_Key is the default callback function 
01797  *  which is used to destroy a key (deallocate all associated memory).
01798  *  This function compares free's the key with the std function free().
01799  *
01800  *  @param table The table, for which these keys are to be used.
01801  *  @param key The pointer to the key to deallocate.
01802  */
01803 static void 
01804 GATTable_Internal_Destroy_Key(GATTable_const table, void **key)
01805 {
01806   table->destroy_key(table, key);
01807 }
01808 
01809 /** GATTable_Internal_Index
01810  *  Find the hash table index for a given hash value.
01811  *  The table must be of 2^n
01812  *  
01813  * @param table_length The length of the hash table.
01814  * @param hash_value The hash value that the index is required for
01815  *
01816  * @return the index for the hash value
01817  */
01818 static GATuint32 
01819 GATTable_Internal_Index(GATuint32 table_length, unsigned long hash_value)
01820 {
01821   return (hash_value & (table_length - 1u));  /* Only works if
01822                                                * tablelength == 2^N */
01823 }
01824 
01825 /** GATTable_Internal_Expand
01826  *  Expands the hash table by a 2^n+1.
01827  *  
01828  * @param table The hash table to expand.
01829  *
01830  * @return GAT error code
01831  */
01832 
01833 static GATResult 
01834 GATTable_Internal_Expand(GATTable table)
01835 {
01836   GATuint32 new_size = table->table_length << 1;
01837   GATuint32 table_index;
01838   GATResult result;
01839 
01840   /* Check table fullness */
01841   if (0 == new_size)  
01842   {
01843     result = GAT_MEMORYFAILURE;
01844   }
01845   else
01846   {
01847     Hash_Element *new_table = (Hash_Element *) realloc(table->table, 
01848       new_size * sizeof (Hash_Element));
01849     if (NULL == new_table)
01850     {
01851       result = GAT_MEMORYFAILURE; /* should new_table be free'd? */
01852     }
01853     else
01854     {
01855       GATuint32 i = table->table_length;
01856       table->table = new_table;
01857 
01858       /* clean contents */
01859       for (/**/; i < new_size; i++) 
01860       {
01861         new_table[i] = NULL;
01862       }
01863 
01864       for (i = 0; i < table->table_length; i++)  /* copy */
01865       {
01866         Hash_Element *pE;           /* pointer to a table element */
01867         Hash_Element e;             /* a table element */
01868         
01869         for (pE = &(new_table[i]), e = *pE; e != NULL; e = *pE)
01870         {
01871           table_index = GATTable_Internal_Index(new_size, e->hash);
01872 
01873           if (table_index == i)
01874           {
01875             pE = &(e->next);
01876           }
01877           else
01878           {
01879             *pE = e->next;
01880             e->next = new_table[table_index];
01881             new_table[table_index] = e;
01882           }
01883         }
01884       }
01885 
01886       table->table_length = new_size;
01887       table->load_limit <<= 1;
01888       result = GAT_SUCCESS;
01889     }
01890   }
01891   
01892   return result;
01893 }
01894 
01895 /** GATTable_Internal_Add
01896  *  Add any type to the hash table
01897  *  Uses void* as the type and the type is defined
01898  *  as a GATType
01899  *  
01900  * @param table The hash table to enter the value into.
01901  * @param key the hash key to use for adding table value
01902  * @param value the value of the data to be added
01903  * @param type the type of data to be added
01904  *
01905  * @return GAT error code
01906  */
01907 
01908 static GATResult 
01909 GATTable_Internal_Add(GATTable table, const void *key, void *value,
01910   GATType type)
01911 {
01912   GATuint32 table_index = 0;
01913   Hash_Element e = NULL;            /* element to add */
01914   GATResult result = GAT_FAIL;
01915   
01916   /* check table fullness */
01917   if ((++(table->element_count) > table->load_limit) 
01918       && (GATTable_Internal_Expand(table) == GAT_MEMORYFAILURE))
01919   {
01920     result = GAT_MEMORYFAILURE;
01921   }
01922   else
01923   if ((e = (Hash_Element) malloc(sizeof (struct Hash_Element_S))) == NULL)
01924   {
01925     result = GAT_MEMORYFAILURE;
01926   }
01927   else
01928   {
01929     /* copy data to element */
01930     memset(e, 0, sizeof(struct Hash_Element_S));
01931     e->type = type;               
01932     e->hash = GATTable_Internal_Hash_sdbm(table, key);
01933     table_index = GATTable_Internal_Index(table->table_length, e->hash);
01934 
01935     table->isdirty = GATTrue;
01936     
01937     e->value = value;
01938     e->next = NULL;
01939     
01940     result = GATTable_Internal_CloneKey(table, key, (void **) &e->key);
01941     if (GAT_SUCCESS == result)
01942     {
01943       /* chain it as index is taken */
01944       if (NULL != table->table[table_index]) 
01945       {
01946         /* get to end of list */
01947         Hash_Element hold = NULL;
01948         for (hold = table->table[table_index]; /**/; hold = hold->next) 
01949         {
01950           if (GATTrue == GATTable_Internal_Equal_Keys(table, key, hold->key))
01951           {
01952             /* table key already exists in the table */
01953             result = GAT_KEY_ALREADY_EXISTS;
01954             break;
01955           }
01956           
01957           if (NULL == hold->next)
01958           {
01959             break;
01960           }
01961         }
01962       
01963         if (GAT_SUCCESS == result)
01964         {
01965           hold->next = e;
01966         }
01967       }
01968       else
01969       {
01970         /* a free index space */
01971         table->table[table_index] = e;
01972       }
01973     }
01974   }
01975   
01976   if (GAT_SUCCESS != result)
01977   {
01978     /* error inserting an item */
01979     --table->element_count;
01980     if (NULL != e)
01981     {
01982       GATTable_Internal_Destroy_Key(table, (void **) &e->key);
01983     }
01984     free(e);
01985   }
01986   return result;
01987 }
01988 
01989 /* Serialize the items stored in the given table */
01990 static GATResult 
01991 GATTable_SerialiseItems(GATTable_const table, GATXds xds,
01992   GATXdsScope flag, void **buffer, size_t *buffer_size, GATBool clear_dirty)
01993 {
01994   GATResult retval = GAT_SUCCESS;
01995   GATuint32 i = 0;
01996   GAT_UNUSED_PARAMETER(flag);
01997   GAT_UNUSED_PARAMETER(clear_dirty);
01998   if (table->equal_keys != GATTable_Internal_Equal_Keys_String ||
01999       table->get_hash != GATTable_Default_Hash_sdbm ||
02000       table->get_key_size != GATTable_Internal_Get_KeySize_String ||
02001       table->clone_key != GATTable_Internal_CloneKey_String ||
02002       table->destroy_key != GATTable_Default_Destroy_Key)
02003   {
02004     /* serialising of GATTableAnyKey objects isn't supported yet, sorry */
02005     retval = GAT_NO_INTERFACE;
02006   }
02007   else 
02008   {
02009     for(/**/; i < table->table_length; ++i)
02010     {
02011       Hash_Element element = table->table[i];
02012 
02013       /* write the elements of table bucket */
02014       for(/**/; NULL != element; element = element->next)
02015       {
02016         retval = GATXds_Encode(xds, (GATXdsScope)0, 0, 0, "uint32", 
02017           (GATuint32)element->type);
02018         if (GAT_SUCCESS != retval)
02019         {
02020           break;
02021         }
02022         
02023         switch(element->type)
02024         {
02025           case GATType_GATint32:
02026             retval = GATXds_Encode(xds, (GATXdsScope)0, 0, 0, "string int32", 
02027               element->key, ((Hash_int) element->value)->data);
02028             break;
02029             
02030           case GATType_GATint16:
02031             retval = GATXds_Encode(xds, (GATXdsScope)0, 0, 0, "string int32", 
02032               element->key, ((Hash_short) element->value)->data);
02033             break;
02034             
02035           case GATType_GATdouble64:
02036             retval = GATXds_Encode(xds,(GATXdsScope) 0, 0, 0, "string double", 
02037               element->key, ((Hash_double) element->value)->data);
02038             break;
02039 
02040           case GATType_GATfloat32:
02041             retval = GATXds_Encode(xds, (GATXdsScope)0, 0, 0, "string double", 
02042               element->key, (double)((Hash_float) element->value)->data);
02043             break;
02044 
02045           case GATType_String:
02046             retval = GATXds_Encode(xds, (GATXdsScope)0, 0, 0, "string string", 
02047               element->key, ((Hash_String) element->value)->data);
02048             break;
02049 
02050           default:
02051             if (GATType_GATObject & element->type)
02052             {
02053               retval = GATXds_Encode(xds, (GATXdsScope)0, 0, 0, "string object", 
02054                 element->key, ((Hash_GATObject) element->value)->data,
02055                 clear_dirty);
02056             }
02057             else
02058             {
02059               retval = GAT_KEY_TYPE_ERROR;
02060             }
02061             break;
02062         }
02063         
02064         if(GAT_SUCCESS != retval)
02065         {
02066           break;
02067         }
02068       }
02069       
02070       if (GAT_SUCCESS != retval)
02071       {
02072         break;
02073       } 
02074     }
02075   }
02076       
02077   if (GAT_SUCCESS == retval)
02078   {
02079     retval = GATXds_GetBuffer(xds, GATXdsScope_Gift, buffer, buffer_size);
02080   }
02081   return retval;
02082 }
02083 
02084 /** GATTable_DeSerialise_Create
02085  *
02086  *  The function GATTable_DeSerialise_Create creates a new GATTable object and 
02087  *  fills it from the given stream.
02088  *
02089  *  @param context The GAT context to be used for object construction.
02090  *  @param xds The XDS engine to use for decoding.
02091  *  @param table_length table is size of the internal table data structure.
02092  *  @param element_count table is the expected table element count.
02093  *  @param table The pointer to the variable, which should receive the 
02094  *        newly constructed GATTable object.
02095  *
02096  *  @return An error code.
02097  */
02098 static GATResult 
02099 GATTable_DeSerialise_Create(GATXds xds, GATuint32 table_length, 
02100   GATuint32 element_count, GATTable *table)
02101 {
02102   GATResult retval = GAT_MEMORYFAILURE;
02103   
02104   GATTable new_table = (GATTable) malloc(sizeof(struct GATTable_S));
02105   if (NULL != new_table)
02106   {
02107     GATuint32 i = 0;
02108     
02109     memset(new_table, 0, sizeof(struct GATTable_S));
02110     new_table->GATObject__vtable = &GATTable__vtable;
02111     new_table->GATSerialisable__vtable = &GATTable_ISerialisable__vtable;
02112 
02113     new_table->equal_keys = GATTable_Internal_Equal_Keys_String;
02114     new_table->get_hash = GATTable_Default_Hash_sdbm;
02115     new_table->get_key_size = GATTable_Internal_Get_KeySize_String;
02116     new_table->clone_key = GATTable_Internal_CloneKey_String;
02117     new_table->destroy_key = GATTable_Default_Destroy_Key;
02118     
02119     new_table->table = 
02120       (Hash_Element *) malloc(sizeof(Hash_Element) * table_length);
02121     
02122     if (NULL == new_table)
02123     {
02124       free(new_table);
02125       new_table = NULL;
02126       retval = GAT_MEMORYFAILURE;
02127     }
02128     else
02129     {
02130       /* initiate the table pointers */
02131       double const maxloadfactor = 0.75f;   /* loading for table expand */
02132 
02133       for (i = 0; i < table_length; i++)
02134       {
02135         new_table->table[i] = NULL;      
02136       }
02137 
02138       new_table->table_length = table_length;
02139       new_table->element_count = 0;
02140 
02141       new_table->load_limit = (GATuint32) (table_length * maxloadfactor);
02142     }
02143 
02144     for(i = 0; i < element_count; ++i)
02145     {
02146       /* read the type of the next element */
02147       GATuint32 type = GATType_NoType;
02148       char *key = NULL;
02149       
02150       retval = GATXds_Decode(xds, (GATXdsScope)0, 0, 0, "uint32", &type);
02151       if (GAT_SUCCESS != retval)
02152       {
02153         break;
02154       }
02155       
02156       switch(type)
02157       {
02158         case GATType_GATint32:
02159           {
02160             int data = 0;
02161             retval = GATXds_Decode(xds, (GATXdsScope)0, 0, 0, "string int32", 
02162               &key, &data);
02163             if (GAT_SUCCESS == retval)
02164             {
02165               retval = GATTable_Add_int(new_table, key, data);
02166             }            
02167           }
02168           break;
02169           
02170         case GATType_GATint16:
02171           {
02172             int data = 0;
02173             retval = GATXds_Decode(xds, (GATXdsScope)0, 0, 0, "string int32", 
02174               &key, &data);
02175             if (GAT_SUCCESS == retval)
02176             {
02177               retval = GATTable_Add_short(new_table, key, data);
02178             }            
02179           }
02180           break;
02181           
02182         case GATType_GATdouble64:
02183           {
02184             double data = 0;
02185             retval = GATXds_Decode(xds, (GATXdsScope)0, 0, 0, "string double", 
02186               &key, &data);
02187             if (GAT_SUCCESS == retval)
02188             {
02189               retval = GATTable_Add_double(new_table, key, data);
02190             }            
02191           }
02192           break;
02193 
02194         case GATType_GATfloat32:
02195           {
02196             double data = 0;
02197             retval = GATXds_Decode(xds, (GATXdsScope)0, 0, 0, "string double", 
02198               &key, &data);
02199             if (GAT_SUCCESS == retval)
02200             {
02201               retval = GATTable_Add_float(new_table, key, (float) data);
02202             }            
02203           }
02204           break;
02205 
02206         case GATType_String:
02207           {
02208             char *data = NULL;
02209             retval = GATXds_Decode(xds, (GATXdsScope)0, 0, 0, "string string", 
02210               &key, &data);
02211             if (GAT_SUCCESS == retval)
02212             {
02213               retval = GATTable_Add_String(new_table, key, data);
02214               free(data);
02215             }            
02216           }
02217           break;
02218 
02219         default:
02220           if (GATType_GATObject & type)
02221           {
02222             GATObject data = NULL;
02223             retval = GATXds_Decode(xds, (GATXdsScope)0, 0, 0, "string object", 
02224               &key, &data);
02225             if (GAT_SUCCESS == retval)
02226             {
02227               retval = GATTable_Add_GATObject(new_table, key, data);
02228               GATObject_Destroy(&data);
02229             }            
02230           }
02231           else
02232           {
02233             retval = GAT_KEY_TYPE_ERROR;
02234           }
02235           break;
02236       }
02237       free(key);
02238       
02239       if (GAT_SUCCESS != retval)
02240       {
02241         break;
02242       } 
02243     }
02244 
02245     if (GAT_SUCCESS == retval)
02246     {
02247       if (NULL != table)
02248       {
02249         *table = new_table;
02250       }
02251       else
02252       {
02253         GATTable_Destroy(&new_table);
02254         retval = GAT_INVALID_PARAMETER;
02255       }
02256     }
02257     else
02258     {
02259       GATTable_Destroy(&new_table);
02260     }
02261   }
02262   return retval;
02263 }