blob: eed3488e074a498c92db30407a75bb044923aa2d [file] [log] [blame]
Amit Pundird477f822020-02-07 22:26:08 +05301/*
2 * Copyright (c) 2008-2009, Courtney Cavin
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * - Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <stdlib.h>
28#include "map.h"
29
30struct map_entry {
31 struct map_item *item;
32};
33
34/* Marker for deleted items */
35static struct map_item deleted;
36
37void map_destroy(struct map *map)
38{
39 free(map->data);
40}
41
42void map_clear(struct map *map, void (*release)(struct map_item *))
43{
44 int i;
45
46 for (i = 0; i < map->size; ++i){
47 if (!map->data[i].item)
48 continue;
49 if (map->data[i].item != &deleted)
50 (* release)(map->data[i].item);
51 map->data[i].item = NULL;
52 }
53 map->count = 0;
54}
55
56int map_create(struct map *map)
57{
58 map->size = 0;
59 map->data = 0;
60 map->count = 0;
61 return 0;
62}
63
64static int map_hash(struct map *map, unsigned int key)
65{
66 struct map_entry *e;
67 int idx, i;
68
69 if (map->count == map->size)
70 return -1;
71
72 idx = key % map->size;
73
74 for (i = 0; i < map->size; ++i) {
75 e = &map->data[idx];
76 if (!e->item || e->item == &deleted) {
77 ++map->count;
78 return idx;
79 }
80 if (e->item->key == key)
81 return idx;
82
83 idx = (idx + 1) % map->size;
84 }
85
86 return -2;
87}
88
89static int map_rehash(struct map *map);
90
91int map_reput(struct map *map, unsigned int key, struct map_item *value,
92 struct map_item **old)
93{
94 int rc;
95
96 while ((rc = map_hash(map, key)) < 0) {
97 if ((rc = map_rehash(map)) < 0)
98 return rc;
99 }
100
101 if (old) {
102 if (map->data[rc].item == &deleted)
103 *old = NULL;
104 else
105 *old = map->data[rc].item;
106 }
107 map->data[rc].item = value;
108 if (value)
109 map->data[rc].item->key = key;
110
111 return 0;
112}
113
114int map_put(struct map *map, unsigned int key, struct map_item *value)
115{
116 return map_reput(map, key, value, NULL);
117}
118
119static int map_rehash(struct map *map)
120{
121 struct map_entry *oldt, *newt;
122 int o_size, i;
123 int rc;
124
125 newt = calloc(sizeof(struct map_entry), map->size + 256);
126 if (!newt)
127 return -1;
128
129 oldt = map->data;
130 map->data = newt;
131
132 o_size = map->size;
133 map->size += 256;
134 map->count = 0;
135
136 for (i = 0; i < o_size; ++i){
137 if (!oldt[i].item || oldt[i].item == &deleted)
138 continue;
139 rc = map_put(map, oldt[i].item->key, oldt[i].item);
140 if (rc < 0)
141 return rc;
142 }
143
144 free(oldt);
145
146 return 0;
147}
148
149static struct map_entry *map_find(const struct map *map, unsigned int key)
150{
151 struct map_entry *e;
152 int idx, i;
153
154 if (map->size == 0)
155 return NULL;
156
157 idx = key % map->size;
158
159 for (i = 0; i < map->size; ++i) {
160 e = &map->data[idx];
161 idx = (idx + 1) % map->size;
162
163 if (!e->item)
164 break;
165 if (e->item == &deleted)
166 continue;
167 if (e->item->key == key)
168 return e;
169 }
170 return NULL;
171}
172
173int map_contains(const struct map *map, unsigned int key)
174{
175 return (map_find(map, key) == NULL) ? 0 : 1;
176}
177
178struct map_item *map_get(const struct map *map, unsigned int key)
179{
180 struct map_entry *e;
181
182 e = map_find(map, key);
183 if (e == NULL)
184 return NULL;
185 return e->item;
186}
187
188int map_remove(struct map *map, unsigned int key)
189{
190 struct map_entry *e;
191
192 e = map_find(map, key);
193 if (e) {
194 e->item = &deleted;
195 --map->count;
196 }
197 return !e;
198}
199
200unsigned int map_length(struct map *map)
201{
202 return map ? map->count : 0;
203}
204
205static struct map_entry *map_iter_from(const struct map *map, unsigned int start)
206{
207 unsigned int i = start;
208
209 for (; i < map->size; ++i) {
210 if (map->data[i].item && map->data[i].item != &deleted)
211 return &map->data[i];
212 }
213 return NULL;
214}
215
216struct map_entry *map_iter_next(const struct map *map, struct map_entry *iter)
217{
218 if (iter == NULL)
219 return NULL;
220
221 return map_iter_from(map, (iter - map->data) + 1);
222}
223
224struct map_entry *map_iter_first(const struct map *map)
225{
226 return map_iter_from(map, 0);
227}
228
229
230struct map_item *map_iter_item(struct map_entry *iter)
231{
232 return iter->item;
233}