2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
20 #include "poolid_private.h"
24 // intern string into pool
28 str2id(Pool *pool, const char *str, int create)
43 hashmask = pool->stringhashmask;
44 hashtbl = pool->stringhashtbl;
46 // expand hashtable if needed
49 if (pool->nstrings * 2 > hashmask)
54 pool->stringhashmask = hashmask = mkmask(pool->nstrings + STRING_BLOCK);
55 pool->stringhashtbl = hashtbl = (Hashtable)xcalloc(hashmask + 1, sizeof(Id));
57 // rehash all strings into new hashtable
58 for (i = 1; i < pool->nstrings; i++)
60 h = strhash(pool->stringspace + pool->strings[i]) & hashmask;
62 while (hashtbl[h] != ID_NULL) // follow overflow chain
63 h = HASHCHAIN_NEXT(h, hh, hashmask);
68 // compute hash and check for match
70 h = strhash(str) & hashmask;
72 while ((id = hashtbl[h]) != ID_NULL) // follow hash overflow chain
74 // break if string already hashed
75 if(!strcmp(pool->stringspace + pool->strings[id], str))
77 h = HASHCHAIN_NEXT(h, hh, hashmask);
79 if (id || !create) // exit here if string found
82 pool_freewhatprovides(pool);
84 // generate next id and save in table
85 id = pool->nstrings++;
89 if ((id & STRING_BLOCK) == 0)
90 pool->strings = xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Hashval));
91 // 'pointer' into stringspace is Offset of next free pos: sstrings
92 pool->strings[id] = pool->sstrings;
94 space_needed = strlen(str) + 1;
96 // resize string buffer if needed
97 if (((pool->sstrings + space_needed - 1) | STRINGSPACE_BLOCK) != ((pool->sstrings - 1) | STRINGSPACE_BLOCK))
98 pool->stringspace = xrealloc(pool->stringspace, (pool->sstrings + space_needed + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
99 // copy new string into buffer
100 memcpy(pool->stringspace + pool->sstrings, str, space_needed);
101 // next free pos is behind new string
102 pool->sstrings += space_needed;
109 rel2id(Pool *pool, Id name, Id evr, int flags, int create)
119 hashmask = pool->relhashmask;
120 hashtbl = pool->relhashtbl;
123 // extend hashtable if needed
124 if (pool->nrels * 2 > hashmask)
126 xfree(pool->relhashtbl);
127 pool->relhashmask = hashmask = mkmask(pool->nstrings + REL_BLOCK);
128 pool->relhashtbl = hashtbl = xcalloc(hashmask + 1, sizeof(Id));
129 // rehash all rels into new hashtable
130 for (i = 1; i < pool->nrels; i++)
132 h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
133 hh = HASHCHAIN_START;
135 h = HASHCHAIN_NEXT(h, hh, hashmask);
140 // compute hash and check for match
142 h = relhash(name, evr, flags) & hashmask;
143 hh = HASHCHAIN_START;
144 while ((id = hashtbl[h]) != 0)
146 if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
148 h = HASHCHAIN_NEXT(h, hh, hashmask);
151 return MAKERELDEP(id);
156 pool_freewhatprovides(pool);
159 // extend rel space if needed
160 if ((id & REL_BLOCK) == 0)
161 pool->rels = xrealloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep));
163 ran = pool->rels + id;
167 return MAKERELDEP(id);
172 // for rels (returns name only) and strings
175 id2str(Pool *pool, Id id)
179 Reldep *rd = GETRELDEP(pool, id);
180 if (ISRELDEP(rd->name))
182 return pool->stringspace + pool->strings[rd->name];
184 return pool->stringspace + pool->strings[id];
187 static const char *rels[] = {
199 // get operator for RelId
201 id2rel(Pool *pool, Id id)
206 rd = GETRELDEP(pool, id);
209 case 0: case 1: case 2: case 3:
210 case 4: case 5: case 6: case 7:
211 return rels[rd->flags & 7];
219 return " NAMESPACE ";
230 id2evr(Pool *pool, Id id)
235 rd = GETRELDEP(pool, id);
236 if (ISRELDEP(rd->evr))
238 return pool->stringspace + pool->strings[rd->evr];
242 dep2str(Pool *pool, Id id)
247 int n, l, ls1, ls2, lsr;
250 return pool->stringspace + pool->strings[id];
251 rd = GETRELDEP(pool, id);
254 sr = id2rel(pool, id);
257 s2 = (char *)dep2str(pool, rd->evr);
261 s1 = (char *)dep2str(pool, rd->name);
265 if (rd->flags == REL_NAMESPACE)
273 if (l + 1 > pool->dep2strlen[n])
275 if (s1 != pool->dep2strbuf[n])
276 pool->dep2strbuf[n] = xrealloc(pool->dep2strbuf[n], l + 32);
279 pool->dep2strbuf[n] = xrealloc(pool->dep2strbuf[n], l + 32);
280 s1 = pool->dep2strbuf[n];
282 pool->dep2strlen[n] = l + 32;
284 if (s1 != pool->dep2strbuf[n])
286 strcpy(pool->dep2strbuf[n], s1);
287 s1 = pool->dep2strbuf[n];
289 strcpy(s1 + ls1, sr);
290 pool->dep2strbuf[n] = s1 + ls1 + lsr;
291 s2 = (char *)dep2str(pool, rd->evr);
292 if (s2 != pool->dep2strbuf[n])
293 strcpy(pool->dep2strbuf[n], s2);
294 pool->dep2strbuf[n] = s1;
295 if (rd->flags == REL_NAMESPACE)
297 s1[ls1 + ls2 + lsr - 1] = ')';
298 s1[ls1 + ls2 + lsr] = 0;
300 pool->dep2strn = (n + 1) % DEP2STRBUF;
306 pool_shrink_strings(Pool *pool)
308 pool->stringspace = (char *)xrealloc(pool->stringspace, (pool->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
309 pool->strings = (Offset *)xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
313 pool_shrink_rels(Pool *pool)
315 pool->rels = (Reldep *)xrealloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep));
318 // reset all hash tables
321 pool_freeidhashes(Pool *pool)
323 pool->stringhashtbl = xfree(pool->stringhashtbl);
324 pool->relhashtbl = xfree(pool->relhashtbl);
325 pool->stringhashmask = 0;
326 pool->relhashmask = 0;