1 /*
2 * Copyright (c) 2007, Novell Inc.
3 *
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
6 */
7
8 /*
9 * poolid.c
10 *
11 * Id management
12 */
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <stdio.h>
17
18 #include "pool.h"
19 #include "poolid.h"
20 #include "poolid_private.h"
21 #include "util.h"
22
23
24 /* intern string into pool, return id */
25
26 Id
pool_str2id(Pool * pool,const char * str,int create)27 pool_str2id(Pool *pool, const char *str, int create)
28 {
29 int oldnstrings = pool->ss.nstrings;
30 Id id = stringpool_str2id(&pool->ss, str, create);
31 if (create && pool->whatprovides && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0)
32 {
33 /* grow whatprovides array */
34 pool->whatprovides = solv_realloc(pool->whatprovides, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset));
35 memset(pool->whatprovides + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
36 }
37 return id;
38 }
39
40 Id
pool_strn2id(Pool * pool,const char * str,unsigned int len,int create)41 pool_strn2id(Pool *pool, const char *str, unsigned int len, int create)
42 {
43 int oldnstrings = pool->ss.nstrings;
44 Id id = stringpool_strn2id(&pool->ss, str, len, create);
45 if (create && pool->whatprovides && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0)
46 {
47 /* grow whatprovides array */
48 pool->whatprovides = solv_realloc(pool->whatprovides, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset));
49 memset(pool->whatprovides + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
50 }
51 return id;
52 }
53
54 Id
pool_rel2id(Pool * pool,Id name,Id evr,int flags,int create)55 pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create)
56 {
57 Hashval h, hh, hashmask;
58 int i;
59 Id id;
60 Hashtable hashtbl;
61 Reldep *ran;
62
63 hashmask = pool->relhashmask;
64 hashtbl = pool->relhashtbl;
65 ran = pool->rels;
66
67 /* extend hashtable if needed */
68 if (pool->nrels * 2 > hashmask)
69 {
70 solv_free(pool->relhashtbl);
71 pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK);
72 pool->relhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id));
73 /* rehash all rels into new hashtable */
74 for (i = 1; i < pool->nrels; i++)
75 {
76 h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
77 hh = HASHCHAIN_START;
78 while (hashtbl[h])
79 h = HASHCHAIN_NEXT(h, hh, hashmask);
80 hashtbl[h] = i;
81 }
82 }
83
84 /* compute hash and check for match */
85 h = relhash(name, evr, flags) & hashmask;
86 hh = HASHCHAIN_START;
87 while ((id = hashtbl[h]) != 0)
88 {
89 if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
90 break;
91 h = HASHCHAIN_NEXT(h, hh, hashmask);
92 }
93 if (id)
94 return MAKERELDEP(id);
95
96 if (!create)
97 return ID_NULL;
98
99 id = pool->nrels++;
100 /* extend rel space if needed */
101 pool->rels = solv_extend(pool->rels, id, 1, sizeof(Reldep), REL_BLOCK);
102 hashtbl[h] = id;
103 ran = pool->rels + id;
104 ran->name = name;
105 ran->evr = evr;
106 ran->flags = flags;
107
108 /* extend whatprovides_rel if needed */
109 if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0)
110 {
111 pool->whatprovides_rel = solv_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset));
112 memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
113 }
114 return MAKERELDEP(id);
115 }
116
117
118 /* Id -> String
119 * for rels (returns name only) and strings
120 */
121 const char *
pool_id2str(const Pool * pool,Id id)122 pool_id2str(const Pool *pool, Id id)
123 {
124 if (ISRELDEP(id))
125 {
126 Reldep *rd = GETRELDEP(pool, id);
127 if (ISRELDEP(rd->name))
128 return "REL";
129 return pool->ss.stringspace + pool->ss.strings[rd->name];
130 }
131 return pool->ss.stringspace + pool->ss.strings[id];
132 }
133
134 static const char *rels[] = {
135 " ! ",
136 " > ",
137 " = ",
138 " >= ",
139 " < ",
140 " <> ",
141 " <= ",
142 " <=> "
143 };
144
145
146 /* get operator for RelId */
147 const char *
pool_id2rel(const Pool * pool,Id id)148 pool_id2rel(const Pool *pool, Id id)
149 {
150 Reldep *rd;
151 if (!ISRELDEP(id))
152 return "";
153 rd = GETRELDEP(pool, id);
154 switch (rd->flags)
155 {
156 case 0: case 2: case 3:
157 case 6: case 7:
158 #if !defined(DEBIAN) && !defined(MULTI_SEMANTICS)
159 case 1: case 4:
160 #endif
161 #if !defined(HAIKU) && !defined(MULTI_SEMANTICS)
162 case 5:
163 #endif
164 return rels[rd->flags];
165 #if defined(DEBIAN) || defined(MULTI_SEMANTICS)
166 case 1:
167 return pool->disttype == DISTTYPE_DEB ? " >> " : rels[rd->flags];
168 case 4:
169 return pool->disttype == DISTTYPE_DEB ? " << " : rels[rd->flags];
170 #endif
171 #if defined(HAIKU) || defined(MULTI_SEMANTICS)
172 case 5:
173 return pool->disttype == DISTTYPE_HAIKU ? " != " : rels[rd->flags];
174 #endif
175 case REL_AND:
176 return " & ";
177 case REL_OR:
178 return " | ";
179 case REL_WITH:
180 return " + ";
181 case REL_NAMESPACE:
182 return " NAMESPACE "; /* actually not used in dep2str */
183 case REL_ARCH:
184 return ".";
185 case REL_FILECONFLICT:
186 return " FILECONFLICT ";
187 case REL_COND:
188 return " IF ";
189 case REL_COMPAT:
190 return " compat >= ";
191 default:
192 break;
193 }
194 return " ??? ";
195 }
196
197
198 /* get e:v.r for Id */
199 const char *
pool_id2evr(const Pool * pool,Id id)200 pool_id2evr(const Pool *pool, Id id)
201 {
202 Reldep *rd;
203 if (!ISRELDEP(id))
204 return "";
205 rd = GETRELDEP(pool, id);
206 if (ISRELDEP(rd->evr))
207 return "(REL)";
208 return pool->ss.stringspace + pool->ss.strings[rd->evr];
209 }
210
211 static int
dep2strlen(const Pool * pool,Id id)212 dep2strlen(const Pool *pool, Id id)
213 {
214 int l = 0;
215
216 while (ISRELDEP(id))
217 {
218 Reldep *rd = GETRELDEP(pool, id);
219 /* add 2 for parens */
220 l += 2 + dep2strlen(pool, rd->name) + strlen(pool_id2rel(pool, id));
221 id = rd->evr;
222 }
223 return l + strlen(pool->ss.stringspace + pool->ss.strings[id]);
224 }
225
226 static void
dep2strcpy(const Pool * pool,char * p,Id id,int oldrel)227 dep2strcpy(const Pool *pool, char *p, Id id, int oldrel)
228 {
229 while (ISRELDEP(id))
230 {
231 Reldep *rd = GETRELDEP(pool, id);
232 if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH)
233 if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH)
234 if (oldrel != rd->flags)
235 {
236 *p++ = '(';
237 dep2strcpy(pool, p, rd->name, rd->flags);
238 p += strlen(p);
239 strcpy(p, pool_id2rel(pool, id));
240 p += strlen(p);
241 dep2strcpy(pool, p, rd->evr, rd->flags);
242 strcat(p, ")");
243 return;
244 }
245 dep2strcpy(pool, p, rd->name, rd->flags);
246 p += strlen(p);
247 if (rd->flags == REL_NAMESPACE)
248 {
249 *p++ = '(';
250 dep2strcpy(pool, p, rd->evr, rd->flags);
251 strcat(p, ")");
252 return;
253 }
254 if (rd->flags == REL_FILECONFLICT)
255 {
256 *p = 0;
257 return;
258 }
259 strcpy(p, pool_id2rel(pool, id));
260 p += strlen(p);
261 id = rd->evr;
262 oldrel = rd->flags;
263 }
264 strcpy(p, pool->ss.stringspace + pool->ss.strings[id]);
265 }
266
267 const char *
pool_dep2str(Pool * pool,Id id)268 pool_dep2str(Pool *pool, Id id)
269 {
270 char *p;
271 if (!ISRELDEP(id))
272 return pool->ss.stringspace + pool->ss.strings[id];
273 p = pool_alloctmpspace(pool, dep2strlen(pool, id) + 1);
274 dep2strcpy(pool, p, id, 0);
275 return p;
276 }
277
278 void
pool_shrink_strings(Pool * pool)279 pool_shrink_strings(Pool *pool)
280 {
281 stringpool_shrink(&pool->ss);
282 }
283
284 void
pool_shrink_rels(Pool * pool)285 pool_shrink_rels(Pool *pool)
286 {
287 pool->rels = solv_extend_resize(pool->rels, pool->nrels, sizeof(Reldep), REL_BLOCK);
288 }
289
290 /* free all hash tables */
291 void
pool_freeidhashes(Pool * pool)292 pool_freeidhashes(Pool *pool)
293 {
294 stringpool_freehash(&pool->ss);
295 pool->relhashtbl = solv_free(pool->relhashtbl);
296 pool->relhashmask = 0;
297 }
298
299 /* EOF */
300