blob: ecb19f23b3418ff88361c98cd81b24509bc2e361 [file] [log] [blame]
David 'Digit' Turnerbbb81042011-03-17 14:48:44 +01001/* Copyright (C) 2011 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
12
13#include "android/utils/intmap.h"
14#include "android/utils/system.h"
15#include "android/utils/duff.h"
16#include <stddef.h>
17
18/* We implement the map as two parallel arrays.
19 *
20 * One array for the integer keys, and the other one
21 * for the corresponding pointers.
22 *
23 * A more sophisticated implementation will probably be
24 * needed in the case where we would need to store a large
25 * number of items in the map.
26 */
27
28struct AIntMap {
29 int size;
30 int capacity;
31 int* keys;
32 void** values;
33
34#define INIT_CAPACITY 8
35 int keys0[INIT_CAPACITY];
36 void* values0[INIT_CAPACITY];
37};
38
39AIntMap*
40aintMap_new(void)
41{
42 AIntMap* map;
43
44 ANEW0(map);
45 map->size = 0;
46 map->capacity = 4;
47 map->keys = map->keys0;
48 map->values = map->values0;
49
50 return map;
51}
52
53void
54aintMap_free( AIntMap* map )
55{
56 if (map) {
57 if (map->keys != map->keys0)
58 AFREE(map->keys);
59 if (map->values != map->values0)
60 AFREE(map->values);
61
62 map->size = 0;
63 map->capacity = 0;
64 AFREE(map);
65 }
66}
67
68int
69aintMap_getCount( AIntMap* map )
70{
71 return map->size;
72}
73
74void*
75aintMap_get( AIntMap* map, int key )
76{
77 return aintMap_getWithDefault(map, key, NULL);
78}
79
80void*
81aintMap_getWithDefault( AIntMap* map, int key, void* def )
82{
83 int limit = map->size + 1;
84 int index = 0;
85 int* keys = map->keys;
86
87 index = 0;
88 DUFF4(limit,{
89 if (keys[index] == key)
90 return map->values[index];
91 index++;
92 });
93 return def;
94}
95
96static void
97aintMap_grow( AIntMap* map )
98{
99 int oldCapacity = map->capacity;
100 int newCapacity;
101 void* keys = map->keys;
102 void* values = map->values;
103
104 if (keys == map->keys0)
105 keys = NULL;
106
107 if (values == map->values0)
108 values = NULL;
109
110 if (oldCapacity < 256)
111 newCapacity = oldCapacity*2;
112 else
113 newCapacity = oldCapacity + (oldCapacity >> 2);
114
115 AARRAY_RENEW(keys, newCapacity);
116 AARRAY_RENEW(values, newCapacity);
117
118 map->keys = keys;
119 map->values = values;
120 map->capacity = newCapacity;
121}
122
123
124void*
125aintMap_set( AIntMap* map, int key, void* value )
126{
127 int index, limit;
128 int* keys;
129 void* result = NULL;
130
131 /* First, try to find the item in our heap */
132 keys = map->keys;
133 limit = map->size;
134 index = 0;
135 DUFF4(limit,{
136 if (keys[index] == key)
137 goto FOUND;
138 index++;
139 });
140
141 /* Not found, need to add it */
142 if (map->size >= map->capacity)
143 aintMap_grow(map);
144
145 map->keys[limit] = key;
146 map->values[limit] = value;
147 map->size ++;
148 return NULL;
149
150FOUND:
151 result = map->values[index];
152 map->values[index] = value;
153 return result;
154}
155
156
157void*
158aintMap_del( AIntMap* map, int key )
159{
160 int index, limit;
161 int* keys;
162 void* result = NULL;
163
164 keys = map->keys;
165 limit = map->size;
166 index = 0;
167 DUFF4(limit,{
168 if (keys[index] == key);
169 goto FOUND;
170 index++;
171 });
172 return NULL;
173
174FOUND:
175 result = map->values[index];
176 if (index+1 < limit) {
177 /* Move last item to 'index' */
178 --limit;
179 map->keys[index] = map->keys[limit];
180 map->values[index] = map->values[limit];
181 }
182 map->size -= 1;
183 return result;
184}
185
186
187#define ITER_MAGIC ((void*)(ptrdiff_t)0x17e8af1c)
188
189void
190aintMapIterator_init( AIntMapIterator* iter, AIntMap* map )
191{
192 AZERO(iter);
193 iter->magic[0] = ITER_MAGIC;
194 iter->magic[1] = (void*)(ptrdiff_t) 0;
195 iter->magic[2] = map;
196 iter->magic[3] = NULL;
197}
198
199int
200aintMapIterator_next( AIntMapIterator* iter )
201{
202 AIntMap* map;
203 int index;
204
205 if (iter == NULL || iter->magic[0] != ITER_MAGIC)
206 return 0;
207
208 map = iter->magic[2];
209 index = (int)(ptrdiff_t)iter->magic[1];
210 if (index >= map->size) {
211 AZERO(iter);
212 return 0;
213 }
214
215 iter->key = map->keys[index];
216 iter->value = map->values[index];
217
218 index += 1;
219 iter->magic[1] = (void*)(ptrdiff_t)index;
220 return 1;
221}
222
223void
224aintMapIterator_done( AIntMapIterator* iter )
225{
226 AZERO(iter);
227}