~ubuntu-branches/ubuntu/trusty/lifelines/trusty

« back to all changes in this revision

Viewing changes to src/stdlib/table.c

  • Committer: Bazaar Package Importer
  • Author(s): Felipe Augusto van de Wiel (faw)
  • Date: 2007-05-23 23:49:53 UTC
  • mfrom: (3.1.3 edgy)
  • Revision ID: james.westby@ubuntu.com-20070523234953-ogno9rnbmth61i7p
Tags: 3.0.50-2etch1
* Changing docs/ll-reportmanual.xml and docs/ll-userguide.xml to fix
  documentation build problems (Closes: #418347).

* lifelines-reports
  - Adding a dependency to lifelines >= 3.0.50 to prevent file conflict.
    (Closes: #405500).

* Updating French translation. Thanks to Bernard Adrian. (Closes: #356671).

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
22
   SOFTWARE.
23
23
*/
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
31
 
 *   3.0.3 - 19 Sep 95
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
 *==============================================================*/
33
30
 
34
 
#include "standard.h"
35
31
#include "llstdlib.h"
 
32
#include "vtable.h"
36
33
#include "table.h"
37
 
#include "vtable.h"
 
34
#include "object.h"
 
35
#include "hashtab.h"
 
36
#include "rbtree.h"
 
37
#include "lloptions.h"
38
38
 
39
39
/*********************************************
40
40
 * local enums & defines
41
41
 *********************************************/
42
42
 
43
 
#define MAXHASH_DEF 512
44
 
 
45
43
enum TB_VALTYPE
46
44
        {
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 */
51
51
        };
52
52
 
53
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
/*********************************************
54
78
 * local function prototypes
55
79
 *********************************************/
56
80
 
57
81
/* alphabetical */
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);
67
95
 
68
96
/*********************************************
69
97
 * local variables
75
103
        , &table_destructor
76
104
        , &refcountable_isref
77
105
        , &refcountable_addref
78
 
        , &refcountable_delref
 
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
79
117
        , 0 /* copy_fnc */
80
118
        , &generic_get_type_name
81
119
};
85
123
 * body of module
86
124
 *********************************************/
87
125
 
88
 
/*======================
89
 
 * hash -- Hash function
90
 
 *====================*/
91
 
static INT
92
 
hash (TABLE tab, CNSTRING key)
93
 
{
94
 
        INT hval = 0;
95
 
        while (*key)
96
 
                hval += *key++;
97
 
        hval %= tab->maxhash;
98
 
        if (hval < 0) hval += tab->maxhash;
99
 
        if (hval < 0) FATAL();
100
 
        if(hval >= tab->maxhash) FATAL();
101
 
        return hval;
102
 
}
103
 
/*================================
104
 
 * fndentry -- Find entry in table
105
 
 *==============================*/
106
 
static ENTRY
107
 
fndentry (TABLE tab, CNSTRING key)
108
 
{
109
 
        ENTRY entry;
110
 
        if (!tab || !key) return NULL;
111
 
        entry = tab->entries[hash(tab, key)];
112
 
        while (entry) {
113
 
                if (eqstr(key, entry->ekey)) return entry;
114
 
                entry = entry->enext;
115
 
        }
116
 
        return NULL;
117
 
}
118
 
/*=============================
119
 
 * create_table -- Create table
120
 
 *===========================*/
121
 
TABLE
122
 
create_table (INT whattofree)
 
126
/*=============================
 
127
 * init_table_module -- Module initialization
 
128
 *===========================*/
 
129
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
 
141
create_table_impl (enum TB_VALTYPE valtype, DELFUNC delfunc)
123
142
{
124
143
        TABLE tab = (TABLE) stdalloc(sizeof(*tab));
125
 
        INT i;
126
 
        memset(tab, 0, sizeof(*tab));
 
144
 
127
145
        tab->vtable = &vtable_for_table;
128
 
        /* refcount zero */
129
 
        tab->maxhash = MAXHASH_DEF;
130
 
        tab->entries = (ENTRY *)stdalloc(tab->maxhash*sizeof(ENTRY));
131
 
        tab->count = 0;
132
 
        tab->valtype = TB_NULL;
133
 
        tab->whattofree = whattofree;
134
 
        for (i = 0; i < tab->maxhash; i++)
135
 
                tab->entries[i] = NULL;
 
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;
136
153
        return tab;
137
154
}
138
155
/*=============================
139
 
 * create_table_old -- Create table
140
 
 *===========================*/
141
 
TABLE
142
 
create_table_old (void)
143
 
{
144
 
        return create_table(-1);
145
 
}
146
 
/*======================================
147
 
 * insert_table_impl -- Insert key & value into table
148
 
 * Caller is reponsible for both key & value memory
149
 
 *====================================*/
150
 
static void
151
 
insert_table_impl (TABLE tab, CNSTRING key, UNION uval)
152
 
{
153
 
        ENTRY entry = fndentry(tab, key);
154
 
        if (entry)
155
 
                entry->uval = uval;
156
 
        else {
157
 
                INT hval = hash(tab, key);
158
 
                entry = (ENTRY) stdalloc(sizeof(*entry));
159
 
                entry->ekey = (STRING)key;
160
 
                entry->uval = uval;
161
 
                entry->enext = tab->entries[hval];
162
 
                tab->entries[hval] = entry;
163
 
                ++tab->count;
164
 
        }
165
 
}
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
 
 *====================================*/
171
 
static void
172
 
replace_table_impl (TABLE tab, STRING key, UNION uval, INT whattofree)
173
 
{
174
 
        ENTRY entry = fndentry(tab, key);
175
 
        if (entry) {
176
 
                free_contents(entry, whattofree);
177
 
                entry->ekey = key;
178
 
                entry->uval = uval;
179
 
        } else {
180
 
                INT hval = hash(tab, key);
181
 
                entry = (ENTRY) stdalloc(sizeof(*entry));
182
 
                entry->ekey = key;
183
 
                entry->uval = uval;
184
 
                entry->enext = tab->entries[hval];
185
 
                tab->entries[hval] = entry;
186
 
                ++tab->count;
187
 
        }
 
156
 * create_table_int -- Create table holding integers
 
157
 * returns addref'd table
 
158
 *===========================*/
 
159
TABLE
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
305
insert_table_str (TABLE tab, CNSTRING key, CNSTRING value)
 
306
{
 
307
        insert_table_ptr(tab, key, strsave(value));
188
308
}
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
 *====================================*/
194
312
void
195
313
insert_table_ptr (TABLE tab, CNSTRING key, VPTR ptr)
196
314
{
197
 
        UNION uval;
198
 
        uval.w = 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);
204
 
}
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
 
 *====================================*/
210
 
void
211
 
insert_table_int (TABLE tab, CNSTRING key, INT ival)
212
 
{
213
 
        UNION uval;
214
 
        uval.i = ival;
215
 
        if (tab->valtype == TB_NULL) {
216
 
                ASSERT(tab->whattofree==-1 || (tab->whattofree!=FREEBOTH && tab->whattofree!=FREEVALUE));
217
 
                tab->valtype = TB_INT;
 
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
                }
218
337
        }
219
 
        /* table must be homogenous, not mixed-type */
220
 
        ASSERT(tab->valtype == TB_INT);
221
 
        insert_table_impl(tab, key, uval);
222
338
}
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
 *====================================*/
