1 /* 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 28 struct 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 39 AIntMap* 40 aintMap_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 53 void 54 aintMap_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 68 int 69 aintMap_getCount( AIntMap* map ) 70 { 71 return map->size; 72 } 73 74 void* 75 aintMap_get( AIntMap* map, int key ) 76 { 77 return aintMap_getWithDefault(map, key, NULL); 78 } 79 80 void* 81 aintMap_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 96 static void 97 aintMap_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 124 void* 125 aintMap_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 150 FOUND: 151 result = map->values[index]; 152 map->values[index] = value; 153 return result; 154 } 155 156 157 void* 158 aintMap_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 174 FOUND: 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 189 void 190 aintMapIterator_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 199 int 200 aintMapIterator_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 223 void 224 aintMapIterator_done( AIntMapIterator* iter ) 225 { 226 AZERO(iter); 227 } 228