| 251 ) { |
251 ) { |
| 252 return cx_hash_map_get_remove(map, key, targetbuf, true); |
252 return cx_hash_map_get_remove(map, key, targetbuf, true); |
| 253 } |
253 } |
| 254 |
254 |
| 255 static void *cx_hash_map_iter_current_entry(const void *it) { |
255 static void *cx_hash_map_iter_current_entry(const void *it) { |
| 256 const struct cx_iterator_s *iter = it; |
256 const CxMapIterator *iter = it; |
| 257 // struct has to have a compatible signature |
257 // we have to cast away const, because of the signature |
| 258 return (struct cx_map_entry_s *) &(iter->kv_data); |
258 return (void*) &iter->entry; |
| 259 } |
259 } |
| 260 |
260 |
| 261 static void *cx_hash_map_iter_current_key(const void *it) { |
261 static void *cx_hash_map_iter_current_key(const void *it) { |
| 262 const struct cx_iterator_s *iter = it; |
262 const CxMapIterator *iter = it; |
| 263 struct cx_hash_map_element_s *elm = iter->elem_handle; |
263 struct cx_hash_map_element_s *elm = iter->elem; |
| 264 return &elm->key; |
264 return &elm->key; |
| 265 } |
265 } |
| 266 |
266 |
| 267 static void *cx_hash_map_iter_current_value(const void *it) { |
267 static void *cx_hash_map_iter_current_value(const void *it) { |
| 268 const struct cx_iterator_s *iter = it; |
268 const CxMapIterator *iter = it; |
| 269 const struct cx_hash_map_s *map = iter->src_handle.c; |
269 const CxMap *map = iter->map.c; |
| 270 struct cx_hash_map_element_s *elm = iter->elem_handle; |
270 struct cx_hash_map_element_s *elm = iter->elem; |
| 271 if (map->base.collection.store_pointer) { |
271 if (map->collection.store_pointer) { |
| 272 return *(void **) elm->data; |
272 return *(void **) elm->data; |
| 273 } else { |
273 } else { |
| 274 return elm->data; |
274 return elm->data; |
| 275 } |
275 } |
| 276 } |
276 } |
| 277 |
277 |
| 278 static bool cx_hash_map_iter_valid(const void *it) { |
278 static bool cx_hash_map_iter_valid(const void *it) { |
| 279 const struct cx_iterator_s *iter = it; |
279 const CxMapIterator *iter = it; |
| 280 return iter->elem_handle != NULL; |
280 return iter->elem != NULL; |
| 281 } |
281 } |
| 282 |
282 |
| 283 static void cx_hash_map_iter_next(void *it) { |
283 static void cx_hash_map_iter_next(void *it) { |
| 284 struct cx_iterator_s *iter = it; |
284 CxMapIterator *iter = it; |
| 285 struct cx_hash_map_element_s *elm = iter->elem_handle; |
285 CxMap *map = iter->map.m; |
| 286 struct cx_hash_map_s *map = iter->src_handle.m; |
286 struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map; |
| |
287 struct cx_hash_map_element_s *elm = iter->elem; |
| 287 |
288 |
| 288 // remove current element, if asked |
289 // remove current element, if asked |
| 289 if (iter->base.remove) { |
290 if (iter->base.remove) { |
| 290 |
291 |
| 291 // clear the flag |
292 // clear the flag |
| 294 // determine the next element |
295 // determine the next element |
| 295 struct cx_hash_map_element_s *next = elm->next; |
296 struct cx_hash_map_element_s *next = elm->next; |
| 296 |
297 |
| 297 // search the previous element |
298 // search the previous element |
| 298 struct cx_hash_map_element_s *prev = NULL; |
299 struct cx_hash_map_element_s *prev = NULL; |
| 299 if (map->buckets[iter->slot] != elm) { |
300 if (hmap->buckets[iter->slot] != elm) { |
| 300 prev = map->buckets[iter->slot]; |
301 prev = hmap->buckets[iter->slot]; |
| 301 while (prev->next != elm) { |
302 while (prev->next != elm) { |
| 302 prev = prev->next; |
303 prev = prev->next; |
| 303 } |
304 } |
| 304 } |
305 } |
| 305 |
306 |
| 306 // destroy |
307 // destroy |
| 307 cx_invoke_destructor((struct cx_map_s *) map, elm->data); |
308 cx_invoke_destructor(map, elm->data); |
| 308 |
309 |
| 309 // unlink |
310 // unlink |
| 310 cx_hash_map_unlink(map, iter->slot, prev, elm); |
311 cx_hash_map_unlink(hmap, iter->slot, prev, elm); |
| 311 |
312 |
| 312 // advance |
313 // advance |
| 313 elm = next; |
314 elm = next; |
| 314 } else { |
315 } else { |
| 315 // just advance |
316 // just advance |
| 316 elm = elm->next; |
317 elm = elm->next; |
| 317 iter->index++; |
318 iter->index++; |
| 318 } |
319 } |
| 319 |
320 |
| 320 // search the next bucket, if required |
321 // search the next bucket, if required |
| 321 while (elm == NULL && ++iter->slot < map->bucket_count) { |
322 while (elm == NULL && ++iter->slot < hmap->bucket_count) { |
| 322 elm = map->buckets[iter->slot]; |
323 elm = hmap->buckets[iter->slot]; |
| 323 } |
324 } |
| 324 |
325 iter->elem = elm; |
| 325 // fill the struct with the next element |
326 |
| 326 iter->elem_handle = elm; |
327 // copy data to a location where the iterator can point to |
| 327 if (elm == NULL) { |
328 // we need to do it here, because the iterator function call |
| 328 iter->kv_data.key = NULL; |
329 // must not modify the iterator (the parameter is const) |
| 329 iter->kv_data.value = NULL; |
330 if (elm != NULL) { |
| 330 } else { |
331 iter->entry.key = &elm->key; |
| 331 iter->kv_data.key = &elm->key; |
332 if (iter->map.c->collection.store_pointer) { |
| 332 if (map->base.collection.store_pointer) { |
333 iter->entry.value = *(void **) elm->data; |
| 333 iter->kv_data.value = *(void **) elm->data; |
|
| 334 } else { |
334 } else { |
| 335 iter->kv_data.value = elm->data; |
335 iter->entry.value = elm->data; |
| 336 } |
336 } |
| 337 } |
337 } |
| 338 } |
338 } |
| 339 |
339 |
| 340 static CxIterator cx_hash_map_iterator( |
340 static CxMapIterator cx_hash_map_iterator( |
| 341 const CxMap *map, |
341 const CxMap *map, |
| 342 enum cx_map_iterator_type type |
342 enum cx_map_iterator_type type |
| 343 ) { |
343 ) { |
| 344 CxIterator iter; |
344 CxMapIterator iter; |
| 345 |
345 |
| 346 iter.src_handle.c = map; |
346 iter.map.c = map; |
| 347 iter.elem_count = map->collection.size; |
347 iter.elem_count = map->collection.size; |
| 348 |
348 |
| 349 switch (type) { |
349 switch (type) { |
| 350 case CX_MAP_ITERATOR_PAIRS: |
350 case CX_MAP_ITERATOR_PAIRS: |
| 351 iter.elem_size = sizeof(CxMapEntry); |
351 iter.elem_size = sizeof(CxMapEntry); |
| 375 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
375 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
| 376 struct cx_hash_map_element_s *elm = hash_map->buckets[0]; |
376 struct cx_hash_map_element_s *elm = hash_map->buckets[0]; |
| 377 while (elm == NULL) { |
377 while (elm == NULL) { |
| 378 elm = hash_map->buckets[++iter.slot]; |
378 elm = hash_map->buckets[++iter.slot]; |
| 379 } |
379 } |
| 380 iter.elem_handle = elm; |
380 iter.elem = elm; |
| 381 iter.kv_data.key = &elm->key; |
381 iter.entry.key = &elm->key; |
| 382 if (map->collection.store_pointer) { |
382 if (map->collection.store_pointer) { |
| 383 iter.kv_data.value = *(void **) elm->data; |
383 iter.entry.value = *(void **) elm->data; |
| 384 } else { |
384 } else { |
| 385 iter.kv_data.value = elm->data; |
385 iter.entry.value = elm->data; |
| 386 } |
386 } |
| 387 } else { |
387 } else { |
| 388 iter.elem_handle = NULL; |
388 iter.elem = NULL; |
| 389 iter.kv_data.key = NULL; |
|
| 390 iter.kv_data.value = NULL; |
|
| 391 } |
389 } |
| 392 |
390 |
| 393 return iter; |
391 return iter; |
| 394 } |
392 } |
| 395 |
393 |