diff options
author | Paul Duncan <pabs@pablotron.org> | 2019-01-15 09:16:56 -0500 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2019-01-15 09:16:56 -0500 |
commit | 3e658ed87b5795b2be8f50d683dc19241aba0111 (patch) | |
tree | 0bc3b6e61e476e7ecdcb3c20429b159ea5465ae2 /src/core/sok-cache.c | |
parent | 914ca426630ccadcbb6f1ff02a599bdaf10b6cb2 (diff) | |
download | sok-3e658ed87b5795b2be8f50d683dc19241aba0111.tar.bz2 sok-3e658ed87b5795b2be8f50d683dc19241aba0111.zip |
s/libsok/core/g
Diffstat (limited to 'src/core/sok-cache.c')
-rw-r--r-- | src/core/sok-cache.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/core/sok-cache.c b/src/core/sok-cache.c new file mode 100644 index 0000000..df3c729 --- /dev/null +++ b/src/core/sok-cache.c @@ -0,0 +1,168 @@ +#include <stdbool.h> // bool +#include <stdint.h> // uint64_t +#include <stdlib.h> // bsearch(), qsort() +#include <string.h> // memcpy +#include <stdio.h> // debug +#include "sok.h" + +#define UNUSED(a) ((void) (a)) +#define GROW_SIZE (4096 / sizeof(uint64_t)) +#define USE_QSORT 1 + +static int +u64_cmp( + const void * const ap, + const void * const bp +) { + const uint64_t a = *((uint64_t*) ap), + b = *((uint64_t*) bp); + + return (a > b) ? -1 : ((a == b) ? 0 : 1); +} + +static bool +sok_cache_grow( + sok_cache_t * const cache +) { + // calculate new capacity + const size_t new_capacity = cache->capacity + GROW_SIZE; + if (new_capacity < cache->capacity) { + return false; + } + + // reallocate memory + uint64_t * const vals = realloc(cache->vals, new_capacity * sizeof(uint64_t)); + if (!vals) { + return false; + } + + // update data + cache->vals = vals; + cache->capacity = new_capacity; + + // return success + return true; +} + +static bool +sok_cache_has_hash( + const sok_cache_t * const cache, + const uint64_t hash +) { +#if 0 + for (size_t i = 0; i < cache->num_vals; i++) { + if (cache->vals[i] == hash) { + return true; + } + } + + // return failure + return false; +#else + return !!bsearch( + &hash, + cache->vals, + cache->num_vals, + sizeof(uint64_t), + u64_cmp + ); +#endif /* 0 */ +} + +bool +sok_cache_has( + const sok_cache_t * const cache, + const sok_ctx_t * const ctx +) { + return sok_cache_has_hash(cache, sok_ctx_hash(ctx)); +} + +bool +sok_cache_add( + sok_cache_t * const cache, + const sok_ctx_t * const ctx +) { +/* + * // hash context + * const uint64_t hash = sok_ctx_hash(ctx); + * + * // check for duplicates + * if (sok_cache_has_hash(cache, hash)) { + * return false; + * } + */ + + // check capacity + if (cache->num_vals >= cache->capacity) { + // grow cache + if (!sok_cache_grow(cache)) { + // return failure + return false; + } + } + + // append hash + const uint64_t hash = sok_ctx_hash(ctx); +#if USE_QSORT + cache->vals[cache->num_vals] = hash; + cache->num_vals++; + + // sort values + qsort(cache->vals, cache->num_vals, sizeof(uint64_t), u64_cmp); +#else + size_t i; + for (i = 0; cache->vals[i] < hash && i < cache->num_vals; i++); + if (i < cache->num_vals) { + if (cache->vals[i] == hash) { + return true; + } + + // move remaining data + const size_t num_bytes = (cache->num_vals - i) * sizeof(uint64_t); + memmove(cache->vals + (i + 1), cache->vals + i, num_bytes); + + // insert value + cache->vals[i] = hash; + cache->num_vals++; + } else { + // append value + cache->vals[cache->num_vals] = hash; + cache->num_vals++; + } +#endif /* USE_QSORT */ + + // return success + return true; +} + +bool +sok_cache_init( + sok_cache_t * const cache, + const size_t capacity +) { + // alloc memory, check for error + uint64_t * const vals = malloc(capacity * sizeof(uint64_t)); + if (!vals) { + // return failure + return false; + } + + // populate cache + cache->vals = vals; + cache->num_vals = 0; + cache->capacity = capacity; + + // return success + return true; +} + +void +sok_cache_fini( + sok_cache_t * const cache +) { + if (cache->vals) { + // free memory + free(cache->vals); + cache->vals = NULL; + } +} |