C:/Users/vincent/Data/Perso/dev/ocilib/ocilib/src/hash.c

00001 /*
00002    +----------------------------------------------------------------------+   
00003    |                                                                      |
00004    |                     OCILIB - C Driver for Oracle                     |
00005    |                                                                      |
00006    |                      (C Wrapper for Oracle OCI)                      |
00007    |                                                                      |
00008    +----------------------------------------------------------------------+
00009    |                      Website : http://www.ocilib.net                 |
00010    +----------------------------------------------------------------------+
00011    |               Copyright (c) 2007-2009 Vincent ROGIER                 |
00012    +----------------------------------------------------------------------+
00013    | This library is free software; you can redistribute it and/or        |
00014    | modify it under the terms of the GNU Lesser General Public           |
00015    | License as published by the Free Software Foundation; either         |
00016    | version 2 of the License, or (at your option) any later version.     |
00017    |                                                                      |
00018    | This library is distributed in the hope that it will be useful,      |
00019    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
00020    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
00021    | Lesser General Public License for more details.                      |
00022    |                                                                      |
00023    | You should have received a copy of the GNU Lesser General Public     |
00024    | License along with this library; if not, write to the Free           |
00025    | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   |
00026    +----------------------------------------------------------------------+
00027    |          Author: Vincent ROGIER <vince.rogier@gmail.com>             |
00028    +----------------------------------------------------------------------+ 
00029 */
00030 
00031 /* ------------------------------------------------------------------------ *
00032  * $Id: hash.c, v 3.4.0 2009-07-30 17:40 Vince $
00033  * ------------------------------------------------------------------------ */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ************************************************************************ *
00038  *                             PRIVATE FUNCTIONS
00039  * ************************************************************************ */
00040 
00041 /* ------------------------------------------------------------------------ *
00042  * OCI_HashCompute
00043  * ------------------------------------------------------------------------ */
00044 
00045 unsigned int OCI_HashCompute(OCI_HashTable *table, const mtext *str)
00046 {
00047     unsigned int h;
00048     mtext *p;
00049     mtext c;
00050 
00051     OCI_CHECK(table == NULL, 0);
00052     OCI_CHECK(str   == NULL, 0);
00053 
00054     for(h = 0, p = (mtext *) str; (*p) != 0; p++)
00055     {
00056         c = *p;
00057 
00058         h = 31 * h + mttoupper(c);
00059     }
00060 
00061     return (h % table->size);
00062 }
00063 
00064 /* ************************************************************************ *
00065  *                            PUBLIC FUNCTIONS
00066  * ************************************************************************ */
00067 
00068 /* ------------------------------------------------------------------------ *
00069  * OCI_HashCreate
00070  * ------------------------------------------------------------------------ */
00071 
00072 OCI_HashTable * OCI_API OCI_HashCreate(unsigned int size, unsigned int type)
00073 {
00074     OCI_HashTable *table = NULL;
00075     boolean res = TRUE;
00076     
00077     /* allocate table structure */
00078 
00079     table = (OCI_HashTable *) OCI_MemAlloc(OCI_IPC_HASHTABLE, sizeof(*table), 1, TRUE);
00080 
00081     /* set up attributes and allocate internal array of hash entry pointers */
00082 
00083     if (table != NULL)
00084     {
00085         table->size     = size;
00086         table->type     = type;
00087         table->count    = 0;
00088 
00089         table->items = (OCI_HashEntry **) OCI_MemAlloc(OCI_IPC_HASHENTRY_ARRAY,
00090                                                        sizeof(*table->items),
00091                                                        size, TRUE);
00092         res = (table->items != NULL);
00093     }
00094     else
00095         res = FALSE;
00096 
00097     if (res == FALSE)
00098         OCI_HashFree(table);
00099 
00100     OCI_RESULT(res);
00101 
00102     return table;
00103 }
00104 
00105 /* ------------------------------------------------------------------------ *
00106  * OCI_HashFree
00107  * ------------------------------------------------------------------------ */
00108 
00109 boolean OCI_API OCI_HashFree(OCI_HashTable *table)
00110 {
00111     unsigned int i;
00112 
00113     OCI_HashEntry *e1, *e2;
00114     OCI_HashValue *v1, *v2;
00115 
00116     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, FALSE);
00117 
00118     for (i = 0; i < table->size; i++)
00119     {
00120         e1 = table->items[i];
00121 
00122         while (e1 != NULL)
00123         {
00124             e2 = e1;
00125             e1 = e1->next;
00126 
00127             v1 = e2->values;
00128 
00129             while (v1 != NULL)
00130             {
00131                 v2 = v1;
00132                 v1 = v1->next;
00133 
00134                 if (table->type == OCI_HASH_STRING)
00135                     OCI_FREE(v2->value.p_mtext);
00136 
00137                 OCI_FREE(v2);
00138             }
00139 
00140             if (e2->key)
00141                 OCI_FREE(e2->key);
00142 
00143             if (e2)
00144                 OCI_FREE(e2);
00145         }
00146     }
00147 
00148     if (table->items != NULL)
00149     {
00150         OCI_FREE(table->items);
00151     }
00152 
00153     OCI_FREE(table);
00154 
00155     OCI_RESULT(TRUE);
00156 
00157     return TRUE;
00158 }
00159 
00160 /* ------------------------------------------------------------------------ *
00161  * OCI_HashGetSize
00162  * ------------------------------------------------------------------------ */
00163 
00164 unsigned int OCI_API OCI_HashGetSize(OCI_HashTable *table)
00165 {
00166     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, 0);
00167 
00168     OCI_RESULT(TRUE);
00169 
00170     return table->size;
00171 }
00172 
00173 /* ------------------------------------------------------------------------ *
00174  * OCI_HashGetType
00175  * ------------------------------------------------------------------------ */
00176 
00177 unsigned int OCI_API OCI_HashGetType(OCI_HashTable *table)
00178 {
00179     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, OCI_UNKNOWN);
00180 
00181     OCI_RESULT(TRUE);
00182 
00183     return table->type;
00184 }
00185 
00186 /* ------------------------------------------------------------------------ *
00187  * OCI_HashGetValue
00188  * ------------------------------------------------------------------------ */
00189 
00190 OCI_HashValue * OCI_API OCI_HashGetValue(OCI_HashTable *table, const mtext *key)
00191 {
00192     OCI_HashEntry *e = NULL;
00193     OCI_HashValue *v = NULL;
00194  
00195     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, NULL);
00196 
00197     e = OCI_HashLookup(table, key, FALSE);
00198 
00199     if (e != NULL)
00200         v = e->values;
00201 
00202     OCI_RESULT(v != NULL);
00203 
00204     return v;
00205 }
00206 
00207 /* ------------------------------------------------------------------------ *
00208  * OCI_HashGetEntry
00209  * ------------------------------------------------------------------------ */
00210 
00211 OCI_HashEntry * OCI_API OCI_HashGetEntry(OCI_HashTable *table, unsigned int index)
00212 {
00213     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, NULL);
00214     OCI_CHECK_BOUND(NULL, index, 1, table->size, NULL);
00215 
00216     OCI_RESULT(TRUE);
00217 
00218     return table->items[index];
00219 }
00220 
00221 /* ------------------------------------------------------------------------ *
00222  * OCI_HashGetString
00223  * ------------------------------------------------------------------------ */
00224 
00225 const mtext * OCI_API OCI_HashGetString(OCI_HashTable *table, const mtext *key)
00226 {
00227     OCI_HashValue *v   = NULL;
00228     const mtext *value = NULL;
00229 
00230     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, NULL);
00231     OCI_CHECK(table->type != OCI_HASH_STRING, NULL);
00232 
00233     v = OCI_HashGetValue(table, key);
00234 
00235     if (v != NULL)
00236     {
00237         value = v->value.p_mtext;
00238     }
00239 
00240     OCI_RESULT(v != NULL);
00241 
00242     return value;
00243 }
00244 
00245 /* ------------------------------------------------------------------------ *
00246  * OCI_HashGetInt
00247  * ------------------------------------------------------------------------ */
00248 
00249 int OCI_API OCI_HashGetInt(OCI_HashTable *table, const mtext *key)
00250 {
00251     OCI_HashValue *v = NULL;
00252     int value = 0;
00253 
00254     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, 0);
00255     OCI_CHECK(table->type != OCI_HASH_INTEGER, 0);
00256 
00257     v = OCI_HashGetValue(table, key);
00258 
00259     if (v != NULL)
00260     {
00261         value = v->value.num;
00262     }
00263 
00264     OCI_RESULT(v != NULL);
00265 
00266     return value;
00267 }
00268 
00269 /* ------------------------------------------------------------------------ *
00270  * OCI_HashGetPointer
00271  * ------------------------------------------------------------------------ */
00272 
00273 void * OCI_API OCI_HashGetPointer(OCI_HashTable *table, const mtext *key)
00274 {
00275     OCI_HashValue *v = NULL;
00276     void *value = NULL;
00277 
00278     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, NULL);
00279     OCI_CHECK(table->type != OCI_HASH_POINTER, NULL);
00280 
00281     v = OCI_HashGetValue(table, key);
00282 
00283     if (v != NULL)
00284     {
00285         value = v->value.p_void;
00286     }
00287 
00288     OCI_RESULT(v != NULL);
00289 
00290     return value;
00291 }
00292 
00293 /* ------------------------------------------------------------------------ *
00294  * OCI_HashAdd
00295  * ------------------------------------------------------------------------ */
00296 
00297 boolean OCI_HashAdd(OCI_HashTable *table, const mtext *key, OCI_Variant value, 
00298                     unsigned int type)
00299 {
00300     OCI_HashEntry * e = NULL;
00301     OCI_HashValue * v = NULL, *v1 = NULL, *v2 = NULL;
00302 
00303     OCI_CHECK(table == NULL, FALSE);
00304     OCI_CHECK(key   == NULL, FALSE);
00305     OCI_CHECK(table->type != type, FALSE);
00306 
00307     e = OCI_HashLookup(table, key, TRUE);
00308 
00309     if (e != NULL)
00310     {
00311         v = (OCI_HashValue *) OCI_MemAlloc(OCI_IPC_HASHVALUE, sizeof(*v), 1, TRUE);
00312 
00313         if (v != NULL)
00314         {
00315             if (table->type == OCI_HASH_STRING && value.p_mtext != NULL)
00316             {
00317                 v->value.p_mtext = mtsdup(value.p_mtext);
00318             }
00319             else if (table->type == OCI_HASH_INTEGER)
00320             {
00321                 v->value.num = value.num;
00322             }
00323             else
00324                 v->value.p_void = value.p_void;
00325 
00326             v1 = v2 = e->values;
00327 
00328             while (v1 != NULL)
00329             {
00330                 v2 = v1;
00331                 v1 = v1->next;
00332             }
00333 
00334             if (v2 != NULL)
00335                 v2->next  = v;
00336             else
00337                 e->values = v;
00338         }
00339     }
00340 
00341     return (v != NULL);
00342 }
00343 
00344 /* ------------------------------------------------------------------------ *
00345  * OCI_HashAddString
00346  * ------------------------------------------------------------------------ */
00347 
00348 boolean OCI_API OCI_HashAddString(OCI_HashTable *table, const mtext *key, 
00349                                   const mtext *value)
00350 {
00351     boolean res = TRUE;
00352     OCI_Variant v;
00353 
00354     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, FALSE);
00355 
00356     v.p_mtext = (mtext *) value;
00357 
00358     res = OCI_HashAdd(table, key, v, OCI_HASH_STRING);
00359 
00360     OCI_RESULT(res);
00361 
00362     return res;
00363 }
00364 
00365 /* ------------------------------------------------------------------------ *
00366  * OCI_HashAddInt
00367  * ------------------------------------------------------------------------ */
00368 
00369 boolean OCI_API OCI_HashAddInt(OCI_HashTable *table, const mtext *key,
00370                                int value)
00371 {
00372     boolean res = TRUE;
00373     OCI_Variant v;
00374 
00375     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, FALSE);
00376 
00377     v.num = value;
00378 
00379     res = OCI_HashAdd(table, key, v, OCI_HASH_INTEGER);
00380 
00381     OCI_RESULT(res);
00382 
00383     return res;
00384 }
00385 
00386 /* ------------------------------------------------------------------------ *
00387  * OCI_HashAddPointer
00388  * ------------------------------------------------------------------------ */
00389 
00390 boolean OCI_API OCI_HashAddPointer(OCI_HashTable *table, const mtext *key, 
00391                                    void *value)
00392 {
00393     boolean res = TRUE;
00394     OCI_Variant v;
00395 
00396     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, FALSE);
00397 
00398     v.p_void = value;
00399 
00400     res  = OCI_HashAdd(table, key, v, OCI_HASH_POINTER);
00401 
00402     OCI_RESULT(res);
00403 
00404     return res;
00405 }
00406 
00407 /* ------------------------------------------------------------------------ *
00408  * OCI_HashLookup
00409  * ------------------------------------------------------------------------ */
00410 
00411 OCI_HashEntry * OCI_API OCI_HashLookup(OCI_HashTable *table, const mtext *key,
00412                                        boolean create)
00413 {
00414     OCI_HashEntry *e = NULL, *e1 = NULL, *e2 = NULL;
00415     unsigned int i;
00416 
00417     OCI_CHECK_PTR(OCI_IPC_HASHTABLE, table, NULL);
00418     OCI_CHECK_PTR(OCI_IPC_STRING, key, NULL);
00419 
00420     i = OCI_HashCompute(table, key);
00421 
00422     if (i < table->size)
00423     {
00424         for(e = table->items[i]; e != NULL; e = e->next)
00425         {
00426             if (mtscasecmp(e->key, key) == 0)
00427                 break;
00428         }
00429 
00430         if ((e == NULL) && (create == TRUE))
00431         {
00432             e = (OCI_HashEntry *) OCI_MemAlloc(OCI_IPC_HASHENTRY, sizeof(*e), 1, TRUE);
00433 
00434             if (e != NULL)
00435             {
00436                 e->key = mtsdup(key);
00437 
00438                 e1 = e2 = table->items[i];
00439 
00440                 while (e1 != NULL)
00441                 {
00442                     e2 = e1;
00443                     e1 = e1->next;
00444                 }
00445 
00446                 if (e2 != NULL)
00447                     e2->next = e;
00448                 else
00449                     table->items[i] = e;
00450             }
00451         }
00452     }
00453 
00454     OCI_RESULT(e != NULL);
00455 
00456     return e;
00457 }

Generated on Thu Jul 30 17:41:52 2009 for OCILIB (C Driver for Oracle) by  doxygen 1.5.4