quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

cutils.h (8619B)


      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 
     60 typedef int BOOL;
     61 
     62 #ifndef FALSE
     63 enum {
     64     FALSE = 0,
     65     TRUE = 1,
     66 };
     67 #endif
     68 
     69 void pstrcpy(char *buf, int buf_size, const char *str);
     70 char *pstrcat(char *buf, int buf_size, const char *s);
     71 int strstart(const char *str, const char *val, const char **ptr);
     72 int has_suffix(const char *str, const char *suffix);
     73 
     74 /* Prevent UB when n == 0 and (src == NULL or dest == NULL) */
     75 static inline void memcpy_no_ub(void *dest, const void *src, size_t n) {
     76     if (n)
     77         memcpy(dest, src, n);
     78 }
     79 
     80 static inline int max_int(int a, int b)
     81 {
     82     if (a > b)
     83         return a;
     84     else
     85         return b;
     86 }
     87 
     88 static inline int min_int(int a, int b)
     89 {
     90     if (a < b)
     91         return a;
     92     else
     93         return b;
     94 }
     95 
     96 static 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 
    104 static 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 
    112 static 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 
    120 static 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 */
    129 static inline int clz32(unsigned int a)
    130 {
    131     return __builtin_clz(a);
    132 }
    133 
    134 /* WARNING: undefined if a = 0 */
    135 static inline int clz64(uint64_t a)
    136 {
    137     return __builtin_clzll(a);
    138 }
    139 
    140 /* WARNING: undefined if a = 0 */
    141 static inline int ctz32(unsigned int a)
    142 {
    143     return __builtin_ctz(a);
    144 }
    145 
    146 /* WARNING: undefined if a = 0 */
    147 static inline int ctz64(uint64_t a)
    148 {
    149     return __builtin_ctzll(a);
    150 }
    151 
    152 struct __attribute__((packed)) packed_u64 {
    153     uint64_t v;
    154 };
    155 
    156 struct __attribute__((packed)) packed_u32 {
    157     uint32_t v;
    158 };
    159 
    160 struct __attribute__((packed)) packed_u16 {
    161     uint16_t v;
    162 };
    163 
    164 static inline uint64_t get_u64(const uint8_t *tab)
    165 {
    166     return ((const struct packed_u64 *)tab)->v;
    167 }
    168 
    169 static inline int64_t get_i64(const uint8_t *tab)
    170 {
    171     return (int64_t)((const struct packed_u64 *)tab)->v;
    172 }
    173 
    174 static inline void put_u64(uint8_t *tab, uint64_t val)
    175 {
    176     ((struct packed_u64 *)tab)->v = val;
    177 }
    178 
    179 static inline uint32_t get_u32(const uint8_t *tab)
    180 {
    181     return ((const struct packed_u32 *)tab)->v;
    182 }
    183 
    184 static inline int32_t get_i32(const uint8_t *tab)
    185 {
    186     return (int32_t)((const struct packed_u32 *)tab)->v;
    187 }
    188 
    189 static inline void put_u32(uint8_t *tab, uint32_t val)
    190 {
    191     ((struct packed_u32 *)tab)->v = val;
    192 }
    193 
    194 static inline uint32_t get_u16(const uint8_t *tab)
    195 {
    196     return ((const struct packed_u16 *)tab)->v;
    197 }
    198 
    199 static inline int32_t get_i16(const uint8_t *tab)
    200 {
    201     return (int16_t)((const struct packed_u16 *)tab)->v;
    202 }
    203 
    204 static inline void put_u16(uint8_t *tab, uint16_t val)
    205 {
    206     ((struct packed_u16 *)tab)->v = val;
    207 }
    208 
    209 static inline uint32_t get_u8(const uint8_t *tab)
    210 {
    211     return *tab;
    212 }
    213 
    214 static inline int32_t get_i8(const uint8_t *tab)
    215 {
    216     return (int8_t)*tab;
    217 }
    218 
    219 static inline void put_u8(uint8_t *tab, uint8_t val)
    220 {
    221     *tab = val;
    222 }
    223 
    224 #ifndef bswap16
    225 static inline uint16_t bswap16(uint16_t x)
    226 {
    227     return (x >> 8) | (x << 8);
    228 }
    229 #endif
    230 
    231 #ifndef bswap32
    232 static 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
    240 static 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 */
    254 typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
    255 
    256 typedef 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 
    265 void dbuf_init(DynBuf *s);
    266 void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
    267 int dbuf_realloc(DynBuf *s, size_t new_size);
    268 int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
    269 int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
    270 int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
    271 int dbuf_putc(DynBuf *s, uint8_t c);
    272 int dbuf_putstr(DynBuf *s, const char *str);
    273 static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
    274 {
    275     return dbuf_put(s, (uint8_t *)&val, 2);
    276 }
    277 static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
    278 {
    279     return dbuf_put(s, (uint8_t *)&val, 4);
    280 }
    281 static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
    282 {
    283     return dbuf_put(s, (uint8_t *)&val, 8);
    284 }
    285 int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
    286                                                       const char *fmt, ...);
    287 void dbuf_free(DynBuf *s);
    288 static inline BOOL dbuf_error(DynBuf *s) {
    289     return s->error;
    290 }
    291 static inline void dbuf_set_error(DynBuf *s)
    292 {
    293     s->error = TRUE;
    294 }
    295 
    296 #define UTF8_CHAR_LEN_MAX 6
    297 
    298 int unicode_to_utf8(uint8_t *buf, unsigned int c);
    299 int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
    300 
    301 static inline BOOL is_surrogate(uint32_t c)
    302 {
    303     return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
    304 }
    305 
    306 static inline BOOL is_hi_surrogate(uint32_t c)
    307 {
    308     return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
    309 }
    310 
    311 static inline BOOL is_lo_surrogate(uint32_t c)
    312 {
    313     return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
    314 }
    315 
    316 static inline uint32_t get_hi_surrogate(uint32_t c)
    317 {
    318     return (c >> 10) - (0x10000 >> 10) + 0xD800;
    319 }
    320 
    321 static inline uint32_t get_lo_surrogate(uint32_t c)
    322 {
    323     return (c & 0x3FF) | 0xDC00;
    324 }
    325 
    326 static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
    327 {
    328     return 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00);
    329 }
    330 
    331 static 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 
    343 void rqsort(void *base, size_t nmemb, size_t size,
    344             int (*cmp)(const void *, const void *, void *),
    345             void *arg);
    346 
    347 #endif  /* CUTILS_H */