summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-05-23 18:34:09 -0300
committerEuAndreh <eu@euandre.org>2024-05-23 18:34:09 -0300
commita5934697be6255a4ed46dafcd9479733313f0af4 (patch)
treea12ee160fd06a89aa79d0b156646688d9ec94401 /src
parentRename "pindaiba" -> "pindaibabs" (diff)
downloadpindaiba-a5934697be6255a4ed46dafcd9479733313f0af4.tar.gz
pindaiba-a5934697be6255a4ed46dafcd9479733313f0af4.tar.xz
Add some version of vector.c
Diffstat (limited to 'src')
-rw-r--r--src/i18n.c1
-rw-r--r--src/i18n.h1
-rw-r--r--src/pindaibabs.en.msg2
-rw-r--r--src/vector.c268
-rw-r--r--src/vector.h29
5 files changed, 301 insertions, 0 deletions
diff --git a/src/i18n.c b/src/i18n.c
index 5d5c33a..81d1e36 100644
--- a/src/i18n.c
+++ b/src/i18n.c
@@ -47,6 +47,7 @@ MSGS[] = {
[MSG_VERSION]= NAME " " VERSION " " DATE "\n",
[MSG_ERR_VECTOR_MAX_CAPACITY]= "Already at max capacity (%ld): %s\n",
[MSG_ERR_VECTOR_OUT_OF_BOUNDS]= "idx (%ld) is beyond bounds (%ld)\n",
+ [MSG_ERR_VECTOR_UNDERFLOW]= "pop on an empty vector\n",
NULL
};
diff --git a/src/i18n.h b/src/i18n.h
index 0472079..3d3f98a 100644
--- a/src/i18n.h
+++ b/src/i18n.h
@@ -36,6 +36,7 @@ enum MSGCATALOG_ID {
MSG_VERSION,
MSG_ERR_VECTOR_MAX_CAPACITY,
MSG_ERR_VECTOR_OUT_OF_BOUNDS,
+ MSG_ERR_VECTOR_UNDERFLOW,
};
diff --git a/src/pindaibabs.en.msg b/src/pindaibabs.en.msg
index a0f6726..24eccbd 100644
--- a/src/pindaibabs.en.msg
+++ b/src/pindaibabs.en.msg
@@ -72,3 +72,5 @@
37 idx (%ld) is beyond bounds (%ld)\n
+38 pop on an empty vector\n
+
diff --git a/src/vector.c b/src/vector.c
new file mode 100644
index 0000000..65f004f
--- /dev/null
+++ b/src/vector.c
@@ -0,0 +1,268 @@
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "logerr.h"
+#include "catalog.h"
+#include "i18n.h"
+
+#include "vector.h"
+
+
+struct Vector {
+ void **values;
+ size_t capacity;
+ size_t back_count;
+ size_t front_count;
+ const size_t max_capacity;
+ const size_t multiplier;
+ const size_t value_size;
+};
+
+static const size_t
+VECTOR_MAX_CAPACITY = SIZE_MAX;
+
+static const size_t
+VECTOR_DEFAULT_CAPACITY = 8;
+
+static const size_t
+GROWTH_MULTIPLIER = 2;
+
+
+int
+vector_new_with(
+ const size_t capacity,
+ const size_t max_capacity,
+ const size_t multiplier,
+ const size_t value_size,
+ struct Vector **const out
+) {
+ int rc = -1;
+
+ struct Vector v = {
+ .values = NULL,
+ .capacity = capacity,
+ .back_count = 0U,
+ .front_count = 0U,
+ .max_capacity = max_capacity,
+ .multiplier = multiplier,
+ .value_size = value_size,
+ };
+ struct Vector *restrict vref = NULL;
+
+ assert(capacity > 0);
+ if (capacity > max_capacity) {
+ logerr(
+ _(MSG_ERR_VECTOR_MAX_CAPACITY),
+ max_capacity,
+ strerror(EOVERFLOW)
+ );
+ rc = EOVERFLOW;
+ goto out;
+ }
+
+ const size_t array_bytes_size = capacity * value_size;
+ v.values = malloc(array_bytes_size);
+ if (v.values == NULL) {
+ logerr("malloc(%ld): %s\n", array_bytes_size, strerror(errno));
+ goto out;
+ }
+
+ vref = malloc(sizeof(*vref));
+ if (vref == NULL) {
+ logerr("malloc(%ld): %s\n", sizeof(vref), strerror(errno));
+ goto out;
+ }
+ memcpy(vref, &v, sizeof(v));
+
+ *out = vref;
+ rc = 0;
+out:
+ if (rc) {
+ if (vref != NULL) {
+ free(vref);
+ }
+ if (v.values != NULL) {
+ free(v.values);
+ }
+ }
+ return rc;
+}
+
+int
+vector_new(const size_t value_size, struct Vector **const out) {
+ return vector_new_with(
+ VECTOR_DEFAULT_CAPACITY,
+ VECTOR_MAX_CAPACITY,
+ GROWTH_MULTIPLIER,
+ value_size,
+ out
+ );
+}
+
+void
+vector_free(const struct Vector *const v) {
+ assert(v != NULL);
+ free(v->values);
+ free((void *)v);
+}
+
+size_t
+vector_count(const struct Vector *const v) {
+ const size_t count = v->back_count + v->front_count;
+ assert(count <= v->capacity);
+ return count;
+}
+
+int
+vector_nth(const struct Vector *const v, const size_t idx, const void **const out) {
+ int rc = -1;
+
+ const size_t count = vector_count(v);
+ if (idx >= count) {
+ logerr(_(MSG_ERR_VECTOR_OUT_OF_BOUNDS), idx, count);
+ goto out;
+ }
+
+ *out = v->values[idx]; // FIXME
+ rc = 0;
+out:
+ return rc;
+}
+
+static size_t
+next_capacity(const struct Vector *const v) {
+ if (v->capacity > v->max_capacity / v->multiplier) {
+ return v->max_capacity;
+ } else {
+ return v->capacity * v->multiplier;
+ }
+}
+
+int
+vector_push_back(struct Vector *const v, void *const value) {
+ int rc = -1;
+
+ void *new_values = NULL;
+
+ const size_t count = vector_count(v);
+ if (count == v->capacity) {
+ if (count == v->max_capacity) {
+ logerr(
+ _(MSG_ERR_VECTOR_MAX_CAPACITY),
+ v->max_capacity,
+ strerror(EOVERFLOW)
+ );
+ rc = EOVERFLOW;
+ goto out;
+ }
+
+ const size_t new_capacity = next_capacity(v);
+ const size_t new_size = new_capacity * v->value_size;
+ new_values = realloc(v->values, new_size);
+ if (new_values == NULL) {
+ logerr(
+ "realloc(v->values, %ld): %s\n",
+ new_size,
+ strerror(errno)
+ );
+ goto out;
+ }
+ v->capacity = new_capacity;
+ v->values = new_values;
+ }
+
+ v->values[v->back_count] = value;
+ v->back_count++;
+ rc = 0;
+out:
+ if (rc) {
+ if (new_values != NULL) {
+ free(new_values);
+ }
+ }
+ return rc;
+}
+
+int
+vector_push_front(struct Vector *const v, void *const value) {
+ int rc = -1;
+
+ void *new_values = NULL;
+
+ const size_t count = vector_count(v);
+ if (count == v->capacity) {
+ if (count == v->max_capacity) {
+ logerr(
+ _(MSG_ERR_VECTOR_MAX_CAPACITY),
+ v->max_capacity,
+ strerror(EOVERFLOW)
+ );
+ }
+
+ const size_t new_capacity = next_capacity(v);
+ const size_t new_size = new_capacity * v->value_size;
+ new_values = realloc(v->values, new_size);
+ if (new_values == NULL) {
+ logerr(
+ "realloc(v->values, %ld): %s\n",
+ new_size,
+ strerror(errno)
+ );
+ goto out;
+ }
+ v->capacity = new_capacity;
+ // FIXME: copy, but leaving things at the beginning
+ }
+
+ v->values[v->front_count] = value;
+ v->front_count++;
+ rc = 0;
+out:
+ if (rc) {
+ if (new_values != NULL) {
+ free(new_values);
+ }
+ }
+ return rc;
+}
+
+int
+vector_pop_back(struct Vector *const v, const void **const out) {
+ int rc = -1;
+
+ const size_t count = vector_count(v);
+ if (count == 0) {
+ logerr(_(MSG_ERR_VECTOR_UNDERFLOW));
+ goto out;
+ }
+
+ *out = v->values[v->back_count - 1]; // FIXME: can become negative!
+ v->back_count--;
+ rc = 0;
+out:
+ return rc;
+}
+
+int
+vector_pop_front(struct Vector *const v, const void **const out) {
+ int rc = -1;
+
+ const size_t count = vector_count(v);
+ if (count == 0) {
+ logerr(_(MSG_ERR_VECTOR_UNDERFLOW));
+ goto out;
+ }
+
+ *out = v->values[v->front_count - 1]; // FIXME: can become negative!
+ v->front_count--;
+ rc = 0;
+out:
+ return rc;
+}
diff --git a/src/vector.h b/src/vector.h
new file mode 100644
index 0000000..cc3c96a
--- /dev/null
+++ b/src/vector.h
@@ -0,0 +1,29 @@
+struct Vector;
+
+
+int
+vector_new(const size_t value_size, struct Vector **out);
+
+int
+vector_new_with(
+ const size_t capacity,
+ const size_t max_capacity,
+ const size_t multiplier,
+ const size_t value_size,
+ struct Vector **out
+);
+
+void
+vector_free(const struct Vector *const v);
+
+size_t
+vector_count(const struct Vector *v);
+
+int
+vector_nth(const struct Vector *const v, const size_t idx, const void **const out);
+
+int
+vector_push_back(struct Vector *const v, void *const value);
+
+int
+vector_pop_back(struct Vector *const v, const void **const out);