Imported Upstream version 0.6.11
[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_SHA224:
175       kv->num = 0;      /* not stringified yet */
176       kv->str = (const char *)dp;
177       return dp + SIZEOF_SHA224;
178     case REPOKEY_TYPE_SHA256:
179       kv->num = 0;      /* not stringified yet */
180       kv->str = (const char *)dp;
181       return dp + SIZEOF_SHA256;
182     case REPOKEY_TYPE_SHA384:
183       kv->num = 0;      /* not stringified yet */
184       kv->str = (const char *)dp;
185       return dp + SIZEOF_SHA384;
186     case REPOKEY_TYPE_SHA512:
187       kv->num = 0;      /* not stringified yet */
188       kv->str = (const char *)dp;
189       return dp + SIZEOF_SHA512;
190     case REPOKEY_TYPE_BINARY:
191       dp = data_read_id(dp, (Id *)&kv->num);
192       kv->str = (const char *)dp;
193       return dp + kv->num;
194     case REPOKEY_TYPE_IDARRAY:
195       return data_read_ideof(dp, &kv->id, &kv->eof);
196     case REPOKEY_TYPE_DIRSTRARRAY:
197       dp = data_read_ideof(dp, &kv->id, &kv->eof);
198       kv->num = 0;      /* not stringified yet */
199       kv->str = (const char *)dp;
200       return dp + strlen(kv->str) + 1;
201     case REPOKEY_TYPE_DIRNUMNUMARRAY:
202       dp = data_read_id(dp, &kv->id);
203       dp = data_read_id(dp, (Id *)&kv->num);
204       return data_read_ideof(dp, (Id *)&kv->num2, &kv->eof);
205     case REPOKEY_TYPE_FIXARRAY:
206       dp = data_read_id(dp, (Id *)&kv->num);
207       return data_read_id(dp, &kv->id);
208     case REPOKEY_TYPE_FLEXARRAY:
209       return data_read_id(dp, (Id *)&kv->num);
210     default:
211       return 0;
212     }
213 }
214
215 static inline unsigned char *
216 data_skip(unsigned char *dp, int type)
217 {
218   unsigned char x;
219   switch (type)
220     {
221     case REPOKEY_TYPE_VOID:
222     case REPOKEY_TYPE_CONSTANT:
223     case REPOKEY_TYPE_CONSTANTID:
224     case REPOKEY_TYPE_DELETED:
225       return dp;
226     case REPOKEY_TYPE_ID:
227     case REPOKEY_TYPE_NUM:
228     case REPOKEY_TYPE_DIR:
229       while ((*dp & 0x80) != 0)
230         dp++;
231       return dp + 1;
232     case REPOKEY_TYPE_U32:
233       return dp + 4;
234     case REPOKEY_TYPE_MD5:
235       return dp + SIZEOF_MD5;
236     case REPOKEY_TYPE_SHA1:
237       return dp + SIZEOF_SHA1;
238     case REPOKEY_TYPE_SHA224:
239       return dp + SIZEOF_SHA224;
240     case REPOKEY_TYPE_SHA256:
241       return dp + SIZEOF_SHA256;
242     case REPOKEY_TYPE_SHA384:
243       return dp + SIZEOF_SHA384;
244     case REPOKEY_TYPE_SHA512:
245       return dp + SIZEOF_SHA512;
246     case REPOKEY_TYPE_IDARRAY:
247     case REPOKEY_TYPE_REL_IDARRAY:
248       while ((*dp & 0xc0) != 0)
249         dp++;
250       return dp + 1;
251     case REPOKEY_TYPE_STR:
252       while ((*dp) != 0)
253         dp++;
254       return dp + 1;
255     case REPOKEY_TYPE_BINARY:
256       {
257         unsigned int len;
258         dp = data_read_id(dp, (Id *)&len);
259         return dp + len;
260       }
261     case REPOKEY_TYPE_DIRSTRARRAY:
262       for (;;)
263         {
264           while ((*dp & 0x80) != 0)
265             dp++;
266           x = *dp++;
267           while ((*dp) != 0)
268             dp++;
269           dp++;
270           if (!(x & 0x40))
271             return dp;
272         }
273     case REPOKEY_TYPE_DIRNUMNUMARRAY:
274       for (;;)
275         {
276           while ((*dp & 0x80) != 0)
277             dp++;
278           dp++;
279           while ((*dp & 0x80) != 0)
280             dp++;
281           dp++;
282           while ((*dp & 0x80) != 0)
283             dp++;
284           if (!(*dp & 0x40))
285             return dp + 1;
286           dp++;
287         }
288     default:
289       return 0;
290     }
291 }
292
293 static inline unsigned char *
294 data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir)
295 {
296   Id id;
297   int eof;
298
299   switch (type)
300     {
301     case REPOKEY_TYPE_VOID:
302     case REPOKEY_TYPE_CONSTANT:
303     case REPOKEY_TYPE_CONSTANTID:
304     case REPOKEY_TYPE_DELETED:
305       return dp;
306     case REPOKEY_TYPE_NUM:
307       while ((*dp & 0x80) != 0)
308         dp++;
309       return dp + 1;
310     case REPOKEY_TYPE_U32:
311       return dp + 4;
312     case REPOKEY_TYPE_MD5:
313       return dp + SIZEOF_MD5;
314     case REPOKEY_TYPE_SHA1:
315       return dp + SIZEOF_SHA1;
316     case REPOKEY_TYPE_SHA224:
317       return dp + SIZEOF_SHA224;
318     case REPOKEY_TYPE_SHA256:
319       return dp + SIZEOF_SHA256;
320     case REPOKEY_TYPE_SHA384:
321       return dp + SIZEOF_SHA384;
322     case REPOKEY_TYPE_SHA512:
323       return dp + SIZEOF_SHA512;
324     case REPOKEY_TYPE_ID:
325       dp = data_read_id(dp, &id);
326       if (id >= maxid)
327         return 0;
328       return dp;
329     case REPOKEY_TYPE_DIR:
330       dp = data_read_id(dp, &id);
331       if (id >= maxdir)
332         return 0;
333       return dp;
334     case REPOKEY_TYPE_IDARRAY:
335       for (;;)
336         {
337           dp = data_read_ideof(dp, &id, &eof);
338           if (id >= maxid)
339             return 0;
340           if (eof)
341             return dp;
342         }
343     case REPOKEY_TYPE_STR:
344       while ((*dp) != 0)
345         dp++;
346       return dp + 1;
347     case REPOKEY_TYPE_BINARY:
348       {
349         unsigned int len;
350         dp = data_read_id(dp, (Id *)&len);
351         return dp + len;
352       }
353     case REPOKEY_TYPE_DIRSTRARRAY:
354       for (;;)
355         {
356           dp = data_read_ideof(dp, &id, &eof);
357           if (id >= maxdir)
358             return 0;
359           while ((*dp) != 0)
360             dp++;
361           dp++;
362           if (eof)
363             return dp;
364         }
365     case REPOKEY_TYPE_DIRNUMNUMARRAY:
366       for (;;)
367         {
368           dp = data_read_id(dp, &id);
369           if (id >= maxdir)
370             return 0;
371           while ((*dp & 0x80) != 0)
372             dp++;
373           dp++;
374           while ((*dp & 0x80) != 0)
375             dp++;
376           if (!(*dp & 0x40))
377             return dp + 1;
378           dp++;
379         }
380     default:
381       return 0;
382     }
383 }
384
385 #endif  /* LIBSOLV_REPOPACK */