atom.c revision c7b4381a
1/* 2 3 Copyright 1990, 1994, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 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 THE 17 OPEN GROUP 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 The Open Group 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 The Open Group. 24 25*/ 26 27/* 28 * Author: Keith Packard, MIT X Consortium 29 */ 30 31/* lame atom replacement routines for font applications */ 32 33#ifdef HAVE_CONFIG_H 34#include <config.h> 35#endif 36#include "libxfontint.h" 37#include "src/util/replace.h" 38#include <X11/fonts/fontmisc.h> 39 40typedef struct _AtomList { 41 char *name; 42 int len; 43 int hash; 44 Atom atom; 45} AtomListRec, *AtomListPtr; 46 47static AtomListPtr *hashTable; 48 49static int hashSize, hashUsed; 50static int hashMask; 51static int rehash; 52 53static AtomListPtr *reverseMap; 54static int reverseMapSize; 55static Atom lastAtom; 56 57static int 58Hash(const char *string, int len) 59{ 60 int h; 61 62 h = 0; 63 while (len--) 64 h = (h << 3) ^ *string++; 65 if (h < 0) 66 return -h; 67 return h; 68} 69 70static int 71ResizeHashTable(void) 72{ 73 int newHashSize; 74 int newHashMask; 75 AtomListPtr *newHashTable; 76 int i; 77 int h; 78 int newRehash; 79 int r; 80 81 if (hashSize == 0) 82 newHashSize = 1024; 83 else 84 newHashSize = hashSize * 2; 85 newHashTable = calloc(newHashSize, sizeof(AtomListPtr)); 86 if (!newHashTable) { 87 fprintf(stderr, "ResizeHashTable(): Error: Couldn't allocate" 88 " newHashTable (%ld)\n", 89 newHashSize * (unsigned long) sizeof(AtomListPtr)); 90 return FALSE; 91 } 92 newHashMask = newHashSize - 1; 93 newRehash = (newHashMask - 2); 94 for (i = 0; i < hashSize; i++) { 95 if (hashTable[i]) { 96 h = (hashTable[i]->hash) & newHashMask; 97 if (newHashTable[h]) { 98 r = hashTable[i]->hash % newRehash | 1; 99 do { 100 h += r; 101 if (h >= newHashSize) 102 h -= newHashSize; 103 } while (newHashTable[h]); 104 } 105 newHashTable[h] = hashTable[i]; 106 } 107 } 108 free(hashTable); 109 hashTable = newHashTable; 110 hashSize = newHashSize; 111 hashMask = newHashMask; 112 rehash = newRehash; 113 return TRUE; 114} 115 116static int 117ResizeReverseMap(void) 118{ 119 AtomListPtr *newMap; 120 int newMapSize; 121 122 if (reverseMapSize == 0) 123 newMapSize = 1000; 124 else 125 newMapSize = reverseMapSize * 2; 126 newMap = reallocarray(reverseMap, newMapSize, sizeof(AtomListPtr)); 127 if (newMap == NULL) { 128 fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate" 129 " reverseMap (%ld)\n", 130 newMapSize * (unsigned long) sizeof(AtomListPtr)); 131 return FALSE; 132 } 133 reverseMap = newMap; 134 reverseMapSize = newMapSize; 135 return TRUE; 136} 137 138static int 139NameEqual(const char *a, const char *b, int l) 140{ 141 while (l--) 142 if (*a++ != *b++) 143 return FALSE; 144 return TRUE; 145} 146 147Atom 148__libxfont_internal__MakeAtom(const char *string, unsigned len, int makeit) 149{ 150 AtomListPtr a; 151 int hash; 152 int h = 0; 153 int r; 154 155 hash = Hash(string, len); 156 if (hashTable) { 157 h = hash & hashMask; 158 if (hashTable[h]) { 159 if (hashTable[h]->hash == hash && hashTable[h]->len == len && 160 NameEqual(hashTable[h]->name, string, len)) { 161 return hashTable[h]->atom; 162 } 163 r = (hash % rehash) | 1; 164 for (;;) { 165 h += r; 166 if (h >= hashSize) 167 h -= hashSize; 168 if (!hashTable[h]) 169 break; 170 if (hashTable[h]->hash == hash && hashTable[h]->len == len && 171 NameEqual(hashTable[h]->name, string, len)) { 172 return hashTable[h]->atom; 173 } 174 } 175 } 176 } 177 if (!makeit) 178 return None; 179 a = malloc(sizeof(AtomListRec) + len + 1); 180 if (a == NULL) { 181 fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec" 182 " (%ld)\n", (unsigned long) sizeof(AtomListRec) + len + 1); 183 return None; 184 } 185 a->name = (char *) (a + 1); 186 a->len = len; 187 strncpy(a->name, string, len); 188 a->name[len] = '\0'; 189 a->atom = ++lastAtom; 190 a->hash = hash; 191 if (hashUsed >= hashSize / 2) { 192 if ((ResizeHashTable() == FALSE) && 193 ((hashTable == NULL) || (hashUsed == hashSize))) 194 return None; 195 h = hash & hashMask; 196 if (hashTable[h]) { 197 r = (hash % rehash) | 1; 198 do { 199 h += r; 200 if (h >= hashSize) 201 h -= hashSize; 202 } while (hashTable[h]); 203 } 204 } 205 hashTable[h] = a; 206 hashUsed++; 207 if (reverseMapSize <= a->atom) { 208 if (!ResizeReverseMap()) 209 return None; 210 } 211 reverseMap[a->atom] = a; 212 return a->atom; 213} 214 215int 216__libxfont_internal__ValidAtom(Atom atom) 217{ 218 return (atom != None) && (atom <= lastAtom); 219} 220 221const char * 222__libxfont_internal__NameForAtom(Atom atom) 223{ 224 if (atom != None && atom <= lastAtom) 225 return reverseMap[atom]->name; 226 return NULL; 227} 228