src/kv_list.c

changeset 1546
c8dd35f3ea53
parent 1545
7822ffe65848
equal deleted inserted replaced
1545:7822ffe65848 1546:c8dd35f3ea53
295 cx_kv_list_update_destructors(kv_list); 295 cx_kv_list_update_destructors(kv_list);
296 kv_list->list_methods->clear(&kv_list->list.base); 296 kv_list->list_methods->clear(&kv_list->list.base);
297 kv_list->map_methods->clear(map); 297 kv_list->map_methods->clear(map);
298 } 298 }
299 299
300 static void *cx_kvl_map_get(const CxMap *map, CxHashKey key) {
301 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
302 void *node_data = kv_list->map_methods->get(map, key);
303 if (node_data == NULL) return NULL; // LCOV_EXCL_LINE
304 // return the node data
305 return kv_list->list.base.collection.store_pointer ? *(void**)node_data : node_data;
306 }
307
308 static int cx_kvl_map_remove(CxMap *map, CxHashKey key, void *targetbuf) {
309 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
310
311 void *node_data;
312 if (kv_list->map_methods->remove(map, key, &node_data)) {
313 return 1;
314 }
315 // we cannot just call a list method (because we don't have the index)
316 // and tbh. we also don't want to (because it's not performant when we
317 // can have the node ptr directly instead)
318 // therefore, we re-implement the logic ourselves
319
320 // check if the outside caller want's us to return or to destroy the element
321 if (targetbuf == NULL) {
322 // patch the destructors and invoke them through the wrapper
323 cx_kv_list_update_destructors(kv_list);
324 cx_invoke_advanced_destructor(&kv_list->list.base, node_data);
325 } else {
326 // copy the element to the target buffer
327 memcpy(targetbuf, node_data, kv_list->list.base.collection.elem_size);
328 }
329
330 // calculate the address of the node
331 void *node_ptr = (char*)node_data - kv_list->list.loc_data;
332
333 // unlink the node
334 cx_linked_list_remove(
335 &kv_list->list.begin,
336 &kv_list->list.end,
337 kv_list->list.loc_prev,
338 kv_list->list.loc_next,
339 node_ptr
340 );
341
342 // decrement the list's size
343 kv_list->list.base.collection.size--;
344
345 // deallocate the node
346 cxFree(kv_list->list.base.collection.allocator, node_ptr);
347
348 return 0;
349 }
350
300 static void *cx_kvl_map_put(CxMap *map, CxHashKey key, void *value) { 351 static void *cx_kvl_map_put(CxMap *map, CxHashKey key, void *value) {
301 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list; 352 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
302 // if the hash has not yet been computed, do it now 353 // if the hash has not yet been computed, do it now
303 if (key.hash == 0) { 354 if (key.hash == 0) {
304 cx_hash_murmur(&key); 355 cx_hash_murmur(&key);
305 } 356 }
306 357
307 // reserve memory in the map first 358 // remove any existing element first
359 cx_kvl_map_remove(map, key, NULL);
360
361 // now reserve new memory in the map
308 void **map_data = kv_list->map_methods->put(map, key, NULL); 362 void **map_data = kv_list->map_methods->put(map, key, NULL);
309 if (map_data == NULL) return NULL; // LCOV_EXCL_LINE 363 if (map_data == NULL) return NULL; // LCOV_EXCL_LINE
310 364
311 // insert the data into the list (which most likely destroys the sorted property) 365 // insert the data into the list (which most likely destroys the sorted property)
312 kv_list->list.base.collection.sorted = false; 366 kv_list->list.base.collection.sorted = false;
327 *key_ptr = key; 381 *key_ptr = key;
328 382
329 // we must return node_data here and not map_data, 383 // we must return node_data here and not map_data,
330 // because the node_data is the actual element of this collection 384 // because the node_data is the actual element of this collection
331 return node_data; 385 return node_data;
332 }
333
334 void *cx_kvl_map_get(const CxMap *map, CxHashKey key) {
335 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
336 void *node_data = kv_list->map_methods->get(map, key);
337 if (node_data == NULL) return NULL; // LCOV_EXCL_LINE
338 // return the node data
339 return kv_list->list.base.collection.store_pointer ? *(void**)node_data : node_data;
340 }
341
342 int cx_kvl_map_remove(CxMap *map, CxHashKey key, void *targetbuf) {
343 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
344
345 void *node_data;
346 if (kv_list->map_methods->remove(map, key, &node_data)) {
347 return 1;
348 }
349 // we cannot just call a list method (because we don't have the index)
350 // and tbh. we also don't want to (because it's not performant when we
351 // can have the node ptr directly instead)
352 // therefore, we re-implement the logic ourselves
353
354 // check if the outside caller want's us to return or to destroy the element
355 if (targetbuf == NULL) {
356 // patch the destructors and invoke them through the wrapper
357 cx_kv_list_update_destructors(kv_list);
358 cx_invoke_advanced_destructor(&kv_list->list.base, node_data);
359 } else {
360 // copy the element to the target buffer
361 memcpy(targetbuf, node_data, kv_list->list.base.collection.elem_size);
362 }
363
364 // calculate the address of the node
365 void *node_ptr = (char*)node_data - kv_list->list.loc_data;
366
367 // unlink the node
368 cx_linked_list_remove(
369 &kv_list->list.begin,
370 &kv_list->list.end,
371 kv_list->list.loc_prev,
372 kv_list->list.loc_next,
373 node_ptr
374 );
375
376 // decrement the list's size
377 kv_list->list.base.collection.size--;
378
379 // deallocate the node
380 cxFree(kv_list->list.base.collection.allocator, node_ptr);
381
382 return 0;
383 } 386 }
384 387
385 static void *cx_kvl_iter_current_entry(const void *it) { 388 static void *cx_kvl_iter_current_entry(const void *it) {
386 const CxMapIterator *iter = it; 389 const CxMapIterator *iter = it;
387 return (void*)&iter->entry; 390 return (void*)&iter->entry;
454 static bool cx_kvl_iter_valid(const void *it) { 457 static bool cx_kvl_iter_valid(const void *it) {
455 const CxMapIterator *iter = it; 458 const CxMapIterator *iter = it;
456 return iter->elem != NULL; 459 return iter->elem != NULL;
457 } 460 }
458 461
459 CxMapIterator cx_kvl_map_iterator(const CxMap *map, enum cx_map_iterator_type type) { 462 static CxMapIterator cx_kvl_map_iterator(const CxMap *map, enum cx_map_iterator_type type) {
460 CxMapIterator iter = {0}; 463 CxMapIterator iter = {0};
461 464
462 iter.type = type; 465 iter.type = type;
463 iter.map = (CxMap*)map; 466 iter.map = (CxMap*)map;
464 // although we iterate over the list, we only report that many elements that have a key in the map 467 // although we iterate over the list, we only report that many elements that have a key in the map

mercurial