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