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