f7828ab4a70526454d8908c65eb4329c2f13b4b8
[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_SHA256:
239       return dp + SIZEOF_SHA256;
240     case REPOKEY_TYPE_IDARRAY:
241     case REPOKEY_TYPE_REL_IDARRAY:
242       while ((*dp & 0xc0) != 0)
243         dp++;
244       return dp + 1;
245     case REPOKEY_TYPE_STR:
246       while ((*dp) != 0)
247         dp++;
248       return dp + 1;
249     case REPOKEY_TYPE_BINARY:
250       {
251         unsigned int len;
252         dp = data_read_id(dp, (Id *)&len);
253         return dp + len;
254       }
255     case REPOKEY_TYPE_DIRSTRARRAY:
256       for (;;)
257         {
258           while ((*dp & 0x80) != 0)
259             dp++;
260           x = *dp++;
261           while ((*dp) != 0)
262             dp++;
263           dp++;
264           if (!(x & 0x40))
265             return dp;
266         }
267     case REPOKEY_TYPE_DIRNUMNUMARRAY:
268       for (;;)
269         {
270           while ((*dp & 0x80) != 0)
271             dp++;
272           dp++;
273           while ((*dp & 0x80) != 0)
274             dp++;
275           dp++;
276           while ((*dp & 0x80) != 0)
277             dp++;
278           if (!(*dp & 0x40))
279             return dp + 1;
280           dp++;
281         }
282     default:
283       return 0;
284     }
285 }
286
287 static inline unsigned char *
288 data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir)
289 {
290   Id id;
291   int eof;
292
293   switch (type)
294     {
295     case REPOKEY_TYPE_VOID:
296     case REPOKEY_TYPE_CONSTANT:
297     case REPOKEY_TYPE_CONSTANTID:
298     case REPOKEY_TYPE_DELETED:
299       return dp;
300     case REPOKEY_TYPE_NUM:
301       while ((*dp & 0x80) != 0)
302         dp++;
303       return dp + 1;
304     case REPOKEY_TYPE_U32:
305       return dp + 4;
306     case REPOKEY_TYPE_MD5:
307       return dp + SIZEOF_MD5;
308     case REPOKEY_TYPE_SHA1:
309       return dp + SIZEOF_SHA1;
310     case REPOKEY_TYPE_SHA256:
311       return dp + SIZEOF_SHA256;
312     case REPOKEY_TYPE_ID:
313       dp = data_read_id(dp, &id);
314       if (id >= maxid)
315         return 0;
316       return dp;
317     case REPOKEY_TYPE_DIR:
318       dp = data_read_id(dp, &id);
319       if (id >= maxdir)
320         return 0;
321       return dp;
322     case REPOKEY_TYPE_IDARRAY:
323       for (;;)
324         {
325           dp = data_read_ideof(dp, &id, &eof);
326           if (id >= maxid)
327             return 0;
328           if (eof)
329             return dp;
330         }
331     case REPOKEY_TYPE_STR:
332       while ((*dp) != 0)
333         dp++;
334       return dp + 1;
335     case REPOKEY_TYPE_BINARY:
336       {
337         unsigned int len;
338         dp = data_read_id(dp, (Id *)&len);
339         return dp + len;
340       }
341     case REPOKEY_TYPE_DIRSTRARRAY:
342       for (;;)
343         {
344           dp = data_read_ideof(dp, &id, &eof);
345           if (id >= maxdir)
346             return 0;
347           while ((*dp) != 0)
348             dp++;
349           dp++;
350           if (eof)
351             return dp;
352         }
353     case REPOKEY_TYPE_DIRNUMNUMARRAY:
354       for (;;)
355         {
356           dp = data_read_id(dp, &id);
357           if (id >= maxdir)
358             return 0;
359           while ((*dp & 0x80) != 0)
360             dp++;
361           dp++;
362           while ((*dp & 0x80) != 0)
363             dp++;
364           if (!(*dp & 0x40))
365             return dp + 1;
366           dp++;
367         }
368     default:
369       return 0;
370     }
371 }
372
373 #endif  /* LIBSOLV_REPOPACK */