228
343
void
229
 
insert_table_str (TABLE tab, CNSTRING key, STRING str)
 
344
insert_table_obj (TABLE tab, CNSTRING key, VPTR obj)
230
345
{
231
 
        UNION uval;
232
 
        uval.w = str;
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);
 
346
        if (obj)
 
347
                addref_object(obj);
 
348
        insert_table_ptr(tab, key, obj);
238
349
}
239
350
/*======================================
240
351
 * replace_table_str -- Insert or replace
242
353
 * Created: 2001/11/23, Perry Rapp
243
354
 *====================================*/
244
355
void
245
 
replace_table_str (TABLE tab, STRING key, STRING str, INT whattofree)
 
356
replace_table_str (TABLE tab, CNSTRING key, CNSTRING str)
246
357
{
247
 
        UNION uval;
248
 
        uval.w = str;
249
 
        if (tab->valtype == TB_NULL)
250
 
                tab->valtype = TB_STR;
251
 
        /* table must be homogenous, not mixed-type */
252
 
        ASSERT(tab->valtype == TB_STR);
253
 
        replace_table_impl(tab, key, uval, whattofree);
 
358
        /* insert function handles deleting old value */
 
359
        insert_table_str(tab, key, str);
254
360
}
255
361
/*==========================================
256
 
 * delete_table -- Remove element from table
 
362
 * delete_table_element -- Delete element from table
257
363
 *  tab: [I/O]  table from which to remove element
258
364
 *  key: [IN]   key to find element to remove
 
365
 * Destroys key and value as appropriate
259
366
 *========================================*/
