git » unicorn-sparkle-basic.git » commit dd8848b

add vec, modify for GC

author Alan Dipert
2024-01-22 23:24:21 UTC
committer Alan Dipert
2024-01-22 23:24:21 UTC
parent 6b3968cf112d7a9b92ab8f803fe25c71c153f19d

add vec, modify for GC

Makefile +6 -3
vec.c +119 -0
vec.h +80 -0

diff --git a/Makefile b/Makefile
index 892f832..9f558af 100644
--- a/Makefile
+++ b/Makefile
@@ -8,13 +8,16 @@ YFLAGS=-d
 
 all: usbasic
 
-usbasic: lex.yy.o usbasic.tab.o parse.o main.o
-	$(CC) $(CFLAGS) -o usbasic lex.yy.o usbasic.tab.o parse.o main.o -lfl -lreadline -lhistory
+usbasic: lex.yy.o usbasic.tab.o parse.o vec.o main.o
+	$(CC) $(CFLAGS) -o usbasic lex.yy.o usbasic.tab.o parse.o vec.o main.o -lgc -lfl -lreadline -lhistory
+
+vec.o: vec.c vec.h
+	$(CC) $(CFLAGS) -c vec.c
 
 parse.o: parse.c usbasic.tab.h parse.h
 	$(CC) $(CFLAGS) -c parse.c
 
-main.o: main.c parse.h
+main.o: main.c parse.h vec.h
 	$(CC) $(CFLAGS) -c main.c
 
 lex.yy.o: lex.yy.c usbasic.tab.h
