#include <stdio.h>
#include <stdlib.h>
#include "st.h"
Go to the source code of this file.
Defines | |
#define | ST_NUMCMP(x, y) ((x) != (y)) |
#define | ST_NUMHASH(x, size) (ABS((long)x)%(size)) |
#define | ST_PTRHASH(x, size) ((int)(((unsigned long)(x)>>2)%size)) |
#define | EQUAL(func, x, y) |
#define | do_hash(key, table) |
#define | PTR_NOT_EQUAL(table, ptr, user_key) (ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) |
#define | FIND_ENTRY(table, hash_val, key, ptr, last) |
#define | ADD_DIRECT(table, key, value, hash_val, new) |
Functions | |
static int | rehash () |
int | st_numhash () |
int | st_ptrhash () |
int | st_numcmp () |
int | st_ptrcmp () |
st_table * | st_init_table_with_params (int(*compare)(), int(*hash)(), int size, int density, double grow_factor, int reorder_flag) |
st_table * | st_init_table (int(*compare)(), int(*hash)()) |
void | st_free_table (st_table *table) |
int | st_lookup (st_table *table, char *key, char **value) |
int | st_lookup_int (st_table *table, char *key, int *value) |
int | st_insert (st_table *table, char *key, char *value) |
int | st_add_direct (st_table *table, char *key, char *value) |
int | st_find_or_add (st_table *table, char *key, char ***slot) |
int | st_find (st_table *table, char *key, char ***slot) |
static int | rehash (st_table *table) |
st_table * | st_copy (st_table *old_table) |
int | st_delete (st_table *table, char **keyp, char **value) |
int | st_delete_int (st_table *table, long *keyp, char **value) |
int | st_foreach (st_table *table, enum st_retval(*func)(), char *arg) |
int | st_strhash (char *string, int modulus) |
int | st_numhash (char *x, int size) |
int | st_ptrhash (char *x, int size) |
int | st_numcmp (char *x, char *y) |
int | st_ptrcmp (char *x, char *y) |
st_generator * | st_init_gen (st_table *table) |
int | st_gen (st_generator *gen, char **key_p, char **value_p) |
int | st_gen_int (st_generator *gen, char **key_p, long *value_p) |
void | st_free_gen (st_generator *gen) |
#define do_hash | ( | key, | |||
table | ) |
((table->hash == st_ptrhash) ? ST_PTRHASH((key),(table)->num_bins) :\ (table->hash == st_numhash) ? ST_NUMHASH((key), (table)->num_bins) :\ (*table->hash)((key), (table)->num_bins))
#define EQUAL | ( | func, | |||
x, | |||||
y | ) |
#define FIND_ENTRY | ( | table, | |||
hash_val, | |||||
key, | |||||
ptr, | |||||
last | ) |
(last) = &(table)->bins[hash_val];\ (ptr) = *(last);\ while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ (last) = &(ptr)->next; (ptr) = *(last);\ }\ if ((ptr) != NULL && (table)->reorder_flag) {\ *(last) = (ptr)->next;\ (ptr)->next = (table)->bins[hash_val];\ (table)->bins[hash_val] = (ptr);\ }
#define PTR_NOT_EQUAL | ( | table, | |||
ptr, | |||||
user_key | ) | (ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) |
static int rehash | ( | st_table * | table | ) | [static] |
Definition at line 321 of file st.c.
00323 { 00324 register st_table_entry *ptr, *next, **old_bins; 00325 int i, old_num_bins, hash_val, old_num_entries; 00326 00327 /* save old values */ 00328 old_bins = table->bins; 00329 old_num_bins = table->num_bins; 00330 old_num_entries = table->num_entries; 00331 00332 /* rehash */ 00333 table->num_bins = (int)(table->grow_factor * old_num_bins); 00334 if (table->num_bins % 2 == 0) { 00335 table->num_bins += 1; 00336 } 00337 table->num_entries = 0; 00338 table->bins = ALLOC(st_table_entry *, table->num_bins); 00339 if (table->bins == NULL) { 00340 table->bins = old_bins; 00341 table->num_bins = old_num_bins; 00342 table->num_entries = old_num_entries; 00343 return ST_OUT_OF_MEM; 00344 } 00345 /* initialize */ 00346 for (i = 0; i < table->num_bins; i++) { 00347 table->bins[i] = 0; 00348 } 00349 00350 /* copy data over */ 00351 for (i = 0; i < old_num_bins; i++) { 00352 ptr = old_bins[i]; 00353 while (ptr != NULL) { 00354 next = ptr->next; 00355 hash_val = do_hash(ptr->key, table); 00356 ptr->next = table->bins[hash_val]; 00357 table->bins[hash_val] = ptr; 00358 table->num_entries++; 00359 ptr = next; 00360 } 00361 } 00362 FREE(old_bins); 00363 00364 return 1; 00365 }
static int rehash | ( | ) | [static] |
int st_add_direct | ( | st_table * | table, | |
char * | key, | |||
char * | value | |||
) |
Definition at line 233 of file st.c.
00237 { 00238 int hash_val; 00239 st_table_entry *new; 00240 00241 hash_val = do_hash(key, table); 00242 if (table->num_entries / table->num_bins >= table->max_density) { 00243 if (rehash(table) == ST_OUT_OF_MEM) { 00244 return ST_OUT_OF_MEM; 00245 } 00246 } 00247 hash_val = do_hash(key, table); 00248 new = ALLOC(st_table_entry, 1); 00249 if (new == NULL) { 00250 return ST_OUT_OF_MEM; 00251 } 00252 new->key = key; 00253 new->record = value; 00254 new->next = table->bins[hash_val]; 00255 table->bins[hash_val] = new; 00256 table->num_entries++; 00257 return 1; 00258 }
Definition at line 368 of file st.c.
00370 { 00371 st_table *new_table; 00372 st_table_entry *ptr, *newptr, *next, *new; 00373 int i, j, num_bins = old_table->num_bins; 00374 00375 new_table = ALLOC(st_table, 1); 00376 if (new_table == NULL) { 00377 return NULL; 00378 } 00379 00380 *new_table = *old_table; 00381 new_table->bins = ALLOC(st_table_entry *, num_bins); 00382 if (new_table->bins == NULL) { 00383 FREE(new_table); 00384 return NULL; 00385 } 00386 for(i = 0; i < num_bins ; i++) { 00387 new_table->bins[i] = NULL; 00388 ptr = old_table->bins[i]; 00389 while (ptr != NULL) { 00390 new = ALLOC(st_table_entry, 1); 00391 if (new == NULL) { 00392 for (j = 0; j <= i; j++) { 00393 newptr = new_table->bins[j]; 00394 while (newptr != NULL) { 00395 next = newptr->next; 00396 FREE(newptr); 00397 newptr = next; 00398 } 00399 } 00400 FREE(new_table->bins); 00401 FREE(new_table); 00402 return NULL; 00403 } 00404 *new = *ptr; 00405 new->next = new_table->bins[i]; 00406 new_table->bins[i] = new; 00407 ptr = ptr->next; 00408 } 00409 } 00410 return new_table; 00411 }
int st_delete | ( | st_table * | table, | |
char ** | keyp, | |||
char ** | value | |||
) |
Definition at line 414 of file st.c.
00418 { 00419 int hash_val; 00420 char *key = *keyp; 00421 register st_table_entry *ptr, **last; 00422 00423 hash_val = do_hash(key, table); 00424 00425 FIND_ENTRY(table, hash_val, key, ptr ,last); 00426 00427 if (ptr == NULL) { 00428 return 0; 00429 } 00430 00431 *last = ptr->next; 00432 if (value != NULL) *value = ptr->record; 00433 *keyp = ptr->key; 00434 FREE(ptr); 00435 table->num_entries--; 00436 return 1; 00437 }
int st_delete_int | ( | st_table * | table, | |
long * | keyp, | |||
char ** | value | |||
) |
Definition at line 440 of file st.c.
00444 { 00445 int hash_val; 00446 char *key = (char *) *keyp; 00447 register st_table_entry *ptr, **last; 00448 00449 hash_val = do_hash(key, table); 00450 00451 FIND_ENTRY(table, hash_val, key, ptr ,last); 00452 00453 if (ptr == NULL) { 00454 return 0; 00455 } 00456 00457 *last = ptr->next; 00458 if (value != NULL) *value = ptr->record; 00459 *keyp = (long) ptr->key; 00460 FREE(ptr); 00461 table->num_entries--; 00462 return 1; 00463 }
int st_find | ( | st_table * | table, | |
char * | key, | |||
char *** | slot | |||
) |
Definition at line 298 of file st.c.
00302 { 00303 int hash_val; 00304 st_table_entry *ptr, **last; 00305 00306 hash_val = do_hash(key, table); 00307 00308 FIND_ENTRY(table, hash_val, key, ptr, last); 00309 00310 if (ptr == NULL) { 00311 return 0; 00312 } else { 00313 if (slot != NULL) { 00314 *slot = &ptr->record; 00315 } 00316 return 1; 00317 } 00318 }
int st_find_or_add | ( | st_table * | table, | |
char * | key, | |||
char *** | slot | |||
) |
Definition at line 261 of file st.c.
00265 { 00266 int hash_val; 00267 st_table_entry *new, *ptr, **last; 00268 00269 hash_val = do_hash(key, table); 00270 00271 FIND_ENTRY(table, hash_val, key, ptr, last); 00272 00273 if (ptr == NULL) { 00274 if (table->num_entries / table->num_bins >= table->max_density) { 00275 if (rehash(table) == ST_OUT_OF_MEM) { 00276 return ST_OUT_OF_MEM; 00277 } 00278 hash_val = do_hash(key, table); 00279 } 00280 new = ALLOC(st_table_entry, 1); 00281 if (new == NULL) { 00282 return ST_OUT_OF_MEM; 00283 } 00284 new->key = key; 00285 new->record = (char *) 0; 00286 new->next = table->bins[hash_val]; 00287 table->bins[hash_val] = new; 00288 table->num_entries++; 00289 if (slot != NULL) *slot = &new->record; 00290 return 0; 00291 } else { 00292 if (slot != NULL) *slot = &ptr->record; 00293 return 1; 00294 } 00295 }
Definition at line 466 of file st.c.
00470 { 00471 st_table_entry *ptr, **last; 00472 enum st_retval retval; 00473 int i; 00474 00475 for(i = 0; i < table->num_bins; i++) { 00476 last = &table->bins[i]; ptr = *last; 00477 while (ptr != NULL) { 00478 retval = (*func)(ptr->key, ptr->record, arg); 00479 switch (retval) { 00480 case ST_CONTINUE: 00481 last = &ptr->next; ptr = *last; 00482 break; 00483 case ST_STOP: 00484 return 0; 00485 case ST_DELETE: 00486 *last = ptr->next; 00487 table->num_entries--; /* cstevens@ic */ 00488 FREE(ptr); 00489 ptr = *last; 00490 } 00491 } 00492 } 00493 return 1; 00494 }
void st_free_gen | ( | st_generator * | gen | ) |
void st_free_table | ( | st_table * | table | ) |
int st_gen | ( | st_generator * | gen, | |
char ** | key_p, | |||
char ** | value_p | |||
) |
Definition at line 561 of file st.c.
00565 { 00566 register int i; 00567 00568 if (gen->entry == NULL) { 00569 /* try to find next entry */ 00570 for(i = gen->index; i < gen->table->num_bins; i++) { 00571 if (gen->table->bins[i] != NULL) { 00572 gen->index = i+1; 00573 gen->entry = gen->table->bins[i]; 00574 break; 00575 } 00576 } 00577 if (gen->entry == NULL) { 00578 return 0; /* that's all folks ! */ 00579 } 00580 } 00581 *key_p = gen->entry->key; 00582 if (value_p != 0) { 00583 *value_p = gen->entry->record; 00584 } 00585 gen->entry = gen->entry->next; 00586 return 1; 00587 }
int st_gen_int | ( | st_generator * | gen, | |
char ** | key_p, | |||
long * | value_p | |||
) |
Definition at line 591 of file st.c.
00595 { 00596 register int i; 00597 00598 if (gen->entry == NULL) { 00599 /* try to find next entry */ 00600 for(i = gen->index; i < gen->table->num_bins; i++) { 00601 if (gen->table->bins[i] != NULL) { 00602 gen->index = i+1; 00603 gen->entry = gen->table->bins[i]; 00604 break; 00605 } 00606 } 00607 if (gen->entry == NULL) { 00608 return 0; /* that's all folks ! */ 00609 } 00610 } 00611 *key_p = gen->entry->key; 00612 if (value_p != 0) { 00613 *value_p = (long) gen->entry->record; 00614 } 00615 gen->entry = gen->entry->next; 00616 return 1; 00617 }
st_generator* st_init_gen | ( | st_table * | table | ) |
st_table* st_init_table | ( | int (*)() | compare, | |
int (*)() | hash | |||
) |
Definition at line 88 of file st.c.
00091 { 00092 return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE, 00093 ST_DEFAULT_MAX_DENSITY, 00094 ST_DEFAULT_GROW_FACTOR, 00095 ST_DEFAULT_REORDER_FLAG); 00096 }
st_table* st_init_table_with_params | ( | int (*)() | compare, | |
int (*)() | hash, | |||
int | size, | |||
int | density, | |||
double | grow_factor, | |||
int | reorder_flag | |||
) |
Definition at line 50 of file st.c.
00058 { 00059 int i; 00060 st_table *new; 00061 00062 new = ALLOC(st_table, 1); 00063 if (new == NULL) { 00064 return NULL; 00065 } 00066 new->compare = compare; 00067 new->hash = hash; 00068 new->num_entries = 0; 00069 new->max_density = density; 00070 new->grow_factor = grow_factor; 00071 new->reorder_flag = reorder_flag; 00072 if (size <= 0) { 00073 size = 1; 00074 } 00075 new->num_bins = size; 00076 new->bins = ALLOC(st_table_entry *, size); 00077 if (new->bins == NULL) { 00078 FREE(new); 00079 return NULL; 00080 } 00081 for(i = 0; i < size; i++) { 00082 new->bins[i] = 0; 00083 } 00084 return new; 00085 }
int st_insert | ( | st_table * | table, | |
char * | key, | |||
char * | value | |||
) |
Definition at line 196 of file st.c.
00200 { 00201 int hash_val; 00202 st_table_entry *new; 00203 register st_table_entry *ptr, **last; 00204 00205 hash_val = do_hash(key, table); 00206 00207 FIND_ENTRY(table, hash_val, key, ptr, last); 00208 00209 if (ptr == NULL) { 00210 if (table->num_entries/table->num_bins >= table->max_density) { 00211 if (rehash(table) == ST_OUT_OF_MEM) { 00212 return ST_OUT_OF_MEM; 00213 } 00214 hash_val = do_hash(key, table); 00215 } 00216 new = ALLOC(st_table_entry, 1); 00217 if (new == NULL) { 00218 return ST_OUT_OF_MEM; 00219 } 00220 new->key = key; 00221 new->record = value; 00222 new->next = table->bins[hash_val]; 00223 table->bins[hash_val] = new; 00224 table->num_entries++; 00225 return 0; 00226 } else { 00227 ptr->record = value; 00228 return 1; 00229 } 00230 }
int st_lookup | ( | st_table * | table, | |
char * | key, | |||
char ** | value | |||
) |
Definition at line 133 of file st.c.
00137 { 00138 int hash_val; 00139 register st_table_entry *ptr, **last; 00140 00141 hash_val = do_hash(key, table); 00142 00143 FIND_ENTRY(table, hash_val, key, ptr, last); 00144 00145 if (ptr == NULL) { 00146 return 0; 00147 } else { 00148 if (value != NULL) { 00149 *value = ptr->record; 00150 } 00151 return 1; 00152 } 00153 }
int st_lookup_int | ( | st_table * | table, | |
char * | key, | |||
int * | value | |||
) |
Definition at line 156 of file st.c.
00160 { 00161 int hash_val; 00162 register st_table_entry *ptr, **last; 00163 00164 hash_val = do_hash(key, table); 00165 00166 FIND_ENTRY(table, hash_val, key, ptr, last); 00167 00168 if (ptr == NULL) { 00169 return 0; 00170 } else { 00171 if (value != 0) { 00172 *value = (long) ptr->record; 00173 } 00174 return 1; 00175 } 00176 }
int st_numcmp | ( | char * | x, | |
char * | y | |||
) |
int st_numcmp | ( | ) |
int st_numhash | ( | char * | x, | |
int | size | |||
) |
Definition at line 512 of file st.c.
00515 { 00516 return ST_NUMHASH(x, size); 00517 }
int st_numhash | ( | ) |
int st_ptrcmp | ( | char * | x, | |
char * | y | |||
) |
int st_ptrcmp | ( | ) |
int st_ptrhash | ( | char * | x, | |
int | size | |||
) |
Definition at line 520 of file st.c.
00523 { 00524 return ST_PTRHASH(x, size); 00525 }
int st_ptrhash | ( | ) |