--- a/src/kv_list.c Sun Sep 21 18:42:18 2025 +0200 +++ b/src/kv_list.c Sun Sep 21 19:31:30 2025 +0200 @@ -246,14 +246,31 @@ kv_list->list_methods->reverse(list); } +static void cx_kvl_list_iter_next(void *it) { + struct cx_iterator_s *iter = it; + if (iter->base.remove) { + // remove the assigned key from the map before calling the actual function + cx_kv_list *kv_list = iter->src_handle.m; + cx_kv_list_update_destructors(kv_list); + char *node = iter->elem_handle; + CxHashKey *key = cx_kv_list_loc_key(kv_list, node + kv_list->list.loc_data); + if (key->hash != 0) { + kv_list->map_methods->remove(&kv_list->map->map_base.base, *key, NULL); + } + } + iter->base.next_impl(it); +} + static struct cx_iterator_s cx_kvl_iterator( const struct cx_list_s *list, size_t index, bool backward ) { const cx_kv_list *kv_list = (const cx_kv_list*)list; - // TODO: cannot really forward, because mutating iterators must be able to remove the element - return kv_list->list_methods->iterator(list, index, backward); + struct cx_iterator_s iter = kv_list->list_methods->iterator(list, index, backward); + iter.base.next_impl = iter.base.next; + iter.base.next = cx_kvl_list_iter_next; + return iter; } static void cx_kvl_map_deallocate(struct cx_map_s *map) { @@ -379,16 +396,37 @@ key = cx_kv_list_loc_key(kv_list, next + kv_list->list.loc_data); if (key->hash != 0) break; } + + // remove previous element if requested + if (iter->base.remove) { + iter->base.remove = false; + cx_kv_list_update_destructors(kv_list); + char *elem = iter->elem; + char *elem_data = elem + kv_list->list.loc_data; + CxHashKey *elem_key = cx_kv_list_loc_key(kv_list, elem_data); + // key is guaranteed to exist because iterator only iterates over elems with a key + kv_list->map_methods->remove(&kv_list->map->map_base.base, *elem_key, NULL); + cx_invoke_advanced_destructor(&kv_list->list.base, elem_data); + cx_linked_list_remove( + &kv_list->list.begin, + &kv_list->list.end, + kv_list->list.loc_prev, + kv_list->list.loc_next, + elem + ); + cxFree(kv_list->list.base.collection.allocator, elem); + kv_list->list.base.collection.size--; + iter->index--; + iter->elem_count--; + } + + // advance to the next element, if any if (next == NULL) { iter->index = kv_list->list.base.collection.size; iter->elem = NULL; iter->entry = (CxMapEntry){NULL, NULL}; return; } - - // TODO: implement removal - - // advance to the next element iter->index++; iter->elem = next; iter->entry.key = key;