Merge pull request #184 from hhyyrylainen/master
[openal-soft.git] / common / uintmap.c
blob18d52d64b57b1eb0b6e64eb6910612373ff12caa
2 #include "config.h"
4 #include "uintmap.h"
6 #include <stdlib.h>
7 #include <string.h>
9 #include "almalloc.h"
12 extern inline void LockUIntMapRead(UIntMap *map);
13 extern inline void UnlockUIntMapRead(UIntMap *map);
14 extern inline void LockUIntMapWrite(UIntMap *map);
15 extern inline void UnlockUIntMapWrite(UIntMap *map);
18 void InitUIntMap(UIntMap *map, ALsizei limit)
20 map->keys = NULL;
21 map->values = NULL;
22 map->size = 0;
23 map->capacity = 0;
24 map->limit = limit;
25 RWLockInit(&map->lock);
28 void ResetUIntMap(UIntMap *map)
30 WriteLock(&map->lock);
31 al_free(map->keys);
32 map->keys = NULL;
33 map->values = NULL;
34 map->size = 0;
35 map->capacity = 0;
36 WriteUnlock(&map->lock);
39 ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
41 ALsizei pos = 0;
43 WriteLock(&map->lock);
44 if(map->size > 0)
46 ALsizei count = map->size;
47 do {
48 ALsizei step = count>>1;
49 ALsizei i = pos+step;
50 if(!(map->keys[i] < key))
51 count = step;
52 else
54 pos = i+1;
55 count -= step+1;
57 } while(count > 0);
60 if(pos == map->size || map->keys[pos] != key)
62 if(map->size >= map->limit)
64 WriteUnlock(&map->lock);
65 return AL_OUT_OF_MEMORY;
68 if(map->size == map->capacity)
70 ALuint *keys = NULL;
71 ALvoid **values;
72 ALsizei newcap, keylen;
74 newcap = (map->capacity ? (map->capacity<<1) : 4);
75 if(map->limit > 0 && newcap > map->limit)
76 newcap = map->limit;
77 if(newcap > map->capacity)
79 /* Round the memory size for keys up to a multiple of the
80 * pointer size.
82 keylen = newcap * sizeof(map->keys[0]);
83 keylen += sizeof(map->values[0]) - 1;
84 keylen -= keylen%sizeof(map->values[0]);
86 keys = al_malloc(16, keylen + newcap*sizeof(map->values[0]));
88 if(!keys)
90 WriteUnlock(&map->lock);
91 return AL_OUT_OF_MEMORY;
93 values = (ALvoid**)((ALbyte*)keys + keylen);
95 if(map->keys)
97 memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
98 memcpy(values, map->values, map->size*sizeof(map->values[0]));
100 al_free(map->keys);
101 map->keys = keys;
102 map->values = values;
103 map->capacity = newcap;
106 if(pos < map->size)
108 memmove(&map->keys[pos+1], &map->keys[pos],
109 (map->size-pos)*sizeof(map->keys[0]));
110 memmove(&map->values[pos+1], &map->values[pos],
111 (map->size-pos)*sizeof(map->values[0]));
113 map->size++;
115 map->keys[pos] = key;
116 map->values[pos] = value;
117 WriteUnlock(&map->lock);
119 return AL_NO_ERROR;
122 ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
124 ALvoid *ptr = NULL;
125 WriteLock(&map->lock);
126 if(map->size > 0)
128 ALsizei pos = 0;
129 ALsizei count = map->size;
130 do {
131 ALsizei step = count>>1;
132 ALsizei i = pos+step;
133 if(!(map->keys[i] < key))
134 count = step;
135 else
137 pos = i+1;
138 count -= step+1;
140 } while(count > 0);
141 if(pos < map->size && map->keys[pos] == key)
143 ptr = map->values[pos];
144 if(pos < map->size-1)
146 memmove(&map->keys[pos], &map->keys[pos+1],
147 (map->size-1-pos)*sizeof(map->keys[0]));
148 memmove(&map->values[pos], &map->values[pos+1],
149 (map->size-1-pos)*sizeof(map->values[0]));
151 map->size--;
154 WriteUnlock(&map->lock);
155 return ptr;
158 ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
160 ALvoid *ptr = NULL;
161 ReadLock(&map->lock);
162 if(map->size > 0)
164 ALsizei pos = 0;
165 ALsizei count = map->size;
166 do {
167 ALsizei step = count>>1;
168 ALsizei i = pos+step;
169 if(!(map->keys[i] < key))
170 count = step;
171 else
173 pos = i+1;
174 count -= step+1;
176 } while(count > 0);
177 if(pos < map->size && map->keys[pos] == key)
178 ptr = map->values[pos];
180 ReadUnlock(&map->lock);
181 return ptr;