13 #include "poolid_private.h"
17 // intern string into pool
21 str2id(Pool *pool, const char *str, int create)
36 hashmask = pool->stringhashmask;
37 hashtbl = pool->stringhashtbl;
39 // expand hashtable if needed
42 if (pool->nstrings * 2 > hashmask)
47 pool->stringhashmask = hashmask = mkmask(pool->nstrings + STRING_BLOCK);
48 pool->stringhashtbl = hashtbl = (Hashtable)xcalloc(hashmask + 1, sizeof(Id));
50 // rehash all strings into new hashtable
51 for (i = 1; i < pool->nstrings; i++)
53 h = strhash(pool->stringspace + pool->strings[i]) & hashmask;
55 while (hashtbl[h] != ID_NULL) // follow overflow chain
56 h = HASHCHAIN_NEXT(h, hh, hashmask);
61 // compute hash and check for match
63 h = strhash(str) & hashmask;
65 while ((id = hashtbl[h]) != ID_NULL) // follow hash overflow chain
67 // break if string already hashed
68 if(!strcmp(pool->stringspace + pool->strings[id], str))
70 h = HASHCHAIN_NEXT(h, hh, hashmask);
72 if (id || !create) // exit here if string found
75 pool_freewhatprovides(pool);
77 // generate next id and save in table
78 id = pool->nstrings++;
82 if ((id & STRING_BLOCK) == 0)
83 pool->strings = xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Hashval));
84 // 'pointer' into stringspace is Offset of next free pos: sstrings
85 pool->strings[id] = pool->sstrings;
87 space_needed = strlen(str) + 1;
89 // resize string buffer if needed
90 if (((pool->sstrings + space_needed - 1) | STRINGSPACE_BLOCK) != ((pool->sstrings - 1) | STRINGSPACE_BLOCK))
91 pool->stringspace = xrealloc(pool->stringspace, (pool->sstrings + space_needed + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
92 // copy new string into buffer
93 memcpy(pool->stringspace + pool->sstrings, str, space_needed);
94 // next free pos is behind new string
95 pool->sstrings += space_needed;
102 rel2id(Pool *pool, Id name, Id evr, int flags, int create)
112 hashmask = pool->relhashmask;
113 hashtbl = pool->relhashtbl;
116 // extend hashtable if needed
117 if (pool->nrels * 2 > hashmask)
119 xfree(pool->relhashtbl);
120 pool->relhashmask = hashmask = mkmask(pool->nstrings + REL_BLOCK);
121 pool->relhashtbl = hashtbl = xcalloc(hashmask + 1, sizeof(Id));
122 // rehash all rels into new hashtable
123 for (i = 1; i < pool->nrels; i++)
125 h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
126 hh = HASHCHAIN_START;
128 h = HASHCHAIN_NEXT(h, hh, hashmask);
133 // compute hash and check for match
135 h = relhash(name, evr, flags) & hashmask;
136 hh = HASHCHAIN_START;
137 while ((id = hashtbl[h]) != 0)
139 if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
141 h = HASHCHAIN_NEXT(h, hh, hashmask);
144 return MAKERELDEP(id);
149 pool_freewhatprovides(pool);
152 // extend rel space if needed
153 if ((id & REL_BLOCK) == 0)
154 pool->rels = xrealloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep));
156 ran = pool->rels + id;
160 return MAKERELDEP(id);
165 // for rels (returns name only) and strings
168 id2str(Pool *pool, Id id)
172 Reldep *rd = GETRELDEP(pool, id);
173 if (ISRELDEP(rd->name))
175 return pool->stringspace + pool->strings[rd->name];
177 return pool->stringspace + pool->strings[id];
180 static const char *rels[] = {
192 // get operator for RelId
194 id2rel(Pool *pool, Id id)
199 rd = GETRELDEP(pool, id);
202 case 0: case 1: case 2: case 3:
203 case 4: case 5: case 6: case 7:
204 return rels[rd->flags & 7];
212 return " NAMESPACE ";
223 id2evr(Pool *pool, Id id)
228 rd = GETRELDEP(pool, id);
229 if (ISRELDEP(rd->evr))
231 return pool->stringspace + pool->strings[rd->evr];
235 dep2str(Pool *pool, Id id)
240 int n, l, ls1, ls2, lsr;
243 return pool->stringspace + pool->strings[id];
244 rd = GETRELDEP(pool, id);
247 sr = id2rel(pool, id);
250 s2 = (char *)dep2str(pool, rd->evr);
254 s1 = (char *)dep2str(pool, rd->name);
258 if (rd->flags == REL_NAMESPACE)
266 if (l + 1 > pool->dep2strlen[n])
268 if (s1 != pool->dep2strbuf[n])
269 pool->dep2strbuf[n] = xrealloc(pool->dep2strbuf[n], l + 32);
272 pool->dep2strbuf[n] = xrealloc(pool->dep2strbuf[n], l + 32);
273 s1 = pool->dep2strbuf[n];
275 pool->dep2strlen[n] = l + 32;
277 if (s1 != pool->dep2strbuf[n])
279 strcpy(pool->dep2strbuf[n], s1);
280 s1 = pool->dep2strbuf[n];
282 strcpy(s1 + ls1, sr);
283 pool->dep2strbuf[n] = s1 + ls1 + lsr;
284 s2 = (char *)dep2str(pool, rd->evr);
285 if (s2 != pool->dep2strbuf[n])
286 strcpy(pool->dep2strbuf[n], s2);
287 pool->dep2strbuf[n] = s1;
288 if (rd->flags == REL_NAMESPACE)
290 s1[ls1 + ls2 + lsr - 1] = ')';
291 s1[ls1 + ls2 + lsr] = 0;
293 pool->dep2strn = (n + 1) % DEP2STRBUF;
299 pool_shrink_strings(Pool *pool)
301 pool->stringspace = (char *)xrealloc(pool->stringspace, (pool->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
302 pool->strings = (Offset *)xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
306 pool_shrink_rels(Pool *pool)
308 pool->rels = (Reldep *)xrealloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep));
311 // reset all hash tables
314 pool_freeidhashes(Pool *pool)
316 pool->stringhashtbl = xfree(pool->stringhashtbl);
317 pool->relhashtbl = xfree(pool->relhashtbl);
318 pool->stringhashmask = 0;
319 pool->relhashmask = 0;