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