]> git.draconx.ca Git - upkg.git/blob - src/pack.c
libupkg: Remove checks for an unsigned quantity being less than 0.
[upkg.git] / src / pack.c
1 /*
2  *  Portable binary serialisation of integral types.
3  *  Copyright (C) 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 <stdio.h>
12 #include <limits.h>
13
14 #include "pack.h"
15
16 /* Unsigned integer packing. */
17 #define DEFPACK_BE(bits, type) void pack_ ## bits ## _be ( \
18         unsigned char *out, type v \
19 ) { \
20         unsigned i; \
21         for (i = 1; i <= bits/8; i++) { \
22                 out[bits/8 - i] = v % 256; \
23                 v /= 256; \
24         } \
25 }
26
27 #define DEFPACK_LE(bits, type) void pack_ ## bits ## _le ( \
28         unsigned char *out, type v \
29 ) { \
30         unsigned i; \
31         for (i = 0; i < bits/8; i++) { \
32                 out[i] = v % 256; \
33                 v /= 256; \
34         } \
35 }
36
37 DEFPACK_BE(16, unsigned short)
38 DEFPACK_BE(32, unsigned long)
39 #ifdef ULLONG_MAX
40 DEFPACK_BE(64, unsigned long long)
41 #endif
42
43 DEFPACK_LE(16, unsigned short)
44 DEFPACK_LE(32, unsigned long)
45 #ifdef ULLONG_MAX
46 DEFPACK_LE(64, unsigned long long)
47 #endif
48
49 #define DEFUNPACK_BE(bits, type) type unpack_ ## bits ## _be ( \
50         const unsigned char *in \
51 ) { \
52         type v = 0; \
53         unsigned i; \
54         for (i = 0; i < bits/8; i++) { \
55                 v *= 256; \
56                 v += in[i]; \
57         } \
58         return v; \
59 }
60
61 #define DEFUNPACK_LE(bits, type) type unpack_ ## bits ## _le ( \
62         const unsigned char *in \
63 ) { \
64         type v = 0; \
65         unsigned i; \
66         for (i = 1; i <= bits/8; i++) { \
67                 v *= 256; \
68                 v += in[bits/8 - i]; \
69         } \
70         return v; \
71 }
72
73 DEFUNPACK_BE(16, unsigned short)
74 DEFUNPACK_BE(32, unsigned long)
75 #ifdef ULLONG_MAX
76 DEFUNPACK_BE(64, unsigned long long)
77 #endif
78
79 DEFUNPACK_LE(16, unsigned short)
80 DEFUNPACK_LE(32, unsigned long)
81 #ifdef ULLONG_MAX
82 DEFUNPACK_LE(64, unsigned long long)
83 #endif
84
85 /*
86  * Two's complement signed integer packing.  This is unlikely to work on
87  * systems that don't themselves use two's complement.
88  */
89
90 #define DEFUNPACK_SBE(bits, max, type) type unpack_s ## bits ## _be ( \
91         const unsigned char *in \
92 ) { \
93         type v = 0; \
94         unsigned i; \
95         int sign = (in[0] & 0x80) ? 1 : 0; \
96         for (i = 0; i < bits/8; i++) { \
97                 v *= 256; \
98                 v += in[i] & (i == 0 ? 0x7f : 0xff); \
99         } \
100         return sign*(-max-1) + v; \
101 }
102
103 #define DEFUNPACK_SLE(bits, max, type) type unpack_s ## bits ## _le ( \
104         const unsigned char *in \
105 ) { \
106         type v = 0; \
107         unsigned i; \
108         int sign = (in[bits/8 - 1] & 0x80) ? 1 : 0; \
109         for (i = 1; i <= bits/8; i++) { \
110                 v *= 256; \
111                 v += in[bits/8 - i] & (i == 1 ? 0x7f : 0xff); \
112         } \
113         return sign*(-max-1) + v; \
114 }
115
116 DEFUNPACK_SBE(16, 32767, short)
117 DEFUNPACK_SBE(32, 2147483647l, long)
118 #ifdef LLONG_MAX
119 DEFUNPACK_SBE(64, 9223372036854775807ll, long long)
120 #endif
121
122 DEFUNPACK_SLE(16, 32767, short)
123 DEFUNPACK_SLE(32, 2147483647l, long)
124 #ifdef LLONG_MAX
125 DEFUNPACK_SLE(64, 9223372036854775807ll, long long)
126 #endif