94 list->map->map_base.base.collection.advanced_destructor = NULL; |
94 list->map->map_base.base.collection.advanced_destructor = NULL; |
95 list->map->map_base.base.collection.destructor_data = NULL; |
95 list->map->map_base.base.collection.destructor_data = NULL; |
96 } |
96 } |
97 } |
97 } |
98 |
98 |
|
99 static CxHashKey *cx_kv_list_loc_key(cx_kv_list *list, void *node_data) { |
|
100 return (CxHashKey*)((char*)node_data + list->list.base.collection.elem_size); |
|
101 } |
|
102 |
99 static void cx_kvl_deallocate(struct cx_list_s *list) { |
103 static void cx_kvl_deallocate(struct cx_list_s *list) { |
100 cx_kv_list *kv_list = (cx_kv_list*)list; |
104 cx_kv_list *kv_list = (cx_kv_list*)list; |
101 // patch the destructors |
105 // patch the destructors |
102 cx_kv_list_update_destructors(kv_list); |
106 cx_kv_list_update_destructors(kv_list); |
103 kv_list->map_methods->deallocate(&kv_list->map->map_base.base); |
107 kv_list->map_methods->deallocate(&kv_list->map->map_base.base); |
148 size_t num, |
152 size_t num, |
149 void *targetbuf |
153 void *targetbuf |
150 ) { |
154 ) { |
151 cx_kv_list *kv_list = (cx_kv_list*)list; |
155 cx_kv_list *kv_list = (cx_kv_list*)list; |
152 // patch the destructors |
156 // patch the destructors |
|
157 // we also have to do that when targetbuf is NULL, |
|
158 // because we do not want wrong destructors to be called when we remove keys from the map |
153 cx_kv_list_update_destructors(kv_list); |
159 cx_kv_list_update_destructors(kv_list); |
154 // TODO: always use the target buffer to get the element first, |
160 // iterate through the elements first and remove their keys from the map |
155 // then obtain the key, remove it from the map, |
161 CxIterator iter = kv_list->list_methods->iterator(list, index, false); |
156 // and finally call any destructors manually |
162 for (size_t i = 0; i < num && cxIteratorValid(iter); i++) { |
|
163 void *node_data = cxIteratorCurrent(iter); |
|
164 CxHashKey *key = cx_kv_list_loc_key(kv_list, node_data); |
|
165 // when the hash is zero, there is no key assigned to that element |
|
166 if (key->hash != 0) { |
|
167 kv_list->map_methods->remove(&kv_list->map->map_base.base, *key, NULL); |
|
168 } |
|
169 cxIteratorNext(iter); |
|
170 } |
157 return kv_list->list_methods->remove(list, index, num, targetbuf); |
171 return kv_list->list_methods->remove(list, index, num, targetbuf); |
158 } |
172 } |
159 |
173 |
160 static void cx_kvl_clear(struct cx_list_s *list) { |
174 static void cx_kvl_clear(struct cx_list_s *list) { |
161 cx_kv_list *kv_list = (cx_kv_list*)list; |
175 cx_kv_list *kv_list = (cx_kv_list*)list; |
234 kv_list->list.base.collection.sorted = false; |
248 kv_list->list.base.collection.sorted = false; |
235 void *node_data = kv_list->list_methods->insert_element( |
249 void *node_data = kv_list->list_methods->insert_element( |
236 &kv_list->list.base, kv_list->list.base.collection.size, |
250 &kv_list->list.base, kv_list->list.base.collection.size, |
237 kv_list->list.base.collection.store_pointer ? &value : value); |
251 kv_list->list.base.collection.store_pointer ? &value : value); |
238 if (node_data == NULL) return NULL; // LCOV_EXCL_LINE |
252 if (node_data == NULL) return NULL; // LCOV_EXCL_LINE |
|
253 // if the hash has not yet been computed, do it now |
|
254 if (key.hash == 0) { |
|
255 cx_hash_murmur(&key); |
|
256 } |
|
257 // copy the key to the node data |
|
258 CxHashKey *key_ptr = cx_kv_list_loc_key(kv_list, node_data); |
|
259 *key_ptr = key; |
239 // then insert the key into the map, referring to the node data |
260 // then insert the key into the map, referring to the node data |
240 return kv_list->map_methods->put(map, key, node_data); |
261 return kv_list->map_methods->put(map, key, node_data); |
241 } |
262 } |
242 |
263 |
243 void *cx_kvl_map_get(const CxMap *map, CxHashKey key) { |
264 void *cx_kvl_map_get(const CxMap *map, CxHashKey key) { |
400 return &((cx_kv_list*)list)->map->map_base.base; |
421 return &((cx_kv_list*)list)->map->map_base.base; |
401 } |
422 } |
402 |
423 |
403 int cx_kv_list_set_key(CxList *list, size_t index, CxHashKey key) { |
424 int cx_kv_list_set_key(CxList *list, size_t index, CxHashKey key) { |
404 cx_kv_list *kv_list = (cx_kv_list*)list; |
425 cx_kv_list *kv_list = (cx_kv_list*)list; |
405 char *node_data = kv_list->list_methods->at(list, index); |
426 void *node_data = kv_list->list_methods->at(list, index); |
406 char *loc_key = node_data + list->collection.elem_size; |
427 if (node_data == NULL) { |
407 memcpy(loc_key, &key, sizeof(key)); |
428 return 1; |
|
429 } |
|
430 // if the hash has not yet been computed, do it now |
|
431 if (key.hash == 0) { |
|
432 cx_hash_murmur(&key); |
|
433 } |
|
434 CxHashKey *loc_key = cx_kv_list_loc_key(kv_list, node_data); |
|
435 *loc_key = key; |
408 |
436 |
409 // TODO: what happens when we are _replacing_ an existing key? |
437 // TODO: what happens when we are _replacing_ an existing key? |
410 kv_list->map_methods->put(&kv_list->map->map_base.base, key, node_data); |
438 kv_list->map_methods->put(&kv_list->map->map_base.base, key, node_data); |
411 // TODO: what happens if the map cocks up and returns NULL? |
439 // TODO: what happens if the map cocks up and returns NULL? |
412 |
440 |