1 /*
2 Copyright (c) 1991-1999 Thomas T. Wetmore IV
3
4 Permission is hereby granted, free of charge, to any person
5 obtaining a copy of this software and associated documentation
6 files (the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use, copy,
8 modify, merge, publish, distribute, sublicense, and/or sell copies
9 of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 /*=============================================================
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 *==============================================================*/
30
31 #include "llstdlib.h"
32 #include "vtable.h"
33 #include "table.h"
34 #include "object.h"
35 #include "hashtab.h"
36 #include "rbtree.h"
37 #include "lloptions.h"
38
39 /*********************************************
40 * local enums & defines
41 *********************************************/
42
43 enum TB_VALTYPE
44 {
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 */
51 };
52
53 /*********************************************
54 * local types
55 *********************************************/
56
57 /* table object itself */
58 struct tag_table {
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 */
63 HASHTAB hashtab;
64 RBTREE rbtree;
65 };
66 /* typedef struct tag_table *TABLE */ /* in table.h */
67
68 /* table iterator */
69 struct tag_table_iter {
70 struct tag_vtable *vtable; /* generic object */
71 INT refcnt; /* ref-countable object */
72 HASHTAB_ITER hashtab_iter;
73 RBITER rbit;
74 };
75 /* typedef struct tag_table_iter * TABLE_ITER; */ /* in table.h */
76
77 /*********************************************
78 * local function prototypes
79 *********************************************/
80
81 /* alphabetical */
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);
92 static void table_destructor(VTABLE *obj);
93 static void table_element_destructor(void * el);
94 static void table_element_obj_destructor(void *el);
95
96 /*********************************************
97 * local variables
98 *********************************************/
99
100 static struct tag_vtable vtable_for_table = {
101 VTABLE_MAGIC
102 , "table"
103 , &table_destructor
104 , &refcountable_isref
105 , &refcountable_addref
106 , &refcountable_release
107 , 0 /* copy_fnc */
108 , &generic_get_type_name
109 };
110 static struct tag_vtable vtable_for_tabit = {
111 VTABLE_MAGIC
112 , "table_iter"
113 , &tabit_destructor
114 , &refcountable_isref
115 , &refcountable_addref
116 , &refcountable_release
117 , 0 /* copy_fnc */
118 , &generic_get_type_name
119 };
120
121 /*********************************************
122 * local & exported function definitions
123 * body of module
124 *********************************************/
125
126 /*=============================
127 * init_table_module -- Module initialization
128 *===========================*/
129 void
init_table_module(void)130 init_table_module (void)
131 {
132 /* Red/Black tree and stack modules need external assert & alloc handlers */
133 RbInitModule(&llassert, &llalloc);
134 }
135 /*=============================
136 * create_table_impl -- Create table
137 * All tables are created in this function
138 * returns addref'd table
139 *===========================*/
140 static TABLE
create_table_impl(enum TB_VALTYPE valtype,DELFUNC delfunc)141 create_table_impl (enum TB_VALTYPE valtype, DELFUNC delfunc)
142 {
143 TABLE tab = (TABLE) stdalloc(sizeof(*tab));
144
145 tab->vtable = &vtable_for_table;
146 tab->refcnt = 1;
147 tab->valtype = valtype;
148 if (getlloptstr("rbtree", 0))
149 tab->rbtree = RbTreeCreate(tab, rbcompare, rbdestroy);
150 else
151 tab->hashtab = create_hashtab();
152 tab->destroyfunc = delfunc;
153 return tab;
154 }
155 /*=============================
156 * create_table_int -- Create table holding integers
157 * returns addref'd table
158 *===========================*/
159 TABLE
create_table_int(void)160 create_table_int (void)
161 {
162 return create_table_impl(TB_INT, table_element_destructor);
163 }
164 /*=============================
165 * create_table_str -- Create table holding heap strings
166 * (table dup & frees strings)
167 * returns addref'd table
168 *===========================*/
169 TABLE
create_table_str(void)170 create_table_str (void)
171 {
172 return create_table_impl(TB_STR, table_element_destructor);
173 }
174 /*=============================
175 * create_table_hptr -- Create table holding heap pointers
176 * (ie, table will free elements)
177 * returns addref'd table
178 *===========================*/
179 TABLE
create_table_hptr(void)180 create_table_hptr (void)
181 {
182 return create_table_impl(TB_HPTR, table_element_destructor);
183 }
184 /*=============================
185 * create_table_vptr -- Create table holding shared pointers
186 * (ie, table will not free elements)
187 * returns addref'd table
188 *===========================*/
189 TABLE
create_table_vptr(void)190 create_table_vptr (void)
191 {
192 return create_table_impl(TB_VPTR, NULL);
193 }
194 /*=============================
195 * create_table_custom_vptr -- Create table holding pointers
196 * (table calls custom function to destroy elements)
197 * returns addref'd table
198 *===========================*/
199 TABLE
create_table_custom_vptr(void (* destroyel)(void * ptr))200 create_table_custom_vptr (void (*destroyel)(void *ptr))
201 {
202 return create_table_impl(TB_VPTR, destroyel);
203 }
204 /*=============================
205 * create_table_obj -- Create table holding objects
206 * (ie, table will release them using release_object)
207 * returns addref'd table
208 *===========================*/
209 TABLE
create_table_obj(void)210 create_table_obj (void)
211 {
212 return create_table_impl(TB_OBJ, table_element_obj_destructor);
213 }
214 /*=================================================
215 * destroy_table -- destroy all element & memory for table
216 *===============================================*/
217 void
destroy_table(TABLE tab)218 destroy_table (TABLE tab)
219 {
220 if (!tab) return;
221 ASSERT(tab->vtable == &vtable_for_table);
222
223 /* should not be called for a shared table */
224 ASSERT(tab->refcnt==1 || tab->refcnt==0);
225
226 if (tab->rbtree)
227 RbTreeDestroy(tab->rbtree);
228 else
229 destroy_hashtab(tab->hashtab, tab->destroyfunc);
230 memset(tab, 0, sizeof(*tab));
231 stdfree(tab);
232 }
233 /*=================================================
234 * table_destructor -- destructor for table
235 * (destructor entry in vtable)
236 *===============================================*/
237 static void
table_destructor(VTABLE * obj)238 table_destructor (VTABLE *obj)
239 {
240 TABLE tab = (TABLE)obj;
241 destroy_table(tab);
242 }
243 /*=================================================
244 * table_element_destructor -- element destructor function
245 * used for all pointer tables except TB_VPTR
246 *===============================================*/
247 static void
table_element_destructor(void * el)248 table_element_destructor (void * el)
249 {
250 stdfree(el);
251 }
252 /*=================================================
253 * table_element_obj_destructor -- object element destructor function
254 * used for object tables (TB_OBJ)
255 *===============================================*/
256 static void
table_element_obj_destructor(void * el)257 table_element_obj_destructor (void *el)
258 {
259 if (el) {
260 release_object(el);
261 }
262 }
263 /*=================================================
264 * addref_table -- increment reference count of table
265 *===============================================*/
266 void
addref_table(TABLE tab)267 addref_table (TABLE tab)
268 {
269 ASSERT(tab->vtable == &vtable_for_table);
270 ++tab->refcnt;
271 }
272 /*=================================================
273 * release_table -- decrement reference count of table
274 * and free if appropriate (ref count hits zero)
275 *===============================================*/
276 void
release_table(TABLE tab)277 release_table (TABLE tab)
278 {
279 if (!tab) return;
280 ASSERT(tab->vtable == &vtable_for_table);
281 --tab->refcnt;
282 if (!tab->refcnt) {
283 destroy_table(tab);
284 }
285 }
286 /*======================================
287 * insert_table_int -- Insert key & INT value into table
288 *====================================*/
289 void
insert_table_int(TABLE tab,CNSTRING key,INT ival)290 insert_table_int (TABLE tab, CNSTRING key, INT ival)
291 {
292 INT * newval = stdalloc(sizeof(*newval));
293
294 *newval = ival;
295
296 ASSERT(tab);
297 ASSERT(tab->valtype == TB_INT);
298
299 insert_table_ptr(tab, key, newval);
300 }
301 /*======================================
302 * insert_table_str -- Insert key & string value into table
303 *====================================*/
304 void
insert_table_str(TABLE tab,CNSTRING key,CNSTRING value)305 insert_table_str (TABLE tab, CNSTRING key, CNSTRING value)
306 {
307 insert_table_ptr(tab, key, strsave(value));
308 }
309 /*======================================
310 * insert_table_ptr -- Insert key & pointer value into table
311 *====================================*/
312 void
insert_table_ptr(TABLE tab,CNSTRING key,VPTR ptr)313 insert_table_ptr (TABLE tab, CNSTRING key, VPTR ptr)
314 {
315 INT * oldval = 0;
316
317 ASSERT(tab);
318 ASSERT(tab->vtable == &vtable_for_table);
319
320 if (tab->rbtree) {
321 /* first see if key already exists, so we can just change value */
322 RBNODE node = RbExactQuery(tab->rbtree, key);
323 if (node) {
324 VPTR oldptr = RbGetInfo(node);
325 if (oldptr != ptr) {
326 RbSetInfo(node, ptr);
327 rbdestroy_value(tab, oldptr);
328 }
329 return;
330 }
331 RbTreeInsert(tab->rbtree, strsave(key), ptr);
332 } else {
333 oldval = insert_hashtab(tab->hashtab, key, ptr);
334 if (oldval && tab->destroyfunc) {
335 (*tab->destroyfunc)(oldval);
336 }
337 }
338 }
339 /*======================================
340 * insert_table_obj -- Insert key & object into table
341 * table addrefs the object
342 *====================================*/
343 void
insert_table_obj(TABLE tab,CNSTRING key,VPTR obj)344 insert_table_obj (TABLE tab, CNSTRING key, VPTR obj)
345 {
346 if (obj)
347 addref_object(obj);
348 insert_table_ptr(tab, key, obj);
349 }
350 /*======================================
351 * replace_table_str -- Insert or replace
352 * key & value
353 * Created: 2001/11/23, Perry Rapp
354 *====================================*/
355 void
replace_table_str(TABLE tab,CNSTRING key,CNSTRING str)356 replace_table_str (TABLE tab, CNSTRING key, CNSTRING str)
357 {
358 /* insert function handles deleting old value */
359 insert_table_str(tab, key, str);
360 }
361 /*==========================================
362 * delete_table_element -- Delete element from table
363 * tab: [I/O] table from which to remove element
364 * key: [IN] key to find element to remove
365 * Destroys key and value as appropriate
366 *========================================*/
367 void
delete_table_element(TABLE tab,CNSTRING key)368 delete_table_element (TABLE tab, CNSTRING key)
369 {
370 void * oldval=0;
371
372 ASSERT(tab);
373 ASSERT(tab->vtable == &vtable_for_table);
374
375 if (tab->rbtree) {
376 RBNODE old = RbExactQuery(tab->rbtree, key);
377 if (old)
378 RbDeleteNode(tab->rbtree, old);
379 } else {
380 oldval = remove_hashtab(tab->hashtab, key);
381 if (oldval && tab->destroyfunc) {
382 (*tab->destroyfunc)(oldval);
383 }
384 }
385 }
386 /*======================================
387 * in_table() - Check for entry in table
388 *====================================*/
389 BOOLEAN
in_table(TABLE tab,CNSTRING key)390 in_table (TABLE tab, CNSTRING key)
391 {
392 ASSERT(tab);
393 ASSERT(tab->vtable == &vtable_for_table);
394
395 if (tab->rbtree) {
396 return RbExactQuery(tab->rbtree, key) != 0;
397 } else {
398 return in_hashtab(tab->hashtab, key);
399 }
400 }
401 /*===============================
402 * valueof_int -- Find int value of entry
403 * return 0 if missing
404 * Created: 2001/06/03 (Perry Rapp)
405 *=============================*/
406 INT
valueof_int(TABLE tab,CNSTRING key)407 valueof_int (TABLE tab, CNSTRING key)
408 {
409 INT * val=0;
410
411 ASSERT(tab);
412 ASSERT(tab->vtable == &vtable_for_table);
413 ASSERT(tab->valtype == TB_INT);
414
415 if (tab->rbtree) {
416 val = get_rb_value(tab->rbtree, key);
417 } else {
418 val = find_hashtab(tab->hashtab, key, NULL);
419 }
420 return (val ? *val : 0);
421 }
422 /*===============================
423 * valueof_str -- Find string value of entry
424 *=============================*/
425 STRING
valueof_str(TABLE tab,CNSTRING key)426 valueof_str (TABLE tab, CNSTRING key)
427 {
428 ASSERT(tab);
429 ASSERT(tab->vtable == &vtable_for_table);
430 ASSERT(tab->valtype == TB_STR);
431
432 if (tab->rbtree) {
433 return (STRING)get_rb_value(tab->rbtree, key);
434 } else {
435 return (STRING)find_hashtab(tab->hashtab, key, NULL);
436 }
437
438
439 }
440 /*===============================
441 * valueof_ptr -- Find pointer value of entry
442 *=============================*/
443 VPTR
valueof_ptr(TABLE tab,CNSTRING key)444 valueof_ptr (TABLE tab, CNSTRING key)
445 {
446 ASSERT(tab);
447 ASSERT(tab->vtable == &vtable_for_table);
448 ASSERT(tab->valtype == TB_HPTR || tab->valtype == TB_VPTR);
449
450 if (tab->rbtree) {
451 return (STRING)get_rb_value(tab->rbtree, key);
452 } else {
453 return find_hashtab(tab->hashtab, key, NULL);
454 }
455 }
456 /*===============================
457 * valueof_obj -- Find object value of entry
458 *=============================*/
459 VPTR
valueof_obj(TABLE tab,CNSTRING key)460 valueof_obj (TABLE tab, CNSTRING key)
461 {
462 ASSERT(tab);
463 ASSERT(tab->vtable == &vtable_for_table);
464 ASSERT(tab->valtype == TB_OBJ);
465
466 if (tab->rbtree) {
467 return get_rb_value(tab->rbtree, key);
468 } else {
469 return find_hashtab(tab->hashtab, key, NULL);
470 }
471 }
472 /*===================================
473 * valueofbool_int -- Find pointer value of entry
474 * BOOLEAN *there: [OUT] FALSE if not found
475 *=================================*/
476 INT
valueofbool_int(TABLE tab,CNSTRING key,BOOLEAN * there)477 valueofbool_int (TABLE tab, CNSTRING key, BOOLEAN *there)
478 {
479 INT * val=0;
480
481 ASSERT(tab);
482 ASSERT(tab->vtable == &vtable_for_table);
483 ASSERT(tab->valtype == TB_INT);
484
485 if (tab->rbtree) {
486 val = (INT *)rb_valueof(tab->rbtree, key, there);
487 } else {
488 val = find_hashtab(tab->hashtab, key, there);
489 }
490 return val ? *val : 0;
491 }
492 /*===================================
493 * valueofbool_str -- Find string value of entry
494 * BOOLEAN *there: [OUT] FALSE if not found
495 *=================================*/
496 STRING
valueofbool_str(TABLE tab,CNSTRING key,BOOLEAN * there)497 valueofbool_str (TABLE tab, CNSTRING key, BOOLEAN *there)
498 {
499 ASSERT(tab);
500 ASSERT(tab->vtable == &vtable_for_table);
501 ASSERT(tab->valtype == TB_STR);
502
503 if (tab->rbtree) {
504 return rb_valueof(tab->rbtree, key, there);
505 } else {
506 return (STRING)find_hashtab(tab->hashtab, key, there);
507 }
508 }
509 /*===================================
510 * valueofbool_ptr -- Find pointer value of entry
511 * BOOLEAN *there: [OUT] FALSE if not found
512 *=================================*/
513 VPTR
valueofbool_ptr(TABLE tab,CNSTRING key,BOOLEAN * there)514 valueofbool_ptr (TABLE tab, CNSTRING key, BOOLEAN *there)
515 {
516 ASSERT(tab);
517 ASSERT(tab->vtable == &vtable_for_table);
518 ASSERT(tab->valtype == TB_HPTR || tab->valtype == TB_VPTR);
519
520 if (tab->rbtree) {
521 return rb_valueof(tab->rbtree, key, there);
522 } else {
523 return find_hashtab(tab->hashtab, key, there);
524 }
525 }
526 /*===================================
527 * valueofbool_obj -- Find object value of entry
528 * BOOLEAN *there: [OUT] FALSE if not found
529 *=================================*/
530 VPTR
valueofbool_obj(TABLE tab,CNSTRING key,BOOLEAN * there)531 valueofbool_obj (TABLE tab, CNSTRING key, BOOLEAN *there)
532 {
533 ASSERT(tab);
534 ASSERT(tab->vtable == &vtable_for_table);
535 ASSERT(tab->valtype == TB_OBJ);
536
537 if (tab->rbtree) {
538 return rb_valueof(tab->rbtree, key, there);
539 } else {
540 return find_hashtab(tab->hashtab, key, there);
541 }
542 }
543 /*=================================================
544 * begin_table_iter -- Begin iteration of table
545 * returns addref'd iterator object
546 *===============================================*/
547 TABLE_ITER
begin_table_iter(TABLE tab)548 begin_table_iter (TABLE tab)
549 {
550 TABLE_ITER tabit = (TABLE_ITER)stdalloc(sizeof(*tabit));
551 ++tabit->refcnt;
552 if (tab->rbtree) {
553 tabit->rbit = RbBeginIter(tab->rbtree, 0, 0);
554 } else {
555 tabit->hashtab_iter = begin_hashtab(tab->hashtab);
556 }
557 return tabit;
558 }
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 *===============================================*/
564 BOOLEAN
next_table_ptr(TABLE_ITER tabit,CNSTRING * pkey,VPTR * pptr)565 next_table_ptr (TABLE_ITER tabit, CNSTRING *pkey, VPTR *pptr)
566 {
567 if (tabit->rbit)
568 return RbNext(tabit->rbit, (RBKEY *)pkey, pptr);
569 else
570 return next_hashtab(tabit->hashtab_iter, pkey, pptr);
571 }
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 *===============================================*/
577 BOOLEAN
next_table_int(TABLE_ITER tabit,CNSTRING * pkey,INT * pival)578 next_table_int (TABLE_ITER tabit, CNSTRING *pkey, INT * pival)
579 {
580 VPTR val=0;
581 if (tabit->rbit) {
582 if (!RbNext(tabit->rbit, (RBKEY *)pkey, &val))
583 return FALSE;
584 } else {
585 if (!next_hashtab(tabit->hashtab_iter, pkey, &val))
586 return FALSE;
587 }
588
589 *pival = *(INT *)val;
590 return TRUE;
591 }
592 /*=================================================
593 * end_table_iter -- Release reference to table iterator object
594 *===============================================*/
595 void
end_table_iter(TABLE_ITER * ptabit)596 end_table_iter (TABLE_ITER * ptabit)
597 {
598 ASSERT(ptabit);
599 ASSERT(*ptabit);
600 --(*ptabit)->refcnt;
601 if (!(*ptabit)->refcnt) {
602 free_table_iter(*ptabit);
603 }
604 *ptabit = 0;
605 }
606 /*=================================================
607 * free_table_iter -- Delete & free table iterator object
608 *===============================================*/
609 static void
free_table_iter(TABLE_ITER tabit)610 free_table_iter (TABLE_ITER tabit)
611 {
612 if (!tabit) return;
613 ASSERT(!tabit->refcnt);
614 if (!tabit->rbit) {
615 end_hashtab(&tabit->hashtab_iter);
616 }
617 memset(tabit, 0, sizeof(*tabit));
618 stdfree(tabit);
619 }
620 /*=================================================
621 * get_table_count -- Return #elements
622 * Created: 2002/02/17, Perry Rapp
623 *===============================================*/
624 INT
get_table_count(TABLE tab)625 get_table_count (TABLE tab)
626 {
627 if (!tab) return 0;
628
629 ASSERT(tab->vtable == &vtable_for_table);
630
631 if (tab->rbtree)
632 return RbGetCount(tab->rbtree);
633 else
634 return get_hashtab_count(tab->hashtab);
635 }
636 /*=================================================
637 * copy_table -- Copy all elements from src to dest
638 *===============================================*/
639 void
copy_table(const TABLE src,TABLE dest)640 copy_table (const TABLE src, TABLE dest)
641 {
642 if (!src || !dest) return;
643
644 ASSERT(src->vtable == &vtable_for_table);
645 ASSERT(dest->vtable == &vtable_for_table);
646
647 if (src->valtype == TB_INT) {
648 TABLE_ITER tabit = begin_table_iter(src);
649 CNSTRING key=0;
650 INT ival=0;
651 ASSERT(dest->valtype == TB_INT);
652 while (next_table_int(tabit, &key, &ival)) {
653 insert_table_int(dest, key, ival);
654 }
655 end_table_iter(&tabit);
656 return;
657 }
658
659 if (src->valtype == TB_STR) {
660 TABLE_ITER tabit = begin_table_iter(src);
661 CNSTRING key=0;
662 VPTR val=0;
663 ASSERT(dest->valtype == src->valtype);
664 while (next_table_ptr(tabit, &key, &val)) {
665 insert_table_str(dest, key, val);
666 }
667 end_table_iter(&tabit);
668 return;
669 }
670
671 if (src->valtype == TB_HPTR) {
672 ASSERT(0);
673 }
674
675 if (src->valtype == TB_VPTR) {
676 TABLE_ITER tabit = begin_table_iter(src);
677 CNSTRING key=0;
678 VPTR val=0;
679 ASSERT(dest->valtype == src->valtype);
680 while (next_table_ptr(tabit, &key, &val)) {
681 insert_table_ptr(dest, key, val);
682 }
683 end_table_iter(&tabit);
684 return;
685 }
686
687 if (src->valtype == TB_OBJ) {
688 TABLE_ITER tabit = begin_table_iter(src);
689 CNSTRING key=0;
690 VPTR val=0;
691 ASSERT(dest->valtype == src->valtype);
692 while (next_table_ptr(tabit, &key, &val)) {
693 addref_object(val);
694 insert_table_obj(dest, key, val);
695 }
696 end_table_iter(&tabit);
697 return;
698 }
699
700 ASSERT(0);
701 }
702 /*=================================================
703 * tabit_destructor -- destructor for table iterator
704 * (vtable destructor)
705 *===============================================*/
706 static void
tabit_destructor(VTABLE * obj)707 tabit_destructor (VTABLE *obj)
708 {
709 TABLE_ITER tabit = (TABLE_ITER)obj;
710 ASSERT(tabit->vtable == &vtable_for_tabit);
711 free_table_iter(tabit);
712 }
713 /*=================================================
714 * increment_table_int -- increment an integer element value
715 * set to 1 if not found
716 *===============================================*/
717 void
increment_table_int(TABLE tab,CNSTRING key)718 increment_table_int (TABLE tab, CNSTRING key)
719 {
720 BOOLEAN found=FALSE;
721 INT value = valueofbool_int(tab, key, &found);
722 if (found) {
723 insert_table_int(tab, key, value+1);
724 } else {
725 insert_table_int(tab, key, 1);
726 }
727 }
728 /*=================================================
729 * llassert -- Implement assertion
730 * (for rbtree module, which does not include lifelines headers)
731 *===============================================*/
732 static void
llassert(int assertion,const char * error)733 llassert (int assertion, const char* error)
734 {
735 if (assertion)
736 return;
737 FATAL2(error);
738 }
739 /*=================================================
740 * llalloc -- Implement alloc
741 * (for rbtree module, which does not include lifelines headers)
742 *===============================================*/
743 static void *
llalloc(size_t size)744 llalloc (size_t size)
745 {
746 return stdalloc(size);
747 }
748 /*=================================================
749 * rbcompare -- compare two rbtree keys
750 * (for rbtree module, which treats keys as opaque)
751 *===============================================*/
752 static int
rbcompare(RBKEY key1,RBKEY key2)753 rbcompare (RBKEY key1, RBKEY key2)
754 {
755 return cmpstrloc(key1, key2);
756 }
757 /*=================================================
758 * rbdestroy -- Destructor for key & value of rbtree
759 * (for rbtree module, which does not manage key or value memory)
760 *===============================================*/
761 static void
rbdestroy(void * param,RBKEY key,RBVALUE info)762 rbdestroy (void * param, RBKEY key, RBVALUE info)
763 {
764 stdfree((void *)key);
765 rbdestroy_value((TABLE)param, info);
766 }
767 /*=================================================
768 * rbdestroy_value -- Destroy value stored in rbtree
769 * (for rbtree module, which does not manage key or value memory)
770 *===============================================*/
771 static void
rbdestroy_value(TABLE tab,RBVALUE info)772 rbdestroy_value (TABLE tab, RBVALUE info)
773 {
774 if (tab->destroyfunc) {
775 (*tab->destroyfunc)(info);
776 return;
777 }
778 switch(tab->valtype) {
779 case TB_INT:
780 case TB_STR:
781 case TB_HPTR:
782 table_element_destructor(info);
783 break;
784 case TB_OBJ:
785 table_element_obj_destructor(info);
786 case TB_NULL:
787 case TB_VPTR:
788 ;
789 }
790 }
791 /*=================================================
792 * get_rb_value -- Shortcut fetch of value from rbtree key
793 *===============================================*/
794 static VPTR
get_rb_value(RBTREE rbtree,CNSTRING key)795 get_rb_value (RBTREE rbtree, CNSTRING key)
796 {
797 RBNODE node = RbExactQuery(rbtree, key);
798 return node ? RbGetInfo(node) : 0;
799 }
800 /*=================================================
801 * rb_valueof -- Get value & set *there to indicate presence
802 *===============================================*/
803 static VPTR
rb_valueof(RBTREE rbtree,CNSTRING key,BOOLEAN * there)804 rb_valueof (RBTREE rbtree, CNSTRING key, BOOLEAN *there)
805 {
806 RBNODE node = RbExactQuery(rbtree, key);
807 if (there)
808 *there = !!node;
809 return node ? RbGetInfo(node) : 0;
810 }
811