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