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];
234 #define DEP2STRBUF 16
237 dep2str(Pool *pool, Id id)
242 int n, l, ls1, ls2, lsr;
244 static char *dep2strbuf[DEP2STRBUF];
245 static int dep2strlen[DEP2STRBUF];
249 return pool->stringspace + pool->strings[id];
250 rd = GETRELDEP(pool, id);
253 sr = id2rel(pool, id);
256 s2 = (char *)dep2str(pool, rd->evr);
260 s1 = (char *)dep2str(pool, rd->name);
264 if (rd->flags == REL_NAMESPACE)
272 if (l + 1 > dep2strlen[n])
274 if (s1 != dep2strbuf[n])
275 dep2strbuf[n] = xrealloc(dep2strbuf[n], l + 32);
278 dep2strbuf[n] = xrealloc(dep2strbuf[n], l + 32);
281 dep2strlen[n] = l + 32;
283 if (s1 != dep2strbuf[n])
285 strcpy(dep2strbuf[n], s1);
288 strcpy(s1 + ls1, sr);
289 dep2strbuf[n] = s1 + ls1 + lsr;
290 s2 = (char *)dep2str(pool, rd->evr);
291 if (s2 != dep2strbuf[n])
292 strcpy(dep2strbuf[n], s2);
294 if (rd->flags == REL_NAMESPACE)
296 s1[ls1 + ls2 + lsr - 1] = ')';
297 s1[ls1 + ls2 + lsr] = 0;
299 dep2strn = (n + 1) % DEP2STRBUF;
305 pool_shrink_strings(Pool *pool)
307 pool->stringspace = (char *)xrealloc(pool->stringspace, (pool->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
308 pool->strings = (Offset *)xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
312 pool_shrink_rels(Pool *pool)
314 pool->rels = (Reldep *)xrealloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep));
317 // reset all hash tables
320 pool_freeidhashes(Pool *pool)
322 pool->stringhashtbl = xfree(pool->stringhashtbl);
323 pool->relhashtbl = xfree(pool->relhashtbl);
324 pool->stringhashmask = 0;
325 pool->relhashmask = 0;