nostril

A C cli tool for creating nostr events
git clone git://jb55.com/nostril
Log | Files | Refs | Submodules | README | LICENSE

cursor.h (7326B)


      1 
      2 #ifndef CURSOR_H
      3 #define CURSOR_H
      4 
      5 #include <stdio.h>
      6 #include <assert.h>
      7 #include <string.h>
      8 #include "hex.h"
      9 
     10 #define unlikely(x) __builtin_expect((x),0)
     11 #define likely(x)   __builtin_expect((x),1)
     12 
     13 struct cursor {
     14 	unsigned char *start;
     15 	unsigned char *p;
     16 	unsigned char *end;
     17 };
     18 
     19 struct array {
     20 	struct cursor cur;
     21 	unsigned int elem_size;
     22 };
     23 
     24 static inline void reset_cursor(struct cursor *cursor)
     25 {
     26 	cursor->p = cursor->start;
     27 }
     28 
     29 static inline void wipe_cursor(struct cursor *cursor)
     30 {
     31 	reset_cursor(cursor);
     32 	memset(cursor->start, 0, cursor->end - cursor->start);
     33 }
     34 
     35 static inline void make_cursor(unsigned char *start, unsigned char *end, struct cursor *cursor)
     36 {
     37 	cursor->start = start;
     38 	cursor->p = start;
     39 	cursor->end = end;
     40 }
     41 
     42 static inline void make_array(struct array *a, unsigned char* start, unsigned char *end, unsigned int elem_size)
     43 {
     44 	make_cursor(start, end, &a->cur);
     45 	a->elem_size = elem_size;
     46 }
     47 
     48 static inline int cursor_eof(struct cursor *c)
     49 {
     50 	return c->p == c->end;
     51 }
     52 
     53 static inline void *cursor_malloc(struct cursor *mem, unsigned long size)
     54 {
     55 	void *ret;
     56 
     57 	if (mem->p + size > mem->end) {
     58 		return NULL;
     59 	}
     60 
     61 	ret = mem->p;
     62 	mem->p += size;
     63 
     64 	return ret;
     65 }
     66 
     67 static inline void *cursor_alloc(struct cursor *mem, unsigned long size)
     68 {
     69 	void *ret;
     70 	if (!(ret = cursor_malloc(mem, size))) {
     71 		return 0;
     72 	}
     73 
     74 	memset(ret, 0, size);
     75 	return ret;
     76 }
     77 
     78 static inline int cursor_slice(struct cursor *mem, struct cursor *slice, size_t size)
     79 {
     80 	unsigned char *p;
     81 	if (!(p = cursor_alloc(mem, size))) {
     82 		return 0;
     83 	}
     84 	make_cursor(p, mem->p, slice);
     85 	return 1;
     86 }
     87 
     88 
     89 static inline void copy_cursor(struct cursor *src, struct cursor *dest)
     90 {
     91 	dest->start = src->start;
     92 	dest->p = src->p;
     93 	dest->end = src->end;
     94 }
     95 
     96 static inline int pull_byte(struct cursor *cursor, unsigned char *c)
     97 {
     98 	if (unlikely(cursor->p + 1 > cursor->end))
     99 		return 0;
    100 
    101 	*c = *cursor->p;
    102 	cursor->p++;
    103 
    104 	return 1;
    105 }
    106 
    107 static inline int cursor_pull_c_str(struct cursor *cursor, const char **str)
    108 {
    109 	*str = (const char*)cursor->p;
    110 
    111 	for (; cursor->p < cursor->end; cursor->p++) {
    112 		if (*cursor->p == 0) {
    113 			cursor->p++;
    114 			return 1;
    115 		}
    116 	}
    117 
    118 	return 0;
    119 }
    120 
    121 
    122 static inline int cursor_push_byte(struct cursor *cursor, unsigned char c)
    123 {
    124 	if (unlikely(cursor->p + 1 > cursor->end)) {
    125 		return 0;
    126 	}
    127 
    128 	*cursor->p = c;
    129 	cursor->p++;
    130 
    131 	return 1;
    132 }
    133 
    134 static inline int cursor_pull(struct cursor *cursor, unsigned char *data, int len)
    135 {
    136 	if (unlikely(cursor->p + len > cursor->end)) {
    137 		return 0;
    138 	}
    139 
    140 	memcpy(data, cursor->p, len);
    141 	cursor->p += len;
    142 
    143 	return 1;
    144 }
    145 
    146 static inline int pull_data_into_cursor(struct cursor *cursor,
    147 			  struct cursor *dest,
    148 			  unsigned char **data,
    149 			  int len)
    150 {
    151 	int ok;
    152 
    153 	if (unlikely(dest->p + len > dest->end)) {
    154 		printf("not enough room in dest buffer\n");
    155 		return 0;
    156 	}
    157 
    158 	ok = cursor_pull(cursor, dest->p, len);
    159 	if (!ok) return 0;
    160 
    161 	*data = dest->p;
    162 	dest->p += len;
    163 
    164 	return 1;
    165 }
    166 
    167 static inline int cursor_dropn(struct cursor *cur, int size, int n)
    168 {
    169 	if (n == 0)
    170 		return 1;
    171 
    172 	if (unlikely(cur->p - size*n < cur->start)) {
    173 		return 0;
    174 	}
    175 
    176 	cur->p -= size*n;
    177 	return 1;
    178 }
    179 
    180 static inline int cursor_drop(struct cursor *cur, int size)
    181 {
    182 	return cursor_dropn(cur, size, 1);
    183 }
    184 
    185 static inline unsigned char *cursor_topn(struct cursor *cur, int len, int n)
    186 {
    187 	n += 1;
    188 	if (unlikely(cur->p - len*n < cur->start)) {
    189 		return NULL;
    190 	}
    191 	return cur->p - len*n;
    192 }
    193 
    194 static inline unsigned char *cursor_top(struct cursor *cur, int len)
    195 {
    196 	if (unlikely(cur->p - len < cur->start)) {
    197 		return NULL;
    198 	}
    199 	return cur->p - len;
    200 }
    201 
    202 static inline int cursor_top_int(struct cursor *cur, int *i)
    203 {
    204 	unsigned char *p;
    205 	if (unlikely(!(p = cursor_top(cur, sizeof(*i))))) {
    206 		return 0;
    207 	}
    208 	*i = *((int*)p);
    209 	return 1;
    210 }
    211 
    212 static inline int cursor_pop(struct cursor *cur, unsigned char *data, int len)
    213 {
    214 	if (unlikely(cur->p - len < cur->start)) {
    215 		return 0;
    216 	}
    217 
    218 	cur->p -= len;
    219 	memcpy(data, cur->p, len);
    220 
    221 	return 1;
    222 }
    223 
    224 static inline int cursor_push(struct cursor *cursor, unsigned char *data, int len)
    225 {
    226 	if (unlikely(cursor->p + len >= cursor->end)) {
    227 		return 0;
    228 	}
    229 
    230 	if (cursor->p != data)
    231 		memcpy(cursor->p, data, len);
    232 
    233 	cursor->p += len;
    234 
    235 	return 1;
    236 }
    237 
    238 static inline int cursor_push_int(struct cursor *cursor, int i)
    239 {
    240 	return cursor_push(cursor, (unsigned char*)&i, sizeof(i));
    241 }
    242 
    243 static inline int cursor_len(struct cursor *cursor)
    244 {
    245 	return cursor->p - cursor->start;
    246 }
    247 
    248 static inline size_t cursor_count(struct cursor *cursor, size_t elem_size)
    249 {
    250 	return cursor_len(cursor)/elem_size;
    251 }
    252 
    253 static inline int cursor_pull_int(struct cursor *cursor, int *i)
    254 {
    255 	return cursor_pull(cursor, (unsigned char*)i, sizeof(*i));
    256 }
    257 
    258 static inline int cursor_pull_u16(struct cursor *cursor, uint16_t *i)
    259 {
    260 	return cursor_pull(cursor, (unsigned char*)i, sizeof(*i));
    261 }
    262 
    263 #define BSWAP_16(val)				\
    264 	((((uint16_t)(val) & 0x00ff) << 8)	\
    265 	 | (((uint16_t)(val) & 0xff00) >> 8))
    266 
    267 static inline uint16_t bswap_16(uint16_t val)
    268 {
    269 	return BSWAP_16(val);
    270 }
    271 
    272 static inline int cursor_push_u16(struct cursor *cursor, unsigned short i)
    273 {
    274 	return cursor_push(cursor, (unsigned char*)&i, sizeof(i));
    275 }
    276 
    277 static int cursor_pull_b16(struct cursor *c, uint16_t *s)
    278 {
    279 	if (!cursor_pull_u16(c, s))
    280 		return 0;
    281 
    282 	// we assume little endian
    283 	*s = bswap_16(*s);
    284 	return 1;
    285 }
    286 
    287 static int cursor_push_b16(struct cursor *c, uint16_t s)
    288 {
    289 	if (!cursor_push_u16(c, bswap_16(s)))
    290 		return 0;
    291 	return 1;
    292 }
    293 
    294 static inline void *index_cursor(struct cursor *cursor, unsigned int index, int elem_size)
    295 {
    296 	unsigned char *p;
    297 	p = &cursor->start[elem_size * index];
    298 
    299 	if (unlikely(p >= cursor->end))
    300 		return NULL;
    301 
    302 	return (void*)p;
    303 }
    304 
    305 
    306 static inline int push_sized_str(struct cursor *cursor, const char *str, int len)
    307 {
    308 	return cursor_push(cursor, (unsigned char*)str, len);
    309 }
    310 
    311 static inline int cursor_push_str(struct cursor *cursor, const char *str)
    312 {
    313 	return cursor_push(cursor, (unsigned char*)str, strlen(str));
    314 }
    315 
    316 static inline int cursor_push_c_str(struct cursor *cursor, const char *str)
    317 {
    318 	return cursor_push_str(cursor, str) && cursor_push_byte(cursor, 0);
    319 }
    320 
    321 static inline int cursor_remaining_capacity(struct cursor *cursor)
    322 {
    323 	return cursor->end - cursor->p;
    324 }
    325 
    326 static inline int cursor_push_hex(struct cursor *c, const void *buf, size_t bufsize)
    327 {
    328 	int size;
    329 	size = hex_encode(buf, bufsize, (char *)c->p, c->end - c->p);
    330 	if (!size)
    331 		return 0;
    332 	c->p += bufsize * 2;
    333 	return 1;
    334 }
    335 
    336 
    337 #define max(a,b) ((a) > (b) ? (a) : (b))
    338 static inline void cursor_print_around(struct cursor *cur, int range)
    339 {
    340 	unsigned char *c;
    341 
    342 	printf("[%ld/%ld]\n", cur->p - cur->start, cur->end - cur->start);
    343 
    344 	c = max(cur->p - range, cur->start);
    345 	for (; c < cur->end && c < (cur->p + range); c++) {
    346 		printf("%02x", *c);
    347 	}
    348 	printf("\n");
    349 
    350 	c = max(cur->p - range, cur->start);
    351 	for (; c < cur->end && c < (cur->p + range); c++) {
    352 		if (c == cur->p) {
    353 			printf("^");
    354 			continue;
    355 		}
    356 		printf("  ");
    357 	}
    358 	printf("\n");
    359 }
    360 #undef max
    361 
    362 static inline int cursor_memset(struct cursor *cursor, unsigned char c, int n)
    363 {
    364 	if (cursor->p + n >= cursor->end)
    365 		return 0;
    366 
    367 	memset(cursor->p, c, n);
    368 	cursor->p += n;
    369 
    370 	return 1;
    371 }
    372 
    373 
    374 static inline int cursor_align(struct cursor *cur, int bytes) {
    375 	size_t size = cur->p - cur->start;
    376 	int pad;
    377 
    378 	// pad to n-byte alignment
    379 	pad = ((size + (bytes-1)) & ~(bytes-1)) - size;
    380 	if (pad > 0 && !cursor_memset(cur, 0, pad))
    381 		return 0;
    382 
    383 	return 1;
    384 }
    385 
    386 #endif