]> git.draconx.ca Git - upkg.git/blob - src/pack.c
libupkg: Make decodeindex test accept an empty string.
[upkg.git] / src / pack.c
1 /*
2  *  Portable binary serialisation of integral types.
3  *  Copyright © 2009 Nick Bowler
4  *
5  *  Copying and distribution of this file, with or without modification,
6  *  are permitted in any medium without royalty provided the copyright
7  *  notice and this notice are preserved.  This file is offered as-is,
8  *  without any warranty.
9  */
10
11 #include "pack.h"
12
13 /* Unsigned integer packing. */
14 #define DEFPACK_BE(bits, type) void pack_ ## bits ## _be ( \
15         unsigned char *out, type v \
16 ) { \
17         unsigned i; \
18         for (i = 1; i <= bits/8; i++) { \
19                 out[bits/8 - i] = v % 256; \
20                 v /= 256; \
21         } \
22 }
23
24 #define DEFPACK_LE(bits, type) void pack_ ## bits ## _le ( \
25         unsigned char *out, type v \
26 ) { \
27         unsigned i; \
28         for (i = 0; i < bits/8; i++) { \
29                 out[i] = v % 256; \
30                 v /= 256; \
31         } \
32 }
33
34 DEFPACK_BE(16, unsigned short)
35 DEFPACK_BE(32, unsigned long)
36 #if PACK_HAVE_64BIT
37 DEFPACK_BE(64, unsigned long long)
38 #endif
39
40 DEFPACK_LE(16, unsigned short)
41 DEFPACK_LE(32, unsigned long)
42 #if PACK_HAVE_64BIT
43 DEFPACK_LE(64, unsigned long long)
44 #endif
45
46 #define DEFUNPACK_BE(bits, type) type unpack_ ## bits ## _be ( \
47         const unsigned char *in \
48 ) { \
49         type v = 0; \
50         unsigned i; \
51         for (i = 0; i < bits/8; i++) { \
52                 v *= 256; \
53                 v += in[i]; \
54         } \
55         return v; \
56 }
57
58 #define DEFUNPACK_LE(bits, type) type unpack_ ## bits ## _le ( \
59         const unsigned char *in \
60 ) { \
61         type v = 0; \
62         unsigned i; \
63         for (i = 1; i <= bits/8; i++) { \
64                 v *= 256; \
65                 v += in[bits/8 - i]; \
66         } \
67         return v; \
68 }
69
70 DEFUNPACK_BE(16, unsigned short)
71 DEFUNPACK_BE(32, unsigned long)
72 #if PACK_HAVE_64BIT
73 DEFUNPACK_BE(64, unsigned long long)
74 #endif
75
76 DEFUNPACK_LE(16, unsigned short)
77 DEFUNPACK_LE(32, unsigned long)
78 #if PACK_HAVE_64BIT
79 DEFUNPACK_LE(64, unsigned long long)
80 #endif
81
82 /*
83  * Two's complement signed integer packing.  This is unlikely to work on
84  * systems that don't themselves use two's complement.
85  */
86
87 #define DEFUNPACK_SBE(bits, max, type) type unpack_s ## bits ## _be ( \
88         const unsigned char *in \
89 ) { \
90         type v = 0; \
91         unsigned i; \
92         int sign = (in[0] & 0x80) ? 1 : 0; \
93         for (i = 0; i < bits/8; i++) { \
94                 v *= 256; \
95                 v += in[i] & (i == 0 ? 0x7f : 0xff); \
96         } \
97         return sign*(-max-1) + v; \
98 }
99
100 #define DEFUNPACK_SLE(bits, max, type) type unpack_s ## bits ## _le ( \
101         const unsigned char *in \
102 ) { \
103         type v = 0; \
104         unsigned i; \
105         int sign = (in[bits/8 - 1] & 0x80) ? 1 : 0; \
106         for (i = 1; i <= bits/8; i++) { \
107                 v *= 256; \
108                 v += in[bits/8 - i] & (i == 1 ? 0x7f : 0xff); \
109         } \
110         return sign*(-max-1) + v; \
111 }
112
113 DEFUNPACK_SBE(16, 32767, short)
114 DEFUNPACK_SBE(32, 2147483647l, long)
115 #if PACK_HAVE_64BIT
116 DEFUNPACK_SBE(64, 9223372036854775807ll, long long)
117 #endif
118
119 DEFUNPACK_SLE(16, 32767, short)
120 DEFUNPACK_SLE(32, 2147483647l, long)
121 #if PACK_HAVE_64BIT
122 DEFUNPACK_SLE(64, 9223372036854775807ll, long long)
123 #endif