My personal project and infrastructure archive
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nomicon/development/libs/libbowl/utils.c

116 lines
2.5 KiB

#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;
}