current state of 'sat-solver'
[platform/upstream/libsolv.git] / src / poolid.c
1 /*
2  * poolid.c
3  *
4  * Id management
5  */
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdio.h>
10
11 #include "pool.h"
12 #include "poolid.h"
13 #include "poolid_private.h"
14 #include "util.h"
15
16
17 // intern string into pool
18 // return Id
19
20 Id
21 str2id(Pool *pool, const char *str, int create)
22 {
23   Hashval h;
24   unsigned int hh;
25   Hashmask hashmask;
26   int i, space_needed;
27   Id id;
28   Hashtable hashtbl;
29
30   // check string
31   if (!str)
32     return ID_NULL;
33   if (!*str)
34     return ID_EMPTY;
35
36   hashmask = pool->stringhashmask;
37   hashtbl = pool->stringhashtbl;
38
39   // expand hashtable if needed
40   // 
41   // 
42   if (pool->nstrings * 2 > hashmask)
43     {
44       xfree(hashtbl);
45
46       // realloc hash table
47       pool->stringhashmask = hashmask = mkmask(pool->nstrings + STRING_BLOCK);
48       pool->stringhashtbl = hashtbl = (Hashtable)xcalloc(hashmask + 1, sizeof(Id));
49
50       // rehash all strings into new hashtable
51       for (i = 1; i < pool->nstrings; i++)
52         {
53           h = strhash(pool->stringspace + pool->strings[i]) & hashmask;
54           hh = HASHCHAIN_START;
55           while (hashtbl[h] != ID_NULL)  // follow overflow chain
56             h = HASHCHAIN_NEXT(h, hh, hashmask);
57           hashtbl[h] = i;
58         }
59     }
60
61   // compute hash and check for match
62
63   h = strhash(str) & hashmask;
64   hh = HASHCHAIN_START;
65   while ((id = hashtbl[h]) != ID_NULL)  // follow hash overflow chain
66     {
67       // break if string already hashed
68       if(!strcmp(pool->stringspace + pool->strings[id], str))
69         break;
70       h = HASHCHAIN_NEXT(h, hh, hashmask);
71     }
72   if (id || !create)    // exit here if string found
73     return id;
74
75   pool_freewhatprovides(pool);
76
77   // generate next id and save in table
78   id = pool->nstrings++;
79   hashtbl[h] = id;
80
81   // 
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;
86
87   space_needed = strlen(str) + 1;
88
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;
96
97   return id;
98 }
99
100
101 Id
102 rel2id(Pool *pool, Id name, Id evr, int flags, int create)
103 {
104   Hashval h;
105   unsigned int hh;
106   Hashmask hashmask;
107   int i;
108   Id id;
109   Hashtable hashtbl;
110   Reldep *ran;
111
112   hashmask = pool->relhashmask;
113   hashtbl = pool->relhashtbl;
114   ran = pool->rels;
115   
116   // extend hashtable if needed
117   if (pool->nrels * 2 > hashmask)
118     {
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++)
124         {
125           h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
126           hh = HASHCHAIN_START;
127           while (hashtbl[h])
128             h = HASHCHAIN_NEXT(h, hh, hashmask);
129           hashtbl[h] = i;
130         }
131     }
132   
133   // compute hash and check for match
134
135   h = relhash(name, evr, flags) & hashmask;
136   hh = HASHCHAIN_START;
137   while ((id = hashtbl[h]) != 0)
138     {
139       if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
140         break;
141       h = HASHCHAIN_NEXT(h, hh, hashmask);
142     }
143   if (id)
144     return MAKERELDEP(id);
145
146   if (!create)
147     return ID_NULL;
148
149   pool_freewhatprovides(pool);
150
151   id = pool->nrels++;
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));
155   hashtbl[h] = id;
156   ran = pool->rels + id;
157   ran->name = name;
158   ran->evr = evr;
159   ran->flags = flags;
160   return MAKERELDEP(id);
161 }
162
163
164 // Id -> String
165 // for rels (returns name only) and strings
166 // 
167 const char *
168 id2str(Pool *pool, Id id)
169 {
170   if (ISRELDEP(id))
171     {
172       Reldep *rd = GETRELDEP(pool, id);
173       return pool->stringspace + pool->strings[rd->name];
174     }
175   return pool->stringspace + pool->strings[id];
176 }
177
178 static const char *rels[] = {
179   " ! ",
180   " > ",
181   " = ",
182   " >= ",
183   " < ",
184   " <> ",
185   " <= ",
186   " <=> "
187 };
188
189
190 // get operator for RelId
191 const char *
192 id2rel(Pool *pool, Id id)
193 {
194   Reldep *rd;
195   if (!ISRELDEP(id))
196     return "";
197   rd = GETRELDEP(pool, id);
198   return rels[rd->flags & 7];
199 }
200
201
202 // get e:v.r for Id
203 // 
204 const char *
205 id2evr(Pool *pool, Id id)
206 {
207   Reldep *rd;
208   if (!ISRELDEP(id))
209     return "";
210   rd = GETRELDEP(pool, id);
211   return pool->stringspace + pool->strings[rd->evr];
212 }
213
214 void
215 pool_shrink_strings(Pool *pool)
216 {
217   pool->stringspace = (char *)xrealloc(pool->stringspace, (pool->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
218   pool->strings = (Offset *)xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
219 }
220
221 void
222 pool_shrink_rels(Pool *pool)
223 {
224   pool->rels = (Reldep *)xrealloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep));
225 }
226
227 // reset all hash tables
228 // 
229 void
230 pool_freeidhashes(Pool *pool)
231 {
232   pool->stringhashtbl = xfree(pool->stringhashtbl);
233   pool->relhashtbl = xfree(pool->relhashtbl);
234   pool->stringhashmask = 0;
235   pool->relhashmask = 0;
236 }
237
238 // EOF