aboutsummaryrefslogtreecommitdiff
path: root/development/libs/libbowl/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'development/libs/libbowl/utils.c')
-rw-r--r--development/libs/libbowl/utils.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/development/libs/libbowl/utils.c b/development/libs/libbowl/utils.c
new file mode 100644
index 000000000000..0979d07bd632
--- /dev/null
+++ b/development/libs/libbowl/utils.c
@@ -0,0 +1,116 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include "utils.h"
+
+#define DELTA 0x2
+#define OVERSHOOT 0x8
+
+err_t _array_rescale(void ***ptr, size_t *len, size_t use)
+{
+ CHECK(len, INVALID_PARAMS)
+ CHECK((use <= *len), INVALID_PARAMS)
+ CHECK(ptr, INVALID_PARAMS)
+
+ // This is a simple linear scale strategy
+ if ((int) (*len - OVERSHOOT) >= (int) (use + DELTA)) *len -= OVERSHOOT;
+ if (use + DELTA >= *len) *len += DELTA;
+
+ *ptr = realloc(*ptr, *len * sizeof(void *));
+ return OK;
+}
+
+err_t _array_search(void **ptr, size_t len, size_t *out, void *in)
+{
+ CHECK(ptr, INVALID_PARAMS)
+ CHECK(in, INVALID_PARAMS)
+ CHECK((len > 0), INVALID_PARAMS)
+ (*out) = -1;
+
+ for(int i = 0; i < len; i++)
+ if((*ptr) == in) (*out) = i;
+
+ return OK;
+}
+
+err_t _array_remove(void **ptr, size_t idx, size_t len, void **out)
+{
+ CHECK(ptr, INVALID_PARAMS)
+ CHECK((idx >= 0), INVALID_PARAMS)
+ CHECK((len > idx), INVALID_PARAMS)
+
+ if(out != NULL) (*out) = ptr[idx];
+ for(int i = idx + 1; idx < len; i++)
+ ptr[i - 1] = ptr[i];
+
+ return OK;
+}
+
+err_t _hash(char *str, size_t len, size_t *out)
+{
+ CHECK(str, INVALID_PARAMS)
+ CHECK((len > 0), INVALID_PARAMS)
+
+ // Implements the "murmur" non-cryptographic hash
+
+#define C1 0xcc9e2d51
+#define C2 0x1b873593
+#define N 0xe6546b64
+#define M 5
+#define C3 0x85ebca6b
+#define C4 0xc2b2ae35
+#define R1 15
+#define R2 13
+#define R3 16
+#define R4 13
+#define ROTL32(v, shift) ( ((v) << (shift)) | ( (v) >> (32 - (shift))) )
+
+ size_t key_len = strlen(str);
+ int l = (int) key_len / 4;
+ uint32_t seed = 0xAF172FE;
+ int i = 0;
+
+ uint32_t k = 0;
+ uint32_t h = seed;
+ uint8_t *d = (uint8_t *) str;
+ const uint32_t *chunks = (const uint32_t *)(d + l * 4);
+ const uint8_t *tail = (const uint8_t *)(d + l * 4);
+
+ for (i = -l; i != 0; ++i) {
+ k = chunks[i];
+ k *= C1;
+ k = ROTL32(k, R1);
+ k *= C2;
+ h ^= k;
+ h = ROTL32(k, R2);
+ h = h * M + N;
+ }
+
+ k = 0;
+ switch(key_len & 3) {
+ case 3:
+ k ^= (tail[2] << 16);
+ case 2:
+ k ^= (tail[1] << 8);
+ case 1:
+ k ^= tail[0];
+ k *= C1;
+ k = ROTL32(k, R1);
+ k *= C2;
+ h ^= k;
+ default: break;
+ }
+
+ /* Finalised hash */
+ h ^= key_len;
+ h ^= (h >> R3);
+ h *= C3;
+ h ^= (h >> R4);
+ h *= C4;
+ h ^= (h >> R3);
+
+ /* Finalise ✨ */
+ h %= len;
+ *out = (size_t) h;
+ return OK;
+}