summaryrefslogtreecommitdiff
path: root/src/std/containers
diff options
context:
space:
mode:
authorOmniscient <17525998+omnisci3nce@users.noreply.github.com>2024-02-24 22:47:46 +1100
committerOmniscient <17525998+omnisci3nce@users.noreply.github.com>2024-02-24 22:47:46 +1100
commit7b3afcaf77f96e7d62f6cd1623ead7f17512d79f (patch)
treeb5f82c64e9c06a84e4d095ab4ac48712e860b673 /src/std/containers
parentb047be5252aeb981faea077409c1768fda0301d9 (diff)
repo init. partial port of existing code
Diffstat (limited to 'src/std/containers')
-rw-r--r--src/std/containers/darray.h147
-rw-r--r--src/std/containers/ring_queue.c66
-rw-r--r--src/std/containers/ring_queue.h35
3 files changed, 248 insertions, 0 deletions
diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h
new file mode 100644
index 0000000..729b4cf
--- /dev/null
+++ b/src/std/containers/darray.h
@@ -0,0 +1,147 @@
+/**
+ * @file darray.h
+ * @brief Typed dynamic array
+ * @copyright Copyright (c) 2023
+ */
+// COPIED FROM KITC WITH SOME MINOR ADJUSTMENTS
+
+#ifndef KITC_TYPED_ARRAY_H
+#define KITC_TYPED_ARRAY_H
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DARRAY_DEFAULT_CAPACITY 64
+#define DARRAY_RESIZE_FACTOR 3
+
+/** @brief create a new darray type and functions with type `N` */
+#define typed_array(T) \
+ struct { \
+ /* @brief current number of items in the array */ \
+ size_t len; \
+ size_t capacity; \
+ T *data; \
+ }
+
+#define typed_array_iterator(T) \
+ struct { \
+ T##_darray *array; \
+ size_t current_idx; \
+ }
+
+#define PREFIX static
+
+#define KITC_DECL_TYPED_ARRAY(T) \
+ typedef typed_array(T) T##_darray; \
+ typedef typed_array_iterator(T) T##_darray_iter; \
+ \
+ /* Create a new one growable array */ \
+ PREFIX T##_darray *T##_darray_new(size_t starting_capacity) { \
+ T##_darray *d = malloc(sizeof(T##_darray)); \
+ T *data = malloc(starting_capacity * sizeof(T)); \
+ \
+ d->len = 0; \
+ d->capacity = starting_capacity; \
+ d->data = data; \
+ \
+ return d; \
+ } \
+ \
+ PREFIX void T##_darray_free(T##_darray *d) { \
+ if (d != NULL) { \
+ free(d->data); \
+ free(d); \
+ } \
+ } \
+ \
+ PREFIX T *T##_darray_resize(T##_darray *d, size_t capacity) { \
+ /* resize the internal data block */ \
+ T *new_data = realloc(d->data, sizeof(T) * capacity); \
+ /* TODO: handle OOM error */ \
+ \
+ d->capacity = capacity; \
+ d->data = new_data; \
+ return new_data; \
+ } \
+ \
+ PREFIX void T##_darray_push(T##_darray *d, T value) { \
+ if (d->len >= d->capacity) { \
+ size_t new_capacity = \
+ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \
+ T *resized = T##_darray_resize(d, new_capacity); \
+ } \
+ \
+ d->data[d->len] = value; \
+ d->len += 1; \
+ } \
+ \
+ PREFIX void T##_darray_push_copy(T##_darray *d, const T *value) { \
+ if (d->len >= d->capacity) { \
+ size_t new_capacity = \
+ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \
+ T *resized = T##_darray_resize(d, new_capacity); \
+ } \
+ \
+ T *place = d->data + d->len; \
+ d->len += 1; \
+ memcpy(place, value, sizeof(T)); \
+ } \
+ \
+ PREFIX void T##_darray_pop(T##_darray *d, T *dest) { \
+ T *item = d->data + (d->len - 1); \
+ d->len -= 1; \
+ memcpy(dest, item, sizeof(T)); \
+ } \
+ \
+ PREFIX void T##_darray_ins(T##_darray *d, const T *value, size_t index) { \
+ /* check if requires resize */ \
+ if (d->len + 1 > d->capacity) { \
+ size_t new_capacity = \
+ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \
+ T *resized = T##_darray_resize(d, new_capacity); \
+ } \
+ \
+ /* shift existing data after index */ \
+ T *insert_dest = d->data + index; \
+ T *shift_dest = insert_dest + 1; \
+ \
+ int num_items = d->len - index; \
+ \
+ d->len += 1; \
+ memcpy(shift_dest, insert_dest, num_items * sizeof(T)); \
+ memcpy(insert_dest, value, sizeof(T)); \
+ } \
+ \
+ PREFIX void T##_darray_clear(T##_darray *d) { \
+ d->len = 0; \
+ memset(d->data, 0, d->capacity * sizeof(T)); \
+ } \
+ \
+ PREFIX size_t T##_darray_len(T##_darray *d) { return d->len; } \
+ \
+ PREFIX void T##_darray_print(T##_darray *d) { \
+ printf("len: %zu ", d->len); \
+ printf("capacity: %zu\n", d->capacity); \
+ for (int i = 0; i < d->len; i++) { \
+ printf("Index %d holds value %d\n", i, d->data[i]); \
+ } \
+ } \
+ \
+ PREFIX T##_darray_iter T##_darray_iter_new(T##_darray *d) { \
+ T##_darray_iter iterator; \
+ iterator.array = d; \
+ iterator.current_idx = 0; \
+ return iterator; \
+ } \
+ \
+ PREFIX void *T##_darray_iter_next(T##_darray_iter *iterator) { \
+ if (iterator->current_idx < iterator->array->len) { \
+ return &iterator->array->data[iterator->current_idx++]; \
+ } else { \
+ return NULL; \
+ } \
+ }
+
+#endif // KITC_TYPED_ARRAY_H
diff --git a/src/std/containers/ring_queue.c b/src/std/containers/ring_queue.c
new file mode 100644
index 0000000..a9d3506
--- /dev/null
+++ b/src/std/containers/ring_queue.c
@@ -0,0 +1,66 @@
+#include "ring_queue.h"
+#include <stdlib.h>
+#include "defines.h"
+
+ring_queue* ring_queue_new(size_t type_size, size_t capacity, void* memory) {
+ ring_queue* q = malloc(sizeof(ring_queue));
+ q->len = 0;
+ q->capacity = capacity;
+ q->type_size = type_size;
+ q->head = 0;
+ q->tail = -1;
+
+ if (memory) {
+ // caller owns the memory
+ q->owns_memory = false;
+ q->data = memory;
+ } else {
+ // ring queue should own the memory
+ q->owns_memory = true;
+ q->data = malloc(capacity * type_size);
+ }
+
+ return q;
+}
+
+void ring_queue_free(ring_queue* queue) {
+ if (queue) {
+ if (queue->owns_memory) {
+ free(queue->data);
+ }
+ free(queue);
+ }
+}
+
+bool ring_queue_enqueue(ring_queue* queue, const void* value) {
+ if (queue->len == queue->capacity) {
+ return false;
+ }
+
+ queue->tail = (queue->tail + 1) % queue->capacity;
+ memcpy(queue->data + (queue->tail * queue->type_size), value, queue->type_size);
+ queue->len++;
+ return true;
+}
+
+bool ring_queue_dequeue(ring_queue* queue, void* out_value) {
+ if (queue->len == 0) {
+ // queue is empty
+ return false;
+ }
+
+ memcpy(out_value, queue->data + (queue->head * queue->type_size), queue->type_size);
+ queue->head = (queue->head + 1) % queue->capacity;
+ queue->len--;
+ return true;
+}
+
+bool ring_queue_peek(const ring_queue* queue, void* out_value) {
+ if (queue->len == 0) {
+ // queue is empty
+ return false;
+ }
+
+ memcpy(out_value, queue->data + (queue->head * queue->type_size), queue->type_size);
+ return true;
+} \ No newline at end of file
diff --git a/src/std/containers/ring_queue.h b/src/std/containers/ring_queue.h
new file mode 100644
index 0000000..15d5da4
--- /dev/null
+++ b/src/std/containers/ring_queue.h
@@ -0,0 +1,35 @@
+/**
+ * @file ring_queue.h
+ * @author your name (you@domain.com)
+ * @brief
+ * @version 0.1
+ * @date 2024-02-24
+ *
+ * @copyright Copyright (c) 2024
+ *
+ */
+#pragma once
+#include "defines.h"
+
+/**
+ * @brief a fixed-size ring queue
+ */
+typedef struct ring_queue {
+ size_t len;
+ size_t capacity;
+ size_t type_size;
+ void* data;
+ bool owns_memory;
+ int32_t head;
+ int32_t tail;
+} ring_queue;
+
+ring_queue* ring_queue_new(size_t type_size, size_t capacity, void* memory_block);
+
+void ring_queue_free(ring_queue* queue);
+
+bool ring_queue_enqueue(ring_queue* queue, const void* value);
+
+bool ring_queue_dequeue(ring_queue* queue, void* out_value);
+
+bool ring_queue_peek(const ring_queue* queue, void* out_value); \ No newline at end of file