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