author | Alan Dipert
<alan@dipert.org> 2024-01-22 23:24:21 UTC |
committer | Alan Dipert
<alan@dipert.org> 2024-01-22 23:24:21 UTC |
parent | 6b3968cf112d7a9b92ab8f803fe25c71c153f19d |
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 */