aboutsummaryrefslogtreecommitdiffstats
path: root/common/uintmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/uintmap.c')
-rw-r--r--common/uintmap.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/common/uintmap.c b/common/uintmap.c
new file mode 100644
index 00000000..b7a9a29c
--- /dev/null
+++ b/common/uintmap.c
@@ -0,0 +1,144 @@
+
+#include "config.h"
+
+#include "uintmap.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+extern inline void LockUIntMapRead(UIntMap *map);
+extern inline void UnlockUIntMapRead(UIntMap *map);
+extern inline void LockUIntMapWrite(UIntMap *map);
+extern inline void UnlockUIntMapWrite(UIntMap *map);
+
+
+void InitUIntMap(UIntMap *map, ALsizei limit)
+{
+ map->array = NULL;
+ map->size = 0;
+ map->maxsize = 0;
+ map->limit = limit;
+ RWLockInit(&map->lock);
+}
+
+void ResetUIntMap(UIntMap *map)
+{
+ WriteLock(&map->lock);
+ free(map->array);
+ map->array = NULL;
+ map->size = 0;
+ map->maxsize = 0;
+ WriteUnlock(&map->lock);
+}
+
+ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
+{
+ ALsizei pos = 0;
+
+ WriteLock(&map->lock);
+ if(map->size > 0)
+ {
+ ALsizei low = 0;
+ ALsizei high = map->size - 1;
+ while(low < high)
+ {
+ ALsizei mid = low + (high-low)/2;
+ if(map->array[mid].key < key)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+ if(map->array[low].key < key)
+ low++;
+ pos = low;
+ }
+
+ if(pos == map->size || map->array[pos].key != key)
+ {
+ if(map->size == map->limit)
+ {
+ WriteUnlock(&map->lock);
+ return AL_OUT_OF_MEMORY;
+ }
+
+ if(map->size == map->maxsize)
+ {
+ ALvoid *temp = NULL;
+ ALsizei newsize;
+
+ newsize = (map->maxsize ? (map->maxsize<<1) : 4);
+ if(newsize >= map->maxsize)
+ temp = realloc(map->array, newsize*sizeof(map->array[0]));
+ if(!temp)
+ {
+ WriteUnlock(&map->lock);
+ return AL_OUT_OF_MEMORY;
+ }
+ map->array = temp;
+ map->maxsize = newsize;
+ }
+
+ if(pos < map->size)
+ memmove(&map->array[pos+1], &map->array[pos],
+ (map->size-pos)*sizeof(map->array[0]));
+ map->size++;
+ }
+ map->array[pos].key = key;
+ map->array[pos].value = value;
+ WriteUnlock(&map->lock);
+
+ return AL_NO_ERROR;
+}
+
+ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
+{
+ ALvoid *ptr = NULL;
+ WriteLock(&map->lock);
+ if(map->size > 0)
+ {
+ ALsizei low = 0;
+ ALsizei high = map->size - 1;
+ while(low < high)
+ {
+ ALsizei mid = low + (high-low)/2;
+ if(map->array[mid].key < key)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+ if(map->array[low].key == key)
+ {
+ ptr = map->array[low].value;
+ if(low < map->size-1)
+ memmove(&map->array[low], &map->array[low+1],
+ (map->size-1-low)*sizeof(map->array[0]));
+ map->size--;
+ }
+ }
+ WriteUnlock(&map->lock);
+ return ptr;
+}
+
+ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
+{
+ ALvoid *ptr = NULL;
+ ReadLock(&map->lock);
+ if(map->size > 0)
+ {
+ ALsizei low = 0;
+ ALsizei high = map->size - 1;
+ while(low < high)
+ {
+ ALsizei mid = low + (high-low)/2;
+ if(map->array[mid].key < key)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+ if(map->array[low].key == key)
+ ptr = map->array[low].value;
+ }
+ ReadUnlock(&map->lock);
+ return ptr;
+}