1.1 --- a/src/hash_map.c Wed Nov 23 22:40:55 2022 +0100 1.2 +++ b/src/hash_map.c Sat Nov 26 16:58:41 2022 +0100 1.3 @@ -201,34 +201,42 @@ 1.4 return cx_hash_map_get_remove(map, key, true); 1.5 } 1.6 1.7 -static void *cx_hash_map_iter_current_entry(CxIterator const *iter) { 1.8 +static void *cx_hash_map_iter_current_entry(void const *it) { 1.9 + struct cx_iterator_s const *iter = it; 1.10 // struct has to have a compatible signature 1.11 return (struct cx_map_entry_s *) &(iter->kv_data); 1.12 } 1.13 1.14 -static void *cx_hash_map_iter_current_key(CxIterator const *iter) { 1.15 +static void *cx_hash_map_iter_current_key(void const *it) { 1.16 + struct cx_iterator_s const *iter = it; 1.17 struct cx_hash_map_element_s *elm = iter->elem_handle; 1.18 return &elm->key; 1.19 } 1.20 1.21 -static void *cx_hash_map_iter_current_value(CxIterator const *iter) { 1.22 +static void *cx_hash_map_iter_current_value(void const *it) { 1.23 + struct cx_iterator_s const *iter = it; 1.24 struct cx_hash_map_element_s *elm = iter->elem_handle; 1.25 // TODO: return a pointer to data if this map is storing copies 1.26 return elm->data; 1.27 } 1.28 1.29 -static bool cx_hash_map_iter_valid(CxIterator const *iter) { 1.30 +static bool cx_hash_map_iter_valid(void const *it) { 1.31 + struct cx_iterator_s const *iter = it; 1.32 return iter->elem_handle != NULL; 1.33 } 1.34 1.35 -static void cx_hash_map_iter_next(CxIterator *iter) { 1.36 - struct cx_hash_map_s *map = iter->src_handle; 1.37 +static void cx_hash_map_iter_next(void *it) { 1.38 + struct cx_iterator_s *iter = it; 1.39 struct cx_hash_map_element_s *elm = iter->elem_handle; 1.40 1.41 // remove current element, if asked 1.42 - if (iter->remove) { 1.43 + if (iter->base.remove) { 1.44 + // obtain mutable pointer to the map 1.45 + struct cx_mut_iterator_s *miter = it; 1.46 + struct cx_hash_map_s *map = miter->src_handle; 1.47 + 1.48 // clear the flag 1.49 - iter->remove = false; 1.50 + iter->base.remove = false; 1.51 1.52 // determine the next element 1.53 struct cx_hash_map_element_s *next = elm->next; 1.54 @@ -254,6 +262,7 @@ 1.55 } 1.56 1.57 // search the next bucket, if required 1.58 + struct cx_hash_map_s const *map = iter->src_handle; 1.59 while (elm == NULL && ++iter->slot < map->bucket_count) { 1.60 elm = map->buckets[iter->slot]; 1.61 } 1.62 @@ -270,17 +279,29 @@ 1.63 } 1.64 } 1.65 1.66 -static CxIterator cx_hash_map_iterator(CxMap *map) { 1.67 +static bool cx_hash_map_iter_flag_rm(void *it) { 1.68 + struct cx_iterator_base_s *iter = it; 1.69 + if (iter->mutating) { 1.70 + iter->remove = true; 1.71 + return true; 1.72 + } else { 1.73 + return false; 1.74 + } 1.75 +} 1.76 + 1.77 +static CxIterator cx_hash_map_iterator(CxMap const *map) { 1.78 CxIterator iter; 1.79 1.80 iter.src_handle = map; 1.81 - iter.valid = cx_hash_map_iter_valid; 1.82 - iter.next = cx_hash_map_iter_next; 1.83 - iter.current = cx_hash_map_iter_current_entry; 1.84 + iter.base.valid = cx_hash_map_iter_valid; 1.85 + iter.base.next = cx_hash_map_iter_next; 1.86 + iter.base.current = cx_hash_map_iter_current_entry; 1.87 + iter.base.flag_removal = cx_hash_map_iter_flag_rm; 1.88 + iter.base.remove = false; 1.89 + iter.base.mutating = false; 1.90 1.91 iter.slot = 0; 1.92 iter.index = 0; 1.93 - iter.remove = false; 1.94 1.95 if (map->size > 0) { 1.96 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; 1.97 @@ -301,15 +322,37 @@ 1.98 return iter; 1.99 } 1.100 1.101 -static CxIterator cx_hash_map_iterator_keys(CxMap *map) { 1.102 +static CxIterator cx_hash_map_iterator_keys(CxMap const *map) { 1.103 CxIterator iter = cx_hash_map_iterator(map); 1.104 - iter.current = cx_hash_map_iter_current_key; 1.105 + iter.base.current = cx_hash_map_iter_current_key; 1.106 return iter; 1.107 } 1.108 1.109 -static CxIterator cx_hash_map_iterator_values(CxMap *map) { 1.110 +static CxIterator cx_hash_map_iterator_values(CxMap const *map) { 1.111 CxIterator iter = cx_hash_map_iterator(map); 1.112 - iter.current = cx_hash_map_iter_current_value; 1.113 + iter.base.current = cx_hash_map_iter_current_value; 1.114 + return iter; 1.115 +} 1.116 + 1.117 +static CxMutIterator cx_hash_map_mut_iterator(CxMap *map) { 1.118 + CxIterator it = cx_hash_map_iterator(map); 1.119 + it.base.mutating = true; 1.120 + 1.121 + // we know the iterators share the same memory layout 1.122 + CxMutIterator iter; 1.123 + memcpy(&iter, &it, sizeof(CxMutIterator)); 1.124 + return iter; 1.125 +} 1.126 + 1.127 +static CxMutIterator cx_hash_map_mut_iterator_keys(CxMap *map) { 1.128 + CxMutIterator iter = cx_hash_map_mut_iterator(map); 1.129 + iter.base.current = cx_hash_map_iter_current_key; 1.130 + return iter; 1.131 +} 1.132 + 1.133 +static CxMutIterator cx_hash_map_mut_iterator_values(CxMap *map) { 1.134 + CxMutIterator iter = cx_hash_map_mut_iterator(map); 1.135 + iter.base.current = cx_hash_map_iter_current_value; 1.136 return iter; 1.137 } 1.138 1.139 @@ -322,6 +365,9 @@ 1.140 cx_hash_map_iterator, 1.141 cx_hash_map_iterator_keys, 1.142 cx_hash_map_iterator_values, 1.143 + cx_hash_map_mut_iterator, 1.144 + cx_hash_map_mut_iterator_keys, 1.145 + cx_hash_map_mut_iterator_values, 1.146 }; 1.147 1.148 CxMap *cxHashMapCreate(