1 /* 2 * Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #ifndef UCODE_UTIL_H 18 #define UCODE_UTIL_H 19 20 #include <stdio.h> 21 #include <stddef.h> 22 #include <stdlib.h> 23 #include <stdbool.h> 24 #include <stdarg.h> /* va_start(), va_end(), va_list */ 25 #include <string.h> /* strdup() */ 26 #include <json-c/json.h> 27 28 29 #ifndef __hidden 30 #define __hidden __attribute__((visibility("hidden"))) 31 #endif 32 33 #ifndef localfunc 34 # if defined(__GNUC__) || defined(__clang__) 35 # define localfunc static __attribute__((noinline,unused)) 36 # else 37 # define localfunc static inline 38 # endif 39 #endif 40 41 42 /* alignment & array size */ 43 44 #ifndef ALIGN 45 #define ALIGN(x) (((x) + sizeof(size_t) - 1) & -sizeof(size_t)) 46 #endif 47 48 #ifndef ARRAY_SIZE 49 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) 50 #endif 51 52 53 /* "failsafe" utility functions */ 54 55 static inline void *xcalloc(size_t size, size_t nmemb) { 56 void *ptr = calloc(size, nmemb); 57 58 if (!ptr) { 59 fprintf(stderr, "Out of memory\n"); 60 abort(); 61 } 62 63 return ptr; 64 } 65 66 static inline void *xalloc(size_t size) { 67 return xcalloc(1, size); 68 } 69 70 static inline void *xrealloc(void *ptr, size_t size) { 71 ptr = realloc(ptr, size); 72 73 if (!ptr) { 74 fprintf(stderr, "Out of memory\n"); 75 abort(); 76 } 77 78 return ptr; 79 } 80 81 static inline char *xstrdup(const char *s) { 82 char *ptr = strdup(s); 83 84 if (!ptr) { 85 fprintf(stderr, "Out of memory\n"); 86 abort(); 87 } 88 89 return ptr; 90 } 91 92 static inline struct json_tokener *xjs_new_tokener(void) { 93 struct json_tokener *tok = json_tokener_new(); 94 95 if (!tok) { 96 fprintf(stderr, "Out of memory\n"); 97 abort(); 98 } 99 100 return tok; 101 } 102 103 __attribute__((format(printf, 2, 0))) 104 static inline int xasprintf(char **strp, const char *fmt, ...) { 105 va_list ap; 106 int len; 107 108 va_start(ap, fmt); 109 len = vasprintf(strp, fmt, ap); 110 va_end(ap); 111 112 if (len == -1) { 113 fprintf(stderr, "Out of memory\n"); 114 abort(); 115 } 116 117 return len; 118 } 119 120 __attribute__((format(printf, 2, 0))) 121 static inline int xvasprintf(char **strp, const char *fmt, va_list ap) { 122 int len = vasprintf(strp, fmt, ap); 123 124 if (len == -1) { 125 fprintf(stderr, "Out of memory\n"); 126 abort(); 127 } 128 129 return len; 130 } 131 132 static inline struct printbuf *xprintbuf_new(void) { 133 struct printbuf *pb = printbuf_new(); 134 135 if (!pb) { 136 fprintf(stderr, "Out of memory\n"); 137 abort(); 138 } 139 140 return pb; 141 } 142 143 144 /* linked lists */ 145 146 typedef struct uc_list { 147 struct uc_list *prev; 148 struct uc_list *next; 149 } uc_list_t; 150 151 static inline void uc_list_insert(uc_list_t *list, uc_list_t *item) 152 { 153 list->next->prev = item; 154 item->next = list->next; 155 item->prev = list; 156 list->next = item; 157 } 158 159 static inline void uc_list_remove(uc_list_t *item) 160 { 161 item->next->prev = item->prev; 162 item->prev->next = item->next; 163 item->prev = item->next = item; 164 } 165 166 #define uc_list_foreach(item, list) \ 167 for (uc_list_t *item = (list)->next; item != (list); item = item->next) 168 169 170 /* vector macros */ 171 172 #define UC_VECTOR_INIT_SIZE 8 173 174 #define uc_declare_vector(name, type) \ 175 typedef struct { \ 176 size_t count; \ 177 type *entries; \ 178 } name 179 180 localfunc size_t 181 uc_vector_capacity(size_t init, size_t count) 182 { 183 if (count == 0) 184 return init; 185 186 size_t capacity = init; 187 188 while (capacity <= count) 189 capacity += (capacity >> 1); 190 191 return capacity; 192 } 193 194 localfunc void 195 uc_vector_reduce_(char **base, size_t itemsize, size_t count, size_t remove) 196 { 197 if (*base == NULL) 198 return; 199 200 if (remove > count) 201 remove = count; 202 203 size_t next_capacity = uc_vector_capacity(UC_VECTOR_INIT_SIZE, count - remove); 204 205 if (uc_vector_capacity(next_capacity, count) != next_capacity) 206 *base = (__typeof__(*base))xrealloc(*base, itemsize * next_capacity); 207 } 208 209 localfunc void * 210 uc_vector_extend_(char **base, size_t itemsize, size_t count, size_t add) 211 { 212 size_t curr_capacity = uc_vector_capacity(UC_VECTOR_INIT_SIZE, count); 213 214 if (*base == NULL || count + add >= curr_capacity) { 215 size_t next_capacity = uc_vector_capacity(curr_capacity, count + add); 216 217 *base = (__typeof__(*base))xrealloc(*base, itemsize * next_capacity); 218 219 memset(*base + itemsize * count, 0, 220 itemsize * (next_capacity - count)); 221 } 222 223 return *base + itemsize * count; 224 } 225 226 #define uc_vector_reduce(vec, remove) \ 227 uc_vector_reduce_((char **)&(vec)->entries, sizeof((vec)->entries[0]), (vec)->count, (remove)) 228 229 #define uc_vector_extend(vec, add) \ 230 (__typeof__((vec)->entries + 0)) uc_vector_extend_( \ 231 (char **)&(vec)->entries, \ 232 sizeof((vec)->entries[0]), \ 233 (vec)->count, (add)) 234 235 #define uc_vector_grow(vec) \ 236 uc_vector_extend_((char **)&(vec)->entries, sizeof((vec)->entries[0]), (vec)->count, 1) 237 238 #define uc_vector_clear(vec) \ 239 do { \ 240 free((vec)->entries); \ 241 (vec)->entries = NULL; \ 242 (vec)->count = 0; \ 243 } while(0) 244 245 #define uc_vector_first(vec) \ 246 (&((vec)->entries[0])) 247 248 #define uc_vector_last(vec) \ 249 ((vec)->count ? &((vec)->entries[(vec)->count - 1]) : NULL) 250 251 #define uc_vector_push(vec, ...) ({ \ 252 *uc_vector_extend((vec), 1) = ((__typeof__((vec)->entries[0]))__VA_ARGS__); \ 253 &(vec)->entries[(vec)->count++]; \ 254 }) 255 256 #define uc_vector_pop(vec) \ 257 ((vec)->count ? &(vec)->entries[--(vec)->count] : NULL) 258 259 #define uc_vector_foreach(vec, iter) \ 260 for (__typeof__((vec)->entries + 0) iter = (vec)->entries; \ 261 iter < (vec)->entries + (vec)->count; \ 262 iter++) 263 264 #define uc_vector_foreach_reverse(vec, iter) \ 265 for (__typeof__((vec)->entries + 0) iter = (vec)->count \ 266 ? (vec)->entries + (vec)->count - 1 : NULL; \ 267 iter != NULL && iter >= (vec)->entries; \ 268 iter--) 269 270 #ifdef __APPLE__ 271 272 # define uc_vector_sort_cb(fn_, optype_, udtype_, ...) \ 273 int fn_(void *ud, const void *k1, const void *k2) { \ 274 optype_ v1 = *(optype_ *)k1; \ 275 optype_ v2 = *(optype_ *)k2; \ 276 udtype_ ctx = (udtype_)ud; \ 277 __VA_ARGS__ \ 278 } 279 280 # define uc_vector_sort(v_, cmp_, ud_) \ 281 qsort_r((v_)->entries, (v_)->count, sizeof((v_)->entries[0]), ud_, cmp_) 282 283 #else 284 285 # define uc_vector_sort_cb(fn_, optype_, udtype_, ...) \ 286 int fn_(const void *k1, const void *k2, void *ud) { \ 287 optype_ v1 = *(optype_ *)k1; \ 288 optype_ v2 = *(optype_ *)k2; \ 289 udtype_ ctx = (udtype_)ud; \ 290 __VA_ARGS__ \ 291 } 292 293 # define uc_vector_sort(v_, cmp_, ud_) \ 294 qsort_r((v_)->entries, (v_)->count, sizeof((v_)->entries[0]), cmp_, ud_) 295 296 #endif 297 298 #endif /* UCODE_UTIL_H */ 299
This page was automatically generated by LXR 0.3.1. • OpenWrt