2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
12 #define STRING_BLOCK 2047
13 #define STRINGSPACE_BLOCK 65535
16 stringpool_init (Stringpool *ss, const char *strs[])
18 unsigned totalsize = 0;
20 // count number and total size of predefined strings
21 for (count = 0; strs[count]; count++)
22 totalsize += strlen(strs[count]) + 1;
24 // alloc appropriate space
25 ss->stringspace = (char *)xmalloc((totalsize + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
26 ss->strings = (Offset *)xmalloc(((count + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
28 // now copy predefined strings into allocated space
30 for (count = 0; strs[count]; count++)
32 strcpy(ss->stringspace + ss->sstrings, strs[count]);
33 ss->strings[count] = ss->sstrings;
34 ss->sstrings += strlen(strs[count]) + 1;
40 stringpool_str2id (Stringpool *ss, const char *str, int create)
55 hashmask = ss->stringhashmask;
56 hashtbl = ss->stringhashtbl;
58 // expand hashtable if needed
61 if (ss->nstrings * 2 > hashmask)
66 ss->stringhashmask = hashmask = mkmask(ss->nstrings + STRING_BLOCK);
67 ss->stringhashtbl = hashtbl = (Hashtable)xcalloc(hashmask + 1, sizeof(Id));
69 // rehash all strings into new hashtable
70 for (i = 1; i < ss->nstrings; i++)
72 h = strhash(ss->stringspace + ss->strings[i]) & hashmask;
74 while (hashtbl[h] != 0) // follow overflow chain
75 h = HASHCHAIN_NEXT(h, hh, hashmask);
80 // compute hash and check for match
82 h = strhash(str) & hashmask;
84 while ((id = hashtbl[h]) != 0) // follow hash overflow chain
86 // break if string already hashed
87 if(!strcmp(ss->stringspace + ss->strings[id], str))
89 h = HASHCHAIN_NEXT(h, hh, hashmask);
91 if (id || !create) // exit here if string found
94 // generate next id and save in table
99 if ((id & STRING_BLOCK) == 0)
100 ss->strings = xrealloc(ss->strings, ((ss->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Hashval));
101 // 'pointer' into stringspace is Offset of next free pos: sstrings
102 ss->strings[id] = ss->sstrings;
104 space_needed = strlen(str) + 1;
106 // resize string buffer if needed
107 if (((ss->sstrings + space_needed - 1) | STRINGSPACE_BLOCK) != ((ss->sstrings - 1) | STRINGSPACE_BLOCK))
108 ss->stringspace = xrealloc(ss->stringspace, (ss->sstrings + space_needed + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
109 // copy new string into buffer
110 memcpy(ss->stringspace + ss->sstrings, str, space_needed);
111 // next free pos is behind new string
112 ss->sstrings += space_needed;
118 stringpool_shrink (Stringpool *ss)
120 ss->stringspace = (char *)xrealloc(ss->stringspace, (ss->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
121 ss->strings = (Offset *)xrealloc(ss->strings, ((ss->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));