aboutsummaryrefslogtreecommitdiff
path: root/Array.c
diff options
context:
space:
mode:
Diffstat (limited to 'Array.c')
-rw-r--r--Array.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/Array.c b/Array.c
new file mode 100644
index 0000000..c9c9984
--- /dev/null
+++ b/Array.c
@@ -0,0 +1,80 @@
+#include "Array.h"
+#include "Types.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct ArrayMeta {
+ BumpArena b;
+ usize element_size;
+ usize count;
+ usize length;
+};
+
+static inline struct ArrayMeta*
+Array_metadata(void* arr) {
+ return arr - sizeof(struct ArrayMeta);
+}
+
+typedef void* Array;
+
+Array
+Array_new(BumpArena b, usize element_size, usize length) {
+ if (NULL == b)
+ return NULL;
+
+ struct ArrayMeta am = {
+ .b = b,
+ .element_size = element_size,
+ .count = 0,
+ .length = length,
+ };
+
+ void* start = Balloc(b, sizeof(am) + element_size * length);
+ memcpy(start, &am, sizeof(am));
+ return start + sizeof(am);
+}
+
+usize
+Array_length(Array arr) {
+ if (NULL == arr)
+ return 0;
+ return Array_metadata(arr)->length;
+}
+
+usize
+Array_count(Array arr) {
+ if (NULL == arr)
+ return 0;
+ return Array_metadata(arr)->count;
+}
+
+Result
+Array_push(Array arr, void *value) {
+ if (NULL == arr)
+ return R_Uninitialized;
+
+ struct ArrayMeta *am = Array_metadata(arr);
+
+ if (am->count >= am->length) {
+ if (!Bresizeable(am->b, arr))
+ abort();
+ Bresize(am->b, sizeof(*am) + am->element_size * (am->length <<= 2));
+ }
+
+ memcpy(arr + am->count++ * am->element_size, value, am->element_size);
+
+ return R_Ok;
+}
+
+void*
+Array_pop(Array arr) {
+ if (NULL == arr)
+ return NULL;
+
+ struct ArrayMeta *am = Array_metadata(arr);
+
+ if (am->count == 0)
+ return NULL;
+
+ return arr + am->element_size * --am->count;
+}