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;
21 memset(ss, 0, sizeof(*ss));
22 /* count number and total size of predefined strings */
23 for (count = 0; strs[count]; count++)
24 totalsize += strlen(strs[count]) + 1;
26 /* alloc appropriate space */
27 ss->stringspace = solv_extend_resize(0, totalsize, 1, STRINGSPACE_BLOCK);
28 ss->strings = solv_extend_resize(0, count, sizeof(Offset), STRING_BLOCK);
30 /* now copy predefined strings into allocated space */
32 for (count = 0; strs[count]; count++)
34 strcpy(ss->stringspace + ss->sstrings, strs[count]);
35 ss->strings[count] = ss->sstrings;
36 ss->sstrings += strlen(strs[count]) + 1;
42 stringpool_free(Stringpool *ss)
44 solv_free(ss->strings);
45 solv_free(ss->stringspace);
46 solv_free(ss->stringhashtbl);
50 stringpool_freehash(Stringpool *ss)
52 ss->stringhashtbl = solv_free(ss->stringhashtbl);
53 ss->stringhashmask = 0;
57 stringpool_init_empty(Stringpool *ss)
59 const char *emptystrs[] = {
64 stringpool_init(ss, emptystrs);
68 stringpool_clone(Stringpool *ss, Stringpool *from)
70 memset(ss, 0, sizeof(*ss));
71 ss->strings = solv_extend_resize(0, from->nstrings, sizeof(Offset), STRING_BLOCK);
72 memcpy(ss->strings, from->strings, from->nstrings * sizeof(Offset));
73 ss->stringspace = solv_extend_resize(0, from->sstrings, 1, STRINGSPACE_BLOCK);
74 memcpy(ss->stringspace, from->stringspace, from->sstrings);
75 ss->nstrings = from->nstrings;
76 ss->sstrings = from->sstrings;
80 stringpool_resize_hash(Stringpool *ss, int numnew)
82 Hashval h, hh, hashmask;
88 hashmask = mkmask(ss->nstrings + numnew);
89 if (hashmask <= ss->stringhashmask)
90 return; /* same as before */
92 /* realloc hash table */
93 ss->stringhashmask = hashmask;
94 solv_free(ss->stringhashtbl);
95 ss->stringhashtbl = hashtbl = (Hashtable)solv_calloc(hashmask + 1, sizeof(Id));
97 /* rehash all strings into new hashtable */
98 for (i = 1; i < ss->nstrings; i++)
100 h = strhash(ss->stringspace + ss->strings[i]) & hashmask;
101 hh = HASHCHAIN_START;
102 while (hashtbl[h] != 0)
103 h = HASHCHAIN_NEXT(h, hh, hashmask);
109 stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create)
111 Hashval h, hh, hashmask, oldhashmask;
120 hashmask = oldhashmask = ss->stringhashmask;
121 /* expand hashtable if needed */
122 if ((Hashval)ss->nstrings * 2 > hashmask)
124 stringpool_resize_hash(ss, STRING_BLOCK);
125 hashmask = ss->stringhashmask;
127 hashtbl = ss->stringhashtbl;
129 /* compute hash and check for match */
130 h = strnhash(str, len) & hashmask;
131 hh = HASHCHAIN_START;
132 while ((id = hashtbl[h]) != 0)
134 if(!memcmp(ss->stringspace + ss->strings[id], str, len)
135 && ss->stringspace[ss->strings[id] + len] == 0)
137 h = HASHCHAIN_NEXT(h, hh, hashmask);
139 if (id || !create) /* exit here if string found */
142 /* this should be a test for a flag that tells us if the
143 * correct blocking is used, but adding a flag would break
144 * the ABI. So we use the existance of the hash area as
145 * indication instead */
148 ss->stringspace = solv_extend_resize(ss->stringspace, ss->sstrings + len + 1, 1, STRINGSPACE_BLOCK);
149 ss->strings = solv_extend_resize(ss->strings, ss->nstrings + 1, sizeof(Offset), STRING_BLOCK);
152 /* generate next id and save in table */
156 ss->strings = solv_extend(ss->strings, id, 1, sizeof(Offset), STRING_BLOCK);
157 ss->strings[id] = ss->sstrings; /* we will append to the end */
159 /* append string to stringspace */
160 ss->stringspace = solv_extend(ss->stringspace, ss->sstrings, len + 1, 1, STRINGSPACE_BLOCK);
161 memcpy(ss->stringspace + ss->sstrings, str, len);
162 ss->stringspace[ss->sstrings + len] = 0;
163 ss->sstrings += len + 1;
168 stringpool_str2id(Stringpool *ss, const char *str, int create)
174 return stringpool_strn2id(ss, str, (unsigned int)strlen(str), create);
178 stringpool_shrink(Stringpool *ss)
180 ss->stringspace = solv_extend_resize(ss->stringspace, ss->sstrings, 1, STRINGSPACE_BLOCK);
181 ss->strings = solv_extend_resize(ss->strings, ss->nstrings, sizeof(Offset), STRING_BLOCK);