]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1989-94 GROUPE BULL | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 | * of this software and associated documentation files (the "Software"), to | |
6 | * deal in the Software without restriction, including without limitation the | |
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |
8 | * sell copies of the Software, and to permit persons to whom the Software is | |
9 | * furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
18 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
20 | * | |
21 | * Except as contained in this notice, the name of GROUPE BULL shall not be | |
22 | * used in advertising or otherwise to promote the sale, use or other dealings | |
23 | * in this Software without prior written authorization from GROUPE BULL. | |
24 | */ | |
25 | ||
26 | /*****************************************************************************\ | |
27 | * hashtable.c: * | |
28 | * * | |
29 | * XPM library * | |
30 | * * | |
31 | * Developed by Arnaud Le Hors * | |
32 | * this originaly comes from Colas Nahaboo as a part of Wool * | |
33 | * * | |
34 | \*****************************************************************************/ | |
35 | ||
36 | #include "xpm34p.h" | |
37 | ||
38 | LFUNC(AtomMake, xpmHashAtom, (char *name, void *data)); | |
39 | LFUNC(HashTableGrows, int, (xpmHashTable * table)); | |
40 | ||
41 | static xpmHashAtom | |
42 | AtomMake(char *name, void *data) /* makes an atom */ | |
43 | /* char *name; */ /* WARNING: is just pointed to */ | |
44 | /* void *data; */ | |
45 | { | |
46 | xpmHashAtom object = (xpmHashAtom) XpmMalloc(sizeof(struct _xpmHashAtom)); | |
47 | ||
48 | if (object) { | |
49 | object->name = name; | |
50 | object->data = data; | |
51 | } | |
52 | return object; | |
53 | } | |
54 | ||
55 | /************************\ | |
56 | * * | |
57 | * hash table routines * | |
58 | * * | |
59 | \************************/ | |
60 | ||
61 | /* | |
62 | * Hash function definition: | |
63 | * HASH_FUNCTION: hash function, hash = hashcode, hp = pointer on char, | |
64 | * hash2 = temporary for hashcode. | |
65 | * INITIAL_TABLE_SIZE in slots | |
66 | * HASH_TABLE_GROWS how hash table grows. | |
67 | */ | |
68 | ||
69 | /* Mock lisp function */ | |
70 | #define HASH_FUNCTION hash = (hash << 5) - hash + *hp++; | |
71 | /* #define INITIAL_HASH_SIZE 2017 */ | |
72 | #define INITIAL_HASH_SIZE 256 /* should be enough for colors */ | |
73 | #define HASH_TABLE_GROWS size = size * 2; | |
74 | ||
75 | /* aho-sethi-ullman's HPJ (sizes should be primes)*/ | |
76 | #ifdef notdef | |
77 | #define HASH_FUNCTION hash <<= 4; hash += *hp++; \ | |
78 | if(hash2 = hash & 0xf0000000) hash ^= (hash2 >> 24) ^ hash2; | |
79 | #define INITIAL_HASH_SIZE 4095 /* should be 2^n - 1 */ | |
80 | #define HASH_TABLE_GROWS size = size << 1 + 1; | |
81 | #endif | |
82 | ||
83 | /* GNU emacs function */ | |
84 | /* | |
85 | #define HASH_FUNCTION hash = (hash << 3) + (hash >> 28) + *hp++; | |
86 | #define INITIAL_HASH_SIZE 2017 | |
87 | #define HASH_TABLE_GROWS size = size * 2; | |
88 | */ | |
89 | ||
90 | /* end of hash functions */ | |
91 | ||
92 | /* | |
93 | * The hash table is used to store atoms via their NAME: | |
94 | * | |
95 | * NAME --hash--> ATOM |--name--> "foo" | |
96 | * |--data--> any value which has to be stored | |
97 | * | |
98 | */ | |
99 | ||
100 | /* | |
101 | * xpmHashSlot gives the slot (pointer to xpmHashAtom) of a name | |
102 | * (slot points to NULL if it is not defined) | |
103 | * | |
104 | */ | |
105 | ||
106 | xpmHashAtom * | |
107 | xpmHashSlot(xpmHashTable *table, char *s) | |
108 | { | |
109 | xpmHashAtom *atomTable = table->atomTable; | |
110 | unsigned int hash; | |
111 | xpmHashAtom *p; | |
112 | char *hp = s; | |
113 | char *ns; | |
114 | ||
115 | hash = 0; | |
116 | while (*hp) { /* computes hash function */ | |
117 | HASH_FUNCTION | |
118 | } | |
119 | p = atomTable + hash % table->size; | |
120 | while (*p) { | |
121 | ns = (*p)->name; | |
122 | if (ns[0] == s[0] && strcmp(ns, s) == 0) | |
123 | break; | |
124 | p--; | |
125 | if (p < atomTable) | |
126 | p = atomTable + table->size - 1; | |
127 | } | |
128 | return p; | |
129 | } | |
130 | ||
131 | static int | |
132 | HashTableGrows(xpmHashTable *table) | |
133 | { | |
134 | xpmHashAtom *atomTable = table->atomTable; | |
135 | int size = table->size; | |
136 | xpmHashAtom *t, *p; | |
137 | int i; | |
138 | int oldSize = size; | |
139 | ||
140 | t = atomTable; | |
141 | HASH_TABLE_GROWS | |
142 | table->size = size; | |
143 | table->limit = size / 3; | |
144 | atomTable = (xpmHashAtom *) XpmMalloc(size * sizeof(*atomTable)); | |
145 | if (!atomTable) | |
146 | return (XpmNoMemory); | |
147 | table->atomTable = atomTable; | |
148 | for (p = atomTable + size; p > atomTable;) | |
149 | *--p = NULL; | |
150 | for (i = 0, p = t; i < oldSize; i++, p++) | |
151 | if (*p) { | |
152 | xpmHashAtom *ps = xpmHashSlot(table, (*p)->name); | |
153 | ||
154 | *ps = *p; | |
155 | } | |
156 | XpmFree(t); | |
157 | return (XpmSuccess); | |
158 | } | |
159 | ||
160 | /* | |
161 | * xpmHashIntern(table, name, data) | |
162 | * an xpmHashAtom is created if name doesn't exist, with the given data. | |
163 | */ | |
164 | ||
165 | int | |
166 | xpmHashIntern(xpmHashTable *table, char *tag, void *data) | |
167 | { | |
168 | xpmHashAtom *slot; | |
169 | ||
170 | if (!*(slot = xpmHashSlot(table, tag))) { | |
171 | /* undefined, make a new atom with the given data */ | |
172 | if (!(*slot = AtomMake(tag, data))) | |
173 | return (XpmNoMemory); | |
174 | if (table->used >= table->limit) { | |
175 | int ErrorStatus; | |
176 | ||
177 | if ((ErrorStatus = HashTableGrows(table)) != XpmSuccess) | |
178 | return (ErrorStatus); | |
179 | table->used++; | |
180 | return (XpmSuccess); | |
181 | } | |
182 | table->used++; | |
183 | } | |
184 | return (XpmSuccess); | |
185 | } | |
186 | ||
187 | /* | |
188 | * must be called before allocating any atom | |
189 | */ | |
190 | ||
191 | int | |
192 | xpmHashTableInit(xpmHashTable *table) | |
193 | { | |
194 | xpmHashAtom *p; | |
195 | xpmHashAtom *atomTable; | |
196 | ||
197 | table->size = INITIAL_HASH_SIZE; | |
198 | table->limit = table->size / 3; | |
199 | table->used = 0; | |
200 | atomTable = (xpmHashAtom *) XpmMalloc(table->size * sizeof(*atomTable)); | |
201 | if (!atomTable) | |
202 | return (XpmNoMemory); | |
203 | for (p = atomTable + table->size; p > atomTable;) | |
204 | *--p = NULL; | |
205 | table->atomTable = atomTable; | |
206 | return (XpmSuccess); | |
207 | } | |
208 | ||
209 | /* | |
210 | * frees a hashtable and all the stored atoms | |
211 | */ | |
212 | ||
213 | void | |
214 | xpmHashTableFree(xpmHashTable *table) | |
215 | { | |
216 | xpmHashAtom *p; | |
217 | xpmHashAtom *atomTable = table->atomTable; | |
218 | ||
219 | for (p = atomTable + table->size; p > atomTable;) | |
220 | if (*--p) | |
221 | XpmFree(*p); | |
222 | XpmFree(atomTable); | |
223 | table->atomTable = NULL; | |
224 | } |