Sun, 21 May 2023 15:07:31 +0200
simplify map class structure
src/cx/map.h | file | annotate | diff | comparison | revisions | |
src/hash_map.c | file | annotate | diff | comparison | revisions | |
src/map.c | file | annotate | diff | comparison | revisions |
1.1 --- a/src/cx/map.h Sun May 21 14:56:10 2023 +0200 1.2 +++ b/src/cx/map.h Sun May 21 15:07:31 2023 +0200 1.3 @@ -63,6 +63,24 @@ 1.4 }; 1.5 1.6 /** 1.7 + * The type of iterator for a map. 1.8 + */ 1.9 +enum cx_map_iterator_type { 1.10 + /** 1.11 + * Iterates over key/value pairs. 1.12 + */ 1.13 + CX_MAP_ITERATOR_PAIRS, 1.14 + /** 1.15 + * Iterates over keys only. 1.16 + */ 1.17 + CX_MAP_ITERATOR_KEYS, 1.18 + /** 1.19 + * Iterates over values only. 1.20 + */ 1.21 + CX_MAP_ITERATOR_VALUES 1.22 +}; 1.23 + 1.24 +/** 1.25 * The class definition for arbitrary maps. 1.26 */ 1.27 struct cx_map_class_s { 1.28 @@ -108,40 +126,10 @@ 1.29 ); 1.30 1.31 /** 1.32 - * Iterator over the key/value pairs. 1.33 + * Creates an iterator for this map. 1.34 */ 1.35 __attribute__((__nonnull__, __warn_unused_result__)) 1.36 - CxIterator (*iterator)(CxMap const *map); 1.37 - 1.38 - /** 1.39 - * Iterator over the keys. 1.40 - */ 1.41 - __attribute__((__nonnull__, __warn_unused_result__)) 1.42 - CxIterator (*iterator_keys)(CxMap const *map); 1.43 - 1.44 - /** 1.45 - * Iterator over the values. 1.46 - */ 1.47 - __attribute__((__nonnull__, __warn_unused_result__)) 1.48 - CxIterator (*iterator_values)(CxMap const *map); 1.49 - 1.50 - /** 1.51 - * Mutating iterator over the key/value pairs. 1.52 - */ 1.53 - __attribute__((__nonnull__, __warn_unused_result__)) 1.54 - CxMutIterator (*mut_iterator)(CxMap *map); 1.55 - 1.56 - /** 1.57 - * Mutating iterator over the keys. 1.58 - */ 1.59 - __attribute__((__nonnull__, __warn_unused_result__)) 1.60 - CxMutIterator (*mut_iterator_keys)(CxMap *map); 1.61 - 1.62 - /** 1.63 - * Mutating iterator over the values. 1.64 - */ 1.65 - __attribute__((__nonnull__, __warn_unused_result__)) 1.66 - CxMutIterator (*mut_iterator_values)(CxMap *map); 1.67 + CxIterator (*iterator)(CxMap const *map, enum cx_map_iterator_type type); 1.68 }; 1.69 1.70 /** 1.71 @@ -228,7 +216,7 @@ 1.72 */ 1.73 __attribute__((__nonnull__, __warn_unused_result__)) 1.74 static inline CxIterator cxMapIteratorValues(CxMap *map) { 1.75 - return map->cl->iterator_values(map); 1.76 + return map->cl->iterator(map, CX_MAP_ITERATOR_VALUES); 1.77 } 1.78 1.79 /** 1.80 @@ -244,7 +232,7 @@ 1.81 */ 1.82 __attribute__((__nonnull__, __warn_unused_result__)) 1.83 static inline CxIterator cxMapIteratorKeys(CxMap *map) { 1.84 - return map->cl->iterator_keys(map); 1.85 + return map->cl->iterator(map, CX_MAP_ITERATOR_KEYS); 1.86 } 1.87 1.88 /** 1.89 @@ -262,7 +250,7 @@ 1.90 */ 1.91 __attribute__((__nonnull__, __warn_unused_result__)) 1.92 static inline CxIterator cxMapIterator(CxMap *map) { 1.93 - return map->cl->iterator(map); 1.94 + return map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS); 1.95 } 1.96 1.97 1.98 @@ -276,9 +264,7 @@ 1.99 * @return an iterator for the currently stored values 1.100 */ 1.101 __attribute__((__nonnull__, __warn_unused_result__)) 1.102 -static inline CxMutIterator cxMapMutIteratorValues(CxMap *map) { 1.103 - return map->cl->mut_iterator_values(map); 1.104 -} 1.105 +CxMutIterator cxMapMutIteratorValues(CxMap *map); 1.106 1.107 /** 1.108 * Creates a mutating iterator over the keys of a map. 1.109 @@ -292,9 +278,7 @@ 1.110 * @return an iterator for the currently stored keys 1.111 */ 1.112 __attribute__((__nonnull__, __warn_unused_result__)) 1.113 -static inline CxMutIterator cxMapMutIteratorKeys(CxMap *map) { 1.114 - return map->cl->mut_iterator_keys(map); 1.115 -} 1.116 +CxMutIterator cxMapMutIteratorKeys(CxMap *map); 1.117 1.118 /** 1.119 * Creates a mutating iterator for a map. 1.120 @@ -310,9 +294,7 @@ 1.121 * @see cxMapMutIteratorValues() 1.122 */ 1.123 __attribute__((__nonnull__, __warn_unused_result__)) 1.124 -static inline CxMutIterator cxMapMutIterator(CxMap *map) { 1.125 - return map->cl->mut_iterator(map); 1.126 -} 1.127 +CxMutIterator cxMapMutIterator(CxMap *map); 1.128 1.129 #ifdef __cplusplus 1.130 } // end the extern "C" block here, because we want to start overloading
2.1 --- a/src/hash_map.c Sun May 21 14:56:10 2023 +0200 2.2 +++ b/src/hash_map.c Sun May 21 15:07:31 2023 +0200 2.3 @@ -26,10 +26,12 @@ 2.4 * POSSIBILITY OF SUCH DAMAGE. 2.5 */ 2.6 2.7 -#include <string.h> 2.8 #include "cx/hash_map.h" 2.9 #include "cx/utils.h" 2.10 2.11 +#include <string.h> 2.12 +#include <assert.h> 2.13 + 2.14 struct cx_hash_map_element_s { 2.15 /** A pointer to the next element in the current bucket. */ 2.16 struct cx_hash_map_element_s *next; 2.17 @@ -334,13 +336,30 @@ 2.18 } 2.19 } 2.20 2.21 -static CxIterator cx_hash_map_iterator(CxMap const *map) { 2.22 +static CxIterator cx_hash_map_iterator( 2.23 + CxMap const *map, 2.24 + enum cx_map_iterator_type type 2.25 +) { 2.26 CxIterator iter; 2.27 2.28 iter.src_handle = map; 2.29 iter.base.valid = cx_hash_map_iter_valid; 2.30 iter.base.next = cx_hash_map_iter_next; 2.31 - iter.base.current = cx_hash_map_iter_current_entry; 2.32 + 2.33 + switch (type) { 2.34 + case CX_MAP_ITERATOR_PAIRS: 2.35 + iter.base.current = cx_hash_map_iter_current_entry; 2.36 + break; 2.37 + case CX_MAP_ITERATOR_KEYS: 2.38 + iter.base.current = cx_hash_map_iter_current_key; 2.39 + break; 2.40 + case CX_MAP_ITERATOR_VALUES: 2.41 + iter.base.current = cx_hash_map_iter_current_value; 2.42 + break; 2.43 + default: 2.44 + assert(false); 2.45 + } 2.46 + 2.47 iter.base.flag_removal = cx_hash_map_iter_flag_rm; 2.48 iter.base.remove = false; 2.49 iter.base.mutating = false; 2.50 @@ -370,40 +389,6 @@ 2.51 return iter; 2.52 } 2.53 2.54 -static CxIterator cx_hash_map_iterator_keys(CxMap const *map) { 2.55 - CxIterator iter = cx_hash_map_iterator(map); 2.56 - iter.base.current = cx_hash_map_iter_current_key; 2.57 - return iter; 2.58 -} 2.59 - 2.60 -static CxIterator cx_hash_map_iterator_values(CxMap const *map) { 2.61 - CxIterator iter = cx_hash_map_iterator(map); 2.62 - iter.base.current = cx_hash_map_iter_current_value; 2.63 - return iter; 2.64 -} 2.65 - 2.66 -static CxMutIterator cx_hash_map_mut_iterator(CxMap *map) { 2.67 - CxIterator it = cx_hash_map_iterator(map); 2.68 - it.base.mutating = true; 2.69 - 2.70 - // we know the iterators share the same memory layout 2.71 - CxMutIterator iter; 2.72 - memcpy(&iter, &it, sizeof(CxMutIterator)); 2.73 - return iter; 2.74 -} 2.75 - 2.76 -static CxMutIterator cx_hash_map_mut_iterator_keys(CxMap *map) { 2.77 - CxMutIterator iter = cx_hash_map_mut_iterator(map); 2.78 - iter.base.current = cx_hash_map_iter_current_key; 2.79 - return iter; 2.80 -} 2.81 - 2.82 -static CxMutIterator cx_hash_map_mut_iterator_values(CxMap *map) { 2.83 - CxMutIterator iter = cx_hash_map_mut_iterator(map); 2.84 - iter.base.current = cx_hash_map_iter_current_value; 2.85 - return iter; 2.86 -} 2.87 - 2.88 static cx_map_class cx_hash_map_class = { 2.89 cx_hash_map_destructor, 2.90 cx_hash_map_clear, 2.91 @@ -411,11 +396,6 @@ 2.92 cx_hash_map_get, 2.93 cx_hash_map_remove, 2.94 cx_hash_map_iterator, 2.95 - cx_hash_map_iterator_keys, 2.96 - cx_hash_map_iterator_values, 2.97 - cx_hash_map_mut_iterator, 2.98 - cx_hash_map_mut_iterator_keys, 2.99 - cx_hash_map_mut_iterator_values, 2.100 }; 2.101 2.102 CxMap *cxHashMapCreate(
3.1 --- a/src/map.c Sun May 21 14:56:10 2023 +0200 3.2 +++ b/src/map.c Sun May 21 15:07:31 2023 +0200 3.3 @@ -27,6 +27,7 @@ 3.4 */ 3.5 3.6 #include "cx/map.h" 3.7 +#include <string.h> 3.8 3.9 // <editor-fold desc="empty map implementation"> 3.10 3.11 @@ -45,32 +46,23 @@ 3.12 return false; 3.13 } 3.14 3.15 -static CxIterator cx_empty_map_iterator(struct cx_map_s const *map) { 3.16 +static CxIterator cx_empty_map_iterator( 3.17 + struct cx_map_s const *map, 3.18 + __attribute__((__unused__)) enum cx_map_iterator_type type 3.19 +) { 3.20 CxIterator iter = {0}; 3.21 iter.src_handle = map; 3.22 iter.base.valid = cx_empty_map_iter_valid; 3.23 return iter; 3.24 } 3.25 3.26 -static CxMutIterator cx_empty_map_miterator(struct cx_map_s *map) { 3.27 - CxMutIterator iter = {0}; 3.28 - iter.src_handle = map; 3.29 - iter.base.valid = cx_empty_map_iter_valid; 3.30 - return iter; 3.31 -} 3.32 - 3.33 static struct cx_map_class_s cx_empty_map_class = { 3.34 - cx_empty_map_noop, 3.35 - cx_empty_map_noop, 3.36 - NULL, 3.37 - cx_empty_map_get, 3.38 - NULL, 3.39 - cx_empty_map_iterator, 3.40 - cx_empty_map_iterator, 3.41 - cx_empty_map_iterator, 3.42 - cx_empty_map_miterator, 3.43 - cx_empty_map_miterator, 3.44 - cx_empty_map_miterator, 3.45 + cx_empty_map_noop, 3.46 + cx_empty_map_noop, 3.47 + NULL, 3.48 + cx_empty_map_get, 3.49 + NULL, 3.50 + cx_empty_map_iterator 3.51 }; 3.52 3.53 CxMap cx_empty_map = { 3.54 @@ -85,6 +77,36 @@ 3.55 &cx_empty_map_class 3.56 }; 3.57 3.58 -CxMap * const cxEmptyMap = &cx_empty_map; 3.59 +CxMap *const cxEmptyMap = &cx_empty_map; 3.60 3.61 // </editor-fold> 3.62 + 3.63 +CxMutIterator cxMapMutIteratorValues(CxMap *map) { 3.64 + CxIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_VALUES); 3.65 + it.base.mutating = true; 3.66 + 3.67 + // we know the iterators share the same memory layout 3.68 + CxMutIterator iter; 3.69 + memcpy(&iter, &it, sizeof(CxMutIterator)); 3.70 + return iter; 3.71 +} 3.72 + 3.73 +CxMutIterator cxMapMutIteratorKeys(CxMap *map) { 3.74 + CxIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_KEYS); 3.75 + it.base.mutating = true; 3.76 + 3.77 + // we know the iterators share the same memory layout 3.78 + CxMutIterator iter; 3.79 + memcpy(&iter, &it, sizeof(CxMutIterator)); 3.80 + return iter; 3.81 +} 3.82 + 3.83 +CxMutIterator cxMapMutIterator(CxMap *map) { 3.84 + CxIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS); 3.85 + it.base.mutating = true; 3.86 + 3.87 + // we know the iterators share the same memory layout 3.88 + CxMutIterator iter; 3.89 + memcpy(&iter, &it, sizeof(CxMutIterator)); 3.90 + return iter; 3.91 +}