website

website.git
git clone git://git.lenczewski.org/website.git
Log | Files | Refs

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 */