diff options
Diffstat (limited to 'development/libs/libbowl/utils.c')
-rw-r--r-- | development/libs/libbowl/utils.c | 116 |
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; +} |