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_strn2id (Stringpool *ss, const char *str, unsigned len, 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 = strnhash(str, len) & hashmask;
84 while ((id = hashtbl[h]) != 0) // follow hash overflow chain
86 // break if string already hashed
87 if(!memcmp(ss->stringspace + ss->strings[id], str, len)
88 && ss->stringspace[ss->strings[id] + len] == 0)
90 h = HASHCHAIN_NEXT(h, hh, hashmask);
92 if (id || !create) // exit here if string found
95 // generate next id and save in table
100 if ((id & STRING_BLOCK) == 0)
101 ss->strings = xrealloc(ss->strings, ((ss->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Hashval));
102 // 'pointer' into stringspace is Offset of next free pos: sstrings
103 ss->strings[id] = ss->sstrings;
105 space_needed = len + 1;
107 // resize string buffer if needed
108 if (((ss->sstrings + space_needed - 1) | STRINGSPACE_BLOCK) != ((ss->sstrings - 1) | STRINGSPACE_BLOCK))
109 ss->stringspace = xrealloc(ss->stringspace, (ss->sstrings + space_needed + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
110 // copy new string into buffer
111 memcpy(ss->stringspace + ss->sstrings, str, space_needed - 1);
112 // add the sentinel, we can't rely on it being in the source string (in
113 // case the LEN is not really strlen(str))
114 ss->stringspace[ss->sstrings + space_needed - 1] = 0;
115 // next free pos is behind new string
116 ss->sstrings += space_needed;
122 stringpool_str2id (Stringpool *ss, const char *str, int create)
124 unsigned len = strlen (str);
125 return stringpool_strn2id (ss, str, len, create);
129 stringpool_shrink (Stringpool *ss)
131 ss->stringspace = (char *)xrealloc(ss->stringspace, (ss->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
132 ss->strings = (Offset *)xrealloc(ss->strings, ((ss->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));