lnsocket

A minimal C library for connecting to the lightning network
git clone git://jb55.com/lnsocket
Log | Files | Refs | Submodules | README | LICENSE

cursor.h (7053B)


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