src/kv_list.c

changeset 1373
a6aaa77b6809
parent 1372
9c176073e771
equal deleted inserted replaced
1372:9c176073e771 1373:a6aaa77b6809
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

mercurial