summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-05-31 15:35:16 -0300
committerEuAndreh <eu@euandre.org>2024-05-31 15:35:16 -0300
commit88f5df59c94fa48c832118e81e6ddf2759cb0231 (patch)
treeeb7aba63f2a6aa1e84a91ae3811a0275d19f2399 /src
parentUse freeit() everywhere (diff)
downloadpindaiba-88f5df59c94fa48c832118e81e6ddf2759cb0231.tar.gz
pindaiba-88f5df59c94fa48c832118e81e6ddf2759cb0231.tar.xz
Add initial private functions for src/set.c and src/tree.c
Diffstat (limited to 'src')
-rw-r--r--src/set.c53
-rw-r--r--src/set.h0
-rw-r--r--src/tree.c205
-rw-r--r--src/tree.h0
4 files changed, 258 insertions, 0 deletions
diff --git a/src/set.c b/src/set.c
new file mode 100644
index 0000000..3c03231
--- /dev/null
+++ b/src/set.c
@@ -0,0 +1,53 @@
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "logerr.h"
+#include "util.h"
+
+#include "set.h"
+
+
+
+struct Set {
+ size_t count;
+};
+
+
+
+int
+set_new(const struct Set **const out) {
+ int rc = -1;
+
+ const struct Set *ret = NULL;
+
+ ret = malloc(sizeof(*ret));
+ if (ret == NULL) {
+ logerr("malloc(): %s", strerror(errno));
+ goto out;
+ }
+
+ memcpy((void *)ret, &(struct Set) {
+ .count = 0U,
+ }, sizeof(*ret));
+ *out = ret;
+ rc = 0;
+out:
+ if (rc) {
+ if (ret != NULL) {
+ freeit((void *)&ret);
+ }
+ }
+ return rc;
+}
+
+void
+set_free(const struct Set **const s) {
+ assert((*s) != NULL);
+ free((void *)*s);
+}
diff --git a/src/set.h b/src/set.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/set.h
diff --git a/src/tree.c b/src/tree.c
new file mode 100644
index 0000000..5edda76
--- /dev/null
+++ b/src/tree.c
@@ -0,0 +1,205 @@
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "logerr.h"
+#include "util.h"
+
+#include "tree.h"
+
+
+
+struct Tree {
+ const void *const value;
+ const struct Tree *left;
+ const struct Tree *right;
+ const size_t value_size;
+ size_t height;
+};
+
+
+
+int
+tree_new(const size_t value_size, const struct Tree **const out) {
+ int rc = -1;
+
+ const struct Tree *ret = NULL;
+
+ ret = malloc(sizeof(*ret));
+ if (ret == NULL) {
+ logerr("malloc(): %s", strerror(errno));
+ goto out;
+ }
+
+ memcpy((void *)ret, &(struct Tree) {
+ .value = NULL,
+ .left = NULL,
+ .right = NULL,
+ .value_size = value_size,
+ .height = 0U,
+ }, sizeof(*ret));
+ *out = ret;
+ rc = 0;
+out:
+ if (rc) {
+ if (ret != NULL) {
+ freeit((void *)&ret);
+ }
+ }
+ return rc;
+}
+
+void
+tree_free(const struct Tree **const t) {
+ const struct Tree *const tree = *t;
+ assert(tree != NULL);
+
+ const struct Tree *left = tree->left;
+ const struct Tree *right = tree->right;
+
+ if (left != NULL) {
+ tree_free(&left);
+ }
+
+ if (right != NULL) {
+ tree_free(&right);
+ }
+
+ freeit((void *)t);
+}
+
+static void
+insert_node(
+ const struct Tree *const t,
+ const struct Tree *node,
+ const void *const value
+) {
+ struct Tree *const t_mut = (struct Tree *const)t;
+ const int cmp = memcmp(value, t->value, t->value_size);
+ if (cmp == 0) {
+ tree_free(&node);
+ } else if (cmp > 0) {
+ if (t->left == NULL) {
+ t_mut->left = (void *)node;
+ } else {
+ insert_node(t->left, node, value);
+ }
+ struct Tree *const t_left_mut = (struct Tree *const)t->left;
+ t_left_mut->height++;
+ } else {
+ if (t->right == NULL) {
+ t_mut->right = node;
+ } else {
+ insert_node(t->right, node, value);
+ }
+ struct Tree *const t_right_mut = (struct Tree *const)t->right;
+ t_right_mut->height++;
+ }
+}
+
+int
+tree_insert(const struct Tree *const t, const void *const value) {
+ int rc = -1;
+
+ const struct Tree *new = NULL;
+ struct Tree *const t_mut = (struct Tree *const)t;
+
+ if (t->value == NULL) {
+ memcpy((void *)t->value, value, t->value_size);
+ t_mut->height++;
+ goto out;
+ }
+
+ if (tree_new(t->value_size, &new)) {
+ logerr("tree_new()");
+ goto out;
+ }
+
+ insert_node(t, new, value);
+
+ rc = 0;
+out:
+ if (rc) {
+ if (new != NULL) {
+ tree_free(&new);
+ }
+ }
+ return rc;
+}
+
+static bool
+remove_ref(
+ const struct Tree *t,
+ const void *const value,
+ const struct Tree **const parent_ptr
+) {
+ if (t->value == NULL) {
+ return false;
+ }
+
+ struct Tree *const t_mut = (struct Tree *const)t;
+
+ const int cmp = memcmp(value, t->value, t->value_size);
+ if (cmp == 0) {
+ if ((t->left == NULL) && (t->right == NULL)) {
+ if (parent_ptr != NULL) {
+ *parent_ptr = NULL;
+ }
+ } else if (t->left != NULL) {
+ if (parent_ptr != NULL) {
+ *parent_ptr = t->left;
+ }
+ } else if (t->right != NULL) {
+ if (parent_ptr != NULL) {
+ *parent_ptr = t->right;
+ }
+ } else {
+ // FIXME: pivot
+ assert(false);
+ }
+ tree_free(&t);
+ return true;
+ } else if (cmp > 0) {
+ if (t->left == NULL) {
+ return false;
+ }
+ return remove_ref(t->left, value, &t_mut->left);
+ } else {
+ if (t->right == NULL) {
+ return false;
+ }
+ return remove_ref(t->right, value, &t_mut->right);
+ }
+}
+
+bool
+tree_remove(const struct Tree *const t, const void *const value) {
+ return remove_ref(t, value, NULL);
+}
+
+bool
+tree_contains(const struct Tree *const t, const void *const value) {
+ if (t->value == NULL) {
+ return false;
+ }
+
+ const int cmp = memcmp(value, t->value, t->value_size);
+ if (cmp == 0) {
+ return true;
+ } else if (cmp > 0) {
+ if (t->left == NULL) {
+ return false;
+ }
+ return tree_contains(t->left, value);
+ } else {
+ if (t->right == NULL) {
+ return false;
+ }
+ return tree_contains(t->right, value);
+ }
+}
diff --git a/src/tree.h b/src/tree.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tree.h