ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/lookup.c
Revision: 2.1
Committed: Wed Jul 6 15:14:15 1994 UTC (29 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# Content
1 /* Copyright (c) 1994 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * Table lookup routines
9 */
10
11 #include <stdio.h>
12 #include "lookup.h"
13
14 #define MEM_PTR char *
15
16 extern MEM_PTR calloc();
17
18
19 int
20 lu_init(tbl, nel) /* initialize tbl for at least nel elements */
21 register LUTAB *tbl;
22 int nel;
23 {
24 static int hsiztab[] = {
25 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, 0
26 };
27 register int *hsp;
28
29 nel += nel>>1; /* 66% occupancy */
30 for (hsp = hsiztab; *hsp; hsp++)
31 if (*hsp > nel)
32 break;
33 if (!(tbl->tsiz = *hsp))
34 tbl->tsiz = nel*2 + 1; /* not always prime */
35 tbl->tabl = (LUENT *)calloc(tbl->tsiz, sizeof(LUENT));
36 if (tbl->tabl == NULL)
37 tbl->tsiz = 0;
38 tbl->ndel = 0;
39 return(tbl->tsiz);
40 }
41
42
43 long
44 lu_shash(s) /* hash a nul-terminated string */
45 register char *s;
46 {
47 register int i = 0;
48 register long h = 0;
49
50 while (*s)
51 h ^= (long)(*s++ & 0xff) << (i++ & 15);
52 return(h);
53 }
54
55
56 LUENT *
57 lu_find(tbl, key) /* find a table entry */
58 register LUTAB *tbl;
59 char *key;
60 {
61 long hval;
62 int i;
63 register int ndx;
64 register LUENT *oldtabl;
65 /* look up object */
66 hval = (*tbl->hashf)(key);
67 tryagain:
68 for (i = 0; i < tbl->tsiz; i++) {
69 ndx = (hval + i*i) % tbl->tsiz;
70 if (tbl->tabl[ndx].key == NULL) {
71 tbl->tabl[ndx].hval = hval;
72 return(&tbl->tabl[ndx]);
73 }
74 if ( tbl->tabl[ndx].hval == hval && (tbl->keycmp == NULL ||
75 !(*tbl->keycmp)(tbl->tabl[ndx].key, key)) )
76 return(&tbl->tabl[ndx]);
77 }
78 /* table is full, reallocate */
79 oldtabl = tbl->tabl;
80 ndx = tbl->tsiz;
81 i = tbl->ndel;
82 if (!lu_init(tbl, ndx-i)) { /* no more memory! */
83 tbl->tabl = oldtabl;
84 tbl->tsiz = ndx;
85 tbl->ndel = i;
86 return(NULL);
87 }
88 if (!ndx)
89 goto tryagain;
90 /*
91 * The following code may fail if the user has reclaimed many
92 * deleted entries and the system runs out of memory in a
93 * recursive call to lu_find().
94 */
95 while (ndx--)
96 if (oldtabl[ndx].key != NULL)
97 if (oldtabl[ndx].data != NULL)
98 *lu_find(tbl, oldtabl[ndx].key) = oldtabl[ndx];
99 else if (tbl->freek != NULL)
100 (*tbl->freek)(oldtabl[ndx].key);
101 free((MEM_PTR)oldtabl);
102 goto tryagain; /* should happen only once! */
103 }
104
105
106 void
107 lu_delete(tbl, key) /* delete a table entry */
108 register LUTAB *tbl;
109 char *key;
110 {
111 register LUENT *le;
112
113 if ((le = lu_find(tbl, key)) == NULL)
114 return;
115 if (le->key == NULL || le->data == NULL)
116 return;
117 if (tbl->freed != NULL)
118 (*tbl->freed)(le->data);
119 le->data = NULL;
120 tbl->ndel++;
121 }
122
123
124 void
125 lu_done(tbl) /* free table and contents */
126 register LUTAB *tbl;
127 {
128 register LUENT *tp;
129
130 if (!tbl->tsiz)
131 return;
132 for (tp = tbl->tabl + tbl->tsiz; tp-- > tbl->tabl; )
133 if (tp->key != NULL) {
134 if (tbl->freek != NULL)
135 (*tbl->freek)(tp->key);
136 if (tp->data != NULL && tbl->freed != NULL)
137 (*tbl->freed)(tp->data);
138 }
139 free((MEM_PTR)tbl->tabl);
140 tbl->tabl = NULL;
141 tbl->tsiz = 0;
142 tbl->ndel = 0;
143 }