protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

cursor.h (7166B)


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