• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/include/ucode/util.h

  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