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