ion: first pass at stretchy buffers.
However, len is expressed as number of elements, and capacity as number of bytes.
This commit is contained in:
		
							parent
							
								
									5f5c4ac7ae
								
							
						
					
					
						commit
						39937b6c00
					
				| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,105 @@
 | 
			
		|||
#include <assert.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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?
 | 
			
		||||
		Loading…
	
		Reference in New Issue