- rename xmalloc/... functions to sat_malloc, as we're a
[platform/upstream/libsolv.git] / src / poolid.c
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
27 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 && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0)
32     {
33       /* grow whatprovides array */
34       pool->whatprovides = sat_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
41 rel2id(Pool *pool, Id name, Id evr, int flags, int create)
42 {
43   Hashval h;
44   unsigned int hh;
45   Hashmask hashmask;
46   int i;
47   Id id;
48   Hashtable hashtbl;
49   Reldep *ran;
50
51   hashmask = pool->relhashmask;
52   hashtbl = pool->relhashtbl;
53   ran = pool->rels;
54   
55   /* extend hashtable if needed */
56   if (pool->nrels * 2 > hashmask)
57     {
58       sat_free(pool->relhashtbl);
59       pool->relhashmask = hashmask = mkmask(pool->ss.nstrings + REL_BLOCK);
60       pool->relhashtbl = hashtbl = sat_calloc(hashmask + 1, sizeof(Id));
61       // rehash all rels into new hashtable
62       for (i = 1; i < pool->nrels; i++)
63         {
64           h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
65           hh = HASHCHAIN_START;
66           while (hashtbl[h])
67             h = HASHCHAIN_NEXT(h, hh, hashmask);
68           hashtbl[h] = i;
69         }
70     }
71   
72   /* compute hash and check for match */
73   h = relhash(name, evr, flags) & hashmask;
74   hh = HASHCHAIN_START;
75   while ((id = hashtbl[h]) != 0)
76     {
77       if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
78         break;
79       h = HASHCHAIN_NEXT(h, hh, hashmask);
80     }
81   if (id)
82     return MAKERELDEP(id);
83
84   if (!create)
85     return ID_NULL;
86
87   id = pool->nrels++;
88   /* extend rel space if needed */
89   if ((id & REL_BLOCK) == 0)
90     pool->rels = sat_realloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep));
91   hashtbl[h] = id;
92   ran = pool->rels + id;
93   ran->name = name;
94   ran->evr = evr;
95   ran->flags = flags;
96
97   /* extend whatprovides_rel if needed */
98   if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0)
99     {
100       pool->whatprovides_rel = sat_realloc(pool->whatprovides_rel, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset));
101       memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
102     }
103   return MAKERELDEP(id);
104 }
105
106
107 // Id -> String
108 // for rels (returns name only) and strings
109 // 
110 const char *
111 id2str(Pool *pool, Id id)
112 {
113   if (ISRELDEP(id))
114     {
115       Reldep *rd = GETRELDEP(pool, id);
116       if (ISRELDEP(rd->name))
117         return "REL";
118       return pool->ss.stringspace + pool->ss.strings[rd->name];
119     }
120   return pool->ss.stringspace + pool->ss.strings[id];
121 }
122
123 static const char *rels[] = {
124   " ! ",
125   " > ",
126   " = ",
127   " >= ",
128   " < ",
129   " <> ",
130   " <= ",
131   " <=> "
132 };
133
134
135 // get operator for RelId
136 const char *
137 id2rel(Pool *pool, Id id)
138 {
139   Reldep *rd;
140   if (!ISRELDEP(id))
141     return "";
142   rd = GETRELDEP(pool, id);
143   switch (rd->flags)
144     {
145     case 0: case 1: case 2: case 3:
146     case 4: case 5: case 6: case 7:
147       return rels[rd->flags & 7];
148     case REL_AND:
149       return " AND ";
150     case REL_OR:
151       return " OR ";
152     case REL_WITH:
153       return " WITH ";
154     case REL_NAMESPACE:
155       return " NAMESPACE ";
156     default:
157       break;
158     }
159   return " ??? ";
160 }
161
162
163 // get e:v.r for Id
164 // 
165 const char *
166 id2evr(Pool *pool, Id id)
167 {
168   Reldep *rd;
169   if (!ISRELDEP(id))
170     return "";
171   rd = GETRELDEP(pool, id);
172   if (ISRELDEP(rd->evr))
173     return "REL";
174   return pool->ss.stringspace + pool->ss.strings[rd->evr];
175 }
176
177 const char *
178 dep2str(Pool *pool, Id id)
179 {
180   Reldep *rd;
181   const char *sr;
182   char *s1, *s2;
183   int n, l, ls1, ls2, lsr;
184
185   if (!ISRELDEP(id))
186     return pool->ss.stringspace + pool->ss.strings[id];
187   rd = GETRELDEP(pool, id);
188   n = pool->dep2strn;
189
190   sr = id2rel(pool, id);
191   lsr = strlen(sr);
192
193   s2 = (char *)dep2str(pool, rd->evr);
194   pool->dep2strn = n;
195   ls2 = strlen(s2);
196
197   s1 = (char *)dep2str(pool, rd->name);
198   pool->dep2strn = n;
199   ls1 = strlen(s1);
200
201   if (rd->flags == REL_NAMESPACE)
202     {
203       sr = "(";
204       lsr = 1;
205       ls2++;
206     }
207
208   l = ls1 + ls2 + lsr;
209   if (l + 1 > pool->dep2strlen[n])
210     {
211       if (s1 != pool->dep2strbuf[n])
212         pool->dep2strbuf[n] = sat_realloc(pool->dep2strbuf[n], l + 32);
213       else
214         {
215           pool->dep2strbuf[n] = sat_realloc(pool->dep2strbuf[n], l + 32);
216           s1 = pool->dep2strbuf[n];
217         }
218       pool->dep2strlen[n] = l + 32;
219     }
220   if (s1 != pool->dep2strbuf[n])
221     {
222       strcpy(pool->dep2strbuf[n], s1);
223       s1 = pool->dep2strbuf[n];
224     }
225   strcpy(s1 + ls1, sr);
226   pool->dep2strbuf[n] = s1 + ls1 + lsr;
227   s2 = (char *)dep2str(pool, rd->evr);
228   if (s2 != pool->dep2strbuf[n])
229     strcpy(pool->dep2strbuf[n], s2);
230   pool->dep2strbuf[n] = s1;
231   if (rd->flags == REL_NAMESPACE)
232     {
233       s1[ls1 + ls2 + lsr - 1] = ')';
234       s1[ls1 + ls2 + lsr] = 0;
235     }
236   pool->dep2strn = (n + 1) % DEP2STRBUF;
237   return s1;
238 }
239
240
241 void
242 pool_shrink_strings(Pool *pool)
243 {
244   stringpool_shrink(&pool->ss);
245 }
246
247 void
248 pool_shrink_rels(Pool *pool)
249 {
250   pool->rels = (Reldep *)sat_realloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep));
251 }
252
253 // reset all hash tables
254 // 
255 void
256 pool_freeidhashes(Pool *pool)
257 {
258   pool->ss.stringhashtbl = sat_free(pool->ss.stringhashtbl);
259   pool->ss.stringhashmask = 0;
260   pool->relhashtbl = sat_free(pool->relhashtbl);
261   pool->relhashmask = 0;
262 }
263
264 // EOF