• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_hash_table.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /****************************************************************************
00025 
00026   ink_hash_table.c
00027 
00028   This file implements hash tables.  This allows us to provide alternative
00029   implementations of hash tables.
00030 
00031  ****************************************************************************/
00032 
00033 #include "ink_error.h"
00034 #include "ink_hash_table.h"
00035 #include "ink_memory.h"
00036 
00037 /*===========================================================================*
00038 
00039   This is the Tcl implementation of InkHashTable
00040 
00041  *===========================================================================*/
00042 
00043 /*---------------------------------------------------------------------------*
00044 
00045   InkHashTable *ink_hash_table_create(InkHashTableKeyType key_type)
00046 
00047   This routine allocates an initializes an empty InkHashTable, and returns a
00048   pointer to the new table.  The <key_type> argument indicates whether keys
00049   are represented as strings, or as words.  Legal values are
00050   InkHashTableKeyType_String and InkHashTableKeyType_Word.
00051 
00052  *---------------------------------------------------------------------------*/
00053 
00054 InkHashTable *
00055 ink_hash_table_create(InkHashTableKeyType key_type)
00056 {
00057   InkHashTable *ht_ptr;
00058   Tcl_HashTable *tcl_ht_ptr;
00059   int tcl_key_type;
00060 
00061   tcl_ht_ptr = (Tcl_HashTable*)ats_malloc(sizeof(Tcl_HashTable));
00062 
00063   if (key_type == InkHashTableKeyType_String)
00064     tcl_key_type = TCL_STRING_KEYS;
00065   else if (key_type == InkHashTableKeyType_Word)
00066     tcl_key_type = TCL_ONE_WORD_KEYS;
00067   else
00068     ink_fatal(1, "ink_hash_table_create: bad key_type %d", key_type);
00069 
00070   Tcl_InitHashTable(tcl_ht_ptr, tcl_key_type);
00071 
00072   ht_ptr = (InkHashTable *) tcl_ht_ptr;
00073   return (ht_ptr);
00074 }                               /* End ink_hash_table_create */
00075 
00076 
00077 /*---------------------------------------------------------------------------*
00078 
00079   void ink_hash_table_destroy(InkHashTable *ht_ptr)
00080 
00081   This routine takes a hash table <ht_ptr>, and frees its storage.
00082 
00083  *---------------------------------------------------------------------------*/
00084 
00085 InkHashTable *
00086 ink_hash_table_destroy(InkHashTable * ht_ptr)
00087 {
00088   Tcl_HashTable *tcl_ht_ptr;
00089 
00090   tcl_ht_ptr = (Tcl_HashTable *) ht_ptr;
00091   Tcl_DeleteHashTable(tcl_ht_ptr);
00092   ats_free(tcl_ht_ptr);
00093   return (InkHashTable *) 0;
00094 }                               /* End ink_hash_table_destroy */
00095 
00096 
00097 /*---------------------------------------------------------------------------*
00098 
00099   void ink_hash_table_destroy_and_free_values(InkHashTable *ht_ptr)
00100 
00101   This routine takes a hash table <ht_ptr>, and frees its storage, after
00102   first calling ink_free on all the values.  You better darn well make sure the
00103   values have been dynamically allocated.
00104 
00105  *---------------------------------------------------------------------------*/
00106 
00107 static int
00108 _ink_hash_table_free_entry_value(InkHashTable * ht_ptr, InkHashTableEntry * e)
00109 {
00110   InkHashTableValue value;
00111 
00112   value = ink_hash_table_entry_value(ht_ptr, e);
00113   if (value != NULL) {
00114     ats_free(value);
00115   }
00116 
00117   return (0);
00118 }                               /* End _ink_hash_table_free_entry_value */
00119 
00120 
00121 static int
00122 _ink_hash_table_xfree_entry_value(InkHashTable * ht_ptr, InkHashTableEntry * e)
00123 {
00124   InkHashTableValue value;
00125 
00126   value = ink_hash_table_entry_value(ht_ptr, e);
00127   if (value != NULL) {
00128     ats_free(value);
00129   }
00130 
00131   return (0);
00132 }                               /* End _ink_hash_table_xfree_entry_value */
00133 
00134 InkHashTable *
00135 ink_hash_table_destroy_and_free_values(InkHashTable * ht_ptr)
00136 {
00137   ink_hash_table_map(ht_ptr, _ink_hash_table_free_entry_value);
00138   ink_hash_table_destroy(ht_ptr);
00139   return (InkHashTable *) 0;
00140 }                               /* End ink_hash_table_destroy_and_free_values */
00141 
00142 InkHashTable *
00143 ink_hash_table_destroy_and_xfree_values(InkHashTable * ht_ptr)
00144 {
00145   ink_hash_table_map(ht_ptr, _ink_hash_table_xfree_entry_value);
00146   ink_hash_table_destroy(ht_ptr);
00147   return (InkHashTable *) 0;
00148 }                               /* End ink_hash_table_destroy_and_xfree_values */
00149 
00150 
00151 /*---------------------------------------------------------------------------*
00152 
00153   int ink_hash_table_isbound(InkHashTable *ht_ptr, InkHashTableKey key)
00154 
00155   This routine takes a hash table <ht_ptr>, a key <key>, and returns 1
00156   if the value <key> is bound in the hash table, 0 otherwise.
00157 
00158  *---------------------------------------------------------------------------*/
00159 
00160 int
00161 ink_hash_table_isbound(InkHashTable * ht_ptr, const char *key)
00162 {
00163   InkHashTableEntry *he_ptr;
00164 
00165   he_ptr = ink_hash_table_lookup_entry(ht_ptr, key);
00166   return ((he_ptr == NULL) ? 0 : 1);
00167 }                               /* End ink_hash_table_isbound */
00168 
00169 
00170 /*---------------------------------------------------------------------------*
00171   int ink_hash_table_lookup(InkHashTable *ht_ptr,
00172                             InkHashTableKey key,
00173                             InkHashTableValue *value_ptr)
00174 
00175   This routine takes a hash table <ht_ptr>, a key <key>, and stores the
00176   value bound to the key by reference through <value_ptr>.  If no binding is
00177   found, 0 is returned, else 1 is returned.
00178 
00179  *---------------------------------------------------------------------------*/
00180 
00181 int
00182 ink_hash_table_lookup(InkHashTable *ht_ptr, const char* key, InkHashTableValue *value_ptr)
00183 {
00184   InkHashTableEntry *he_ptr;
00185   InkHashTableValue value;
00186 
00187   he_ptr = ink_hash_table_lookup_entry(ht_ptr, key);
00188   if (he_ptr == NULL)
00189     return (0);
00190 
00191   value = ink_hash_table_entry_value(ht_ptr, he_ptr);
00192   *value_ptr = value;
00193   return (1);
00194 }                               /* End ink_hash_table_lookup */
00195 
00196 
00197 /*---------------------------------------------------------------------------*
00198 
00199   int ink_hash_table_delete(InkHashTable *ht_ptr, InkHashTableKey key)
00200 
00201   This routine takes a hash table <ht_ptr> and a key <key>, and deletes the
00202   binding for the <key> in the hash table if it exists.  This routine
00203   returns 1 if the key existed, else 0.
00204 
00205  *---------------------------------------------------------------------------*/
00206 
00207 int
00208 ink_hash_table_delete(InkHashTable * ht_ptr, const char *key)
00209 {
00210   char *tcl_key;
00211   Tcl_HashTable *tcl_ht_ptr;
00212   Tcl_HashEntry *tcl_he_ptr;
00213 
00214   tcl_key = (char *) key;
00215   tcl_ht_ptr = (Tcl_HashTable *) ht_ptr;
00216   tcl_he_ptr = Tcl_FindHashEntry(tcl_ht_ptr, tcl_key);
00217 
00218   if (!tcl_he_ptr)
00219     return (0);
00220   Tcl_DeleteHashEntry(tcl_he_ptr);
00221 
00222   return (1);
00223 }                               /* End ink_hash_table_delete */
00224 
00225 
00226 /*---------------------------------------------------------------------------*
00227 
00228   InkHashTableEntry *ink_hash_table_lookup_entry(InkHashTable *ht_ptr,
00229                                                  InkHashTableKey key)
00230 
00231   This routine takes a hash table <ht_ptr> and a key <key>, and returns the
00232   entry matching the key, or NULL otherwise.
00233 
00234  *---------------------------------------------------------------------------*/
00235 
00236 InkHashTableEntry *
00237 ink_hash_table_lookup_entry(InkHashTable * ht_ptr, const char* key)
00238 {
00239   Tcl_HashTable *tcl_ht_ptr;
00240   Tcl_HashEntry *tcl_he_ptr;
00241   InkHashTableEntry *he_ptr;
00242 
00243   tcl_ht_ptr = (Tcl_HashTable *) ht_ptr;
00244   tcl_he_ptr = Tcl_FindHashEntry(tcl_ht_ptr, key);
00245   he_ptr = (InkHashTableEntry *) tcl_he_ptr;
00246 
00247   return (he_ptr);
00248 }                               /* End ink_hash_table_lookup_entry */
00249 
00250 
00251 /*---------------------------------------------------------------------------*
00252 
00253   InkHashTableEntry *ink_hash_table_get_entry(InkHashTable *ht_ptr,
00254                                               InkHashTableKey key,
00255                                               int *new_value)
00256 
00257   This routine takes a hash table <ht_ptr> and a key <key>, and returns the
00258   entry matching the key, or creates, binds, and returns a new entry.
00259   If the binding already existed, *new is set to 0, else 1.
00260 
00261  *---------------------------------------------------------------------------*/
00262 
00263 InkHashTableEntry *
00264 ink_hash_table_get_entry(InkHashTable *ht_ptr, const char *key, int *new_value)
00265 {
00266   Tcl_HashTable *tcl_ht_ptr;
00267   Tcl_HashEntry *tcl_he_ptr;
00268 
00269   tcl_ht_ptr = (Tcl_HashTable *) ht_ptr;
00270   tcl_he_ptr = Tcl_CreateHashEntry(tcl_ht_ptr, key, new_value);
00271 
00272   if (tcl_he_ptr == NULL) {
00273     ink_fatal(1, "%s: Tcl_CreateHashEntry returned NULL", "ink_hash_table_get_entry");
00274   }
00275 
00276   return ((InkHashTableEntry *) tcl_he_ptr);
00277 }                               /* End ink_hash_table_get_entry */
00278 
00279 
00280 /*---------------------------------------------------------------------------*
00281 
00282   void ink_hash_table_set_entry(InkHashTable *ht_ptr,
00283                                 InkHashTableEntry *he_ptr,
00284                                 InkHashTableValue value)
00285 
00286   This routine takes a hash table <ht_ptr>, a hash table entry <he_ptr>,
00287   and changes the value field of the entry to <value>.
00288 
00289  *---------------------------------------------------------------------------*/
00290 
00291 void
00292 ink_hash_table_set_entry(InkHashTable * ht_ptr, InkHashTableEntry * he_ptr, InkHashTableValue value)
00293 {
00294   (void) ht_ptr;
00295   ClientData tcl_value;
00296   Tcl_HashEntry *tcl_he_ptr;
00297 
00298   tcl_value = (ClientData) value;
00299   tcl_he_ptr = (Tcl_HashEntry *) he_ptr;
00300   Tcl_SetHashValue(tcl_he_ptr, tcl_value);
00301 }                               /* End ink_hash_table_set_entry */
00302 
00303 
00304 /*---------------------------------------------------------------------------*
00305 
00306   void ink_hash_table_insert(InkHashTable *ht_ptr,
00307                              InkHashTableKey key,
00308                              InkHashTableValue value)
00309 
00310   This routine takes a hash table <ht_ptr>, a key <key>, and binds the value
00311   <value> to the key, replacing any previous binding, if any.
00312 
00313  *---------------------------------------------------------------------------*/
00314 
00315 void
00316 ink_hash_table_insert(InkHashTable * ht_ptr, const char *key, InkHashTableValue value)
00317 {
00318   int new_value;
00319   InkHashTableEntry *he_ptr;
00320 
00321   he_ptr = ink_hash_table_get_entry(ht_ptr, key, &new_value);
00322   ink_hash_table_set_entry(ht_ptr, he_ptr, value);
00323 }                               /* End ink_hash_table_insert */
00324 
00325 
00326 /*---------------------------------------------------------------------------*
00327 
00328   void ink_hash_table_map(InkHashTable *ht_ptr, InkHashTableEntryFunction map)
00329 
00330   This routine takes a hash table <ht_ptr> and a function pointer <map>, and
00331   applies the function <map> to each entry in the hash table.  The function
00332   <map> should return 0 normally, otherwise the iteration will stop.
00333 
00334  *---------------------------------------------------------------------------*/
00335 
00336 void
00337 ink_hash_table_map(InkHashTable * ht_ptr, InkHashTableEntryFunction map)
00338 {
00339   int retcode;
00340   InkHashTableEntry *e;
00341   InkHashTableIteratorState state;
00342 
00343   for (e = ink_hash_table_iterator_first(ht_ptr, &state); e != NULL; e = ink_hash_table_iterator_next(ht_ptr, &state)) {
00344     retcode = (*map) (ht_ptr, e);
00345     if (retcode != 0)
00346       break;
00347   }
00348 }                               /* End ink_hash_table_map */
00349 
00350 
00351 /*---------------------------------------------------------------------------*
00352 
00353   InkHashTableKey ink_hash_table_entry_key(InkHashTable *ht_ptr,
00354                                            InkHashTableEntry *entry_ptr)
00355 
00356   This routine takes a hash table <ht_ptr> and a pointer to a hash table
00357   entry <entry_ptr>, and returns the key portion of the entry.
00358 
00359  *---------------------------------------------------------------------------*/
00360 
00361 InkHashTableKey
00362 ink_hash_table_entry_key(InkHashTable * ht_ptr, InkHashTableEntry * entry_ptr)
00363 {
00364   char *tcl_key;
00365 
00366   tcl_key = (char*) Tcl_GetHashKey((Tcl_HashTable *) ht_ptr, (Tcl_HashEntry *) entry_ptr);
00367   return ((InkHashTableKey) tcl_key);
00368 }                               /* End ink_hash_table_entry_key */
00369 
00370 
00371 /*---------------------------------------------------------------------------*
00372 
00373   InkHashTableValue ink_hash_table_entry_value(InkHashTable *ht_ptr,
00374                                                InkHashTableEntry *entry_ptr)
00375 
00376   This routine takes a hash table <ht_ptr> and a pointer to a hash table
00377   entry <entry_ptr>, and returns the value portion of the entry.
00378 
00379  *---------------------------------------------------------------------------*/
00380 
00381 InkHashTableValue
00382 ink_hash_table_entry_value(InkHashTable * ht_ptr, InkHashTableEntry * entry_ptr)
00383 {
00384   (void) ht_ptr;
00385   ClientData tcl_value;
00386 
00387   tcl_value = Tcl_GetHashValue((Tcl_HashEntry *) entry_ptr);
00388   return ((InkHashTableValue) tcl_value);
00389 }                               /* End ink_hash_table_entry_value */
00390 
00391 
00392 
00393 /*---------------------------------------------------------------------------*
00394 
00395   void ink_hash_table_dump_strings(InkHashTable *ht_ptr)
00396 
00397   This routine takes a hash table of string values, and dumps the keys and
00398   string values to stdout.  It is the caller's responsibility to ensure that
00399   both the key and the value are NUL terminated strings.
00400 
00401  *---------------------------------------------------------------------------*/
00402 
00403 static int
00404 DumpStringEntry(InkHashTable * ht_ptr, InkHashTableEntry * e)
00405 {
00406   InkHashTableKey key;
00407   InkHashTableValue value;
00408 
00409   key = ink_hash_table_entry_key(ht_ptr, e);
00410   value = ink_hash_table_entry_value(ht_ptr, e);
00411 
00412   fprintf(stderr, "key = '%s', value = '%s'\n", (char *) key, (char *) value);
00413 
00414   return (0);
00415 }
00416 
00417 
00418 void
00419 ink_hash_table_dump_strings(InkHashTable * ht_ptr)
00420 {
00421   ink_hash_table_map(ht_ptr, DumpStringEntry);
00422 }                               /* End ink_hash_table_dump_strings */
00423 
00424 
00425 /*---------------------------------------------------------------------------*
00426 
00427   void ink_hash_table_replace_string(InkHashTable *ht_ptr,
00428                                      char *string_key, char *string_value)
00429 
00430   This conveninece routine is intended for hash tables with keys of type
00431   InkHashTableKeyType_String, and values being dynamically allocated strings.
00432   This routine binds <string_key> to a copy of <string_value>, and any
00433   previous bound value is deallocated.
00434 
00435  *---------------------------------------------------------------------------*/
00436 
00437 void
00438 ink_hash_table_replace_string(InkHashTable * ht_ptr, char *string_key, char *string_value)
00439 {
00440   int new_value;
00441   char *old_str;
00442   InkHashTableEntry *he_ptr;
00443 
00444   /*
00445    * The following line will flag a type-conversion warning on the
00446    * DEC Alpha, but that message can be ignored, since we're
00447    * still dealing with pointers, and we aren't loosing any bits.
00448    */
00449 
00450   he_ptr = ink_hash_table_get_entry(ht_ptr, (InkHashTableKey) string_key, &new_value);
00451   if (new_value == 0) {
00452     old_str = (char *) ink_hash_table_entry_value(ht_ptr, he_ptr);
00453     if (old_str)
00454       ats_free(old_str);
00455   }
00456 
00457   ink_hash_table_set_entry(ht_ptr, he_ptr, (InkHashTableValue)(ats_strdup(string_value)));
00458 }                               /* End ink_hash_table_replace_string */

Generated by  doxygen 1.7.1