src/hash_map.c

changeset 630
ac5e7f789048
parent 575
b05935945637
child 658
56c62780582e
     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(

mercurial