1 /*
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
30 struct map_entry {
31 struct map_item *item;
32 };
33
34 /* Marker for deleted items */
35 static struct map_item deleted;
36
map_destroy(struct map * map)37 void map_destroy(struct map *map)
38 {
39 free(map->data);
40 }
41
map_clear(struct map * map,void (* release)(struct map_item *))42 void 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
map_create(struct map * map)56 int map_create(struct map *map)
57 {
58 map->size = 0;
59 map->data = 0;
60 map->count = 0;
61 return 0;
62 }
63
map_hash(struct map * map,unsigned int key)64 static 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
89 static int map_rehash(struct map *map);
90
map_reput(struct map * map,unsigned int key,struct map_item * value,struct map_item ** old)91 int 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
map_put(struct map * map,unsigned int key,struct map_item * value)114 int map_put(struct map *map, unsigned int key, struct map_item *value)
115 {
116 return map_reput(map, key, value, NULL);
117 }
118
map_rehash(struct map * map)119 static 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
map_find(const struct map * map,unsigned int key)149 static 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
map_contains(const struct map * map,unsigned int key)173 int map_contains(const struct map *map, unsigned int key)
174 {
175 return (map_find(map, key) == NULL) ? 0 : 1;
176 }
177
map_get(const struct map * map,unsigned int key)178 struct 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
map_remove(struct map * map,unsigned int key)188 int 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
map_length(struct map * map)200 unsigned int map_length(struct map *map)
201 {
202 return map ? map->count : 0;
203 }
204
map_iter_from(const struct map * map,unsigned int start)205 static 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
map_iter_next(const struct map * map,struct map_entry * iter)216 struct 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
map_iter_first(const struct map * map)224 struct map_entry *map_iter_first(const struct map *map)
225 {
226 return map_iter_from(map, 0);
227 }
228
229
map_iter_item(struct map_entry * iter)230 struct map_item *map_iter_item(struct map_entry *iter)
231 {
232 return iter->item;
233 }
234