260
367
void
261
 
delete_table (TABLE tab, STRING key)
 
368
delete_table_element (TABLE tab, CNSTRING key)
262
369
{
263
 
        INT hval = hash(tab, key);
264
 
        ENTRY preve = NULL;
265
 
        ENTRY thise = tab->entries[hval];
266
 
        while (thise && nestr(key, thise->ekey)) {
267
 
                preve = thise;
268
 
                thise = thise->enext;
 
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
                }
269
384
        }
270
 
        if (!thise) return;
271
 
        if (preve)
272
 
                preve->enext = thise->enext;
273
 
        else
274
 
                tab->entries[hval] = thise->enext;
275
 
        stdfree(thise);
276
 
        --tab->count;
277
385
}
278
386
/*======================================
279
387
 * in_table() - Check for entry in table
281
389
BOOLEAN
282
390
in_table (TABLE tab, CNSTRING key)
283
391
{
284
 
        return fndentry(tab, key) != NULL;
285
 
}
286
 
/*===============================
287
 
 * valueof_ptr -- Find pointer value of entry
288
 
 * Created: 2001/06/03 (Perry Rapp)
289
 
 *=============================*/
290
 
VPTR
291
 
valueof_ptr (TABLE tab, CNSTRING key)
292
 
{
293
 
        ENTRY entry;
294
 
        if (!tab->count || !key) return NULL;
295
 
        ASSERT(tab->valtype == TB_PTR);
296
 
        if ((entry = fndentry(tab, key)))
297
 
                return entry->uval.w;
298
 
        else
299
 
                return NULL;
 
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
        }
300
400
}
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
 *=============================*/
306
406
INT
307
 
valueof_int (TABLE tab, CNSTRING key, INT defval)
 
407
valueof_int (TABLE tab, CNSTRING key)
308
408
{
309
 
        ENTRY entry;
310
 
        if (!tab->count || !key) return defval;
 
409
        INT * val=0;
 
410
 
 
411
        ASSERT(tab);
 
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;
314
 
        else
315
 
                return defval;
 
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);
316
421
}
317
422
/*===============================
318
423
 * valueof_str -- Find string value of entry
319
 
 * Created: 2001/06/03 (Perry Rapp)
320
424
 *=============================*/
321
425
STRING
322
426
valueof_str (TABLE tab, CNSTRING key)
323
427
{
324
 
        ENTRY entry;
325
 
        if (!tab->count || !key) return NULL;
 
428
        ASSERT(tab);
 
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;
329
 
        else
330
 
                return NULL;
331
 
}
332
 
/*===================================
333
 
 * valueofbool_impl -- Find value of entry
334
 
 *=================================*/
335
 
static UNION *
336
 
valueofbool_impl (TABLE tab, STRING key)
337
 
{
338
 
        ENTRY entry;
339
 
        if (!tab->count || !key) return NULL;
340
 
        if ((entry = fndentry(tab, key))) {
341
 
                return &entry->uval;
342
 
        }
343
 
        return NULL;
344
 
}
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
 
 *=================================*/
350
 
VPTR
351
 
valueofbool_ptr (TABLE tab, STRING key, BOOLEAN *there)
352
 
{
353
 
        UNION * val = valueofbool_impl(tab, key);
354
 
        if (val) {
355
 
                ASSERT(tab->valtype == TB_PTR);
356
 
                *there = TRUE;
357
 
                return val->w;
358
 
        } else {
359
 
                *there = FALSE;
360
 
                return NULL;
 
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
 
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
 
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);
361
470
        }
362
471
}
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
 *=================================*/
368
476
INT
369
 
valueofbool_int (TABLE tab, STRING key, BOOLEAN *there)
 
