atom.c revision 23a0898a
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 = (AtomListPtr *) xalloc (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 bzero ((char *) newHashTable, newHashSize * sizeof (AtomListPtr)); 95 newHashMask = newHashSize - 1; 96 newRehash = (newHashMask - 2); 97 for (i = 0; i < hashSize; i++) 98 { 99 if (hashTable[i]) 100 { 101 h = (hashTable[i]->hash) & newHashMask; 102 if (newHashTable[h]) 103 { 104 r = hashTable[i]->hash % newRehash | 1; 105 do { 106 h += r; 107 if (h >= newHashSize) 108 h -= newHashSize; 109 } while (newHashTable[h]); 110 } 111 newHashTable[h] = hashTable[i]; 112 } 113 } 114 xfree (hashTable); 115 hashTable = newHashTable; 116 hashSize = newHashSize; 117 hashMask = newHashMask; 118 rehash = newRehash; 119 return TRUE; 120} 121 122static int 123ResizeReverseMap (void) 124{ 125 int ret = TRUE; 126 if (reverseMapSize == 0) 127 reverseMapSize = 1000; 128 else 129 reverseMapSize *= 2; 130 reverseMap = (AtomListPtr *) xrealloc (reverseMap, reverseMapSize * sizeof (AtomListPtr)); 131 if (!reverseMap) { 132 fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate" 133 " reverseMap (%ld)\n", 134 reverseMapSize * (unsigned long)sizeof(AtomListPtr)); 135 ret = FALSE; 136 } 137 return ret; 138} 139 140static int 141NameEqual (const char *a, const char *b, int l) 142{ 143 while (l--) 144 if (*a++ != *b++) 145 return FALSE; 146 return TRUE; 147} 148 149#ifdef __SUNPRO_C 150#pragma weak MakeAtom 151#endif 152 153weak Atom 154MakeAtom(char *string, unsigned len, int makeit) 155{ 156 AtomListPtr a; 157 int hash; 158 int h = 0; 159 int r; 160 161 hash = Hash (string, len); 162 if (hashTable) 163 { 164 h = hash & hashMask; 165 if (hashTable[h]) 166 { 167 if (hashTable[h]->hash == hash && hashTable[h]->len == len && 168 NameEqual (hashTable[h]->name, string, len)) 169 { 170 return hashTable[h]->atom; 171 } 172 r = (hash % rehash) | 1; 173 for (;;) 174 { 175 h += r; 176 if (h >= hashSize) 177 h -= hashSize; 178 if (!hashTable[h]) 179 break; 180 if (hashTable[h]->hash == hash && hashTable[h]->len == len && 181 NameEqual (hashTable[h]->name, string, len)) 182 { 183 return hashTable[h]->atom; 184 } 185 } 186 } 187 } 188 if (!makeit) 189 return None; 190 a = (AtomListPtr) xalloc (sizeof (AtomListRec) + len + 1); 191 if (a == NULL) { 192 fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec" 193 " (%ld)\n", (unsigned long)sizeof (AtomListRec) + len + 1); 194 return None; 195 } 196 a->name = (char *) (a + 1); 197 a->len = len; 198 strncpy (a->name, string, len); 199 a->name[len] = '\0'; 200 a->atom = ++lastAtom; 201 a->hash = hash; 202 if (hashUsed >= hashSize / 2) 203 { 204 ResizeHashTable (); 205 h = hash & hashMask; 206 if (hashTable[h]) 207 { 208 r = (hash % rehash) | 1; 209 do { 210 h += r; 211 if (h >= hashSize) 212 h -= hashSize; 213 } while (hashTable[h]); 214 } 215 } 216 hashTable[h] = a; 217 hashUsed++; 218 if (reverseMapSize <= a->atom) { 219 if (!ResizeReverseMap()) 220 return None; 221 } 222 reverseMap[a->atom] = a; 223 return a->atom; 224} 225 226#ifdef __SUNPRO_C 227#pragma weak ValidAtom 228#endif 229 230weak int 231ValidAtom(Atom atom) 232{ 233 return (atom != None) && (atom <= lastAtom); 234} 235 236#ifdef __SUNPRO_C 237#pragma weak NameForAtom 238#endif 239 240weak char * 241NameForAtom(Atom atom) 242{ 243 if (atom != None && atom <= lastAtom) 244 return reverseMap[atom]->name; 245 return NULL; 246} 247