st.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
  2. /* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #ifdef _WIN32
  7. #include <malloc.h>
  8. #endif
  9. #include "regint.h"
  10. #include "st.h"
  11. typedef struct st_table_entry st_table_entry;
  12. struct st_table_entry {
  13. unsigned int hash;
  14. st_data_t key;
  15. st_data_t record;
  16. st_table_entry *next;
  17. };
  18. #define ST_DEFAULT_MAX_DENSITY 5
  19. #define ST_DEFAULT_INIT_TABLE_SIZE 11
  20. /*
  21. * DEFAULT_MAX_DENSITY is the default for the largest we allow the
  22. * average number of items per bin before increasing the number of
  23. * bins
  24. *
  25. * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
  26. * allocated initially
  27. *
  28. */
  29. static int numcmp(long, long);
  30. static int numhash(long);
  31. static struct st_hash_type type_numhash = {
  32. numcmp,
  33. numhash,
  34. };
  35. /* extern int strcmp(const char *, const char *); */
  36. static int strhash(const char *);
  37. static struct st_hash_type type_strhash = {
  38. strcmp,
  39. strhash,
  40. };
  41. static void rehash(st_table *);
  42. #define alloc(type) (type*)xmalloc((unsigned)sizeof(type))
  43. #define Calloc(n,s) (char*)xcalloc((n),(s))
  44. #define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0)
  45. #define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key))
  46. #define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins)
  47. /*
  48. * MINSIZE is the minimum size of a dictionary.
  49. */
  50. #define MINSIZE 8
  51. /*
  52. Table of prime numbers 2^n+a, 2<=n<=30.
  53. */
  54. static const long primes[] = {
  55. 8 + 3,
  56. 16 + 3,
  57. 32 + 5,
  58. 64 + 3,
  59. 128 + 3,
  60. 256 + 27,
  61. 512 + 9,
  62. 1024 + 9,
  63. 2048 + 5,
  64. 4096 + 3,
  65. 8192 + 27,
  66. 16384 + 43,
  67. 32768 + 3,
  68. 65536 + 45,
  69. 131072 + 29,
  70. 262144 + 3,
  71. 524288 + 21,
  72. 1048576 + 7,
  73. 2097152 + 17,
  74. 4194304 + 15,
  75. 8388608 + 9,
  76. 16777216 + 43,
  77. 33554432 + 35,
  78. 67108864 + 15,
  79. 134217728 + 29,
  80. 268435456 + 3,
  81. 536870912 + 11,
  82. 1073741824 + 85,
  83. 0
  84. };
  85. static int
  86. new_size(size)
  87. int size;
  88. {
  89. int i;
  90. #if 0
  91. for (i=3; i<31; i++) {
  92. if ((1<<i) > size) return 1<<i;
  93. }
  94. return -1;
  95. #else
  96. int newsize;
  97. for (i = 0, newsize = MINSIZE;
  98. i < (int )(sizeof(primes)/sizeof(primes[0]));
  99. i++, newsize <<= 1)
  100. {
  101. if (newsize > size) return primes[i];
  102. }
  103. /* Ran out of polynomials */
  104. return -1; /* should raise exception */
  105. #endif
  106. }
  107. #ifdef HASH_LOG
  108. static int collision = 0;
  109. static int init_st = 0;
  110. static void
  111. stat_col()
  112. {
  113. FILE *f = fopen("/tmp/col", "w");
  114. fprintf(f, "collision: %d\n", collision);
  115. fclose(f);
  116. }
  117. #endif
  118. st_table*
  119. st_init_table_with_size(type, size)
  120. struct st_hash_type *type;
  121. int size;
  122. {
  123. st_table *tbl;
  124. #ifdef HASH_LOG
  125. if (init_st == 0) {
  126. init_st = 1;
  127. atexit(stat_col);
  128. }
  129. #endif
  130. size = new_size(size); /* round up to prime number */
  131. tbl = alloc(st_table);
  132. tbl->type = type;
  133. tbl->num_entries = 0;
  134. tbl->num_bins = size;
  135. tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
  136. return tbl;
  137. }
  138. st_table*
  139. st_init_table(type)
  140. struct st_hash_type *type;
  141. {
  142. return st_init_table_with_size(type, 0);
  143. }
  144. st_table*
  145. st_init_numtable(void)
  146. {
  147. return st_init_table(&type_numhash);
  148. }
  149. st_table*
  150. st_init_numtable_with_size(size)
  151. int size;
  152. {
  153. return st_init_table_with_size(&type_numhash, size);
  154. }
  155. st_table*
  156. st_init_strtable(void)
  157. {
  158. return st_init_table(&type_strhash);
  159. }
  160. st_table*
  161. st_init_strtable_with_size(size)
  162. int size;
  163. {
  164. return st_init_table_with_size(&type_strhash, size);
  165. }
  166. void
  167. st_free_table(table)
  168. st_table *table;
  169. {
  170. register st_table_entry *ptr, *next;
  171. int i;
  172. for(i = 0; i < table->num_bins; i++) {
  173. ptr = table->bins[i];
  174. while (ptr != 0) {
  175. next = ptr->next;
  176. free(ptr);
  177. ptr = next;
  178. }
  179. }
  180. free(table->bins);
  181. free(table);
  182. }
  183. #define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
  184. ((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
  185. #ifdef HASH_LOG
  186. #define COLLISION collision++
  187. #else
  188. #define COLLISION
  189. #endif
  190. #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
  191. bin_pos = hash_val%(table)->num_bins;\
  192. ptr = (table)->bins[bin_pos];\
  193. if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\
  194. COLLISION;\
  195. while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
  196. ptr = ptr->next;\
  197. }\
  198. ptr = ptr->next;\
  199. }\
  200. } while (0)
  201. int
  202. st_lookup(table, key, value)
  203. st_table *table;
  204. register st_data_t key;
  205. st_data_t *value;
  206. {
  207. unsigned int hash_val, bin_pos;
  208. register st_table_entry *ptr;
  209. hash_val = do_hash(key, table);
  210. FIND_ENTRY(table, ptr, hash_val, bin_pos);
  211. if (ptr == 0) {
  212. return 0;
  213. }
  214. else {
  215. if (value != 0) *value = ptr->record;
  216. return 1;
  217. }
  218. }
  219. #define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
  220. do {\
  221. st_table_entry *entry;\
  222. if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\
  223. rehash(table);\
  224. bin_pos = hash_val % table->num_bins;\
  225. }\
  226. \
  227. entry = alloc(st_table_entry);\
  228. \
  229. entry->hash = hash_val;\
  230. entry->key = key;\
  231. entry->record = value;\
  232. entry->next = table->bins[bin_pos];\
  233. table->bins[bin_pos] = entry;\
  234. table->num_entries++;\
  235. } while (0)
  236. int
  237. st_insert(table, key, value)
  238. register st_table *table;
  239. register st_data_t key;
  240. st_data_t value;
  241. {
  242. unsigned int hash_val, bin_pos;
  243. register st_table_entry *ptr;
  244. hash_val = do_hash(key, table);
  245. FIND_ENTRY(table, ptr, hash_val, bin_pos);
  246. if (ptr == 0) {
  247. ADD_DIRECT(table, key, value, hash_val, bin_pos);
  248. return 0;
  249. }
  250. else {
  251. ptr->record = value;
  252. return 1;
  253. }
  254. }
  255. void
  256. st_add_direct(table, key, value)
  257. st_table *table;
  258. st_data_t key;
  259. st_data_t value;
  260. {
  261. unsigned int hash_val, bin_pos;
  262. hash_val = do_hash(key, table);
  263. bin_pos = hash_val % table->num_bins;
  264. ADD_DIRECT(table, key, value, hash_val, bin_pos);
  265. }
  266. static void
  267. rehash(table)
  268. register st_table *table;
  269. {
  270. register st_table_entry *ptr, *next, **new_bins;
  271. int i, old_num_bins = table->num_bins, new_num_bins;
  272. unsigned int hash_val;
  273. new_num_bins = new_size(old_num_bins+1);
  274. new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*));
  275. for(i = 0; i < old_num_bins; i++) {
  276. ptr = table->bins[i];
  277. while (ptr != 0) {
  278. next = ptr->next;
  279. hash_val = ptr->hash % new_num_bins;
  280. ptr->next = new_bins[hash_val];
  281. new_bins[hash_val] = ptr;
  282. ptr = next;
  283. }
  284. }
  285. free(table->bins);
  286. table->num_bins = new_num_bins;
  287. table->bins = new_bins;
  288. }
  289. st_table*
  290. st_copy(old_table)
  291. st_table *old_table;
  292. {
  293. st_table *new_table;
  294. st_table_entry *ptr, *entry;
  295. int i, num_bins = old_table->num_bins;
  296. new_table = alloc(st_table);
  297. if (new_table == 0) {
  298. return 0;
  299. }
  300. *new_table = *old_table;
  301. new_table->bins = (st_table_entry**)
  302. Calloc((unsigned)num_bins, sizeof(st_table_entry*));
  303. if (new_table->bins == 0) {
  304. free(new_table);
  305. return 0;
  306. }
  307. for(i = 0; i < num_bins; i++) {
  308. new_table->bins[i] = 0;
  309. ptr = old_table->bins[i];
  310. while (ptr != 0) {
  311. entry = alloc(st_table_entry);
  312. if (entry == 0) {
  313. free(new_table->bins);
  314. free(new_table);
  315. return 0;
  316. }
  317. *entry = *ptr;
  318. entry->next = new_table->bins[i];
  319. new_table->bins[i] = entry;
  320. ptr = ptr->next;
  321. }
  322. }
  323. return new_table;
  324. }
  325. int
  326. st_delete(table, key, value)
  327. register st_table *table;
  328. register st_data_t *key;
  329. st_data_t *value;
  330. {
  331. unsigned int hash_val;
  332. st_table_entry *tmp;
  333. register st_table_entry *ptr;
  334. hash_val = do_hash_bin(*key, table);
  335. ptr = table->bins[hash_val];
  336. if (ptr == 0) {
  337. if (value != 0) *value = 0;
  338. return 0;
  339. }
  340. if (EQUAL(table, *key, ptr->key)) {
  341. table->bins[hash_val] = ptr->next;
  342. table->num_entries--;
  343. if (value != 0) *value = ptr->record;
  344. *key = ptr->key;
  345. free(ptr);
  346. return 1;
  347. }
  348. for(; ptr->next != 0; ptr = ptr->next) {
  349. if (EQUAL(table, ptr->next->key, *key)) {
  350. tmp = ptr->next;
  351. ptr->next = ptr->next->next;
  352. table->num_entries--;
  353. if (value != 0) *value = tmp->record;
  354. *key = tmp->key;
  355. free(tmp);
  356. return 1;
  357. }
  358. }
  359. return 0;
  360. }
  361. int
  362. st_delete_safe(table, key, value, never)
  363. register st_table *table;
  364. register st_data_t *key;
  365. st_data_t *value;
  366. st_data_t never;
  367. {
  368. unsigned int hash_val;
  369. register st_table_entry *ptr;
  370. hash_val = do_hash_bin(*key, table);
  371. ptr = table->bins[hash_val];
  372. if (ptr == 0) {
  373. if (value != 0) *value = 0;
  374. return 0;
  375. }
  376. for(; ptr != 0; ptr = ptr->next) {
  377. if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
  378. table->num_entries--;
  379. *key = ptr->key;
  380. if (value != 0) *value = ptr->record;
  381. ptr->key = ptr->record = never;
  382. return 1;
  383. }
  384. }
  385. return 0;
  386. }
  387. static int
  388. #if defined(__GNUC__)
  389. delete_never(st_data_t key __attribute__ ((unused)), st_data_t value,
  390. st_data_t never)
  391. #else
  392. delete_never(key, value, never)
  393. st_data_t key, value, never;
  394. #endif
  395. {
  396. if (value == never) return ST_DELETE;
  397. return ST_CONTINUE;
  398. }
  399. void
  400. st_cleanup_safe(table, never)
  401. st_table *table;
  402. st_data_t never;
  403. {
  404. int num_entries = table->num_entries;
  405. st_foreach(table, delete_never, never);
  406. table->num_entries = num_entries;
  407. }
  408. int
  409. st_foreach(table, func, arg)
  410. st_table *table;
  411. int (*func)();
  412. st_data_t arg;
  413. {
  414. st_table_entry *ptr, *last, *tmp;
  415. enum st_retval retval;
  416. int i;
  417. for(i = 0; i < table->num_bins; i++) {
  418. last = 0;
  419. for(ptr = table->bins[i]; ptr != 0;) {
  420. retval = (*func)(ptr->key, ptr->record, arg);
  421. switch (retval) {
  422. case ST_CHECK: /* check if hash is modified during iteration */
  423. tmp = 0;
  424. if (i < table->num_bins) {
  425. for (tmp = table->bins[i]; tmp; tmp=tmp->next) {
  426. if (tmp == ptr) break;
  427. }
  428. }
  429. if (!tmp) {
  430. /* call func with error notice */
  431. return 1;
  432. }
  433. /* fall through */
  434. case ST_CONTINUE:
  435. last = ptr;
  436. ptr = ptr->next;
  437. break;
  438. case ST_STOP:
  439. return 0;
  440. case ST_DELETE:
  441. tmp = ptr;
  442. if (last == 0) {
  443. table->bins[i] = ptr->next;
  444. }
  445. else {
  446. last->next = ptr->next;
  447. }
  448. ptr = ptr->next;
  449. free(tmp);
  450. table->num_entries--;
  451. }
  452. }
  453. }
  454. return 0;
  455. }
  456. static int
  457. strhash(string)
  458. register const char *string;
  459. {
  460. register int c;
  461. #ifdef HASH_ELFHASH
  462. register unsigned int h = 0, g;
  463. while ((c = *string++) != '\0') {
  464. h = ( h << 4 ) + c;
  465. if ( g = h & 0xF0000000 )
  466. h ^= g >> 24;
  467. h &= ~g;
  468. }
  469. return h;
  470. #elif HASH_PERL
  471. register int val = 0;
  472. while ((c = *string++) != '\0') {
  473. val += c;
  474. val += (val << 10);
  475. val ^= (val >> 6);
  476. }
  477. val += (val << 3);
  478. val ^= (val >> 11);
  479. return val + (val << 15);
  480. #else
  481. register int val = 0;
  482. while ((c = *string++) != '\0') {
  483. val = val*997 + c;
  484. }
  485. return val + (val>>5);
  486. #endif
  487. }
  488. static int
  489. numcmp(x, y)
  490. long x, y;
  491. {
  492. return x != y;
  493. }
  494. static int
  495. numhash(n)
  496. long n;
  497. {
  498. return n;
  499. }