From 39937b6c001d3a0e994fb6d4222c21ba20ca6ea1 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Thu, 15 Mar 2018 13:43:46 -0700 Subject: [PATCH] ion: first pass at stretchy buffers. However, len is expressed as number of elements, and capacity as number of bytes. --- bitwise/ion/Makefile | 12 +++++ bitwise/ion/ion.c | 105 ++++++++++++++++++++++++++++++++++++++++++ bitwise/ion/notes.txt | 11 +++++ 3 files changed, 128 insertions(+) create mode 100644 bitwise/ion/Makefile create mode 100644 bitwise/ion/ion.c create mode 100644 bitwise/ion/notes.txt diff --git a/bitwise/ion/Makefile b/bitwise/ion/Makefile new file mode 100644 index 0000000..6240cd4 --- /dev/null +++ b/bitwise/ion/Makefile @@ -0,0 +1,12 @@ +TARGET := ion +OBJS := $(TARGET).o +CFLAGS := -g + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(CFLAGS) -o $@ $(OBJS) + +.PHONY: clean +clean: + rm -f $(OBJS) $(TARGET) \ No newline at end of file diff --git a/bitwise/ion/ion.c b/bitwise/ion/ion.c new file mode 100644 index 0000000..b4062c4 --- /dev/null +++ b/bitwise/ion/ion.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include + + + +// stretchy buffers +static size_t +buf_len(void *buf) +{ + return *(size_t *)(buf - (2 * sizeof(size_t))); +} + +static void +buf_set_len(void *buf, size_t len) +{ + *(size_t *)(buf - (2 * sizeof(size_t))) = len; +} + +static size_t +buf_cap(void *buf) +{ + return *(size_t *)(buf - sizeof(size_t)); +} + +static size_t +buf_set_cap(void *buf, size_t cap) +{ + *(size_t *)(buf - sizeof(size_t)) = cap; +} + +static const size_t buf_overhead = 2 * sizeof(size_t); + +static void +buf_allocate(void **buf, size_t nelem, size_t size) +{ + size_t len = 0, cap = nelem * size; + if (*buf == NULL) { + *buf = malloc(buf_overhead + cap); + *buf += buf_overhead; + } + else { + len = buf_len(*buf); + assert(len < cap); + void *new_buf = malloc(buf_overhead + cap); + new_buf += buf_overhead; + memcpy(new_buf, *buf, cap); + free(*buf); + *buf = new_buf; + } + + buf_set_len(*buf, len); + buf_set_cap(*buf, cap); +} + +static bool +buf_must_grow(void *buf) +{ + return (buf == NULL) || (buf_len(buf) == buf_cap(buf)); +} + +static const size_t buf_initial_length = 32; + +#define buf_push(buf, x) { \ + if ((void *)buf == NULL) { buf_allocate((void **)&(buf), buf_initial_length, sizeof((x))); } \ + if (buf_must_grow((void *)(buf))) { buf_allocate((void **)&(buf), 2 * buf_cap((void *)(buf)), 1); } \ + (buf)[buf_len((buf))] = (x); \ + buf_set_len((void *)(buf), buf_len((void *)(buf)) + 1); \ +} \ + +static void +buf_free(void *buf) +{ + buf = (void *)buf - buf_overhead; + free(buf); +} + +/* + * 1. NULL? → allocate with default size (32?) + * 2. + */ + +int +main(int argc, char *argv[]) +{ + int *buf = NULL; + buf_push(buf, 47); // std::vector::push_back + // now buf actually points to a buffer + buf_push(buf, 1234); + + printf("buf length: %lu / cap: %lu\n", buf_len(buf), buf_cap(buf)); + for (int i = 0; i < buf_len(buf); i++) { + printf("%d\n", buf[i]); + } + + for (int i = 0; i < 1024; i++) { + buf_push(buf, i+1); + } + printf("buf length: %lu / cap: %lu\n", buf_len(buf), buf_cap(buf)); + + buf_free(buf); + return 0; +} \ No newline at end of file diff --git a/bitwise/ion/notes.txt b/bitwise/ion/notes.txt new file mode 100644 index 0000000..30584a2 --- /dev/null +++ b/bitwise/ion/notes.txt @@ -0,0 +1,11 @@ +NOTES +===== + +2018-03-15 +---------- + ++ chapter 2 - 4.1 of Wirth's [compiler book](http://www.ethoberon.ethz.ch/WirthPubl/CBEAll.pdf) + +stretch buffers: ++ dynamically growable arrays such that with a few pitfalls but is easy to generate ++ invented by stb? \ No newline at end of file