src/hash_map.c

changeset 994
3603bdf4a78b
parent 989
8aa57a7fecc4
equal deleted inserted replaced
993:b642eca4b956 994:3603bdf4a78b
170 } 170 }
171 171
172 /** 172 /**
173 * Helper function to avoid code duplication. 173 * Helper function to avoid code duplication.
174 * 174 *
175 * If \p remove is true, and \p targetbuf is \c NULL, the element
176 * will be destroyed when found.
177 *
178 * If \p remove is true, and \p targetbuf is set, the element will
179 * be copied to that buffer and no destructor function is called.
180 *
181 * If \p remove is false, \p targetbuf must not be non-null and
182 * either the pointer, when the map is storing pointers, is copied
183 * to the target buffer, or a pointer to the stored object will
184 * be copied to the target buffer.
185 *
175 * @param map the map 186 * @param map the map
176 * @param key the key to look up 187 * @param key the key to look up
188 * @param targetbuf see description
177 * @param remove flag indicating whether the looked up entry shall be removed 189 * @param remove flag indicating whether the looked up entry shall be removed
178 * @param destroy flag indicating whether the destructor shall be invoked 190 * @return zero, if the key was found, non-zero otherwise
179 * @return a pointer to the value corresponding to the key or \c NULL
180 */ 191 */
181 static void *cx_hash_map_get_remove( 192 static int cx_hash_map_get_remove(
182 CxMap *map, 193 CxMap *map,
183 CxHashKey key, 194 CxHashKey key,
184 bool remove, 195 void *targetbuf,
185 bool destroy 196 bool remove
186 ) { 197 ) {
187 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; 198 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map;
188 199
189 unsigned hash = key.hash; 200 unsigned hash = key.hash;
190 if (hash == 0) { 201 if (hash == 0) {
196 struct cx_hash_map_element_s *elm = hash_map->buckets[slot]; 207 struct cx_hash_map_element_s *elm = hash_map->buckets[slot];
197 struct cx_hash_map_element_s *prev = NULL; 208 struct cx_hash_map_element_s *prev = NULL;
198 while (elm && elm->key.hash <= hash) { 209 while (elm && elm->key.hash <= hash) {
199 if (elm->key.hash == hash && elm->key.len == key.len) { 210 if (elm->key.hash == hash && elm->key.len == key.len) {
200 if (memcmp(elm->key.data, key.data, key.len) == 0) { 211 if (memcmp(elm->key.data, key.data, key.len) == 0) {
201 void *data = NULL; 212 if (remove) {
202 if (destroy) { 213 if (targetbuf == NULL) {
203 cx_invoke_destructor(map, elm->data); 214 cx_invoke_destructor(map, elm->data);
215 } else {
216 memcpy(targetbuf, elm->data, map->collection.elem_size);
217 }
218 cx_hash_map_unlink(hash_map, slot, prev, elm);
204 } else { 219 } else {
220 assert(targetbuf != NULL);
221 void *data = NULL;
205 if (map->collection.store_pointer) { 222 if (map->collection.store_pointer) {
206 data = *(void **) elm->data; 223 data = *(void **) elm->data;
207 } else { 224 } else {
208 data = elm->data; 225 data = elm->data;
209 } 226 }
227 memcpy(targetbuf, &data, sizeof(void *));
210 } 228 }
211 if (remove) { 229 return 0;
212 cx_hash_map_unlink(hash_map, slot, prev, elm);
213 }
214 return data;
215 } 230 }
216 } 231 }
217 prev = elm; 232 prev = elm;
218 elm = prev->next; 233 elm = prev->next;
219 } 234 }
220 235
221 return NULL; 236 return 1;
222 } 237 }
223 238
224 static void *cx_hash_map_get( 239 static void *cx_hash_map_get(
225 const CxMap *map, 240 const CxMap *map,
226 CxHashKey key 241 CxHashKey key
227 ) { 242 ) {
228 // we can safely cast, because we know the map stays untouched 243 // we can safely cast, because we know the map stays untouched
229 return cx_hash_map_get_remove((CxMap *) map, key, false, false); 244 void *ptr = NULL;
230 } 245 int found = cx_hash_map_get_remove((CxMap *) map, key, &ptr, false);
231 246 return found == 0 ? ptr : NULL;
232 static void *cx_hash_map_remove( 247 }
248
249 static int cx_hash_map_remove(
233 CxMap *map, 250 CxMap *map,
234 CxHashKey key, 251 CxHashKey key,
235 bool destroy 252 void *targetbuf
236 ) { 253 ) {
237 return cx_hash_map_get_remove(map, key, true, destroy); 254 return cx_hash_map_get_remove(map, key, targetbuf, true);
238 } 255 }
239 256
240 static void *cx_hash_map_iter_current_entry(const void *it) { 257 static void *cx_hash_map_iter_current_entry(const void *it) {
241 const struct cx_iterator_s *iter = it; 258 const struct cx_iterator_s *iter = it;
242 // struct has to have a compatible signature 259 // struct has to have a compatible signature

mercurial