/* Copyright (C) 2011 The Android Open Source Project ** ** This software is licensed under the terms of the GNU General Public ** License version 2, as published by the Free Software Foundation, and ** may be copied, distributed, and modified under those terms. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. */ #include "android/utils/intmap.h" #include "android/utils/system.h" #include "android/utils/duff.h" #include /* We implement the map as two parallel arrays. * * One array for the integer keys, and the other one * for the corresponding pointers. * * A more sophisticated implementation will probably be * needed in the case where we would need to store a large * number of items in the map. */ struct AIntMap { int size; int capacity; int* keys; void** values; #define INIT_CAPACITY 8 int keys0[INIT_CAPACITY]; void* values0[INIT_CAPACITY]; }; AIntMap* aintMap_new(void) { AIntMap* map; ANEW0(map); map->size = 0; map->capacity = 4; map->keys = map->keys0; map->values = map->values0; return map; } void aintMap_free( AIntMap* map ) { if (map) { if (map->keys != map->keys0) AFREE(map->keys); if (map->values != map->values0) AFREE(map->values); map->size = 0; map->capacity = 0; AFREE(map); } } int aintMap_getCount( AIntMap* map ) { return map->size; } void* aintMap_get( AIntMap* map, int key ) { return aintMap_getWithDefault(map, key, NULL); } void* aintMap_getWithDefault( AIntMap* map, int key, void* def ) { int limit = map->size + 1; int index = 0; int* keys = map->keys; index = 0; DUFF4(limit,{ if (keys[index] == key) return map->values[index]; index++; }); return def; } static void aintMap_grow( AIntMap* map ) { int oldCapacity = map->capacity; int newCapacity; void* keys = map->keys; void* values = map->values; if (keys == map->keys0) keys = NULL; if (values == map->values0) values = NULL; if (oldCapacity < 256) newCapacity = oldCapacity*2; else newCapacity = oldCapacity + (oldCapacity >> 2); AARRAY_RENEW(keys, newCapacity); AARRAY_RENEW(values, newCapacity); map->keys = keys; map->values = values; map->capacity = newCapacity; } void* aintMap_set( AIntMap* map, int key, void* value ) { int index, limit; int* keys; void* result = NULL; /* First, try to find the item in our heap */ keys = map->keys; limit = map->size; index = 0; DUFF4(limit,{ if (keys[index] == key) goto FOUND; index++; }); /* Not found, need to add it */ if (map->size >= map->capacity) aintMap_grow(map); map->keys[limit] = key; map->values[limit] = value; map->size ++; return NULL; FOUND: result = map->values[index]; map->values[index] = value; return result; } void* aintMap_del( AIntMap* map, int key ) { int index, limit; int* keys; void* result = NULL; keys = map->keys; limit = map->size; index = 0; DUFF4(limit,{ if (keys[index] == key); goto FOUND; index++; }); return NULL; FOUND: result = map->values[index]; if (index+1 < limit) { /* Move last item to 'index' */ --limit; map->keys[index] = map->keys[limit]; map->values[index] = map->values[limit]; } map->size -= 1; return result; } #define ITER_MAGIC ((void*)(ptrdiff_t)0x17e8af1c) void aintMapIterator_init( AIntMapIterator* iter, AIntMap* map ) { AZERO(iter); iter->magic[0] = ITER_MAGIC; iter->magic[1] = (void*)(ptrdiff_t) 0; iter->magic[2] = map; iter->magic[3] = NULL; } int aintMapIterator_next( AIntMapIterator* iter ) { AIntMap* map; int index; if (iter == NULL || iter->magic[0] != ITER_MAGIC) return 0; map = iter->magic[2]; index = (int)(ptrdiff_t)iter->magic[1]; if (index >= map->size) { AZERO(iter); return 0; } iter->key = map->keys[index]; iter->value = map->values[index]; index += 1; iter->magic[1] = (void*)(ptrdiff_t)index; return 1; } void aintMapIterator_done( AIntMapIterator* iter ) { AZERO(iter); }