mirror of
https://github.com/jb55/nostril.git
synced 2024-11-21 16:29:06 -05:00
009af9ed5b
Signed-off-by: William Casarin <jb55@jb55.com>
321 lines
5.9 KiB
C
321 lines
5.9 KiB
C
|
|
#ifndef CURSOR_H
|
|
#define CURSOR_H
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
#define unlikely(x) __builtin_expect((x),0)
|
|
#define likely(x) __builtin_expect((x),1)
|
|
|
|
struct cursor {
|
|
unsigned char *start;
|
|
unsigned char *p;
|
|
unsigned char *end;
|
|
};
|
|
|
|
struct array {
|
|
struct cursor cur;
|
|
unsigned int elem_size;
|
|
};
|
|
|
|
static inline void reset_cursor(struct cursor *cursor)
|
|
{
|
|
cursor->p = cursor->start;
|
|
}
|
|
|
|
static inline void wipe_cursor(struct cursor *cursor)
|
|
{
|
|
reset_cursor(cursor);
|
|
memset(cursor->start, 0, cursor->end - cursor->start);
|
|
}
|
|
|
|
static inline void make_cursor(unsigned char *start, unsigned char *end, struct cursor *cursor)
|
|
{
|
|
cursor->start = start;
|
|
cursor->p = start;
|
|
cursor->end = end;
|
|
}
|
|
|
|
static inline void make_array(struct array *a, unsigned char* start, unsigned char *end, unsigned int elem_size)
|
|
{
|
|
make_cursor(start, end, &a->cur);
|
|
a->elem_size = elem_size;
|
|
}
|
|
|
|
static inline int cursor_eof(struct cursor *c)
|
|
{
|
|
return c->p == c->end;
|
|
}
|
|
|
|
static inline void *cursor_malloc(struct cursor *mem, unsigned long size)
|
|
{
|
|
void *ret;
|
|
|
|
if (mem->p + size > mem->end) {
|
|
return NULL;
|
|
}
|
|
|
|
ret = mem->p;
|
|
mem->p += size;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline void *cursor_alloc(struct cursor *mem, unsigned long size)
|
|
{
|
|
void *ret;
|
|
if (!(ret = cursor_malloc(mem, size))) {
|
|
return 0;
|
|
}
|
|
|
|
memset(ret, 0, size);
|
|
return ret;
|
|
}
|
|
|
|
static inline int cursor_slice(struct cursor *mem, struct cursor *slice, size_t size)
|
|
{
|
|
unsigned char *p;
|
|
if (!(p = cursor_alloc(mem, size))) {
|
|
return 0;
|
|
}
|
|
make_cursor(p, mem->p, slice);
|
|
return 1;
|
|
}
|
|
|
|
|
|
static inline void copy_cursor(struct cursor *src, struct cursor *dest)
|
|
{
|
|
dest->start = src->start;
|
|
dest->p = src->p;
|
|
dest->end = src->end;
|
|
}
|
|
|
|
static inline int pull_byte(struct cursor *cursor, unsigned char *c)
|
|
{
|
|
if (unlikely(cursor->p + 1 > cursor->end))
|
|
return 0;
|
|
|
|
*c = *cursor->p;
|
|
cursor->p++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline int cursor_pull_c_str(struct cursor *cursor, const char **str)
|
|
{
|
|
*str = (const char*)cursor->p;
|
|
|
|
for (; cursor->p < cursor->end; cursor->p++) {
|
|
if (*cursor->p == 0) {
|
|
cursor->p++;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static inline int cursor_push_byte(struct cursor *cursor, unsigned char c)
|
|
{
|
|
if (unlikely(cursor->p + 1 > cursor->end)) {
|
|
return 0;
|
|
}
|
|
|
|
*cursor->p = c;
|
|
cursor->p++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline int cursor_pull(struct cursor *cursor, unsigned char *data, int len)
|
|
{
|
|
if (unlikely(cursor->p + len > cursor->end)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(data, cursor->p, len);
|
|
cursor->p += len;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline int pull_data_into_cursor(struct cursor *cursor,
|
|
struct cursor *dest,
|
|
unsigned char **data,
|
|
int len)
|
|
{
|
|
int ok;
|
|
|
|
if (unlikely(dest->p + len > dest->end)) {
|
|
printf("not enough room in dest buffer\n");
|
|
return 0;
|
|
}
|
|
|
|
ok = cursor_pull(cursor, dest->p, len);
|
|
if (!ok) return 0;
|
|
|
|
*data = dest->p;
|
|
dest->p += len;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline int cursor_dropn(struct cursor *cur, int size, int n)
|
|
{
|
|
if (n == 0)
|
|
return 1;
|
|
|
|
if (unlikely(cur->p - size*n < cur->start)) {
|
|
return 0;
|
|
}
|
|
|
|
cur->p -= size*n;
|
|
return 1;
|
|
}
|
|
|
|
static inline int cursor_drop(struct cursor *cur, int size)
|
|
{
|
|
return cursor_dropn(cur, size, 1);
|
|
}
|
|
|
|
static inline unsigned char *cursor_topn(struct cursor *cur, int len, int n)
|
|
{
|
|
n += 1;
|
|
if (unlikely(cur->p - len*n < cur->start)) {
|
|
return NULL;
|
|
}
|
|
return cur->p - len*n;
|
|
}
|
|
|
|
static inline unsigned char *cursor_top(struct cursor *cur, int len)
|
|
{
|
|
if (unlikely(cur->p - len < cur->start)) {
|
|
return NULL;
|
|
}
|
|
return cur->p - len;
|
|
}
|
|
|
|
static inline int cursor_top_int(struct cursor *cur, int *i)
|
|
{
|
|
unsigned char *p;
|
|
if (unlikely(!(p = cursor_top(cur, sizeof(*i))))) {
|
|
return 0;
|
|
}
|
|
*i = *((int*)p);
|
|
return 1;
|
|
}
|
|
|
|
static inline int cursor_pop(struct cursor *cur, unsigned char *data, int len)
|
|
{
|
|
if (unlikely(cur->p - len < cur->start)) {
|
|
return 0;
|
|
}
|
|
|
|
cur->p -= len;
|
|
memcpy(data, cur->p, len);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline int cursor_push(struct cursor *cursor, unsigned char *data, int len)
|
|
{
|
|
if (unlikely(cursor->p + len >= cursor->end)) {
|
|
return 0;
|
|
}
|
|
|
|
if (cursor->p != data)
|
|
memcpy(cursor->p, data, len);
|
|
|
|
cursor->p += len;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline int cursor_push_int(struct cursor *cursor, int i)
|
|
{
|
|
return cursor_push(cursor, (unsigned char*)&i, sizeof(i));
|
|
}
|
|
|
|
static inline int cursor_len(struct cursor *cursor)
|
|
{
|
|
return cursor->p - cursor->start;
|
|
}
|
|
|
|
static inline size_t cursor_count(struct cursor *cursor, size_t elem_size)
|
|
{
|
|
return cursor_len(cursor)/elem_size;
|
|
}
|
|
|
|
static inline int cursor_pull_int(struct cursor *cursor, int *i)
|
|
{
|
|
return cursor_pull(cursor, (unsigned char*)i, sizeof(*i));
|
|
}
|
|
|
|
static inline int cursor_push_u16(struct cursor *cursor, unsigned short i)
|
|
{
|
|
return cursor_push(cursor, (unsigned char*)&i, sizeof(i));
|
|
}
|
|
|
|
static inline void *index_cursor(struct cursor *cursor, unsigned int index, int elem_size)
|
|
{
|
|
unsigned char *p;
|
|
p = &cursor->start[elem_size * index];
|
|
|
|
if (unlikely(p >= cursor->end))
|
|
return NULL;
|
|
|
|
return (void*)p;
|
|
}
|
|
|
|
|
|
static inline int push_sized_str(struct cursor *cursor, const char *str, int len)
|
|
{
|
|
return cursor_push(cursor, (unsigned char*)str, len);
|
|
}
|
|
|
|
static inline int cursor_push_str(struct cursor *cursor, const char *str)
|
|
{
|
|
return cursor_push(cursor, (unsigned char*)str, strlen(str));
|
|
}
|
|
|
|
static inline int cursor_push_c_str(struct cursor *cursor, const char *str)
|
|
{
|
|
return cursor_push_str(cursor, str) && cursor_push_byte(cursor, 0);
|
|
}
|
|
|
|
static inline int cursor_remaining_capacity(struct cursor *cursor)
|
|
{
|
|
return cursor->end - cursor->p;
|
|
}
|
|
|
|
|
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
|
static inline void cursor_print_around(struct cursor *cur, int range)
|
|
{
|
|
unsigned char *c;
|
|
|
|
printf("[%ld/%ld]\n", cur->p - cur->start, cur->end - cur->start);
|
|
|
|
c = max(cur->p - range, cur->start);
|
|
for (; c < cur->end && c < (cur->p + range); c++) {
|
|
printf("%02x", *c);
|
|
}
|
|
printf("\n");
|
|
|
|
c = max(cur->p - range, cur->start);
|
|
for (; c < cur->end && c < (cur->p + range); c++) {
|
|
if (c == cur->p) {
|
|
printf("^");
|
|
continue;
|
|
}
|
|
printf(" ");
|
|
}
|
|
printf("\n");
|
|
}
|
|
#undef max
|
|
|
|
#endif
|