fix dataiterator returning random data in some cases
[platform/upstream/libsolv.git] / src / repopack.h
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 /* pack/unpack functions for key data */
9
10 #ifndef LIBSOLV_REPOPACK_H
11 #define LIBSOLV_REPOPACK_H
12
13 static inline unsigned char *
14 data_read_id(unsigned char *dp, Id *idp)
15 {
16   Id x;
17   unsigned char c;
18   if (!(dp[0] & 0x80))
19     {
20       *idp = dp[0];
21       return dp + 1;
22     }
23   if (!(dp[1] & 0x80))
24     {
25       *idp = dp[0] << 7 ^ dp[1] ^ 0x4000;
26       return dp + 2;
27     }
28   if (!(dp[2] & 0x80))
29     {
30       *idp = dp[0] << 14 ^ dp[1] << 7 ^ dp[2] ^ 0x204000;
31       return dp + 3;
32     }
33   if (!(dp[3] & 0x80))
34     {
35       *idp = dp[0] << 21 ^ dp[1] << 14 ^ dp[2] << 7 ^ dp[3] ^ 0x10204000;
36       return dp + 4;
37     }
38   x = dp[0] << 28 ^ dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204000;
39   if (!(dp[4] & 0x80))
40     {
41       *idp = x;
42       return dp + 5;
43     }
44   x ^= 80;
45   dp += 5;
46   for (;;)
47     {
48       c = *dp++;
49       if (!(c & 0x80))
50         {
51           *idp = (x << 7) ^ c;
52           return dp;
53         }
54       x = (x << 7) ^ (c ^ 128);
55     }
56 }
57
58 static inline unsigned char *
59 data_read_num64(unsigned char *dp, unsigned int *low, unsigned int *high)
60 {
61   unsigned long long int x;
62   unsigned char c;
63
64   *high = 0;
65   if (!(dp[0] & 0x80))
66     {
67       *low = dp[0];
68       return dp + 1;
69     }
70   if (!(dp[1] & 0x80))
71     {
72       *low = dp[0] << 7 ^ dp[1] ^ 0x4000;
73       return dp + 2;
74     }
75   if (!(dp[2] & 0x80))
76     {
77       *low = dp[0] << 14 ^ dp[1] << 7 ^ dp[2] ^ 0x204000;
78       return dp + 3;
79     }
80   if (!(dp[3] & 0x80))
81     {
82       *low = dp[0] << 21 ^ dp[1] << 14 ^ dp[2] << 7 ^ dp[3] ^ 0x10204000;
83       return dp + 4;
84     }
85   if (!(dp[4] & 0x80))
86     {
87       *low = dp[0] << 28 ^ dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204000;
88       *high = (dp[0] ^ 0x80) >> 4;
89       return dp + 5;
90     }
91   x = (unsigned long long)(dp[0] ^ 0x80) << 28 ^ (unsigned int)(dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204080);
92   dp += 5;
93   for (;;)
94     {
95       c = *dp++;
96       if (!(c & 0x80))
97         {
98           x = (x << 7) ^ c;
99           *low = x;
100           *high = x >> 32;
101           return dp;
102         }
103       x = (x << 7) ^ (c ^ 128);
104     }
105 }
106
107 static inline unsigned char *
108 data_read_ideof(unsigned char *dp, Id *idp, int *eof)
109 {
110   Id x = 0;
111   unsigned char c;
112   for (;;)
113     {
114       c = *dp++;
115       if (!(c & 0x80))
116         {
117           if (c & 0x40)
118             {
119               c ^= 0x40;
120               *eof = 0;
121             }
122           else
123             *eof = 1;
124           *idp = (x << 6) ^ c;
125           return dp;
126         }
127       x = (x << 7) ^ c ^ 128;
128     }
129 }
130
131 static inline unsigned char *
132 data_read_u32(unsigned char *dp, unsigned int *nump)
133 {
134   *nump = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3];
135   return dp + 4;
136 }
137
138 static inline unsigned char *
139 data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key)
140 {
141   kv->eof = 1;
142   if (!dp)
143     return 0;
144   switch (key->type)
145     {
146     case REPOKEY_TYPE_VOID:
147       return dp;
148     case REPOKEY_TYPE_CONSTANT:
149       kv->num2 = 0;
150       kv->num = key->size;
151       return dp;
152     case REPOKEY_TYPE_CONSTANTID:
153       kv->id = key->size;
154       return dp;
155     case REPOKEY_TYPE_STR:
156       kv->str = (const char *)dp;
157       return dp + strlen(kv->str) + 1;
158     case REPOKEY_TYPE_ID:
159     case REPOKEY_TYPE_DIR:
160       return data_read_id(dp, &kv->id);
161     case REPOKEY_TYPE_NUM:
162       return data_read_num64(dp, &kv->num, &kv->num2);
163     case REPOKEY_TYPE_U32:
164       kv->num2 = 0;
165       return data_read_u32(dp, &kv->num);
166     case REPOKEY_TYPE_MD5:
167       kv->num = 0;      /* not stringified yet */
168       kv->str = (const char *)dp;
169       return dp + SIZEOF_MD5;
170     case REPOKEY_TYPE_SHA1:
171       kv->num = 0;      /* not stringified yet */
172       kv->str = (const char *)dp;
173       return dp + SIZEOF_SHA1;
174     case REPOKEY_TYPE_SHA256:
175       kv->num = 0;      /* not stringified yet */
176       kv->str = (const char *)dp;
177       return dp + SIZEOF_SHA256;
178     case REPOKEY_TYPE_BINARY:
179       dp = data_read_id(dp, (Id *)&kv->num);
180       kv->str = (const char *)dp;
181       return dp + kv->num;
182     case REPOKEY_TYPE_IDARRAY:
183       return data_read_ideof(dp, &kv->id, &kv->eof);
184     case REPOKEY_TYPE_DIRSTRARRAY:
185       dp = data_read_ideof(dp, &kv->id, &kv->eof);
186       kv->num = 0;      /* not stringified yet */
187       kv->str = (const char *)dp;
188       return dp + strlen(kv->str) + 1;
189     case REPOKEY_TYPE_DIRNUMNUMARRAY:
190       dp = data_read_id(dp, &kv->id);
191       dp = data_read_id(dp, (Id *)&kv->num);
192       return data_read_ideof(dp, (Id *)&kv->num2, &kv->eof);
193     case REPOKEY_TYPE_FIXARRAY:
194       dp = data_read_id(dp, (Id *)&kv->num);
195       return data_read_id(dp, &kv->id);
196     case REPOKEY_TYPE_FLEXARRAY:
197       return data_read_id(dp, (Id *)&kv->num);
198     default:
199       return 0;
200     }
201 }
202
203 static inline unsigned char *
204 data_skip(unsigned char *dp, int type)
205 {
206   unsigned char x;
207   switch (type)
208     {
209     case REPOKEY_TYPE_VOID:
210     case REPOKEY_TYPE_CONSTANT:
211     case REPOKEY_TYPE_CONSTANTID:
212     case REPOKEY_TYPE_DELETED:
213       return dp;
214     case REPOKEY_TYPE_ID:
215     case REPOKEY_TYPE_NUM:
216     case REPOKEY_TYPE_DIR:
217       while ((*dp & 0x80) != 0)
218         dp++;
219       return dp + 1;
220     case REPOKEY_TYPE_U32:
221       return dp + 4;
222     case REPOKEY_TYPE_MD5:
223       return dp + SIZEOF_MD5;
224     case REPOKEY_TYPE_SHA1:
225       return dp + SIZEOF_SHA1;
226     case REPOKEY_TYPE_SHA256:
227       return dp + SIZEOF_SHA256;
228     case REPOKEY_TYPE_IDARRAY:
229     case REPOKEY_TYPE_REL_IDARRAY:
230       while ((*dp & 0xc0) != 0)
231         dp++;
232       return dp + 1;
233     case REPOKEY_TYPE_STR:
234       while ((*dp) != 0)
235         dp++;
236       return dp + 1;
237     case REPOKEY_TYPE_BINARY:
238       {
239         unsigned int len;
240         dp = data_read_id(dp, (Id *)&len);
241         return dp + len;
242       }
243     case REPOKEY_TYPE_DIRSTRARRAY:
244       for (;;)
245         {
246           while ((*dp & 0x80) != 0)
247             dp++;
248           x = *dp++;
249           while ((*dp) != 0)
250             dp++;
251           dp++;
252           if (!(x & 0x40))
253             return dp;
254         }
255     case REPOKEY_TYPE_DIRNUMNUMARRAY:
256       for (;;)
257         {
258           while ((*dp & 0x80) != 0)
259             dp++;
260           dp++;
261           while ((*dp & 0x80) != 0)
262             dp++;
263           dp++;
264           while ((*dp & 0x80) != 0)
265             dp++;
266           if (!(*dp & 0x40))
267             return dp + 1;
268           dp++;
269         }
270     default:
271       return 0;
272     }
273 }
274
275 static inline unsigned char *
276 data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir)
277 {
278   Id id;
279   int eof;
280
281   switch (type)
282     {
283     case REPOKEY_TYPE_VOID:
284     case REPOKEY_TYPE_CONSTANT:
285     case REPOKEY_TYPE_CONSTANTID:
286     case REPOKEY_TYPE_DELETED:
287       return dp;
288     case REPOKEY_TYPE_NUM:
289       while ((*dp & 0x80) != 0)
290         dp++;
291       return dp + 1;
292     case REPOKEY_TYPE_U32:
293       return dp + 4;
294     case REPOKEY_TYPE_MD5:
295       return dp + SIZEOF_MD5;
296     case REPOKEY_TYPE_SHA1:
297       return dp + SIZEOF_SHA1;
298     case REPOKEY_TYPE_SHA256:
299       return dp + SIZEOF_SHA256;
300     case REPOKEY_TYPE_ID:
301       dp = data_read_id(dp, &id);
302       if (id >= maxid)
303         return 0;
304       return dp;
305     case REPOKEY_TYPE_DIR:
306       dp = data_read_id(dp, &id);
307       if (id >= maxdir)
308         return 0;
309       return dp;
310     case REPOKEY_TYPE_IDARRAY:
311       for (;;)
312         {
313           dp = data_read_ideof(dp, &id, &eof);
314           if (id >= maxid)
315             return 0;
316           if (eof)
317             return dp;
318         }
319     case REPOKEY_TYPE_STR:
320       while ((*dp) != 0)
321         dp++;
322       return dp + 1;
323     case REPOKEY_TYPE_BINARY:
324       {
325         unsigned int len;
326         dp = data_read_id(dp, (Id *)&len);
327         return dp + len;
328       }
329     case REPOKEY_TYPE_DIRSTRARRAY:
330       for (;;)
331         {
332           dp = data_read_ideof(dp, &id, &eof);
333           if (id >= maxdir)
334             return 0;
335           while ((*dp) != 0)
336             dp++;
337           dp++;
338           if (eof)
339             return dp;
340         }
341     case REPOKEY_TYPE_DIRNUMNUMARRAY:
342       for (;;)
343         {
344           dp = data_read_id(dp, &id);
345           if (id >= maxdir)
346             return 0;
347           while ((*dp & 0x80) != 0)
348             dp++;
349           dp++;
350           while ((*dp & 0x80) != 0)
351             dp++;
352           if (!(*dp & 0x40))
353             return dp + 1;
354           dp++;
355         }
356     default:
357       return 0;
358     }
359 }
360
361 #endif  /* LIBSOLV_REPOPACK */