477
valueofbool_int (TABLE tab, CNSTRING key, BOOLEAN *there)
370
478
{
371
 
        UNION * val = valueofbool_impl(tab, key);
372
 
        if (val) {
373
 
                ASSERT(tab->valtype == TB_INT);
374
 
                *there = TRUE;
375
 
                return val->i;
 
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);
376
487
        } else {
377
 
                *there = FALSE;
378
 
                return 0;
 
488
                val = find_hashtab(tab->hashtab, key, there);
379
489
        }
 
490
        return val ? *val : 0;
380
491
}
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
 *=================================*/
386
496
STRING
387
 
valueofbool_str (TABLE tab, STRING key, BOOLEAN *there)
388
 
{
389
 
        UNION * val = valueofbool_impl(tab, key);
390
 
        if (val) {
391
 
                ASSERT(tab->valtype == TB_STR);
392
 
                *there = TRUE;
393
 
                return val->w;
394
 
        } else {
395
 
                *there = FALSE;
396
 
                return NULL;
397
 
        }
398
 
}
399
 
/*===================================
400
 
 * access_value_impl -- get pointer to value
401
 
 * returns NULL if not found
402
 
 * Created: 2001/01/01, Perry Rapp
403
 
 *=================================*/
404
 
static UNION *
405
 
access_value_impl (TABLE tab, STRING key)
406
 
{
407
 
        ENTRY entry;
408
 
        if (!tab->count || !key) return NULL;
409
 
        if (NULL == (entry = fndentry(tab, key)))
410
 
                return 0;
411
 
        return &entry->uval;
412
 
}
413
 
/*===================================
414
 
 * access_value_ptr -- get pointer to VPTR value
415
 
 * returns NULL if not found
416
 
 * Created: 2001/06/03 (Perry Rapp)
417
 
 *=================================*/
418
 
VPTR *
419
 
access_value_ptr (TABLE tab, STRING key)
420
 
{
421
 
        UNION * val = access_value_impl(tab, key);
422
 
        if (!val) return NULL;
423
 
        ASSERT(tab->valtype == TB_PTR);
424
 
        return &val->w;
425
 
}
426
 
/*===================================
427
 
 * access_value_int -- get pointer to int value
428
 
 * returns NULL if not found
429
 
 * Created: 2001/06/03 (Perry Rapp)
430
 
 *=================================*/
431
 
INT *
432
 
access_value_int (TABLE tab, STRING key)
433
 
{
434
 
        UNION * val = access_value_impl(tab, key);
435
 
        if (!val) return NULL;
436
 
        ASSERT(tab->valtype == TB_INT);
437
 
        return &val->i;
438
 
}
439
 
/*===================================
440
 
 * access_value_str -- get pointer to string value
441
 
 * returns NULL if not found
442
 
 * Created: 2003/06/16 (Matt Emmerton)
443
 
 *=================================*/
444
 
STRING *
445
 
access_value_str (TABLE tab, STRING key)
446
 
{
447
 
        UNION * val = access_value_impl(tab, key);
448
 
        if (!val) return NULL;
 
497
valueofbool_str (TABLE tab, CNSTRING key, BOOLEAN *there)
 
498
{
 
499
        ASSERT(tab);
 
500
        ASSERT(tab->vtable == &vtable_for_table);
449
501
        ASSERT(tab->valtype == TB_STR);
450
 
        return &val->s;
451
 
}
452
 
/*=============================
453
 
 * remove_table -- Remove table
454
 
 * TABLE tab
455
 
 * INT whattofree:  FREEKEY, DONTFREE, etc
456
 
 *===========================*/
 
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
 
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
 
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
 
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
 
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
 
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
 *===============================================*/
457
595
void
458
 
remove_table (TABLE tab, INT whattofree)
 
596
end_table_iter (TABLE_ITER * ptabit)
459
597
{
460
 
        INT i;
461
 
        ENTRY ent, nxt;
462
 
        if (!tab) return;
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);
467
 
        }
468
 
        for (i = 0; i < tab->maxhash; i++) {
469
 
                nxt = tab->entries[i];
470
 
                while ((ent = nxt)) {
471
 
                        nxt = ent->enext;
472
 
                        free_contents(ent, whattofree);
473
 
                        stdfree(ent);
474
 
                }
475
 
        }
