#ifndef RESIZEABLE_BUF_H
#define RESIZEABLE_BUF_H

/* arch-tag: 5b2628fc-37e5-4f25-a9ca-2d9a35997db2 */

#include <stdlib.h>
#include <stdbool.h>

typedef struct rb rb_t;
typedef struct fifo fifo_t;

struct rb {
	void *buf;
	unsigned len;
	unsigned size;
};



#define RB_BLANK	{NULL, 0, 0}
#define RB_PTR(b)	((b)->buf)
#define RB_LEN(b)	((b)->len)
#define RB_CLEAR(b)	((b).len = 0)
#define RB_FREE(b)	do {rb_t *_rb = (b); _rb->len = _rb->size = 0; free(_rb->buf); _rb->buf = NULL;} while(0)
#define RB_INIT(b)	do {(b)->len = (b)->size = 0; (b)->buf = NULL;} while(0)
#define RB_ENDPTR(b)    ((RB_PTR(b) + RB_LEN(b)))

#define RBP(t,b)           ((t *)((b)->buf))
#define RBPE(t,b)           ((t *)RB_ENDPTR(b))
#define RBL(t,b)           (RB_LEN(b)/sizeof(t))
#define RB_APPEND(t, b, v) do {t _rba = (v); rb_append((b), &_rba, sizeof(t)); } while(0)
#define RB_LAST(t, b)      (RBP(t,b)[RBL(t,b) - 1])

void rb_append(rb_t *rb, void *data, size_t len);
void rb_set(rb_t *rb, void *data, size_t len);
void rbs_set(rb_t *rb, char *str);
void rbs_append(rb_t *rb, char *str);
void rb_extract(rb_t *rb, rb_t *rb2, unsigned loc, size_t len);
void rb_insert(rb_t *rb, unsigned loc, char *data, size_t len);
void rb_insert_space(rb_t *rb, unsigned loc, size_t len);
void rb_delete(rb_t *rb, unsigned loc, size_t len);
void rb_stringize(rb_t *rb);
void rb_resize(rb_t *rb, size_t len, bool preserve);
void rb_resize_zero(rb_t *rb, size_t len, bool preserve);

const extern rb_t rb_blank;

struct fifo {
        struct rb rb;
        unsigned offset;
};

#define FIFO_PTR(f) (RB_PTR(&(f).rb) + (f).offset)
#define FIFO_LEN(f) (RB_LEN(&(f).rb) - (f).offset)
#define FIFO_EMPTY(f) (!FIFO_LEN(f))
#define FIFO_BLANK  {RB_BLANK, 0}
#define FIFO_POP(f, l) do { if (l == FIFO_LEN(f)) {(f).offset = 0; RB_CLEAR((f).rb); } else (f).offset += l;  } while (0)
#define FIFO_CLEAR(f) do { (f).offset = 0; RB_CLEAR((f).rb);   } while (0)

void fifo_append(fifo_t *fifo, void *data, size_t len);


#endif

