aboutsummaryrefslogtreecommitdiff
path: root/src/hashtable.h
blob: 03a1f5a998e373cd9976924221726369c6f789be (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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
 * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the MIT license. See LICENSE for details.
 */

#ifndef HASHTABLE_H
#define HASHTABLE_H

#include "jansson.h"
#include <stdlib.h>

struct hashtable_list {
    struct hashtable_list *prev;
    struct hashtable_list *next;
};

/* "pair" may be a bit confusing a name, but think of it as a
   key-value pair. In this case, it just encodes some extra data,
   too */
struct hashtable_pair {
    struct hashtable_list list;
    struct hashtable_list ordered_list;
    size_t hash;
    json_t *value;
    size_t key_len;
    char key[1];
};

struct hashtable_bucket {
    struct hashtable_list *first;
    struct hashtable_list *last;
};

typedef struct hashtable {
    size_t size;
    struct hashtable_bucket *buckets;
    size_t order; /* hashtable has pow(2, order) buckets */
    struct hashtable_list list;
    struct hashtable_list ordered_list;
} hashtable_t;

#define hashtable_key_to_iter(key_)                                                      \
    (&(container_of(key_, struct hashtable_pair, key)->ordered_list))

/**
 * hashtable_init - Initialize a hashtable object
 *
 * @hashtable: The (statically allocated) hashtable object
 *
 * Initializes a statically allocated hashtable object. The object
 * should be cleared with hashtable_close when it's no longer used.
 *
 * Returns 0 on success, -1 on error (out of memory).
 */
int hashtable_init(hashtable_t *hashtable) JANSSON_ATTRS((warn_unused_result));

/**
 * hashtable_close - Release all resources used by a hashtable object
 *
 * @hashtable: The hashtable
 *
 * Destroys a statically allocated hashtable object.
 */
void hashtable_close(hashtable_t *hashtable);

/**
 * hashtable_set - Add/modify value in hashtable
 *
 * @hashtable: The hashtable object
 * @key: The key
 * @key: The length of key
 * @serial: For addition order of keys
 * @value: The value
 *
 * If a value with the given key already exists, its value is replaced
 * with the new value. Value is "stealed" in the sense that hashtable
 * doesn't increment its refcount but decreases the refcount when the
 * value is no longer needed.
 *
 * Returns 0 on success, -1 on failure (out of memory).
 */
int hashtable_set(hashtable_t *hashtable, const char *key, size_t key_len, json_t *value);

/**
 * hashtable_get - Get a value associated with a key
 *
 * @hashtable: The hashtable object
 * @key: The key
 * @key: The length of key
 *
 * Returns value if it is found, or NULL otherwise.
 */
void *hashtable_get(hashtable_t *hashtable, const char *key, size_t key_len);

/**
 * hashtable_del - Remove a value from the hashtable
 *
 * @hashtable: The hashtable object
 * @key: The key
 * @key: The length of key
 *
 * Returns 0 on success, or -1 if the key was not found.
 */
int hashtable_del(hashtable_t *hashtable, const char *key, size_t key_len);

/**
 * hashtable_clear - Clear hashtable
 *
 * @hashtable: The hashtable object
 *
 * Removes all items from the hashtable.
 */
void hashtable_clear(hashtable_t *hashtable);

/**
 * hashtable_iter - Iterate over hashtable
 *
 * @hashtable: The hashtable object
 *
 * Returns an opaque iterator to the first element in the hashtable.
 * The iterator should be passed to hashtable_iter_* functions.
 * The hashtable items are not iterated over in any particular order.
 *
 * There's no need to free the iterator in any way. The iterator is
 * valid as long as the item that is referenced by the iterator is not
 * deleted. Other values may be added or deleted. In particular,
 * hashtable_iter_next() may be called on an iterator, and after that
 * the key/value pair pointed by the old iterator may be deleted.
 */
void *hashtable_iter(hashtable_t *hashtable);

/**
 * hashtable_iter_at - Return an iterator at a specific key
 *
 * @hashtable: The hashtable object
 * @key: The key that the iterator should point to
 * @key: The length of key
 *
 * Like hashtable_iter() but returns an iterator pointing to a
 * specific key.
 */
void *hashtable_iter_at(hashtable_t *hashtable, const char *key, size_t key_len);

/**
 * hashtable_iter_next - Advance an iterator
 *
 * @hashtable: The hashtable object
 * @iter: The iterator
 *
 * Returns a new iterator pointing to the next element in the
 * hashtable or NULL if the whole hastable has been iterated over.
 */
void *hashtable_iter_next(hashtable_t *hashtable, void *iter);

/**
 * hashtable_iter_key - Retrieve the key pointed by an iterator
 *
 * @iter: The iterator
 */
void *hashtable_iter_key(void *iter);

/**
 * hashtable_iter_key_len - Retrieve the key length pointed by an iterator
 *
 * @iter: The iterator
 */
size_t hashtable_iter_key_len(void *iter);

/**
 * hashtable_iter_value - Retrieve the value pointed by an iterator
 *
 * @iter: The iterator
 */
void *hashtable_iter_value(void *iter);

/**
 * hashtable_iter_set - Set the value pointed by an iterator
 *
 * @iter: The iterator
 * @value: The value to set
 */
void hashtable_iter_set(void *iter, json_t *value);

#endif