476
 
        stdfree(tab->entries);
477
 
        stdfree(tab);
 
598
        ASSERT(ptabit);
 
599
        ASSERT(*ptabit);
 
600
        --(*ptabit)->refcnt;
 
601
        if (!(*ptabit)->refcnt) {
 
602
                free_table_iter(*ptabit);
 
603
        }
 
604
        *ptabit = 0;
478
605
}
479
606
/*=================================================
480
 
 * free_contents -- Free key and/or value as appropriate
 
607
 * free_table_iter -- Delete & free table iterator object
481
608
 *===============================================*/
482
609
static void
483
 
free_contents (ENTRY ent, INT whattofree)
484
 
{
485
 
        if (whattofree==FREEBOTH || whattofree==FREEKEY)
486
 
                stdfree(ent->ekey);
487
 
        if (whattofree==FREEBOTH || whattofree==FREEVALUE) {
488
 
                if (ent->uval.w)
489
 
                        stdfree(ent->uval.w);
490
 
        }
491
 
}
492
 
/*=================================================
493
 
 * traverse_table -- Traverse table doing something
494
 
 * tproc: callback for each entry
495
 
 *===============================================*/
496
 
void
497
 
traverse_table (TABLE tab, void (*tproc)(ENTRY))
498
 
{
499
 
        INT i;
500
 
        ENTRY ent, nxt;
501
 
        if (!tab || !tproc) return;
502
 
        for (i = 0; i < tab->maxhash; i++) {
503
 
                nxt = tab->entries[i];
504
 
                while ((ent = nxt)) {
505
 
                        nxt = ent->enext;
506
 
                        (*tproc)(ent);
507
 
                }
508
 
        }
509
 
}
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
 
 *===============================================*/
515
 
void
516
 
traverse_table_param (TABLE tab,
517
 
                INT (*tproc)(ENTRY, VPTR),
518
 
                VPTR param)
519
 
{
520
 
        INT i;
521
 
        ENTRY ent, nxt;
522
 
        if (!tab || !tproc) return;
523
 
        for (i = 0; i < tab->maxhash; i++) {
524
 
                nxt = tab->entries[i];
525
 
                while ((ent = nxt)) {
526
 
                        nxt = ent->enext;
527
 
                        if (!(*tproc)(ent, param))
528
 
                                return;
529
 
                }
530
 
        }
531
 
}
532
 
/*=================================================
533
 
 * begin_table -- Begin iteration of table
534
 
 * Created: 2002/06/16, Perry Rapp
535
 
 *===============================================*/
536
 
BOOLEAN
537
 
begin_table (TABLE tab, TABLE_ITER tabit)
538
 
{
 
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
        }
539
617
        memset(tabit, 0, sizeof(*tabit));
540
 
        tabit->table = tab;
541
 
        tabit->enext = 0;
542
 
        tabit->index = 0;
543
 
        return tabit->table->count>0;
544
 
}
545
 
/*=================================================
546
 
 * next_element -- Find next element in table (iterating)
547
 
 * Created: 2002/06/16, Perry Rapp
548
 
 *===============================================*/
549
 
static BOOLEAN
550
 
next_element (TABLE_ITER tabit)
551
 
{
552
 
        if (tabit->index == -1 || tabit->table->count == 0)
553
 
                return FALSE;
554
 
        if (tabit->enext) {
555
 
                tabit->enext = tabit->enext->enext;
556
 
                if (tabit->enext)
557
 
                        return TRUE;
558
 
                ++tabit->index;
559
 
        }
560
 
        for ( ; tabit->index < tabit->table->maxhash; ++tabit->index) {
561
 
                        tabit->enext = tabit->table->entries[tabit->index];
562
 
                        if (tabit->enext)
563
 
                                return TRUE;
564
 
        }
565
 
        tabit->index = -1;
566
 
        tabit->enext = 0;
567
 
        return FALSE;
568
 
}
569
 
/*=================================================
570
 
 * next_table_str -- Iterating table with strings
571
 
 * Created: 2002/06/16, Perry Rapp
572
 
 *===============================================*/
573
 
BOOLEAN
574
 
next_table_str (TABLE_ITER tabit, STRING *pkey, STRING *pstr)
575
 
