21
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
/* modified 05 Jan 2000 by Paul B. McBride (pmcbride@tiac.net) */
25
24
/*=============================================================
26
* table.c -- Hash table operations
27
* Copyright(c) 1991-94 by T.T. Wetmore IV; all rights reserved
28
* pre-SourceForge version information:
29
* 2.3.4 - 24 Jun 93 2.3.5 - 29 Aug 93
30
* 3.0.0 - 04 Sep 94 3.0.2 - 22 Dec 94
32
*===========================================================*/
25
* table.c -- Provides a table container object
26
* This provides type-safe tables
27
* These tables are reference counted objects
28
* This uses either hashtbl or rbtree for storage
29
*==============================================================*/
35
31
#include "llstdlib.h"
37
#include "lloptions.h"
39
39
/*********************************************
40
40
* local enums & defines
41
41
*********************************************/
43
#define MAXHASH_DEF 512
47
TB_PTR /* VPTR values */
48
, TB_INT /* INT values */
49
, TB_STR /* STRING values */
50
, TB_NULL /* placeholder for newly created tables */
45
TB_NULL /* (not used) */
46
, TB_INT /* table of integers */
47
, TB_STR /* table of strings */
48
, TB_HPTR /* table of heap pointers (table frees them) */
49
, TB_VPTR /* table of void pointers (table does not free) */
50
, TB_OBJ /* table of objects */
53
53
/*********************************************
55
*********************************************/
57
/* table object itself */
59
struct tag_vtable *vtable; /* generic object */
60
INT refcnt; /* ref-countable object */
61
enum TB_VALTYPE valtype;
62
DELFUNC destroyfunc; /* how to destroy elements */
66
/* typedef struct tag_table *TABLE */ /* in table.h */
69
struct tag_table_iter {
70
struct tag_vtable *vtable; /* generic object */
71
INT refcnt; /* ref-countable object */
72
HASHTAB_ITER hashtab_iter;
75
/* typedef struct tag_table_iter * TABLE_ITER; */ /* in table.h */
77
/*********************************************
54
78
* local function prototypes
55
79
*********************************************/
58
static UNION* access_value_impl (TABLE tab, STRING key);
59
static ENTRY fndentry(TABLE, CNSTRING);
60
static void free_contents(ENTRY ent, INT whattofree);
61
static void insert_table_impl(TABLE tab, CNSTRING key, UNION uval);
62
static INT hash(TABLE tab, CNSTRING key);
63
static BOOLEAN next_element(TABLE_ITER tabit);
64
static void replace_table_impl(TABLE tab, STRING key, UNION uval, INT whattofree);
82
static TABLE create_table_impl(enum TB_VALTYPE valtype, DELFUNC delfunc);
83
static void free_table_iter(TABLE_ITER tabit);
84
static VPTR get_rb_value(RBTREE rbtree, CNSTRING key);
85
static void * llalloc(size_t size);
86
static void llassert(int assertion, const char* error);
87
static int rbcompare(RBKEY key1, RBKEY key2);
88
static void rbdestroy(void * param, RBKEY key, RBVALUE info);
89
static void rbdestroy_value(TABLE tab, RBVALUE info);
90
static VPTR rb_valueof(RBTREE rbtree, CNSTRING key, BOOLEAN *there);
91
static void tabit_destructor(VTABLE *obj);
65
92
static void table_destructor(VTABLE *obj);
66
static UNION* valueofbool_impl(TABLE tab, STRING key);
93
static void table_element_destructor(void * el);
94
static void table_element_obj_destructor(void *el);
68
96
/*********************************************
86
124
*********************************************/
88
/*======================
89
* hash -- Hash function
90
*====================*/
92
hash (TABLE tab, CNSTRING key)
98
if (hval < 0) hval += tab->maxhash;
99
if (hval < 0) FATAL();
100
if(hval >= tab->maxhash) FATAL();
103
/*================================
104
* fndentry -- Find entry in table
105
*==============================*/
107
fndentry (TABLE tab, CNSTRING key)
110
if (!tab || !key) return NULL;
111
entry = tab->entries[hash(tab, key)];
113
if (eqstr(key, entry->ekey)) return entry;
114
entry = entry->enext;
118
/*=============================
119
* create_table -- Create table
120
*===========================*/
122
create_table (INT whattofree)
126
/*=============================
127
* init_table_module -- Module initialization
128
*===========================*/
130
init_table_module (void)
132
/* Red/Black tree and stack modules need external assert & alloc handlers */
133
RbInitModule(&llassert, &llalloc);
135
/*=============================
136
* create_table_impl -- Create table
137
* All tables are created in this function
138
* returns addref'd table
139
*===========================*/
141
create_table_impl (enum TB_VALTYPE valtype, DELFUNC delfunc)
124
143
TABLE tab = (TABLE) stdalloc(sizeof(*tab));
126
memset(tab, 0, sizeof(*tab));
127
145
tab->vtable = &vtable_for_table;
129
tab->maxhash = MAXHASH_DEF;
130
tab->entries = (ENTRY *)stdalloc(tab->maxhash*sizeof(ENTRY));
132
tab->valtype = TB_NULL;
133
tab->whattofree = whattofree;
134
for (i = 0; i < tab->maxhash; i++)
135
tab->entries[i] = NULL;
147
tab->valtype = valtype;
148
if (getlloptstr("rbtree", 0))
149
tab->rbtree = RbTreeCreate(tab, rbcompare, rbdestroy);
151
tab->hashtab = create_hashtab();
152
tab->destroyfunc = delfunc;
138
155
/*=============================
139
* create_table_old -- Create table
140
*===========================*/
142
create_table_old (void)
144
return create_table(-1);
146
/*======================================
147
* insert_table_impl -- Insert key & value into table
148
* Caller is reponsible for both key & value memory
149
*====================================*/
151
insert_table_impl (TABLE tab, CNSTRING key, UNION uval)
153
ENTRY entry = fndentry(tab, key);
157
INT hval = hash(tab, key);
158
entry = (ENTRY) stdalloc(sizeof(*entry));
159
entry->ekey = (STRING)key;
161
entry->enext = tab->entries[hval];
162
tab->entries[hval] = entry;
166
/*======================================
167
* replace_table_impl -- Insert key & value into table
168
* replacing existing key & value if key already present
169
* Created: 2001/11/23, Perry Rapp
170
*====================================*/
172
replace_table_impl (TABLE tab, STRING key, UNION uval, INT whattofree)
174
ENTRY entry = fndentry(tab, key);
176
free_contents(entry, whattofree);
180
INT hval = hash(tab, key);
181
entry = (ENTRY) stdalloc(sizeof(*entry));
184
entry->enext = tab->entries[hval];
185
tab->entries[hval] = entry;
156
* create_table_int -- Create table holding integers
157
* returns addref'd table
158
*===========================*/
160
create_table_int (void)
162
return create_table_impl(TB_INT, table_element_destructor);
164
/*=============================
165
* create_table_str -- Create table holding heap strings
166
* (table dup & frees strings)
167
* returns addref'd table
168
*===========================*/
170
create_table_str (void)
172
return create_table_impl(TB_STR, table_element_destructor);
174
/*=============================
175
* create_table_hptr -- Create table holding heap pointers
176
* (ie, table will free elements)
177
* returns addref'd table
178
*===========================*/
180
create_table_hptr (void)
182
return create_table_impl(TB_HPTR, table_element_destructor);
184
/*=============================
185
* create_table_vptr -- Create table holding shared pointers
186
* (ie, table will not free elements)
187
* returns addref'd table
188
*===========================*/
190
create_table_vptr (void)
192
return create_table_impl(TB_VPTR, NULL);
194
/*=============================
195
* create_table_custom_vptr -- Create table holding pointers
196
* (table calls custom function to destroy elements)
197
* returns addref'd table
198
*===========================*/
200
create_table_custom_vptr (void (*destroyel)(void *ptr))
202
return create_table_impl(TB_VPTR, destroyel);
204
/*=============================
205
* create_table_obj -- Create table holding objects
206
* (ie, table will release them using release_object)
207
* returns addref'd table
208
*===========================*/
210
create_table_obj (void)
212
return create_table_impl(TB_OBJ, table_element_obj_destructor);
214
/*=================================================
215
* destroy_table -- destroy all element & memory for table
216
*===============================================*/
218
destroy_table (TABLE tab)
221
ASSERT(tab->vtable == &vtable_for_table);
223
/* should not be called for a shared table */
224
ASSERT(tab->refcnt==1 || tab->refcnt==0);
227
RbTreeDestroy(tab->rbtree);
229
destroy_hashtab(tab->hashtab, tab->destroyfunc);
230
memset(tab, 0, sizeof(*tab));
233
/*=================================================
234
* table_destructor -- destructor for table
235
* (destructor entry in vtable)
236
*===============================================*/
238
table_destructor (VTABLE *obj)
240
TABLE tab = (TABLE)obj;
243
/*=================================================
244
* table_element_destructor -- element destructor function
245
* used for all pointer tables except TB_VPTR
246
*===============================================*/
248
table_element_destructor (void * el)
252
/*=================================================
253
* table_element_obj_destructor -- object element destructor function
254
* used for object tables (TB_OBJ)
255
*===============================================*/
257
table_element_obj_destructor (void *el)
263
/*=================================================
264
* addref_table -- increment reference count of table
265
*===============================================*/
267
addref_table (TABLE tab)
269
ASSERT(tab->vtable == &vtable_for_table);
272
/*=================================================
273
* release_table -- decrement reference count of table
274
* and free if appropriate (ref count hits zero)
275
*===============================================*/
277
release_table (TABLE tab)
280
ASSERT(tab->vtable == &vtable_for_table);
286
/*======================================
287
* insert_table_int -- Insert key & INT value into table
288
*====================================*/
290
insert_table_int (TABLE tab, CNSTRING key, INT ival)
292
INT * newval = stdalloc(sizeof(*newval));
297
ASSERT(tab->valtype == TB_INT);
299
insert_table_ptr(tab, key, newval);
301
/*======================================
302
* insert_table_str -- Insert key & string value into table
303
*====================================*/
305
insert_table_str (TABLE tab, CNSTRING key, CNSTRING value)
307
insert_table_ptr(tab, key, strsave(value));
189
309
/*======================================
190
310
* insert_table_ptr -- Insert key & pointer value into table
191
* Caller is responsible for both key & ptr memory (no dups here)
192
* Created: 2001/06/03 (Perry Rapp)
193
311
*====================================*/
195
313
insert_table_ptr (TABLE tab, CNSTRING key, VPTR ptr)
199
if (tab->valtype == TB_NULL)
200
tab->valtype = TB_PTR;
201
/* table must be homogenous, not mixed-type */
202
ASSERT(tab->valtype == TB_PTR);
203
insert_table_impl(tab, key, uval);
205
/*======================================
206
* insert_table_int -- Insert key & INT value into table
207
* Caller is responsible for key memory (no dups here)
208
* Created: 2001/06/03 (Perry Rapp)
209
*====================================*/
211
insert_table_int (TABLE tab, CNSTRING key, INT ival)
215
if (tab->valtype == TB_NULL) {
216
ASSERT(tab->whattofree==-1 || (tab->whattofree!=FREEBOTH && tab->whattofree!=FREEVALUE));
217
tab->valtype = TB_INT;
318
ASSERT(tab->vtable == &vtable_for_table);
321
/* first see if key already exists, so we can just change value */
322
RBNODE node = RbExactQuery(tab->rbtree, key);
324
VPTR oldptr = RbGetInfo(node);
326
RbSetInfo(node, ptr);
327
rbdestroy_value(tab, oldptr);
331
RbTreeInsert(tab->rbtree, strsave(key), ptr);
333
oldval = insert_hashtab(tab->hashtab, key, ptr);
334
if (oldval && tab->destroyfunc) {
335
(*tab->destroyfunc)(oldval);
219
/* table must be homogenous, not mixed-type */
220
ASSERT(tab->valtype == TB_INT);
221
insert_table_impl(tab, key, uval);
223
339
/*======================================
224
* insert_table_str -- Insert key & STRING value into table
225
* Caller is responsible for both key & ptr memory (no dups here)
226
* Created: 2001/06/03 (Perry Rapp)
340
* insert_table_obj -- Insert key & object into table
341
* table addrefs the object
227
342
*====================================*/
229
insert_table_str (TABLE tab, CNSTRING key, STRING str)
344
insert_table_obj (TABLE tab, CNSTRING key, VPTR obj)
233
if (tab->valtype == TB_NULL)
234
tab->valtype = TB_STR;
235
/* table must be homogenous, not mixed-type */
236
ASSERT(tab->valtype == TB_STR);
237
insert_table_impl(tab, key, uval);
348
insert_table_ptr(tab, key, obj);
239
350
/*======================================
240
351
* replace_table_str -- Insert or replace
282
390
in_table (TABLE tab, CNSTRING key)
284
return fndentry(tab, key) != NULL;
286
/*===============================
287
* valueof_ptr -- Find pointer value of entry
288
* Created: 2001/06/03 (Perry Rapp)
289
*=============================*/
291
valueof_ptr (TABLE tab, CNSTRING key)
294
if (!tab->count || !key) return NULL;
295
ASSERT(tab->valtype == TB_PTR);
296
if ((entry = fndentry(tab, key)))
297
return entry->uval.w;
393
ASSERT(tab->vtable == &vtable_for_table);
396
return RbExactQuery(tab->rbtree, key) != 0;
398
return in_hashtab(tab->hashtab, key);
301
401
/*===============================
302
402
* valueof_int -- Find int value of entry
303
* return defval if missing
403
* return 0 if missing
304
404
* Created: 2001/06/03 (Perry Rapp)
305
405
*=============================*/
307
valueof_int (TABLE tab, CNSTRING key, INT defval)
407
valueof_int (TABLE tab, CNSTRING key)
310
if (!tab->count || !key) return defval;
412
ASSERT(tab->vtable == &vtable_for_table);
311
413
ASSERT(tab->valtype == TB_INT);
312
if ((entry = fndentry(tab, key)))
313
return entry->uval.i;
416
val = get_rb_value(tab->rbtree, key);
418
val = find_hashtab(tab->hashtab, key, NULL);
420
return (val ? *val : 0);
317
422
/*===============================
318
423
* valueof_str -- Find string value of entry
319
* Created: 2001/06/03 (Perry Rapp)
320
424
*=============================*/
322
426
valueof_str (TABLE tab, CNSTRING key)
325
if (!tab->count || !key) return NULL;
429
ASSERT(tab->vtable == &vtable_for_table);
326
430
ASSERT(tab->valtype == TB_STR);
327
if ((entry = fndentry(tab, key)))
328
return entry->uval.w;
332
/*===================================
333
* valueofbool_impl -- Find value of entry
334
*=================================*/
336
valueofbool_impl (TABLE tab, STRING key)
339
if (!tab->count || !key) return NULL;
340
if ((entry = fndentry(tab, key))) {
345
/*===================================
346
* valueofbool_ptr -- Find pointer value of entry
347
* BOOLEAN *there: [OUT] FALSE if not found
348
* Created: 2001/06/03 (Perry Rapp)
349
*=================================*/
351
valueofbool_ptr (TABLE tab, STRING key, BOOLEAN *there)
353
UNION * val = valueofbool_impl(tab, key);
355
ASSERT(tab->valtype == TB_PTR);
433
return (STRING)get_rb_value(tab->rbtree, key);
435
return (STRING)find_hashtab(tab->hashtab, key, NULL);
440
/*===============================
441
* valueof_ptr -- Find pointer value of entry
442
*=============================*/
444
valueof_ptr (TABLE tab, CNSTRING key)
447
ASSERT(tab->vtable == &vtable_for_table);
448
ASSERT(tab->valtype == TB_HPTR || tab->valtype == TB_VPTR);
451
return (STRING)get_rb_value(tab->rbtree, key);
453
return find_hashtab(tab->hashtab, key, NULL);
456
/*===============================
457
* valueof_obj -- Find object value of entry
458
*=============================*/
460
valueof_obj (TABLE tab, CNSTRING key)
463
ASSERT(tab->vtable == &vtable_for_table);
464
ASSERT(tab->valtype == TB_OBJ);
467
return get_rb_value(tab->rbtree, key);
469
return find_hashtab(tab->hashtab, key, NULL);
363
472
/*===================================
364
473
* valueofbool_int -- Find pointer value of entry
365
474
* BOOLEAN *there: [OUT] FALSE if not found
366
* Created: 2001/06/03 (Perry Rapp)
367
475
*=================================*/
369
valueofbool_int (TABLE tab, STRING key, BOOLEAN *there)
477
valueofbool_int (TABLE tab, CNSTRING key, BOOLEAN *there)
371
UNION * val = valueofbool_impl(tab, key);
373
ASSERT(tab->valtype == TB_INT);
482
ASSERT(tab->vtable == &vtable_for_table);
483
ASSERT(tab->valtype == TB_INT);
486
val = (INT *)rb_valueof(tab->rbtree, key, there);
488
val = find_hashtab(tab->hashtab, key, there);
490
return val ? *val : 0;
381
492
/*===================================
382
493
* valueofbool_str -- Find string value of entry
383
494
* BOOLEAN *there: [OUT] FALSE if not found
384
* Created: 2001/06/03 (Perry Rapp)
385
495
*=================================*/
387
valueofbool_str (TABLE tab, STRING key, BOOLEAN *there)
389
UNION * val = valueofbool_impl(tab, key);
391
ASSERT(tab->valtype == TB_STR);
399
/*===================================
400
* access_value_impl -- get pointer to value
401
* returns NULL if not found
402
* Created: 2001/01/01, Perry Rapp
403
*=================================*/
405
access_value_impl (TABLE tab, STRING key)
408
if (!tab->count || !key) return NULL;
409
if (NULL == (entry = fndentry(tab, key)))
413
/*===================================
414
* access_value_ptr -- get pointer to VPTR value
415
* returns NULL if not found
416
* Created: 2001/06/03 (Perry Rapp)
417
*=================================*/
419
access_value_ptr (TABLE tab, STRING key)
421
UNION * val = access_value_impl(tab, key);
422
if (!val) return NULL;
423
ASSERT(tab->valtype == TB_PTR);
426
/*===================================
427
* access_value_int -- get pointer to int value
428
* returns NULL if not found
429
* Created: 2001/06/03 (Perry Rapp)
430
*=================================*/
432
access_value_int (TABLE tab, STRING key)
434
UNION * val = access_value_impl(tab, key);
435
if (!val) return NULL;
436
ASSERT(tab->valtype == TB_INT);
439
/*===================================
440
* access_value_str -- get pointer to string value
441
* returns NULL if not found
442
* Created: 2003/06/16 (Matt Emmerton)
443
*=================================*/
445
access_value_str (TABLE tab, STRING key)
447
UNION * val = access_value_impl(tab, key);
448
if (!val) return NULL;
497
valueofbool_str (TABLE tab, CNSTRING key, BOOLEAN *there)
500
ASSERT(tab->vtable == &vtable_for_table);
449
501
ASSERT(tab->valtype == TB_STR);
452
/*=============================
453
* remove_table -- Remove table
455
* INT whattofree: FREEKEY, DONTFREE, etc
456
*===========================*/
504
return rb_valueof(tab->rbtree, key, there);
506
return (STRING)find_hashtab(tab->hashtab, key, there);
509
/*===================================
510
* valueofbool_ptr -- Find pointer value of entry
511
* BOOLEAN *there: [OUT] FALSE if not found
512
*=================================*/
514
valueofbool_ptr (TABLE tab, CNSTRING key, BOOLEAN *there)
517
ASSERT(tab->vtable == &vtable_for_table);
518
ASSERT(tab->valtype == TB_HPTR || tab->valtype == TB_VPTR);
521
return rb_valueof(tab->rbtree, key, there);
523
return find_hashtab(tab->hashtab, key, there);
526
/*===================================
527
* valueofbool_obj -- Find object value of entry
528
* BOOLEAN *there: [OUT] FALSE if not found
529
*=================================*/
531
valueofbool_obj (TABLE tab, CNSTRING key, BOOLEAN *there)
534
ASSERT(tab->vtable == &vtable_for_table);
535
ASSERT(tab->valtype == TB_OBJ);
538
return rb_valueof(tab->rbtree, key, there);
540
return find_hashtab(tab->hashtab, key, there);
543
/*=================================================
544
* begin_table_iter -- Begin iteration of table
545
* returns addref'd iterator object
546
*===============================================*/
548
begin_table_iter (TABLE tab)
550
TABLE_ITER tabit = (TABLE_ITER)stdalloc(sizeof(*tabit));
553
tabit->rbit = RbBeginIter(tab->rbtree, 0, 0);
555
tabit->hashtab_iter = begin_hashtab(tab->hashtab);
559
/*=================================================
560
* next_table_ptr -- Advance to next pointer in table
561
* skips over any other types of table elements
562
* returns FALSE if runs out of table elements
563
*===============================================*/
565
next_table_ptr (TABLE_ITER tabit, CNSTRING *pkey, VPTR *pptr)
568
return RbNext(tabit->rbit, (RBKEY *)pkey, pptr);
570
return next_hashtab(tabit->hashtab_iter, pkey, pptr);
572
/*=================================================
573
* next_table_int -- Advance to next int in table
574
* skips over any other types of table elements
575
* returns FALSE if runs out of table elements
576
*===============================================*/
578
next_table_int (TABLE_ITER tabit, CNSTRING *pkey, INT * pival)
582
if (!RbNext(tabit->rbit, (RBKEY *)pkey, &val))
585
if (!next_hashtab(tabit->hashtab_iter, pkey, &val))
589
*pival = *(INT *)val;
592
/*=================================================
593
* end_table_iter -- Release reference to table iterator object
594
*===============================================*/
458
remove_table (TABLE tab, INT whattofree)
596
end_table_iter (TABLE_ITER * ptabit)
463
if (tab->whattofree!=-1) { ASSERT(whattofree==tab->whattofree); }
464
if (tab->valtype == TB_INT) {
465
/* can't free INTs */
466
ASSERT(whattofree != FREEBOTH && whattofree != FREEVALUE);
468
for (i = 0; i < tab->maxhash; i++) {
469
nxt = tab->entries[i];
470
while ((ent = nxt)) {
472
free_contents(ent, whattofree);
476
stdfree(tab->entries);
601
if (!(*ptabit)->refcnt) {
602
free_table_iter(*ptabit);
479
606
/*=================================================
480
* free_contents -- Free key and/or value as appropriate
607
* free_table_iter -- Delete & free table iterator object
481
608
*===============================================*/
483
free_contents (ENTRY ent, INT whattofree)
485
if (whattofree==FREEBOTH || whattofree==FREEKEY)
487
if (whattofree==FREEBOTH || whattofree==FREEVALUE) {
489
stdfree(ent->uval.w);
492
/*=================================================
493
* traverse_table -- Traverse table doing something
494
* tproc: callback for each entry
495
*===============================================*/
497
traverse_table (TABLE tab, void (*tproc)(ENTRY))
501
if (!tab || !tproc) return;
502
for (i = 0; i < tab->maxhash; i++) {
503
nxt = tab->entries[i];
504
while ((ent = nxt)) {
510
/*=================================================
511
* traverse_table_param -- Traverse table doing something, with extra callback param
512
* also, use return value of proc to allow abort (proc returns 0 for abort)
513
* Created: 2001/01/01, Perry Rapp
514
*===============================================*/
516
traverse_table_param (TABLE tab,
517
INT (*tproc)(ENTRY, VPTR),
522
if (!tab || !tproc) return;
523
for (i = 0; i < tab->maxhash; i++) {
524
nxt = tab->entries[i];
525
while ((ent = nxt)) {
527
if (!(*tproc)(ent, param))
532
/*=================================================
533
* begin_table -- Begin iteration of table
534
* Created: 2002/06/16, Perry Rapp
535
*===============================================*/
537
begin_table (TABLE tab, TABLE_ITER tabit)
610
free_table_iter (TABLE_ITER tabit)
613
ASSERT(!tabit->refcnt);
615
end_hashtab(&tabit->hashtab_iter);
539
617
memset(tabit, 0, sizeof(*tabit));
543
return tabit->table->count>0;
545
/*=================================================
546
* next_element -- Find next element in table (iterating)
547
* Created: 2002/06/16, Perry Rapp
548
*===============================================*/
550
next_element (TABLE_ITER tabit)
552
if (tabit->index == -1 || tabit->table->count == 0)
555
tabit->enext = tabit->enext->enext;
560
for ( ; tabit->index < tabit->table->maxhash; ++tabit->index) {
561
tabit->enext = tabit->table->entries[tabit->index];
569
/*=================================================
570
* next_table_str -- Iterating table with strings
571
* Created: 2002/06/16, Perry Rapp
572
*===============================================*/
574
next_table_str (TABLE_ITER tabit, STRING *pkey, STRING *pstr)
576
ASSERT(tabit->table->valtype == TB_STR || tabit->table->valtype == TB_NULL);
577
if (!next_element(tabit)) {
582
*pkey = tabit->enext->ekey;
583
*pstr = tabit->enext->uval.w;
586
/*=================================================
587
* next_table_ptr -- Iterating table with pointers
588
* Created: 2002/06/16, Perry Rapp
589
*===============================================*/
591
next_table_ptr (TABLE_ITER tabit, STRING *pkey, VPTR *pptr)
593
ASSERT(tabit->table->valtype == TB_PTR || tabit->table->valtype == TB_NULL);
594
if (!next_element(tabit)) {
599
*pkey = tabit->enext->ekey;
600
*pptr = tabit->enext->uval.w;
603
/*=================================================
604
* change_table_ptr -- User changing value in iteration
605
* Created: 2002/06/17, Perry Rapp
606
*===============================================*/
608
change_table_ptr (TABLE_ITER tabit, VPTR newptr)
610
if (!tabit || !tabit->enext)
612
tabit->enext->uval.w = newptr;
615
620
/*=================================================
616
621
* get_table_count -- Return #elements
620
625
get_table_count (TABLE tab)
622
627
if (!tab) return 0;
629
ASSERT(tab->vtable == &vtable_for_table);
632
return RbGetCount(tab->rbtree);
634
return get_hashtab_count(tab->hashtab);
625
636
/*=================================================
626
637
* copy_table -- Copy all elements from src to dest
627
* Created: 2002/02/17, Perry Rapp
628
*===============================================*/
630
copy_table (const TABLE src, TABLE dest, INT whattodup)
634
BOOLEAN dupkey = whattodup&FREEBOTH || whattodup&FREEKEY;
635
BOOLEAN dupval = whattodup&FREEBOTH || whattodup&FREEVALUE;
637
ASSERT(get_table_count(dest)==0);
638
if (get_table_count(src)==0)
640
ASSERT(!dupval || src->valtype==TB_STR); /* can only dup strings */
642
dest->valtype = src->valtype;
643
if (src->maxhash == dest->maxhash)
644
dest->count = src->count;
646
for (i = 0; i < src->maxhash; i++) {
647
nxt = src->entries[i];
648
while ((ent = nxt)) {
649
UNION uval = ent->uval;
650
STRING key = ent->ekey;
651
if (dupkey) key = strsave(key);
652
if (dupval) uval.w = strsave(uval.w);
653
if (src->maxhash == dest->maxhash) {
654
/* copy src item directly into dest (skip hashing) */
655
ENTRY entry = (ENTRY) stdalloc(sizeof(*entry));
658
entry->enext = dest->entries[i];
659
dest->entries[i] = entry;
661
/* insert src item into dest */
662
insert_table_impl(dest, key, uval);
668
/*=================================================
669
* destroy_table -- public destructor for a table
670
*===============================================*/
672
destroy_table (TABLE tab)
675
/* to use this (and I'd prefer all code to use this)
676
the whattofree must have been set, so I plan to revise
677
all code to set it at creation time */
678
ASSERT(tab->whattofree != -1);
679
remove_table(tab, tab->whattofree);
681
/*=================================================
682
* table_destructor -- destructor for vtable
683
*===============================================*/
685
table_destructor (VTABLE *obj)
687
TABLE tab = (TABLE)obj;
688
ASSERT((*obj) == &vtable_for_table);
638
*===============================================*/
640
copy_table (const TABLE src, TABLE dest)
642
if (!src || !dest) return;
644
ASSERT(src->vtable == &vtable_for_table);
645
ASSERT(dest->vtable == &vtable_for_table);
647
if (src->valtype == TB_INT) {
648
TABLE_ITER tabit = begin_table_iter(src);
651
ASSERT(dest->valtype == TB_INT);
652
while (next_table_int(tabit, &key, &ival)) {
653
insert_table_int(dest, key, ival);
655
end_table_iter(&tabit);
659
if (src->valtype == TB_STR) {
660
TABLE_ITER tabit = begin_table_iter(src);
663
ASSERT(dest->valtype == src->valtype);
664
while (next_table_ptr(tabit, &key, &val)) {
665
insert_table_str(dest, key, val);
667
end_table_iter(&tabit);
671
if (src->valtype == TB_HPTR) {
675
if (src->valtype == TB_VPTR) {
676
TABLE_ITER tabit = begin_table_iter(src);
679
ASSERT(dest->valtype == src->valtype);
680
while (next_table_ptr(tabit, &key, &val)) {
681
insert_table_ptr(dest, key, val);
683
end_table_iter(&tabit);
687
if (src->valtype == TB_OBJ) {
688
TABLE_ITER tabit = begin_table_iter(src);
691
ASSERT(dest->valtype == src->valtype);
692
while (next_table_ptr(tabit, &key, &val)) {
694
insert_table_obj(dest, key, val);
696
end_table_iter(&tabit);
702
/*=================================================
703
* tabit_destructor -- destructor for table iterator
704
* (vtable destructor)
705
*===============================================*/
707
tabit_destructor (VTABLE *obj)
709
TABLE_ITER tabit = (TABLE_ITER)obj;
710
ASSERT(tabit->vtable == &vtable_for_tabit);
711
free_table_iter(tabit);
713
/*=================================================
714
* increment_table_int -- increment an integer element value
715
* set to 1 if not found
716
*===============================================*/
718
increment_table_int (TABLE tab, CNSTRING key)
721
INT value = valueofbool_int(tab, key, &found);
723
insert_table_int(tab, key, value+1);
725
insert_table_int(tab, key, 1);
728
/*=================================================
729
* llassert -- Implement assertion
730
* (for rbtree module, which does not include lifelines headers)
731
*===============================================*/
733
llassert (int assertion, const char* error)
739
/*=================================================
740
* llalloc -- Implement alloc
741
* (for rbtree module, which does not include lifelines headers)
742
*===============================================*/
744
llalloc (size_t size)
746
return stdalloc(size);
748
/*=================================================
749
* rbcompare -- compare two rbtree keys
750
* (for rbtree module, which treats keys as opaque)
751
*===============================================*/
753
rbcompare (RBKEY key1, RBKEY key2)
755
return cmpstrloc(key1, key2);
757
/*=================================================
758
* rbdestroy -- Destructor for key & value of rbtree
759
* (for rbtree module, which does not manage key or value memory)
760
*===============================================*/
762
rbdestroy (void * param, RBKEY key, RBVALUE info)
764
stdfree((void *)key);
765
rbdestroy_value((TABLE)param, info);
767
/*=================================================
768
* rbdestroy_value -- Destroy value stored in rbtree
769
* (for rbtree module, which does not manage key or value memory)
770
*===============================================*/
772
rbdestroy_value (TABLE tab, RBVALUE info)
774
if (tab->destroyfunc) {
775
(*tab->destroyfunc)(info);
778
switch(tab->valtype) {
782
table_element_destructor(info);
785
table_element_obj_destructor(info);
791
/*=================================================
792
* get_rb_value -- Shortcut fetch of value from rbtree key
793
*===============================================*/
795
get_rb_value (RBTREE rbtree, CNSTRING key)
797
RBNODE node = RbExactQuery(rbtree, key);
798
return node ? RbGetInfo(node) : 0;
800
/*=================================================
801
* rb_valueof -- Get value & set *there to indicate presence
802
*===============================================*/
804
rb_valueof (RBTREE rbtree, CNSTRING key, BOOLEAN *there)
806
RBNODE node = RbExactQuery(rbtree, key);
809
return node ? RbGetInfo(node) : 0;