aboutsummaryrefslogtreecommitdiff
path: root/include/erofs/hashmap.h
blob: d25092d5081efc96d833fe1ddb6e5d68bbf846ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __EROFS_HASHMAP_H
#define __EROFS_HASHMAP_H

#ifdef __cplusplus
extern "C"
{
#endif

/* Copied from https://github.com/git/git.git */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "flex-array.h"

/*
 * Generic implementation of hash-based key-value mappings.
 * See Documentation/technical/api-hashmap.txt.
 */

/* FNV-1 functions */
unsigned int strhash(const char *str);
unsigned int strihash(const char *str);
unsigned int memhash(const void *buf, size_t len);
unsigned int memihash(const void *buf, size_t len);

static inline unsigned int sha1hash(const unsigned char *sha1)
{
	/*
	 * Equivalent to 'return *(unsigned int *)sha1;', but safe on
	 * platforms that don't support unaligned reads.
	 */
	unsigned int hash;

	memcpy(&hash, sha1, sizeof(hash));
	return hash;
}

/* data structures */
struct hashmap_entry {
	struct hashmap_entry *next;
	unsigned int hash;
};

typedef int (*hashmap_cmp_fn)(const void *entry, const void *entry_or_key,
		const void *keydata);

struct hashmap {
	struct hashmap_entry **table;
	hashmap_cmp_fn cmpfn;
	unsigned int size, tablesize, grow_at, shrink_at;
};

struct hashmap_iter {
	struct hashmap *map;
	struct hashmap_entry *next;
	unsigned int tablepos;
};

/* hashmap functions */
void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
		  size_t initial_size);
int hashmap_free(struct hashmap *map);

/* hashmap_entry functions */
static inline void hashmap_entry_init(void *entry, unsigned int hash)
{
	struct hashmap_entry *e = entry;

	e->hash = hash;
	e->next = NULL;
}

void *hashmap_get(const struct hashmap *map, const void *key, const void *keydata);
void *hashmap_get_next(const struct hashmap *map, const void *entry);
void hashmap_add(struct hashmap *map, void *entry);
void *hashmap_remove(struct hashmap *map, const void *key);

static inline void *hashmap_get_from_hash(const struct hashmap *map,
					  unsigned int hash,
					  const void *keydata)
{
	struct hashmap_entry key;

	hashmap_entry_init(&key, hash);
	return hashmap_get(map, &key, keydata);
}

/* hashmap_iter functions */
void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter);
void *hashmap_iter_next(struct hashmap_iter *iter);
static inline void *hashmap_iter_first(struct hashmap *map,
				       struct hashmap_iter *iter)
{
	hashmap_iter_init(map, iter);
	return hashmap_iter_next(iter);
}

/* string interning */
const void *memintern(const void *data, size_t len);
static inline const char *strintern(const char *string)
{
	return memintern(string, strlen(string));
}

#ifdef __cplusplus
}
#endif

#endif