1 /*
2 * C utilities
3 *
4 * Copyright (c) 2017 Fabrice Bellard
5 * Copyright (c) 2018 Charlie Gordon
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25 #ifndef CUTILS_H
26 #define CUTILS_H
27
28 #include <stdlib.h>
29 #include <inttypes.h>
30
31 /* set if CPU is big endian */
32 #undef WORDS_BIGENDIAN
33
34 #define likely(x) __builtin_expect(!!(x), 1)
35 #define unlikely(x) __builtin_expect(!!(x), 0)
36 #define force_inline inline __attribute__((always_inline))
37 #define no_inline __attribute__((noinline))
38 #define __maybe_unused __attribute__((unused))
39
40 #define xglue(x, y) x ## y
41 #define glue(x, y) xglue(x, y)
42 #define stringify(s) tostring(s)
43 #define tostring(s) #s
44
45 #ifndef offsetof
46 #define offsetof(type, field) ((size_t) &((type *)0)->field)
47 #endif
48 #ifndef countof
49 #define countof(x) (sizeof(x) / sizeof((x)[0]))
50 #endif
51
52 typedef int BOOL;
53
54 #ifndef FALSE
55 enum {
56 FALSE = 0,
57 TRUE = 1,
58 };
59 #endif
60
61 void pstrcpy(char *buf, int buf_size, const char *str);
62 char *pstrcat(char *buf, int buf_size, const char *s);
63 int strstart(const char *str, const char *val, const char **ptr);
64 int has_suffix(const char *str, const char *suffix);
65
max_int(int a,int b)66 static inline int max_int(int a, int b)
67 {
68 if (a > b)
69 return a;
70 else
71 return b;
72 }
73
min_int(int a,int b)74 static inline int min_int(int a, int b)
75 {
76 if (a < b)
77 return a;
78 else
79 return b;
80 }
81
max_uint32(uint32_t a,uint32_t b)82 static inline uint32_t max_uint32(uint32_t a, uint32_t b)
83 {
84 if (a > b)
85 return a;
86 else
87 return b;
88 }
89
min_uint32(uint32_t a,uint32_t b)90 static inline uint32_t min_uint32(uint32_t a, uint32_t b)
91 {
92 if (a < b)
93 return a;
94 else
95 return b;
96 }
97
max_int64(int64_t a,int64_t b)98 static inline int64_t max_int64(int64_t a, int64_t b)
99 {
100 if (a > b)
101 return a;
102 else
103 return b;
104 }
105
min_int64(int64_t a,int64_t b)106 static inline int64_t min_int64(int64_t a, int64_t b)
107 {
108 if (a < b)
109 return a;
110 else
111 return b;
112 }
113
114 /* WARNING: undefined if a = 0 */
clz32(unsigned int a)115 static inline int clz32(unsigned int a)
116 {
117 return __builtin_clz(a);
118 }
119
120 /* WARNING: undefined if a = 0 */
clz64(uint64_t a)121 static inline int clz64(uint64_t a)
122 {
123 return __builtin_clzll(a);
124 }
125
126 /* WARNING: undefined if a = 0 */
ctz32(unsigned int a)127 static inline int ctz32(unsigned int a)
128 {
129 return __builtin_ctz(a);
130 }
131
132 /* WARNING: undefined if a = 0 */
ctz64(uint64_t a)133 static inline int ctz64(uint64_t a)
134 {
135 return __builtin_ctzll(a);
136 }
137
138 struct __attribute__((packed)) packed_u64 {
139 uint64_t v;
140 };
141
142 struct __attribute__((packed)) packed_u32 {
143 uint32_t v;
144 };
145
146 struct __attribute__((packed)) packed_u16 {
147 uint16_t v;
148 };
149
get_u64(const uint8_t * tab)150 static inline uint64_t get_u64(const uint8_t *tab)
151 {
152 return ((const struct packed_u64 *)tab)->v;
153 }
154
get_i64(const uint8_t * tab)155 static inline int64_t get_i64(const uint8_t *tab)
156 {
157 return (int64_t)((const struct packed_u64 *)tab)->v;
158 }
159
put_u64(uint8_t * tab,uint64_t val)160 static inline void put_u64(uint8_t *tab, uint64_t val)
161 {
162 ((struct packed_u64 *)tab)->v = val;
163 }
164
get_u32(const uint8_t * tab)165 static inline uint32_t get_u32(const uint8_t *tab)
166 {
167 return ((const struct packed_u32 *)tab)->v;
168 }
169
get_i32(const uint8_t * tab)170 static inline int32_t get_i32(const uint8_t *tab)
171 {
172 return (int32_t)((const struct packed_u32 *)tab)->v;
173 }
174
put_u32(uint8_t * tab,uint32_t val)175 static inline void put_u32(uint8_t *tab, uint32_t val)
176 {
177 ((struct packed_u32 *)tab)->v = val;
178 }
179
get_u16(const uint8_t * tab)180 static inline uint32_t get_u16(const uint8_t *tab)
181 {
182 return ((const struct packed_u16 *)tab)->v;
183 }
184
get_i16(const uint8_t * tab)185 static inline int32_t get_i16(const uint8_t *tab)
186 {
187 return (int16_t)((const struct packed_u16 *)tab)->v;
188 }
189
put_u16(uint8_t * tab,uint16_t val)190 static inline void put_u16(uint8_t *tab, uint16_t val)
191 {
192 ((struct packed_u16 *)tab)->v = val;
193 }
194
get_u8(const uint8_t * tab)195 static inline uint32_t get_u8(const uint8_t *tab)
196 {
197 return *tab;
198 }
199
get_i8(const uint8_t * tab)200 static inline int32_t get_i8(const uint8_t *tab)
201 {
202 return (int8_t)*tab;
203 }
204
put_u8(uint8_t * tab,uint8_t val)205 static inline void put_u8(uint8_t *tab, uint8_t val)
206 {
207 *tab = val;
208 }
209
bswap16(uint16_t x)210 static inline uint16_t bswap16(uint16_t x)
211 {
212 return (x >> 8) | (x << 8);
213 }
214
bswap32(uint32_t v)215 static inline uint32_t bswap32(uint32_t v)
216 {
217 return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
218 ((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
219 }
220
bswap64(uint64_t v)221 static inline uint64_t bswap64(uint64_t v)
222 {
223 return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
224 ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
225 ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
226 ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
227 ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
228 ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
229 ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
230 ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
231 }
232
233 /* XXX: should take an extra argument to pass slack information to the caller */
234 typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
235
236 typedef struct DynBuf {
237 uint8_t *buf;
238 size_t size;
239 size_t allocated_size;
240 BOOL error; /* true if a memory allocation error occurred */
241 DynBufReallocFunc *realloc_func;
242 void *opaque; /* for realloc_func */
243 } DynBuf;
244
245 void dbuf_init(DynBuf *s);
246 void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
247 int dbuf_realloc(DynBuf *s, size_t new_size);
248 int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
249 int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
250 int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
251 int dbuf_putc(DynBuf *s, uint8_t c);
252 int dbuf_putstr(DynBuf *s, const char *str);
dbuf_put_u16(DynBuf * s,uint16_t val)253 static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
254 {
255 return dbuf_put(s, (uint8_t *)&val, 2);
256 }
dbuf_put_u32(DynBuf * s,uint32_t val)257 static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
258 {
259 return dbuf_put(s, (uint8_t *)&val, 4);
260 }
dbuf_put_u64(DynBuf * s,uint64_t val)261 static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
262 {
263 return dbuf_put(s, (uint8_t *)&val, 8);
264 }
265 int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
266 const char *fmt, ...);
267 void dbuf_free(DynBuf *s);
dbuf_error(DynBuf * s)268 static inline BOOL dbuf_error(DynBuf *s) {
269 return s->error;
270 }
dbuf_set_error(DynBuf * s)271 static inline void dbuf_set_error(DynBuf *s)
272 {
273 s->error = TRUE;
274 }
275
276 #define UTF8_CHAR_LEN_MAX 6
277
278 int unicode_to_utf8(uint8_t *buf, unsigned int c);
279 int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
280
from_hex(int c)281 static inline int from_hex(int c)
282 {
283 if (c >= '0' && c <= '9')
284 return c - '0';
285 else if (c >= 'A' && c <= 'F')
286 return c - 'A' + 10;
287 else if (c >= 'a' && c <= 'f')
288 return c - 'a' + 10;
289 else
290 return -1;
291 }
292
293 void rqsort(void *base, size_t nmemb, size_t size,
294 int (*cmp)(const void *, const void *, void *),
295 void *arg);
296
297 #endif /* CUTILS_H */
298