diff -r 545010bc5e71 -r 22eca559aded src/ucx/hash_map.c --- a/src/ucx/hash_map.c Sun Nov 20 12:43:44 2022 +0100 +++ b/src/ucx/hash_map.c Sat Nov 26 17:07:08 2022 +0100 @@ -201,34 +201,42 @@ return cx_hash_map_get_remove(map, key, true); } -static void *cx_hash_map_iter_current_entry(CxIterator const *iter) { +static void *cx_hash_map_iter_current_entry(void const *it) { + struct cx_iterator_s const *iter = it; // struct has to have a compatible signature return (struct cx_map_entry_s *) &(iter->kv_data); } -static void *cx_hash_map_iter_current_key(CxIterator const *iter) { +static void *cx_hash_map_iter_current_key(void const *it) { + struct cx_iterator_s const *iter = it; struct cx_hash_map_element_s *elm = iter->elem_handle; return &elm->key; } -static void *cx_hash_map_iter_current_value(CxIterator const *iter) { +static void *cx_hash_map_iter_current_value(void const *it) { + struct cx_iterator_s const *iter = it; struct cx_hash_map_element_s *elm = iter->elem_handle; // TODO: return a pointer to data if this map is storing copies return elm->data; } -static bool cx_hash_map_iter_valid(CxIterator const *iter) { +static bool cx_hash_map_iter_valid(void const *it) { + struct cx_iterator_s const *iter = it; return iter->elem_handle != NULL; } -static void cx_hash_map_iter_next(CxIterator *iter) { - struct cx_hash_map_s *map = iter->src_handle; +static void cx_hash_map_iter_next(void *it) { + struct cx_iterator_s *iter = it; struct cx_hash_map_element_s *elm = iter->elem_handle; // remove current element, if asked - if (iter->remove) { + if (iter->base.remove) { + // obtain mutable pointer to the map + struct cx_mut_iterator_s *miter = it; + struct cx_hash_map_s *map = miter->src_handle; + // clear the flag - iter->remove = false; + iter->base.remove = false; // determine the next element struct cx_hash_map_element_s *next = elm->next; @@ -254,6 +262,7 @@ } // search the next bucket, if required + struct cx_hash_map_s const *map = iter->src_handle; while (elm == NULL && ++iter->slot < map->bucket_count) { elm = map->buckets[iter->slot]; } @@ -270,17 +279,29 @@ } } -static CxIterator cx_hash_map_iterator(CxMap *map) { +static bool cx_hash_map_iter_flag_rm(void *it) { + struct cx_iterator_base_s *iter = it; + if (iter->mutating) { + iter->remove = true; + return true; + } else { + return false; + } +} + +static CxIterator cx_hash_map_iterator(CxMap const *map) { CxIterator iter; iter.src_handle = map; - iter.valid = cx_hash_map_iter_valid; - iter.next = cx_hash_map_iter_next; - iter.current = cx_hash_map_iter_current_entry; + iter.base.valid = cx_hash_map_iter_valid; + iter.base.next = cx_hash_map_iter_next; + iter.base.current = cx_hash_map_iter_current_entry; + iter.base.flag_removal = cx_hash_map_iter_flag_rm; + iter.base.remove = false; + iter.base.mutating = false; iter.slot = 0; iter.index = 0; - iter.remove = false; if (map->size > 0) { struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; @@ -301,15 +322,37 @@ return iter; } -static CxIterator cx_hash_map_iterator_keys(CxMap *map) { +static CxIterator cx_hash_map_iterator_keys(CxMap const *map) { CxIterator iter = cx_hash_map_iterator(map); - iter.current = cx_hash_map_iter_current_key; + iter.base.current = cx_hash_map_iter_current_key; + return iter; +} + +static CxIterator cx_hash_map_iterator_values(CxMap const *map) { + CxIterator iter = cx_hash_map_iterator(map); + iter.base.current = cx_hash_map_iter_current_value; return iter; } -static CxIterator cx_hash_map_iterator_values(CxMap *map) { - CxIterator iter = cx_hash_map_iterator(map); - iter.current = cx_hash_map_iter_current_value; +static CxMutIterator cx_hash_map_mut_iterator(CxMap *map) { + CxIterator it = cx_hash_map_iterator(map); + it.base.mutating = true; + + // we know the iterators share the same memory layout + CxMutIterator iter; + memcpy(&iter, &it, sizeof(CxMutIterator)); + return iter; +} + +static CxMutIterator cx_hash_map_mut_iterator_keys(CxMap *map) { + CxMutIterator iter = cx_hash_map_mut_iterator(map); + iter.base.current = cx_hash_map_iter_current_key; + return iter; +} + +static CxMutIterator cx_hash_map_mut_iterator_values(CxMap *map) { + CxMutIterator iter = cx_hash_map_mut_iterator(map); + iter.base.current = cx_hash_map_iter_current_value; return iter; } @@ -322,6 +365,9 @@ cx_hash_map_iterator, cx_hash_map_iterator_keys, cx_hash_map_iterator_values, + cx_hash_map_mut_iterator, + cx_hash_map_mut_iterator_keys, + cx_hash_map_mut_iterator_values, }; CxMap *cxHashMapCreate(