diff options
author | Christian Grothoff <christian@grothoff.org> | 2005-01-21 16:42:45 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2005-01-21 16:42:45 +0000 |
commit | 7166eaa7ff40782f89aca81bf30e2e4ceac7fb76 (patch) | |
tree | 146f465aaa565a327fb3a3dd85c3b5eb7900d497 /src/plugins/pack.c | |
download | libextractor-7166eaa7ff40782f89aca81bf30e2e4ceac7fb76.tar.gz libextractor-7166eaa7ff40782f89aca81bf30e2e4ceac7fb76.zip |
Importing libextractor.
Diffstat (limited to 'src/plugins/pack.c')
-rw-r--r-- | src/plugins/pack.c | 469 |
1 files changed, 469 insertions, 0 deletions
diff --git a/src/plugins/pack.c b/src/plugins/pack.c new file mode 100644 index 0000000..e7bae79 --- /dev/null +++ b/src/plugins/pack.c | |||
@@ -0,0 +1,469 @@ | |||
1 | /* | ||
2 | Catlib Copyright Notice | ||
3 | |||
4 | The author of this software is Christopher Adam Telfer | ||
5 | Copyright (c) 1998, 1999, 2000, 2001, 2002 | ||
6 | by Christopher Adam Telfer. All Rights Reserved. | ||
7 | |||
8 | Permission to use, copy, modify, and distribute this software for any | ||
9 | purpose without fee is hereby granted, provided that the above copyright | ||
10 | notice, this paragraph, and the following two paragraphs appear in all | ||
11 | copies, modifications, and distributions. | ||
12 | |||
13 | IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | ||
14 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | ||
15 | ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | ||
16 | THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
17 | |||
18 | THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT | ||
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
20 | PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF | ||
21 | ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO | ||
22 | OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR | ||
23 | MODIFICATIONS. | ||
24 | |||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "pack.h" | ||
29 | |||
30 | typedef unsigned char byte; | ||
31 | typedef unsigned short half; | ||
32 | typedef unsigned long word; | ||
33 | typedef signed char sbyte; | ||
34 | typedef signed short shalf; | ||
35 | typedef signed long sword; | ||
36 | |||
37 | |||
38 | /* | ||
39 | "bhwAcslPBHWCSL" | ||
40 | |||
41 | Small letters: do not convert (not implemented for arrays and P) | ||
42 | Captial letters: convert from network byte order to host byte order | ||
43 | |||
44 | b - byte | ||
45 | h - half-word | ||
46 | w - word | ||
47 | a - array (32-byte unsigned long + that many bytes) | ||
48 | c - signed 8 bit value | ||
49 | s - signed 16 bit value | ||
50 | l - signed 32 bit value | ||
51 | p - (unpack only) value is a pointer to a pointer. Generate the buffer | ||
52 | to hold the data. | ||
53 | |||
54 | prefixing with a number K means that the argument will be an array of K | ||
55 | of the arguments specified by the letter | ||
56 | */ | ||
57 | |||
58 | int cat_pack(void * buf, | ||
59 | const char *fmt, | ||
60 | ...) { | ||
61 | va_list ap; | ||
62 | word blen, val; | ||
63 | int npacked; | ||
64 | unsigned int nreps, i; | ||
65 | byte *bp, *bytep; | ||
66 | half *halfp; | ||
67 | word *wordp; | ||
68 | void * arr; | ||
69 | struct cat_bvec *cbvp; | ||
70 | char *cp; | ||
71 | |||
72 | va_start(ap, fmt); | ||
73 | |||
74 | npacked = 0; | ||
75 | bp = (byte *)buf; | ||
76 | |||
77 | while( *fmt ) { | ||
78 | nreps = 0; | ||
79 | |||
80 | if ( isdigit(*fmt) ) { | ||
81 | /* We use cp instead of fmt to keep the 'const' qualifier of fmt */ | ||
82 | nreps = strtoul(fmt, &cp, 0); | ||
83 | fmt = cp; | ||
84 | } | ||
85 | |||
86 | switch(*fmt) { | ||
87 | case 'B': | ||
88 | case 'b': | ||
89 | case 'C': | ||
90 | case 'c': | ||
91 | if ( ! nreps ) { | ||
92 | *bp++ = va_arg(ap, int); | ||
93 | npacked += 1; | ||
94 | } else { | ||
95 | bytep = va_arg(ap, byte*); | ||
96 | for ( i = 0 ; i < nreps ; ++i ) { | ||
97 | *bp++ = bytep[i]; | ||
98 | npacked += 1; | ||
99 | } | ||
100 | } | ||
101 | break; | ||
102 | |||
103 | case 'h': | ||
104 | case 's': | ||
105 | if ( ! nreps ) { | ||
106 | val = va_arg(ap, int); | ||
107 | *bp++ = val & 0xFF; | ||
108 | *bp++ = val >> 8; | ||
109 | npacked += 2; | ||
110 | } else { | ||
111 | halfp = va_arg(ap, half*); | ||
112 | for ( i = 0 ; i < nreps ; ++i ) { | ||
113 | val = halfp[i]; | ||
114 | *bp++ = val & 0xFF; | ||
115 | *bp++ = val >> 8; | ||
116 | npacked += 2; | ||
117 | } | ||
118 | } | ||
119 | break; | ||
120 | |||
121 | case 'H': | ||
122 | case 'S': | ||
123 | if ( ! nreps ) { | ||
124 | val = va_arg(ap, int); | ||
125 | *bp++ = val >> 8; | ||
126 | *bp++ = val & 0xFF; | ||
127 | npacked += 2; | ||
128 | } else { | ||
129 | halfp = va_arg(ap, half*); | ||
130 | for ( i = 0 ; i < nreps ; ++i ) { | ||
131 | val = halfp[i]; | ||
132 | *bp++ = val >> 8; | ||
133 | *bp++ = val & 0xFF; | ||
134 | npacked += 2; | ||
135 | } | ||
136 | } | ||
137 | break; | ||
138 | |||
139 | case 'l': | ||
140 | case 'w': | ||
141 | if ( ! nreps ) { | ||
142 | val = va_arg(ap, word); | ||
143 | *bp++ = val & 0xFF; | ||
144 | *bp++ = val >> 8; | ||
145 | *bp++ = val >> 16; | ||
146 | *bp++ = val >> 24; | ||
147 | npacked += 4; | ||
148 | } else { | ||
149 | wordp = va_arg(ap, word*); | ||
150 | for ( i = 0 ; i < nreps ; ++i ) { | ||
151 | val = wordp[i]; | ||
152 | *bp++ = val & 0xFF; | ||
153 | *bp++ = val >> 8; | ||
154 | *bp++ = val >> 16; | ||
155 | *bp++ = val >> 24; | ||
156 | npacked += 4; | ||
157 | } | ||
158 | } | ||
159 | break; | ||
160 | |||
161 | case 'L': | ||
162 | case 'W': | ||
163 | if ( ! nreps ) { | ||
164 | val = va_arg(ap, word); | ||
165 | *bp++ = val >> 24; | ||
166 | *bp++ = val >> 16; | ||
167 | *bp++ = val >> 8; | ||
168 | *bp++ = val & 0xFF; | ||
169 | npacked += 4; | ||
170 | } else { | ||
171 | wordp = va_arg(ap, word*); | ||
172 | for ( i = 0 ; i < nreps ; ++i ) { | ||
173 | val = wordp[i]; | ||
174 | *bp++ = val >> 24; | ||
175 | *bp++ = val >> 16; | ||
176 | *bp++ = val >> 8; | ||
177 | *bp++ = val & 0xFF; | ||
178 | npacked += 4; | ||
179 | } | ||
180 | } | ||
181 | break; | ||
182 | |||
183 | case 'A': | ||
184 | if ( ! nreps ) { | ||
185 | blen = va_arg(ap, word); | ||
186 | arr = va_arg(ap, void *); | ||
187 | *bp++ = blen >> 24; | ||
188 | *bp++ = blen >> 16; | ||
189 | *bp++ = blen >> 8; | ||
190 | *bp++ = blen & 0xFF; | ||
191 | memmove(bp, arr, blen); | ||
192 | bp += blen; | ||
193 | npacked += blen + 4; /* +4 for the 32 bits of length field */ | ||
194 | } else { | ||
195 | cbvp = va_arg(ap, struct cat_bvec*); | ||
196 | for ( i = 0 ; i < nreps ; ++i ) { | ||
197 | blen = cbvp[i].len; | ||
198 | arr = cbvp[i].data; | ||
199 | *bp++ = blen >> 24; | ||
200 | *bp++ = blen >> 16; | ||
201 | *bp++ = blen >> 8; | ||
202 | *bp++ = blen & 0xFF; | ||
203 | memmove(bp, arr, blen); | ||
204 | bp += blen; | ||
205 | npacked += blen + 4; /* see above */ | ||
206 | } | ||
207 | } | ||
208 | break; | ||
209 | |||
210 | default: | ||
211 | va_end(ap); | ||
212 | return -1; | ||
213 | } | ||
214 | ++fmt; | ||
215 | } | ||
216 | |||
217 | va_end(ap); | ||
218 | return npacked; | ||
219 | } | ||
220 | |||
221 | |||
222 | |||
223 | int cat_unpack(const void * buf, | ||
224 | const char *fmt, | ||
225 | ...) { | ||
226 | va_list ap; | ||
227 | word maxlen, len, *wordp; | ||
228 | void * arr; | ||
229 | byte *bp, *bytep, *newbuf; | ||
230 | half *halfp; | ||
231 | sbyte *sbytep; | ||
232 | shalf *shalfp; | ||
233 | sword *swordp; | ||
234 | int npacked; | ||
235 | unsigned int nreps, i, isnonprefixed = 1; /* used for 'a' types only */ | ||
236 | struct cat_bvec *cbvp; | ||
237 | char *cp; | ||
238 | |||
239 | bp = (byte *)buf; | ||
240 | npacked = 0; | ||
241 | |||
242 | va_start(ap, fmt); | ||
243 | |||
244 | while ( *fmt ) { | ||
245 | nreps = 1; | ||
246 | |||
247 | if ( isdigit(*fmt) ) { | ||
248 | /* We use cp instead of format to keep the 'const' qualifier of fmt */ | ||
249 | nreps = strtoul(fmt, &cp, 0); | ||
250 | fmt = cp; | ||
251 | if ( *fmt == 'a' ) | ||
252 | isnonprefixed = 0; | ||
253 | } | ||
254 | |||
255 | switch (*fmt) { | ||
256 | case 'B': | ||
257 | case 'b': | ||
258 | bytep = va_arg(ap, byte*); | ||
259 | for ( i = 0 ; i < nreps ; ++i ) { | ||
260 | *bytep = *bp++; | ||
261 | ++bytep; | ||
262 | npacked += 1; | ||
263 | } | ||
264 | break; | ||
265 | |||
266 | |||
267 | |||
268 | case 'h': | ||
269 | halfp = va_arg(ap, half*); | ||
270 | for ( i = 0 ; i < nreps ; ++i ) { | ||
271 | *halfp = *bp++; | ||
272 | *halfp |= *bp++ << 8; | ||
273 | ++halfp; | ||
274 | npacked += 2; | ||
275 | } | ||
276 | break; | ||
277 | |||
278 | case 'H': | ||
279 | halfp = va_arg(ap, half*); | ||
280 | for ( i = 0 ; i < nreps ; ++i ) { | ||
281 | *halfp = *bp++ << 8; | ||
282 | *halfp |= *bp++; | ||
283 | ++halfp; | ||
284 | npacked += 2; | ||
285 | } | ||
286 | break; | ||
287 | |||
288 | |||
289 | case 'w': | ||
290 | wordp = va_arg(ap, word*); | ||
291 | for ( i = 0 ; i < nreps ; ++i ) { | ||
292 | *wordp = *bp++; | ||
293 | *wordp |= *bp++ << 8; | ||
294 | *wordp |= *bp++ << 16; | ||
295 | *wordp |= *bp++ << 24; | ||
296 | ++wordp; | ||
297 | npacked += 4; | ||
298 | } | ||
299 | break; | ||
300 | |||
301 | case 'W': | ||
302 | wordp = va_arg(ap, word*); | ||
303 | for ( i = 0 ; i < nreps ; ++i ) { | ||
304 | *wordp = *bp++ << 24; | ||
305 | *wordp |= *bp++ << 16; | ||
306 | *wordp |= *bp++ << 8; | ||
307 | *wordp |= *bp++; | ||
308 | ++wordp; | ||
309 | npacked += 4; | ||
310 | } | ||
311 | break; | ||
312 | |||
313 | case 'A': | ||
314 | if ( isnonprefixed ) { | ||
315 | maxlen = va_arg(ap, word); | ||
316 | arr = va_arg(ap, void *); | ||
317 | |||
318 | len = *bp++ << 24; | ||
319 | len |= *bp++ << 16; | ||
320 | len |= *bp++ << 8; | ||
321 | len |= *bp++; | ||
322 | |||
323 | if ( len > maxlen ) | ||
324 | return -1; | ||
325 | |||
326 | memmove(arr, bp, len); | ||
327 | bp += len; | ||
328 | |||
329 | npacked += len; | ||
330 | } else { | ||
331 | cbvp = va_arg(ap, struct cat_bvec *); | ||
332 | for ( i = 0 ; i < nreps ; ++i ) { | ||
333 | maxlen = cbvp->len; | ||
334 | arr = cbvp->data; | ||
335 | |||
336 | len = *bp++ << 24; | ||
337 | len |= *bp++ << 16; | ||
338 | len |= *bp++ << 8; | ||
339 | len |= *bp++; | ||
340 | |||
341 | if ( len > maxlen ) | ||
342 | return -1; | ||
343 | |||
344 | memmove(arr, bp, len); | ||
345 | cbvp->len = len; | ||
346 | bp += len; | ||
347 | |||
348 | ++cbvp; | ||
349 | npacked += len; | ||
350 | } | ||
351 | isnonprefixed = 1; | ||
352 | } | ||
353 | break; | ||
354 | |||
355 | case 'C': | ||
356 | case 'c': | ||
357 | sbytep = va_arg(ap, sbyte*); | ||
358 | for ( i = 0 ; i < nreps ; ++i ) { | ||
359 | *sbytep = *bp++; | ||
360 | |||
361 | if ( (sizeof(sbyte) > 1) && (*sbytep & 0x80) ) | ||
362 | *sbytep |= (~0) << ((sizeof(sbyte)-1) * 8); | ||
363 | |||
364 | ++sbytep; | ||
365 | npacked += 1; | ||
366 | } | ||
367 | break; | ||
368 | |||
369 | |||
370 | case 's': | ||
371 | shalfp = va_arg(ap, shalf*); | ||
372 | for ( i = 0 ; i < nreps ; ++i ) { | ||
373 | *shalfp = *bp++; | ||
374 | *shalfp |= *bp++ << 8; | ||
375 | |||
376 | if ( (sizeof(shalf) > 2) && (*shalfp & 0x8000) ) | ||
377 | *shalfp |= (~0) << ((sizeof(shalf)-2) * 8); | ||
378 | |||
379 | ++shalfp; | ||
380 | npacked += 2; | ||
381 | } | ||
382 | break; | ||
383 | |||
384 | case 'S': | ||
385 | shalfp = va_arg(ap, shalf*); | ||
386 | for ( i = 0 ; i < nreps ; ++i ) { | ||
387 | *shalfp = *bp++ << 8; | ||
388 | *shalfp |= *bp++; | ||
389 | |||
390 | if ( (sizeof(shalf) > 2) && (*shalfp & 0x8000) ) | ||
391 | *shalfp |= (~0) << ((sizeof(shalf)-2) * 8); | ||
392 | |||
393 | ++shalfp; | ||
394 | npacked += 2; | ||
395 | } | ||
396 | break; | ||
397 | |||
398 | case 'l': | ||
399 | swordp = va_arg(ap, sword*); | ||
400 | for ( i = 0 ; i < nreps ; ++i ) { | ||
401 | *swordp = *bp++; | ||
402 | *swordp |= *bp++ << 8; | ||
403 | *swordp |= *bp++ << 16; | ||
404 | *swordp |= *bp++ << 24; | ||
405 | |||
406 | if ( (sizeof(swordp) > 4) && (*swordp & 0x80000000) ) | ||
407 | *swordp |= (~0) << ((sizeof(sword)-4) * 8); | ||
408 | |||
409 | ++swordp; | ||
410 | npacked += 4; | ||
411 | } | ||
412 | break; | ||
413 | |||
414 | case 'L': | ||
415 | swordp = va_arg(ap, sword*); | ||
416 | for ( i = 0 ; i < nreps ; ++i ) { | ||
417 | *swordp = *bp++ << 24; | ||
418 | *swordp |= *bp++ << 16; | ||
419 | *swordp |= *bp++ << 8; | ||
420 | *swordp |= *bp++; | ||
421 | |||
422 | if ( (sizeof(swordp) > 4) && (*swordp & 0x80000000) ) | ||
423 | *swordp |= (~0) << ((sizeof(sword)-4) * 8); | ||
424 | |||
425 | ++swordp; | ||
426 | npacked += 4; | ||
427 | } | ||
428 | break; | ||
429 | |||
430 | case 'P': | ||
431 | cbvp = va_arg(ap, struct cat_bvec *); | ||
432 | for ( i = 0 ; i < nreps ; ++i ) { | ||
433 | len = *bp++ << 24; | ||
434 | len |= *bp++ << 16; | ||
435 | len |= *bp++ << 8; | ||
436 | len |= *bp++; | ||
437 | |||
438 | newbuf = (byte *)malloc(len); | ||
439 | |||
440 | if ( ! newbuf ) { | ||
441 | int j; | ||
442 | for ( j = 0 ; j < i ; j++ ) | ||
443 | free(cbvp[i].data); | ||
444 | return -1; | ||
445 | } | ||
446 | |||
447 | memmove(newbuf, bp, len); | ||
448 | cbvp[i].data = newbuf; | ||
449 | cbvp[i].len = len; | ||
450 | |||
451 | bp += len; | ||
452 | npacked += len; | ||
453 | } | ||
454 | break; | ||
455 | |||
456 | default: | ||
457 | va_end(ap); | ||
458 | return -1; | ||
459 | } | ||
460 | |||
461 | ++fmt; | ||
462 | } | ||
463 | |||
464 | va_end(ap); | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | |||
469 | |||