{
576
 
        ASSERT(tabit->table->valtype == TB_STR || tabit->table->valtype == TB_NULL);
577
 
        if (!next_element(tabit)) {
578
 
                *pkey = 0;
579
 
                *pstr = 0;
580
 
                return FALSE;
581
 
        }
582
 
        *pkey = tabit->enext->ekey;
583
 
        *pstr = tabit->enext->uval.w;
584
 
        return TRUE;
585
 
}
586
 
/*=================================================
587
 
 * next_table_ptr -- Iterating table with pointers
588
 
 * Created: 2002/06/16, Perry Rapp
589
 
 *===============================================*/
590
 
BOOLEAN
591
 
next_table_ptr (TABLE_ITER tabit, STRING *pkey, VPTR *pptr)
592
 
{
593
 
        ASSERT(tabit->table->valtype == TB_PTR || tabit->table->valtype == TB_NULL);
594
 
        if (!next_element(tabit)) {
595
 
                *pkey = 0;
596
 
                *pptr = 0;
597
 
                return FALSE;
598
 
        }
599
 
        *pkey = tabit->enext->ekey;
600
 
        *pptr = tabit->enext->uval.w;
601
 
        return TRUE;
602
 
}
603
 
/*=================================================
604
 
 * change_table_ptr -- User changing value in iteration
605
 
 * Created: 2002/06/17, Perry Rapp
606
 
 *===============================================*/
607
 
BOOLEAN
608
 
change_table_ptr (TABLE_ITER tabit, VPTR newptr)
609
 
{
610
 
        if (!tabit || !tabit->enext)
611
 
                return FALSE;
612
 
        tabit->enext->uval.w = newptr;
613
 
        return TRUE;
 
618
        stdfree(tabit);
614
619
}
615
620
/*=================================================
616
621
 * get_table_count -- Return #elements
620
625
get_table_count (TABLE tab)
621
626
{
622
627
        if (!tab) return 0;
623
 
        return tab->count;
 
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);
624
635
}
625
636
/*=================================================
626
637
 * copy_table -- Copy all elements from src to dest
627
 
 * Created: 2002/02/17, Perry Rapp
628
 
 *===============================================*/
629
 
void
630
 
copy_table (const TABLE src, TABLE dest, INT whattodup)
631
 
{
632
 
        INT i;
633
 
        ENTRY ent, nxt;
634
 
        BOOLEAN dupkey = whattodup&FREEBOTH || whattodup&FREEKEY;
635
 
        BOOLEAN dupval = whattodup&FREEBOTH || whattodup&FREEVALUE;
636
 
 
637
 
        ASSERT(get_table_count(dest)==0);
638
 
        if (get_table_count(src)==0)
639
 
                return;
640
 
        ASSERT(!dupval || src->valtype==TB_STR); /* can only dup strings */
641
 
 
642
 
        dest->valtype = src->valtype;
643
 
        if (src->maxhash == dest->maxhash)
644
 
                dest->count = src->count;
645
 
        
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));
656
 
                                entry->ekey = key;
657
 
                                entry->uval = uval;
658
 
                                entry->enext = dest->entries[i];
659
 
                                dest->entries[i] = entry;
660
 
                        } else {
661
 
                                /* insert src item into dest */
662
 
                                insert_table_impl(dest, key, uval);
663
 
                        }
664
 
                        nxt = ent->enext;
665
 
                }
666
 
        }
667
 
}
668
 
/*=================================================
669
 
 * destroy_table -- public destructor for a table
670
 
 *===============================================*/
671
 
void
672
 
destroy_table (TABLE tab)
673
 
{
674
 
        if (!tab) return;
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);
680
 
}
681
 
/*=================================================
682
 
 * table_destructor -- destructor for vtable
683
 
 *===============================================*/
684
 
static void
685
 
table_destructor (VTABLE *obj)
686
 
{
687
 
        TABLE tab = (TABLE)obj;
688
 
        ASSERT((*obj) == &vtable_for_table);
689
 
        destroy_table(tab);
 
638
 *===============================================*/
 
639
void
 
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
 
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
 
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
 
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 *
 
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
 
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
 
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
 
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
 
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
 
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;
690
810
}