utils.h (3930B)
1 #ifndef UTILS_H 2 #define UTILS_H 3 4 #ifdef _XOPEN_SOURCE 5 # undef _XOPEN_SOURCE 6 #endif 7 8 #define _XOPEN_SOURCE 700 9 10 #ifndef _DEFAULT_SOURCE 11 # define _DEFAULT_SOURCE 1 12 #endif 13 14 #include <assert.h> 15 #include <stdalign.h> 16 #include <stddef.h> 17 #include <stdint.h> 18 #include <stdio.h> 19 #include <string.h> 20 #include <unistd.h> 21 22 #include <fcntl.h> 23 #include <sys/stat.h> 24 25 #include <sys/mman.h> 26 27 #define KiB 1024 28 #define MiB (1024 * KiB) 29 30 struct str { 31 char *ptr; 32 size_t len; 33 }; 34 35 #define ALIGN_PREV(v, align) ((v) & ~((align) - 1)) 36 #define ALIGN_NEXT(v, align) ALIGN_PREV((v) + ((align) - 1), (align)) 37 38 struct arena { 39 void *ptr; 40 uint64_t cap, len; 41 }; 42 43 inline void * 44 arena_alloc(struct arena *arena, uint64_t size, uint64_t align) 45 { 46 uint64_t aligned_len = ALIGN_NEXT(arena->len, align); 47 if (aligned_len + size > arena->cap) 48 return NULL; 49 50 void *ptr = (void *) ((uintptr_t) arena->ptr + aligned_len); 51 arena->len = aligned_len + size; 52 53 return ptr; 54 } 55 56 #define ALLOC_ARRAY(arena, T, n) \ 57 arena_alloc(arena, sizeof(T) * (n), alignof(T)) 58 #define ALLOC_SIZED(arena, T) ALLOC_ARRAY(arena, T, 1) 59 60 inline void 61 arena_reset(struct arena *arena) 62 { 63 arena->len = 0; 64 } 65 66 struct list_node { 67 struct list_node *prev, *next; 68 }; 69 70 #define FROM_NODE(node, T, member) \ 71 ((node) \ 72 ? ((T *) ((uintptr_t) (node) - offsetof(T, member))) \ 73 : NULL) 74 75 #define list_node_iter(node) \ 76 for (struct list_node *it = (node); it; it = it->next) 77 78 struct list { 79 struct list_node *head, *tail; 80 }; 81 82 #define list_iter(list) \ 83 list_node_iter((list)->head) 84 85 inline void 86 list_push_tail(struct list *list, struct list_node *node) 87 { 88 if (!list->head) 89 list->head = node; 90 91 if (list->tail) 92 list->tail->next = node; 93 94 list->tail = node; 95 } 96 97 inline struct list_node * 98 list_pop_tail(struct list *list) 99 { 100 struct list_node *node = list->tail; 101 102 if (node) 103 list->tail = list->tail->prev; 104 105 return node; 106 } 107 108 inline int 109 mmap_file(char *path, int flags, char **out_src, size_t *out_len, struct stat *out_stat) 110 { 111 int fd = open(path, flags | O_CLOEXEC); 112 if (fd < 0) { 113 fprintf(stderr, "Failed to open() file: %s\n", path); 114 return -1; 115 } 116 117 struct stat statbuf; 118 if (fstat(fd, &statbuf) < 0) { 119 perror("fstat()"); 120 goto error; 121 } 122 123 char *src = NULL; 124 size_t len = statbuf.st_size; 125 if (!len) 126 goto end; 127 128 src = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 129 if (src == MAP_FAILED) { 130 perror("mmap()"); 131 goto error; 132 } 133 134 end: 135 close(fd); 136 137 *out_src = src; 138 *out_len = len; 139 140 if (out_stat) 141 memcpy(out_stat, &statbuf, sizeof statbuf); 142 143 return 0; 144 145 error: 146 close(fd); 147 148 return -1; 149 } 150 151 inline int 152 timespec_compare(struct timespec const *lhs, struct timespec const *rhs) 153 { 154 if (lhs->tv_sec == rhs->tv_sec) 155 return lhs->tv_nsec - rhs->tv_nsec; 156 return lhs->tv_sec - rhs->tv_sec; 157 } 158 159 inline char * 160 strnchr(char *restrict src, char const *restrict end, char marker) 161 { 162 while (src < end && *src != marker) 163 src++; 164 165 return src; 166 } 167 168 inline char * 169 strnstr(char *restrict src, char const *restrict end, char const *restrict marker) 170 { 171 while (src < end) { 172 char *ptr = src; 173 char const *cur = marker; 174 while (src < end && *cur && *src++ == *cur) 175 cur++; 176 177 if (*cur == '\0') /* found marker in source */ 178 return ptr; 179 } 180 181 return src; 182 } 183 184 #ifdef UTILS_IMPL 185 186 extern inline void * 187 arena_alloc(struct arena *arena, uint64_t size, uint64_t align); 188 189 extern inline void 190 arena_reset(struct arena *arena); 191 192 extern inline void 193 list_push_tail(struct list *list, struct list_node *node); 194 195 extern inline struct list_node * 196 list_pop_tail(struct list *list); 197 198 extern inline int 199 mmap_file(char *path, int flags, char **out_src, size_t *out_len, struct stat *out_stat); 200 201 extern inline int 202 timespec_compare(struct timespec const *lhs, struct timespec const *rhs); 203 204 extern inline char * 205 strnchr(char *restrict src, char const *restrict end, char marker); 206 207 extern inline char * 208 strnstr(char *restrict src, char const *restrict end, char const *restrict marker); 209 210 #endif 211 212 #endif /* UTILS_H */