diff --git a/vec.c b/vec.c
new file mode 100644
index 0000000..9a4f53d
--- /dev/null
+++ b/vec.c
@@ -0,0 +1,119 @@
+//
+//  vec.c
+//
+//  Created by Mashpoe on 2/26/19.
+//
+
+#include "vec.h"
+#include <gc.h>
+#include <string.h>
+
+typedef struct vector_data vector_data;
+
+struct vector_data
+{
+	vec_size_t alloc; // stores the number of bytes allocated
+	vec_size_t length;
+	char buff[]; // use char to store bytes of an unknown type
+};
+
+vector_data* vector_alloc(vec_size_t alloc, vec_size_t size)
+{
+	vector_data* v_data = (vector_data*)
+		GC_malloc(sizeof(vector_data) + alloc * size);
+	v_data->alloc = alloc;
+	return v_data;
+}
+
+vector_data* vector_get_data(vector vec) { return &((vector_data*)vec)[-1]; }
+
+vector vector_create(void)
+{
+	vector_data* v = (vector_data*)GC_malloc(sizeof(vector_data));
+	v->alloc = 0;
+	v->length = 0;
+
+	return &v->buff;
+}
+
+void vector_free(vector vec) { GC_free(vector_get_data(vec)); }
+
+vec_size_t vector_size(vector vec) { return vector_get_data(vec)->length; }
+
+vec_size_t vector_get_alloc(vector vec) { return vector_get_data(vec)->alloc; }
+
+vector_data* vector_realloc(vector_data* v_data, vec_type_t type_size)
+{
+	vec_size_t new_alloc = (v_data->alloc == 0) ? 1 : v_data->alloc * 2;
+	vector_data* new_v_data = (vector_data*)
+	    GC_realloc(v_data, sizeof(vector_data) + new_alloc * type_size);
+	new_v_data->alloc = new_alloc;
+	return new_v_data;
+}
+
+bool vector_has_space(vector_data* v_data)
+{
+	return v_data->alloc - v_data->length > 0;
+}
+
+void* _vector_add(vector* vec_addr, vec_type_t type_size)
+{
+	vector_data* v_data = vector_get_data(*vec_addr);
+
+	if (!vector_has_space(v_data))
+	{
+		v_data = vector_realloc(v_data, type_size);
+		*vec_addr = v_data->buff;
+	}
+
+	return (void*)&v_data->buff[type_size * v_data->length++];
+}
+
+void* _vector_insert(vector* vec_addr, vec_type_t type_size, vec_size_t pos)
+{
+	vector_data* v_data = vector_get_data(*vec_addr);
+
+	vec_size_t new_length = v_data->length + 1;
+
+	// make sure there is enough room for the new element
+	if (!vector_has_space(v_data))
+	{
+		v_data = vector_realloc(v_data, type_size);
+		*vec_addr = v_data->buff;
+	}
+	memmove(&v_data->buff[(pos + 1) * type_size],
+		&v_data->buff[pos * type_size],
+		(v_data->length - pos) * type_size); // move trailing elements
+
+	v_data->length = new_length;
+
+	return &v_data->buff[pos * type_size];
+}
+
+void _vector_erase(vector* vec_addr, vec_type_t type_size, vec_size_t pos,
+		   vec_size_t len)
+{
+	vector_data* v_data = vector_get_data(*vec_addr);
+	// anyone who puts in a bad index can face the consequences on their own
+	memmove(&v_data->buff[pos * type_size],
+		&v_data->buff[(pos + len) * type_size],
+		(v_data->length - pos - len) * type_size);
+
+	v_data->length -= len;
+}
+
+void _vector_remove(vector* vec_addr, vec_type_t type_size, vec_size_t pos)
+{
+	_vector_erase(vec_addr, type_size, pos, 1);
+}
+
+void vector_pop(vector vec) { --vector_get_data(vec)->length; }
+
+vector _vector_copy(vector vec, vec_type_t type_size)
+{
+	vector_data* vec_data = vector_get_data(vec);
+	size_t alloc_size = sizeof(vector_data) + vec_data->length * type_size;
+	vector_data* v = (vector_data*)GC_malloc(alloc_size);
+	memcpy(v, vec_data, alloc_size);
+	return (void*)&v->buff;
+}
diff --git a/vec.h b/vec.h
new file mode 100644
index 0000000..4c2d586
--- /dev/null
+++ b/vec.h
@@ -0,0 +1,80 @@
+//
+//  vec.h
+//
+//  Created by Mashpoe on 2/26/19.
+//
+
+#ifndef vec_h
+#define vec_h
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+typedef void* vector; // you can't use this to store vectors, it's just used
+		      // internally as a generic type
+typedef size_t vec_size_t;	  // stores the number of elements
+typedef unsigned char vec_type_t; // stores the number of bytes for a type
+
+typedef int* vec_int;
+typedef char* vec_char;
+
+#ifndef _MSC_VER
+
+// shortcut defines
+
+// vec_addr is a vector* (aka type**)
+#define vector_add_asg(vec_addr)                                               \
+	((typeof(*vec_addr))(                                                  \
+	    _vector_add((vector*)vec_addr, sizeof(**vec_addr))))
+#define vector_insert_asg(vec_addr, pos)                                       \
+	((typeof(*vec_addr))(                                                  \
+	    _vector_insert((vector*)vec_addr, sizeof(**vec_addr), pos)))
+
+#define vector_add(vec_addr, value) (*vector_add_asg(vec_addr) = value)
+#define vector_insert(vec_addr, pos, value)                                    \
+	(*vector_insert_asg(vec_addr, pos) = value)
+
+#else
+
+#define vector_add_asg(vec_addr, type)                                         \
+	((type*)_vector_add((vector*)vec_addr, sizeof(type)))
+#define vector_insert_asg(vec_addr, type, pos)                                 \
+	((type*)_vector_insert((vector*)vec_addr, sizeof(type), pos))
+
+#define vector_add(vec_addr, type, value)                                      \
+	(*vector_add_asg(vec_addr, type) = value)
+#define vector_insert(vec_addr, type, pos, value)                              \
+	(*vector_insert_asg(vec_addr, type, pos) = value)
+
+#endif
+
+// vec is a vector (aka type*)
+#define vector_erase(vec, pos, len)                                            \
+	(_vector_erase((vector*)vec, sizeof(*vec), pos, len))
+#define vector_remove(vec, pos)                                                \
+	(_vector_remove((vector*)vec, sizeof(*vec), pos))
+
+#define vector_copy(vec) (_vector_copy((vector*)vec, sizeof(*vec)))
+
+vector vector_create(void);
+
+void vector_free(vector vec);
+
+vector _vector_add(vector* vec_addr, vec_type_t type_size);
+
+vector _vector_insert(vector* vec_addr, vec_type_t type_size, vec_size_t pos);
+
+void _vector_erase(vector* vec_addr, vec_type_t type_size, vec_size_t pos,
+		   vec_size_t len);
+
+void _vector_remove(vector* vec_addr, vec_type_t type_size, vec_size_t pos);
+
+void vector_pop(vector vec);
+
+vector _vector_copy(vector vec, vec_type_t type_size);
+
+vec_size_t vector_size(vector vec);
+
+vec_size_t vector_get_alloc(vector vec);
+
+#endif /* vec_h */