libdiscord

libdiscord.git
git clone git://git.lenczewski.org/libdiscord.git
Log | Files | Refs | README | LICENSE

utils.h (4143B)


      1 #ifndef UTILS_H
      2 #define UTILS_H
      3 
      4 #include <assert.h>
      5 #include <stdalign.h>
      6 #include <stddef.h>
      7 #include <stdint.h>
      8 #include <string.h>
      9 
     10 #define KiB (1024ull)
     11 #define MiB (1024 * KiB)
     12 #define GiB (1024 * MiB)
     13 #define TiB (1024 * GiB)
     14 
     15 #define ARRLEN(arr) (sizeof (arr) / sizeof (arr)[0])
     16 
     17 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
     18 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
     19 #define CLAMP(min, max, v) MIN((max), MAX((min), (v)))
     20 
     21 #define IS_POW2(v) (((v) & ((v) - 1)) == 0)
     22 
     23 #define IS_ALIGNED(v, align) (((v) & ((align) - 1)) == 0)
     24 #define ALIGN_PREV(v, align) ((v) & ~((align) - 1))
     25 #define ALIGN_NEXT(v, align) ALIGN_PREV((v) + ((align) - 1), (align))
     26 
     27 #define TYPEOF(v) (__typeof__ (v))
     28 
     29 #define TO_PARENT_PTR(ptr, T, member) \
     30 	((T *) (((uintptr_t) (ptr)) - offsetof(T, member)))
     31 
     32 // =======================================================================
     33 
     34 struct arena {
     35 	void *ptr;
     36 	size_t cap, len;
     37 };
     38 
     39 inline void
     40 arena_reset(struct arena *arena)
     41 {
     42 	arena->len = 0;
     43 }
     44 
     45 inline void *
     46 arena_alloc(struct arena *arena, size_t size, size_t alignment)
     47 {
     48 	assert(size);
     49 	assert(alignment);
     50 	assert(IS_POW2(alignment));
     51 
     52 	uintptr_t base = (uintptr_t) arena->ptr;
     53 	uintptr_t end = base + arena->cap;
     54 
     55 	uintptr_t aligned_ptr = ALIGN_NEXT(base + arena->len, alignment);
     56 	if (end < aligned_ptr + size)
     57 		return NULL;
     58 
     59 	arena->len = (aligned_ptr + size) - base;
     60 
     61 	return (void *) aligned_ptr;
     62 }
     63 
     64 #define ARENA_ALLOC_ARRAY(arena, T, n) \
     65 	arena_alloc((arena), sizeof(T) * (n), alignof(T))
     66 
     67 #define ARENA_ALLOC_SIZED(arena, T) \
     68 	ARENA_ALLOC_ARRAY((arena), T, 1)
     69 
     70 // =======================================================================
     71 
     72 struct list_node {
     73 	struct list_node *prev, *next;
     74 };
     75 
     76 #define LIST_INIT(list) ((struct list_node) { &(list), &(list), })
     77 
     78 #define LIST_HEAD(list) ((list)->next)
     79 #define LIST_TAIL(list) ((list)->prev)
     80 
     81 #define LIST_EMPTY(list) \
     82 	(LIST_HEAD(list) == (list) && LIST_TAIL(list) == (list))
     83 
     84 #define LIST_NODE_ITER(list, it) \
     85 	for ((it) = LIST_HEAD(list); (it) != (list); (it) = LIST_HEAD(it))
     86 
     87 #define LIST_NODE_RITER(list, it) \
     88 	for ((it) = LIST_TAIL(list); (it) != (list); (it) = LIST_TAIL(it))
     89 
     90 #define LIST_NODE_ENTRY(node, T, member) \
     91 	TO_PARENT_PTR((node), T, member)
     92 
     93 #define LIST_ENTRY_ITER(list, it, member) \
     94 	for ((it) = LIST_NODE_ENTRY(LIST_HEAD(list), \
     95 				    TYPEOF(*(it)), member); \
     96 	    &(it)->member != (list); \
     97 	     (it) = LIST_NODE_ENTRY(LIST_HEAD(&(it)->member), \
     98 				    TYPEOF(*(it)), member))
     99 
    100 #define LIST_ENTRY_RITER(list, it, member) \
    101 	for ((it) = LIST_NODE_ENTRY(LIST_TAIL(list), \
    102 				    TYPEOF(*(it)), member); \
    103 	    &(it)->member != (list); \
    104 	     (it) = LIST_NODE_ENTRY(LIST_TAIL(&(it)->member), \
    105 				    TYPEOF(*(it)), member))
    106 
    107 
    108 inline void
    109 list_node_link(struct list_node *node,
    110 	       struct list_node *prev,
    111 	       struct list_node *next)
    112 {
    113 	node->prev = prev;
    114 	prev->next = node;
    115 	node->next = next;
    116 	next->prev = node;
    117 }
    118 
    119 inline struct list_node *
    120 list_node_unlink(struct list_node *node)
    121 {
    122 	node->prev->next = node->next;
    123 	node->next->prev = node->prev;
    124 	return node;
    125 }
    126 
    127 inline void
    128 list_push_head(struct list_node *restrict list,
    129 	       struct list_node *restrict node)
    130 {
    131 	list_node_link(node, list, LIST_HEAD(list));
    132 }
    133 
    134 inline void
    135 list_push_tail(struct list_node *restrict list,
    136 	       struct list_node *restrict node)
    137 {
    138 	list_node_link(node, LIST_TAIL(list), list);
    139 }
    140 
    141 inline struct list_node *
    142 list_pop_head(struct list_node *list)
    143 {
    144 	struct list_node *res = list_node_unlink(LIST_HEAD(list));
    145 	return res;
    146 }
    147 
    148 inline struct list_node *
    149 list_pop_tail(struct list_node *list)
    150 {
    151 	struct list_node *res = list_node_unlink(LIST_TAIL(list));
    152 	return res;
    153 }
    154 
    155 // ======================================================================
    156 
    157 struct stringview {
    158 	unsigned char *ptr;
    159 	size_t len;
    160 };
    161 
    162 #define FROM_CSTR(cstr) ((struct stringview) { (cstr), strlen(cstr), })
    163 
    164 inline int
    165 svcmp(struct stringview a, struct stringview b)
    166 {
    167 	if (a.len != b.len)
    168 		return a.len - b.len;
    169 
    170 	return strncmp((char *) a.ptr, (char *) b.ptr, a.len);
    171 }
    172 
    173 inline unsigned char *
    174 svstr(struct stringview haystack, struct stringview needle)
    175 {
    176 	return NULL;
    177 }
    178 
    179 #endif /* UTILS_H */