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