ucx/kv_list.c

changeset 31
287484519844
parent 30
d33eaaec15da
equal deleted inserted replaced
30:d33eaaec15da 31:287484519844
219 // (the first to find the index, the second to get a pointer) 219 // (the first to find the index, the second to get a pointer)
220 if (list->collection.size == 0) return 0; 220 if (list->collection.size == 0) return 0;
221 221
222 size_t index; 222 size_t index;
223 cx_linked_list *ll = &kv_list->list; 223 cx_linked_list *ll = &kv_list->list;
224 char *node = cx_linked_list_find( 224 char *node = cx_linked_list_find_c(
225 ll->begin, 225 ll->begin,
226 ll->loc_next, ll->loc_data, 226 ll->loc_next, ll->loc_data,
227 list->collection.cmpfunc, elem, 227 elem, &index,
228 &index 228 cx_list_compare_wrapper,
229 list
229 ); 230 );
230 if (node == NULL) { 231 if (node == NULL) {
231 return list->collection.size; 232 return list->collection.size;
232 } 233 }
233 if (remove) { 234 if (remove) {
346 cxFree(kv_list->list.base.collection.allocator, node_ptr); 347 cxFree(kv_list->list.base.collection.allocator, node_ptr);
347 348
348 return 0; 349 return 0;
349 } 350 }
350 351
351 static void *cx_kvl_map_put(CxMap *map, CxHashKey key, void *value) { 352 static CxMapEntry cx_kvl_map_put(CxMap *map, CxHashKey key, void *value) {
352 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list; 353 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
353 // if the hash has not yet been computed, do it now 354 // if the hash has not yet been computed, do it now
354 if (key.hash == 0) { 355 if (key.hash == 0) {
355 cx_hash_murmur(&key); 356 cx_hash_murmur(&key);
356 } 357 }
357 358
358 // remove any existing element first 359 // remove any existing element first
359 cx_kvl_map_remove(map, key, NULL); 360 cx_kvl_map_remove(map, key, NULL);
360 361
361 // now reserve new memory in the map 362 // now reserve new memory in the map
362 void **map_data = kv_list->map_methods->put(map, key, NULL); 363 CxMapEntry map_entry = kv_list->map_methods->put(map, key, NULL);
363 if (map_data == NULL) return NULL; // LCOV_EXCL_LINE 364 if (map_entry.key == NULL) return (CxMapEntry){NULL, NULL}; // LCOV_EXCL_LINE
364 365
365 // insert the data into the list (which most likely destroys the sorted property) 366 // insert the data into the list (which most likely destroys the sorted property)
366 kv_list->list.base.collection.sorted = false; 367 kv_list->list.base.collection.sorted = false;
367 void *node_data = kv_list->list_methods->insert_element( 368 void *node_data = kv_list->list_methods->insert_element(
368 &kv_list->list.base, kv_list->list.base.collection.size, 369 &kv_list->list.base, kv_list->list.base.collection.size,
369 kv_list->list.base.collection.store_pointer ? &value : value); 370 kv_list->list.base.collection.store_pointer ? &value : value);
370 if (node_data == NULL) { // LCOV_EXCL_START 371 if (node_data == NULL) { // LCOV_EXCL_START
371 // non-destructively remove the key again 372 // non-destructively remove the key again
372 kv_list->map_methods->remove(&kv_list->map->map_base.base, key, &map_data); 373 void *dummy;
373 return NULL; 374 kv_list->map_methods->remove(&kv_list->map->map_base.base, key, &dummy);
375 return (CxMapEntry){NULL, NULL};
374 } // LCOV_EXCL_STOP 376 } // LCOV_EXCL_STOP
375 377
376 // write the node pointer to the map entry 378 // write the node pointer to the map entry
377 *map_data = node_data; 379 *(void**)map_entry.value = node_data;
378 380
379 // copy the key to the node data 381 // copy the key to the node data
380 CxHashKey *key_ptr = cx_kv_list_loc_key(kv_list, node_data); 382 CxHashKey *key_ptr = cx_kv_list_loc_key(kv_list, node_data);
381 *key_ptr = key; 383 *key_ptr = *map_entry.key;
382 384
383 // we must return node_data here and not map_data, 385 // we must return an entry that points to the node data!
384 // because the node_data is the actual element of this collection 386 return (CxMapEntry ){key_ptr, node_data};
385 return node_data;
386 } 387 }
387 388
388 static void *cx_kvl_iter_current_entry(const void *it) { 389 static void *cx_kvl_iter_current_entry(const void *it) {
389 const CxMapIterator *iter = it; 390 const CxMapIterator *iter = it;
390 return (void*)&iter->entry; 391 return (void*)&iter->entry;
550 cx_kvl_map_iterator, 551 cx_kvl_map_iterator,
551 }; 552 };
552 553
553 CxList *cxKvListCreate( 554 CxList *cxKvListCreate(
554 const CxAllocator *allocator, 555 const CxAllocator *allocator,
555 cx_compare_func comparator,
556 size_t elem_size 556 size_t elem_size
557 ) { 557 ) {
558 if (allocator == NULL) { 558 if (allocator == NULL) {
559 allocator = cxDefaultAllocator; 559 allocator = cxDefaultAllocator;
560 } 560 }
561 561
562 // create a normal linked list and a normal hash map, first 562 // create a normal linked list and a normal hash map, first
563 CxList *list = cxLinkedListCreate(allocator, comparator, elem_size); 563 CxList *list = cxLinkedListCreate(allocator, elem_size);
564 if (list == NULL) return NULL; // LCOV_EXCL_LINE 564 if (list == NULL) return NULL; // LCOV_EXCL_LINE
565 cx_linked_list *ll = (cx_linked_list*)list; 565 cx_linked_list *ll = (cx_linked_list*)list;
566 cx_linked_list_extra_data(ll, sizeof(CxHashKey)); 566 cx_linked_list_extra_data(ll, sizeof(CxHashKey));
567 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0); 567 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0);
568 if (map == NULL) { // LCOV_EXCL_START 568 if (map == NULL) { // LCOV_EXCL_START
598 kv_map->list = kv_list; 598 kv_map->list = kv_list;
599 599
600 // remember the base methods and override them 600 // remember the base methods and override them
601 kv_list->map_methods = map->cl; 601 kv_list->map_methods = map->cl;
602 map->cl = &cx_kv_map_class; 602 map->cl = &cx_kv_map_class;
603 if (list->climpl == NULL) { 603 kv_list->list_methods = list->cl;
604 kv_list->list_methods = list->cl; 604 list->cl = &cx_kv_list_class;
605 list->cl = &cx_kv_list_class;
606 } else {
607 kv_list->list_methods = list->climpl;
608 list->climpl = &cx_kv_list_class;
609 }
610 605
611 return list; 606 return list;
612 } 607 }
613 608
614 CxMap *cxKvListCreateAsMap( 609 CxMap *cxKvListCreateAsMap(
615 const CxAllocator *allocator, 610 const CxAllocator *allocator,
616 cx_compare_func comparator,
617 size_t elem_size 611 size_t elem_size
618 ) { 612 ) {
619 CxList *list = cxKvListCreate(allocator, comparator, elem_size); 613 CxList *list = cxKvListCreate(allocator, elem_size);
620 return list == NULL ? NULL : cxKvListAsMap(list); 614 return list == NULL ? NULL : cxKvListAsMap(list);
621 } 615 }
622 616
623 CxList *cxKvListAsList(CxMap *map) { 617 CxList *cxKvListAsList(CxMap *map) {
624 return &((struct cx_kv_list_map_s*)map)->list->list.base; 618 return &((struct cx_kv_list_map_s*)map)->list->list.base;
647 if (existing != NULL) { 641 if (existing != NULL) {
648 // the key is already assigned to another node, we disallow re-assignment 642 // the key is already assigned to another node, we disallow re-assignment
649 return 1; 643 return 1;
650 } 644 }
651 645
652 // add the key to the map; 646 // add the key to the map
653 if (NULL == kv_list->map_methods->put(&kv_list->map->map_base.base, key, node_data)) { 647 const CxMapEntry entry = kv_list->map_methods->put(
654 return 1; // LCOV_EXCL_LINE 648 &kv_list->map->map_base.base, key, node_data);
655 } 649 if (entry.key == NULL) return 1; // LCOV_EXCL_LINE
656 650
657 // write the key to the list's node 651 // write the key to the list's node
658 CxHashKey *loc_key = cx_kv_list_loc_key(kv_list, node_data); 652 CxHashKey *loc_key = cx_kv_list_loc_key(kv_list, node_data);
659 *loc_key = key; 653 *loc_key = *entry.key;
660 654
661 return 0; 655 return 0;
662 } 656 }
663 657
664 int cxKvListRemoveKey(CxList *list, size_t index) { 658 int cxKvListRemoveKey(CxList *list, size_t index) {
696 list->collection.sorted = false; 690 list->collection.sorted = false;
697 691
698 cx_kv_list *kv_list = (cx_kv_list*)list; 692 cx_kv_list *kv_list = (cx_kv_list*)list;
699 693
700 // reserve memory in the map 694 // reserve memory in the map
701 void **map_data = kv_list->map_methods->put(&kv_list->map->map_base.base, key, NULL); 695 CxMapEntry map_entry = kv_list->map_methods->put(&kv_list->map->map_base.base, key, NULL);
702 if (map_data == NULL) return 1; // LCOV_EXCL_LINE 696 if (map_entry.key == NULL) return 1; // LCOV_EXCL_LINE
703 697
704 // insert the node 698 // insert the node
705 void *node_data = kv_list->list_methods->insert_element(&kv_list->list.base, index, 699 void *node_data = kv_list->list_methods->insert_element(&kv_list->list.base, index,
706 kv_list->list.base.collection.store_pointer ? &value : value); 700 kv_list->list.base.collection.store_pointer ? &value : value);
707 if (node_data == NULL) { // LCOV_EXCL_START 701 if (node_data == NULL) { // LCOV_EXCL_START
708 // non-destructively remove the key again 702 // non-destructively remove the key again
709 kv_list->map_methods->remove(&kv_list->map->map_base.base, key, &map_data); 703 void *dummy;
704 kv_list->map_methods->remove(&kv_list->map->map_base.base, key, &dummy);
710 return 1; 705 return 1;
711 } // LCOV_EXCL_STOP 706 } // LCOV_EXCL_STOP
712 *map_data = node_data; 707 *(void**)map_entry.value = node_data;
713 708
714 // write the key to the node 709 // write the key to the node
715 CxHashKey *loc_key = cx_kv_list_loc_key(kv_list, node_data); 710 CxHashKey *loc_key = cx_kv_list_loc_key(kv_list, node_data);
716 *loc_key = key; 711 *loc_key = *map_entry.key;
717 712
718 return 0; 713 return 0;
719 } 714 }

mercurial