Updated hashmap.c

This commit is contained in:
CPunch 2022-08-02 11:19:29 -05:00
parent fab6c5b4f6
commit 10a36df090
2 changed files with 69 additions and 36 deletions

View File

@ -1,3 +1,4 @@
// https://github.com/tidwall/hashmap.c
// Copyright 2020 Joshua J Baker. All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
@ -11,44 +12,32 @@
struct hashmap;
struct hashmap *hashmap_new(size_t elsize, size_t cap,
uint64_t seed0, uint64_t seed1,
uint64_t (*hash)(const void *item,
uint64_t seed0, uint64_t seed1),
int (*compare)(const void *a, const void *b,
void *udata),
void (*elfree)(void *item),
void *udata);
struct hashmap *hashmap_new_with_allocator(
void *(*malloc)(size_t),
void *(*realloc)(void *, size_t),
void (*free)(void*),
size_t elsize, size_t cap,
uint64_t seed0, uint64_t seed1,
uint64_t (*hash)(const void *item,
uint64_t seed0, uint64_t seed1),
int (*compare)(const void *a, const void *b,
void *udata),
void (*elfree)(void *item),
void *udata);
struct hashmap *hashmap_new(size_t elsize, size_t cap, uint64_t seed0, uint64_t seed1,
uint64_t (*hash)(const void *item, uint64_t seed0, uint64_t seed1),
int (*compare)(const void *a, const void *b, void *udata),
void (*elfree)(void *item), void *udata);
struct hashmap *
hashmap_new_with_allocator(void *(*malloc)(size_t), void *(*realloc)(void *, size_t),
void (*free)(void *), size_t elsize, size_t cap, uint64_t seed0,
uint64_t seed1,
uint64_t (*hash)(const void *item, uint64_t seed0, uint64_t seed1),
int (*compare)(const void *a, const void *b, void *udata),
void (*elfree)(void *item), void *udata);
void hashmap_free(struct hashmap *map);
void hashmap_clear(struct hashmap *map, bool update_cap);
size_t hashmap_count(struct hashmap *map);
bool hashmap_oom(struct hashmap *map);
void *hashmap_get(struct hashmap *map, const void *item);
void *hashmap_set(struct hashmap *map, void *item);
void *hashmap_set(struct hashmap *map, const void *item);
void *hashmap_delete(struct hashmap *map, void *item);
void *hashmap_probe(struct hashmap *map, uint64_t position);
bool hashmap_scan(struct hashmap *map,
bool (*iter)(const void *item, void *udata), void *udata);
uint64_t hashmap_sip(const void *data, size_t len,
uint64_t seed0, uint64_t seed1);
uint64_t hashmap_murmur(const void *data, size_t len,
uint64_t seed0, uint64_t seed1);
bool hashmap_scan(struct hashmap *map, bool (*iter)(const void *item, void *udata), void *udata);
bool hashmap_iter(struct hashmap *map, size_t *i, void **item);
uint64_t hashmap_sip(const void *data, size_t len, uint64_t seed0, uint64_t seed1);
uint64_t hashmap_murmur(const void *data, size_t len, uint64_t seed0, uint64_t seed1);
// DEPRECATED: use `hashmap_new_with_allocator`
void hashmap_set_allocator(void *(*malloc)(size_t), void (*free)(void*));
void hashmap_set_allocator(void *(*malloc)(size_t), void (*free)(void *));
#endif

58
lib/vendor/hashmap.c vendored
View File

@ -2,13 +2,14 @@
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include "hashmap.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void *(*_malloc)(size_t) = NULL;
static void *(*_realloc)(void *, size_t) = NULL;
static void (*_free)(void *) = NULL;
@ -23,7 +24,7 @@ void hashmap_set_allocator(void *(*malloc)(size_t), void (*free)(void*))
}
#define panic(_msg_) { \
/*fprintf(stderr, "panic: %s (%s:%d)\n", (_msg_), __FILE__, __LINE__);*/ \
fprintf(stderr, "panic: %s (%s:%d)\n", (_msg_), __FILE__, __LINE__); \
exit(1); \
}
@ -248,7 +249,7 @@ static bool resize(struct hashmap *map, size_t new_cap) {
// replaced then it is returned otherwise NULL is returned. This operation
// may allocate memory. If the system is unable to allocate additional
// memory then NULL is returned and hashmap_oom() returns true.
void *hashmap_set(struct hashmap *map, void *item) {
void *hashmap_set(struct hashmap *map, const void *item) {
if (!item) {
panic("item is null");
}
@ -408,6 +409,42 @@ bool hashmap_scan(struct hashmap *map,
return true;
}
// hashmap_iter iterates one key at a time yielding a reference to an
// entry at each iteration. Useful to write simple loops and avoid writing
// dedicated callbacks and udata structures, as in hashmap_scan.
//
// map is a hash map handle. i is a pointer to a size_t cursor that
// should be initialized to 0 at the beginning of the loop. item is a void
// pointer pointer that is populated with the retrieved item. Note that this
// is NOT a copy of the item stored in the hash map and can be directly
// modified.
//
// Note that if hashmap_delete() is called on the hashmap being iterated,
// the buckets are rearranged and the iterator must be reset to 0, otherwise
// unexpected results may be returned after deletion.
//
// This function has not been tested for thread safety.
//
// The function returns true if an item was retrieved; false if the end of the
// iteration has been reached.
bool hashmap_iter(struct hashmap *map, size_t *i, void **item)
{
struct bucket *bucket;
do {
if (*i >= map->nbuckets) return false;
bucket = bucket_at(map, *i);
(*i)++;
} while (!bucket->dib);
*item = bucket_item(bucket);
return true;
}
//-----------------------------------------------------------------------------
// SipHash reference C implementation
//
@ -738,6 +775,13 @@ static void all() {
while (!(vals2 = xmalloc(N * sizeof(int)))) {}
memset(vals2, 0, N * sizeof(int));
assert(hashmap_scan(map, iter_ints, &vals2));
// Test hashmap_iter. This does the same as hashmap_scan above.
size_t iter = 0;
void *iter_val;
while (hashmap_iter (map, &iter, &iter_val)) {
assert (iter_ints(iter_val, &vals2));
}
for (int i = 0; i < N; i++) {
assert(vals2[i] == 1);
}