atom.c revision 7f7f5e4e
1/* $Xorg: atom.c,v 1.5 2001/02/09 02:04:04 xorgcvs Exp $ */
2
3/*
4
5Copyright 1990, 1994, 1998  The Open Group
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall not be
24used in advertising or otherwise to promote the sale, use or other dealings
25in this Software without prior written authorization from The Open Group.
26
27*/
28/* $XFree86: xc/lib/font/util/atom.c,v 1.9 2002/09/19 13:22:00 tsi Exp $ */
29
30/*
31 * Author:  Keith Packard, MIT X Consortium
32 */
33
34/* lame atom replacement routines for font applications */
35
36#ifdef HAVE_CONFIG_H
37#include <config.h>
38#endif
39#include <X11/fonts/fontmisc.h>
40#include "stubs.h"
41
42typedef struct _AtomList {
43    char		*name;
44    int			len;
45    int			hash;
46    Atom		atom;
47} AtomListRec, *AtomListPtr;
48
49static AtomListPtr  *hashTable;
50
51static int	    hashSize, hashUsed;
52static int	    hashMask;
53static int	    rehash;
54
55static AtomListPtr  *reverseMap;
56static int	    reverseMapSize;
57static Atom	    lastAtom;
58
59static int
60Hash(char *string, int len)
61{
62    int	h;
63
64    h = 0;
65    while (len--)
66	h = (h << 3) ^ *string++;
67    if (h < 0)
68	return -h;
69    return h;
70}
71
72static int
73ResizeHashTable (void)
74{
75    int		newHashSize;
76    int		newHashMask;
77    AtomListPtr	*newHashTable;
78    int		i;
79    int		h;
80    int		newRehash;
81    int		r;
82
83    if (hashSize == 0)
84	newHashSize = 1024;
85    else
86	newHashSize = hashSize * 2;
87    newHashTable = calloc (newHashSize, sizeof (AtomListPtr));
88    if (!newHashTable) {
89	fprintf(stderr, "ResizeHashTable(): Error: Couldn't allocate"
90		" newHashTable (%ld)\n",
91		newHashSize * (unsigned long)sizeof (AtomListPtr));
92	return FALSE;
93    }
94    newHashMask = newHashSize - 1;
95    newRehash = (newHashMask - 2);
96    for (i = 0; i < hashSize; i++)
97    {
98	if (hashTable[i])
99	{
100	    h = (hashTable[i]->hash) & newHashMask;
101	    if (newHashTable[h])
102	    {
103		r = hashTable[i]->hash % newRehash | 1;
104		do {
105		    h += r;
106		    if (h >= newHashSize)
107			h -= newHashSize;
108		} while (newHashTable[h]);
109	    }
110	    newHashTable[h] = hashTable[i];
111	}
112    }
113    free (hashTable);
114    hashTable = newHashTable;
115    hashSize = newHashSize;
116    hashMask = newHashMask;
117    rehash = newRehash;
118    return TRUE;
119}
120
121static int
122ResizeReverseMap (void)
123{
124    int ret = TRUE;
125    if (reverseMapSize == 0)
126	reverseMapSize = 1000;
127    else
128	reverseMapSize *= 2;
129    reverseMap = realloc (reverseMap, reverseMapSize * sizeof (AtomListPtr));
130    if (!reverseMap) {
131	fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate"
132		" reverseMap (%ld)\n",
133		reverseMapSize * (unsigned long)sizeof(AtomListPtr));
134	ret = FALSE;
135    }
136    return ret;
137}
138
139static int
140NameEqual (const char *a, const char *b, int l)
141{
142    while (l--)
143	if (*a++ != *b++)
144	    return FALSE;
145    return TRUE;
146}
147
148#ifdef __SUNPRO_C
149#pragma weak MakeAtom
150#endif
151
152weak Atom
153MakeAtom(char *string, unsigned len, int makeit)
154{
155    AtomListPtr	a;
156    int		hash;
157    int		h = 0;
158    int		r;
159
160    hash = Hash (string, len);
161    if (hashTable)
162    {
163    	h = hash & hashMask;
164	if (hashTable[h])
165	{
166	    if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
167	    	NameEqual (hashTable[h]->name, string, len))
168	    {
169	    	return hashTable[h]->atom;
170	    }
171	    r = (hash % rehash) | 1;
172	    for (;;)
173	    {
174		h += r;
175		if (h >= hashSize)
176		    h -= hashSize;
177		if (!hashTable[h])
178		    break;
179		if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
180		    NameEqual (hashTable[h]->name, string, len))
181		{
182		    return hashTable[h]->atom;
183		}
184	    }
185    	}
186    }
187    if (!makeit)
188	return None;
189    a = malloc (sizeof (AtomListRec) + len + 1);
190    if (a == NULL) {
191	fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec"
192		" (%ld)\n", (unsigned long)sizeof (AtomListRec) + len + 1);
193	return None;
194    }
195    a->name = (char *) (a + 1);
196    a->len = len;
197    strncpy (a->name, string, len);
198    a->name[len] = '\0';
199    a->atom = ++lastAtom;
200    a->hash = hash;
201    if (hashUsed >= hashSize / 2)
202    {
203	ResizeHashTable ();
204	h = hash & hashMask;
205	if (hashTable[h])
206	{
207	    r = (hash % rehash) | 1;
208	    do {
209		h += r;
210		if (h >= hashSize)
211		    h -= hashSize;
212	    } while (hashTable[h]);
213	}
214    }
215    hashTable[h] = a;
216    hashUsed++;
217    if (reverseMapSize <= a->atom) {
218	if (!ResizeReverseMap())
219	    return None;
220    }
221    reverseMap[a->atom] = a;
222    return a->atom;
223}
224
225#ifdef __SUNPRO_C
226#pragma weak ValidAtom
227#endif
228
229weak int
230ValidAtom(Atom atom)
231{
232    return (atom != None) && (atom <= lastAtom);
233}
234
235#ifdef __SUNPRO_C
236#pragma weak NameForAtom
237#endif
238
239weak char *
240NameForAtom(Atom atom)
241{
242    if (atom != None && atom <= lastAtom)
243	return reverseMap[atom]->name;
244    return NULL;
245}
246