Merge pull request #64 from tpetazzoni/arm-neon-fix
[openal-soft.git] / common / uintmap.c
blobd3b5192366a9ba3bd060bde455c1b639df5e601c
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 low = 0;
47 ALsizei high = map->size - 1;
48 while(low < high)
50 ALsizei mid = low + (high-low)/2;
51 if(map->keys[mid] < key)
52 low = mid + 1;
53 else
54 high = mid;
56 if(map->keys[low] < key)
57 low++;
58 pos = low;
61 if(pos == map->size || map->keys[pos] != key)
63 if(map->size == map->limit)
65 WriteUnlock(&map->lock);
66 return AL_OUT_OF_MEMORY;
69 if(map->size == map->capacity)
71 ALuint *keys = NULL;
72 ALvoid **values;
73 ALsizei newcap, keylen;
75 newcap = (map->capacity ? (map->capacity<<1) : 4);
76 if(map->limit > 0 && newcap > map->limit)
77 newcap = map->limit;
78 if(newcap > map->capacity)
80 /* Round the memory size for keys up to a multiple of the
81 * pointer size.
83 keylen = newcap * sizeof(map->keys[0]);
84 keylen += sizeof(map->values[0]) - 1;
85 keylen -= keylen%sizeof(map->values[0]);
87 keys = al_malloc(16, keylen + newcap*sizeof(map->values[0]));
89 if(!keys)
91 WriteUnlock(&map->lock);
92 return AL_OUT_OF_MEMORY;
94 values = (ALvoid**)((ALbyte*)keys + keylen);
96 if(map->keys)
98 memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
99 memcpy(values, map->values, map->size*sizeof(map->values[0]));
101 al_free(map->keys);
102 map->keys = keys;
103 map->values = values;
104 map->capacity = newcap;
107 if(pos < map->size)
109 memmove(&map->keys[pos+1], &map->keys[pos],
110 (map->size-pos)*sizeof(map->keys[0]));
111 memmove(&map->values[pos+1], &map->values[pos],
112 (map->size-pos)*sizeof(map->values[0]));
114 map->size++;
116 map->keys[pos] = key;
117 map->values[pos] = value;
118 WriteUnlock(&map->lock);
120 return AL_NO_ERROR;
123 ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
125 ALvoid *ptr = NULL;
126 WriteLock(&map->lock);
127 if(map->size > 0)
129 ALsizei low = 0;
130 ALsizei high = map->size - 1;
131 while(low < high)
133 ALsizei mid = low + (high-low)/2;
134 if(map->keys[mid] < key)
135 low = mid + 1;
136 else
137 high = mid;
139 if(map->keys[low] == key)
141 ptr = map->values[low];
142 if(low < map->size-1)
144 memmove(&map->keys[low], &map->keys[low+1],
145 (map->size-1-low)*sizeof(map->keys[0]));
146 memmove(&map->values[low], &map->values[low+1],
147 (map->size-1-low)*sizeof(map->values[0]));
149 map->size--;
152 WriteUnlock(&map->lock);
153 return ptr;
156 ALvoid *RemoveUIntMapKeyNoLock(UIntMap *map, ALuint key)
158 if(map->size > 0)
160 ALsizei low = 0;
161 ALsizei high = map->size - 1;
162 while(low < high)
164 ALsizei mid = low + (high-low)/2;
165 if(map->keys[mid] < key)
166 low = mid + 1;
167 else
168 high = mid;
170 if(map->keys[low] == key)
172 ALvoid *ptr = map->values[low];
173 if(low < map->size-1)
175 memmove(&map->keys[low], &map->keys[low+1],
176 (map->size-1-low)*sizeof(map->keys[0]));
177 memmove(&map->values[low], &map->values[low+1],
178 (map->size-1-low)*sizeof(map->values[0]));
180 map->size--;
181 return ptr;
184 return NULL;
187 ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
189 ALvoid *ptr = NULL;
190 ReadLock(&map->lock);
191 if(map->size > 0)
193 ALsizei low = 0;
194 ALsizei high = map->size - 1;
195 while(low < high)
197 ALsizei mid = low + (high-low)/2;
198 if(map->keys[mid] < key)
199 low = mid + 1;
200 else
201 high = mid;
203 if(map->keys[low] == key)
204 ptr = map->values[low];
206 ReadUnlock(&map->lock);
207 return ptr;
210 ALvoid *LookupUIntMapKeyNoLock(UIntMap *map, ALuint key)
212 if(map->size > 0)
214 ALsizei low = 0;
215 ALsizei high = map->size - 1;
216 while(low < high)
218 ALsizei mid = low + (high-low)/2;
219 if(map->keys[mid] < key)
220 low = mid + 1;
221 else
222 high = mid;
224 if(map->keys[low] == key)
225 return map->values[low];
227 return NULL;