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