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 <string.h>
30#include <inttypes.h>
31
32#define likely(x) __builtin_expect(!!(x), 1)
33#define unlikely(x) __builtin_expect(!!(x), 0)
34#define force_inline inline __attribute__((always_inline))
35#define no_inline __attribute__((noinline))
36#define __maybe_unused __attribute__((unused))
37
38#define xglue(x, y) x ## y
39#define glue(x, y) xglue(x, y)
40#define stringify(s) tostring(s)
41#define tostring(s) #s
42
43#ifndef offsetof
44#define offsetof(type, field) ((size_t) &((type *)0)->field)
45#endif
46#ifndef countof
47#define countof(x) (sizeof(x) / sizeof((x)[0]))
48#endif
49#ifndef container_of
50/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
51#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
52#endif
53
54#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
55#define minimum_length(n) static n
56#else
57#define minimum_length(n) n
58#endif
59
60typedef int BOOL;
61
62#ifndef FALSE
63enum {
64 FALSE = 0,
65 TRUE = 1,
66};
67#endif
68
69void pstrcpy(char *buf, int buf_size, const char *str);
70char *pstrcat(char *buf, int buf_size, const char *s);
71int strstart(const char *str, const char *val, const char **ptr);
72int has_suffix(const char *str, const char *suffix);
73
74/* Prevent UB when n == 0 and (src == NULL or dest == NULL) */
75static inline void memcpy_no_ub(void *dest, const void *src, size_t n) {
76 if (n)
77 memcpy(dest, src, n);
78}
79
80static inline int max_int(int a, int b)
81{
82 if (a > b)
83 return a;
84 else
85 return b;
86}
87
88static inline int min_int(int a, int b)
89{
90 if (a < b)
91 return a;
92 else
93 return b;
94}
95
96static inline uint32_t max_uint32(uint32_t a, uint32_t b)
97{
98 if (a > b)
99 return a;
100 else
101 return b;
102}
103
104static inline uint32_t min_uint32(uint32_t a, uint32_t b)
105{
106 if (a < b)
107 return a;
108 else
109 return b;
110}
111
112static inline int64_t max_int64(int64_t a, int64_t b)
113{
114 if (a > b)
115 return a;
116 else
117 return b;
118}
119
120static inline int64_t min_int64(int64_t a, int64_t b)
121{
122 if (a < b)
123 return a;
124 else
125 return b;
126}
127
128/* WARNING: undefined if a = 0 */
129static inline int clz32(unsigned int a)
130{
131 return __builtin_clz(a);
132}
133
134/* WARNING: undefined if a = 0 */
135static inline int clz64(uint64_t a)
136{
137 return __builtin_clzll(a);
138}
139
140/* WARNING: undefined if a = 0 */
141static inline int ctz32(unsigned int a)
142{
143 return __builtin_ctz(a);
144}
145
146/* WARNING: undefined if a = 0 */
147static inline int ctz64(uint64_t a)
148{
149 return __builtin_ctzll(a);
150}
151
152struct __attribute__((packed)) packed_u64 {
153 uint64_t v;
154};
155
156struct __attribute__((packed)) packed_u32 {
157 uint32_t v;
158};
159
160struct __attribute__((packed)) packed_u16 {
161 uint16_t v;
162};
163
164static inline uint64_t get_u64(const uint8_t *tab)
165{
166 return ((const struct packed_u64 *)tab)->v;
167}
168
169static inline int64_t get_i64(const uint8_t *tab)
170{
171 return (int64_t)((const struct packed_u64 *)tab)->v;
172}
173
174static inline void put_u64(uint8_t *tab, uint64_t val)
175{
176 ((struct packed_u64 *)tab)->v = val;
177}
178
179static inline uint32_t get_u32(const uint8_t *tab)
180{
181 return ((const struct packed_u32 *)tab)->v;
182}
183
184static inline int32_t get_i32(const uint8_t *tab)
185{
186 return (int32_t)((const struct packed_u32 *)tab)->v;
187}
188
189static inline void put_u32(uint8_t *tab, uint32_t val)
190{
191 ((struct packed_u32 *)tab)->v = val;
192}
193
194static inline uint32_t get_u16(const uint8_t *tab)
195{
196 return ((const struct packed_u16 *)tab)->v;
197}
198
199static inline int32_t get_i16(const uint8_t *tab)
200{
201 return (int16_t)((const struct packed_u16 *)tab)->v;
202}
203
204static inline void put_u16(uint8_t *tab, uint16_t val)
205{
206 ((struct packed_u16 *)tab)->v = val;
207}
208
209static inline uint32_t get_u8(const uint8_t *tab)
210{
211 return *tab;
212}
213
214static inline int32_t get_i8(const uint8_t *tab)
215{
216 return (int8_t)*tab;
217}
218
219static inline void put_u8(uint8_t *tab, uint8_t val)
220{
221 *tab = val;
222}
223
224#ifndef bswap16
225static inline uint16_t bswap16(uint16_t x)
226{
227 return (x >> 8) | (x << 8);
228}
229#endif
230
231#ifndef bswap32
232static inline uint32_t bswap32(uint32_t v)
233{
234 return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
235 ((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
236}
237#endif
238
239#ifndef bswap64
240static inline uint64_t bswap64(uint64_t v)
241{
242 return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
243 ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
244 ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
245 ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
246 ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
247 ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
248 ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
249 ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
250}
251#endif
252
253/* XXX: should take an extra argument to pass slack information to the caller */
254typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
255
256typedef struct DynBuf {
257 uint8_t *buf;
258 size_t size;
259 size_t allocated_size;
260 BOOL error; /* true if a memory allocation error occurred */
261 DynBufReallocFunc *realloc_func;
262 void *opaque; /* for realloc_func */
263} DynBuf;
264
265void dbuf_init(DynBuf *s);
266void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
267int dbuf_realloc(DynBuf *s, size_t new_size);
268int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
269int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
270int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
271int dbuf_putc(DynBuf *s, uint8_t c);
272int dbuf_putstr(DynBuf *s, const char *str);
273static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
274{
275 return dbuf_put(s, (uint8_t *)&val, 2);
276}
277static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
278{
279 return dbuf_put(s, (uint8_t *)&val, 4);
280}
281static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
282{
283 return dbuf_put(s, (uint8_t *)&val, 8);
284}
285int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
286 const char *fmt, ...);
287void dbuf_free(DynBuf *s);
288static inline BOOL dbuf_error(DynBuf *s) {
289 return s->error;
290}
291static inline void dbuf_set_error(DynBuf *s)
292{
293 s->error = TRUE;
294}
295
296#define UTF8_CHAR_LEN_MAX 6
297
298int unicode_to_utf8(uint8_t *buf, unsigned int c);
299int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
300
301static inline BOOL is_surrogate(uint32_t c)
302{
303 return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
304}
305
306static inline BOOL is_hi_surrogate(uint32_t c)
307{
308 return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
309}
310
311static inline BOOL is_lo_surrogate(uint32_t c)
312{
313 return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
314}
315
316static inline uint32_t get_hi_surrogate(uint32_t c)
317{
318 return (c >> 10) - (0x10000 >> 10) + 0xD800;
319}
320
321static inline uint32_t get_lo_surrogate(uint32_t c)
322{
323 return (c & 0x3FF) | 0xDC00;
324}
325
326static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
327{
328 return 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00);
329}
330
331static inline int from_hex(int c)
332{
333 if (c >= '0' && c <= '9')
334 return c - '0';
335 else if (c >= 'A' && c <= 'F')
336 return c - 'A' + 10;
337 else if (c >= 'a' && c <= 'f')
338 return c - 'a' + 10;
339 else
340 return -1;
341}
342
343void rqsort(void *base, size_t nmemb, size_t size,
344 int (*cmp)(const void *, const void *, void *),
345 void *arg);
346
347static inline uint64_t float64_as_uint64(double d)
348{
349 union {
350 double d;
351 uint64_t u64;
352 } u;
353 u.d = d;
354 return u.u64;
355}
356
357static inline double uint64_as_float64(uint64_t u64)
358{
359 union {
360 double d;
361 uint64_t u64;
362 } u;
363 u.u64 = u64;
364 return u.d;
365}
366
367#endif /* CUTILS_H */
368