244 static void cx_kvl_reverse(struct cx_list_s *list) { |
244 static void cx_kvl_reverse(struct cx_list_s *list) { |
245 cx_kv_list *kv_list = (cx_kv_list*)list; |
245 cx_kv_list *kv_list = (cx_kv_list*)list; |
246 kv_list->list_methods->reverse(list); |
246 kv_list->list_methods->reverse(list); |
247 } |
247 } |
248 |
248 |
|
249 static void cx_kvl_list_iter_next(void *it) { |
|
250 struct cx_iterator_s *iter = it; |
|
251 if (iter->base.remove) { |
|
252 // remove the assigned key from the map before calling the actual function |
|
253 cx_kv_list *kv_list = iter->src_handle.m; |
|
254 cx_kv_list_update_destructors(kv_list); |
|
255 char *node = iter->elem_handle; |
|
256 CxHashKey *key = cx_kv_list_loc_key(kv_list, node + kv_list->list.loc_data); |
|
257 if (key->hash != 0) { |
|
258 kv_list->map_methods->remove(&kv_list->map->map_base.base, *key, NULL); |
|
259 } |
|
260 } |
|
261 iter->base.next_impl(it); |
|
262 } |
|
263 |
249 static struct cx_iterator_s cx_kvl_iterator( |
264 static struct cx_iterator_s cx_kvl_iterator( |
250 const struct cx_list_s *list, |
265 const struct cx_list_s *list, |
251 size_t index, |
266 size_t index, |
252 bool backward |
267 bool backward |
253 ) { |
268 ) { |
254 const cx_kv_list *kv_list = (const cx_kv_list*)list; |
269 const cx_kv_list *kv_list = (const cx_kv_list*)list; |
255 // TODO: cannot really forward, because mutating iterators must be able to remove the element |
270 struct cx_iterator_s iter = kv_list->list_methods->iterator(list, index, backward); |
256 return kv_list->list_methods->iterator(list, index, backward); |
271 iter.base.next_impl = iter.base.next; |
|
272 iter.base.next = cx_kvl_list_iter_next; |
|
273 return iter; |
257 } |
274 } |
258 |
275 |
259 static void cx_kvl_map_deallocate(struct cx_map_s *map) { |
276 static void cx_kvl_map_deallocate(struct cx_map_s *map) { |
260 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list; |
277 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list; |
261 kv_list->map_methods->deallocate(map); |
278 kv_list->map_methods->deallocate(map); |
377 next = *(char**)(next + kv_list->list.loc_next); |
394 next = *(char**)(next + kv_list->list.loc_next); |
378 if (next == NULL) break; |
395 if (next == NULL) break; |
379 key = cx_kv_list_loc_key(kv_list, next + kv_list->list.loc_data); |
396 key = cx_kv_list_loc_key(kv_list, next + kv_list->list.loc_data); |
380 if (key->hash != 0) break; |
397 if (key->hash != 0) break; |
381 } |
398 } |
|
399 |
|
400 // remove previous element if requested |
|
401 if (iter->base.remove) { |
|
402 iter->base.remove = false; |
|
403 cx_kv_list_update_destructors(kv_list); |
|
404 char *elem = iter->elem; |
|
405 char *elem_data = elem + kv_list->list.loc_data; |
|
406 CxHashKey *elem_key = cx_kv_list_loc_key(kv_list, elem_data); |
|
407 // key is guaranteed to exist because iterator only iterates over elems with a key |
|
408 kv_list->map_methods->remove(&kv_list->map->map_base.base, *elem_key, NULL); |
|
409 cx_invoke_advanced_destructor(&kv_list->list.base, elem_data); |
|
410 cx_linked_list_remove( |
|
411 &kv_list->list.begin, |
|
412 &kv_list->list.end, |
|
413 kv_list->list.loc_prev, |
|
414 kv_list->list.loc_next, |
|
415 elem |
|
416 ); |
|
417 cxFree(kv_list->list.base.collection.allocator, elem); |
|
418 kv_list->list.base.collection.size--; |
|
419 iter->index--; |
|
420 iter->elem_count--; |
|
421 } |
|
422 |
|
423 // advance to the next element, if any |
382 if (next == NULL) { |
424 if (next == NULL) { |
383 iter->index = kv_list->list.base.collection.size; |
425 iter->index = kv_list->list.base.collection.size; |
384 iter->elem = NULL; |
426 iter->elem = NULL; |
385 iter->entry = (CxMapEntry){NULL, NULL}; |
427 iter->entry = (CxMapEntry){NULL, NULL}; |
386 return; |
428 return; |
387 } |
429 } |
388 |
|
389 // TODO: implement removal |
|
390 |
|
391 // advance to the next element |
|
392 iter->index++; |
430 iter->index++; |
393 iter->elem = next; |
431 iter->elem = next; |
394 iter->entry.key = key; |
432 iter->entry.key = key; |
395 if (kv_list->list.base.collection.store_pointer) { |
433 if (kv_list->list.base.collection.store_pointer) { |
396 iter->entry.value = *(void**)(next + kv_list->list.loc_data); |
434 iter->entry.value = *(void**)(next + kv_list->list.loc_data); |