src/ucx/kv_list.c

Sun, 07 Dec 2025 20:16:02 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 07 Dec 2025 20:16:02 +0100
changeset 656
59dd1fb27639
parent 645
0c85c4cd0dd8
permissions
-rw-r--r--

update uwproj

622
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
1 /*
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
3 *
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
4 * Copyright 2025 Mike Becker, Olaf Wintermann All rights reserved.
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
5 *
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
6 * Redistribution and use in source and binary forms, with or without
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
7 * modification, are permitted provided that the following conditions are met:
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
8 *
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
9 * 1. Redistributions of source code must retain the above copyright
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
10 * notice, this list of conditions and the following disclaimer.
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
11 *
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
12 * 2. Redistributions in binary form must reproduce the above copyright
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
13 * notice, this list of conditions and the following disclaimer in the
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
14 * documentation and/or other materials provided with the distribution.
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
15 *
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
26 * POSSIBILITY OF SUCH DAMAGE.
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
27 */
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
28
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
29 #include "cx/kv_list.h"
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
30 #include "cx/hash_map.h"
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
31 #include "cx/linked_list.h"
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
32
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
33 #include <string.h>
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
34 #include <assert.h>
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
35
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
36 typedef struct cx_kv_list_s cx_kv_list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
37
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
38 struct cx_kv_list_map_s {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
39 struct cx_hash_map_s map_base;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
40 /** Back-reference to the list. */
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
41 cx_kv_list *list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
42 };
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
43
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
44 struct cx_kv_list_s {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
45 struct cx_linked_list_s list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
46 /** The lookup map - stores pointers to the nodes. */
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
47 struct cx_kv_list_map_s *map;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
48 const cx_list_class *list_methods;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
49 const cx_map_class *map_methods;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
50 cx_destructor_func list_destr;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
51 cx_destructor_func2 list_destr2;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
52 void *list_destr_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
53 cx_destructor_func map_destr;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
54 cx_destructor_func2 map_destr2;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
55 void *map_destr_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
56 };
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
57
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
58 static void cx_kv_list_destructor_wrapper(void *list_ptr, void *elem) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
59 const cx_kv_list *kv_list = list_ptr;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
60 // list destructor is already called with proper deref of the elem
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
61 if (kv_list->list_destr) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
62 kv_list->list_destr(elem);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
63 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
64 if (kv_list->list_destr2) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
65 kv_list->list_destr2(kv_list->list_destr_data, elem);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
66 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
67 if (kv_list->map_destr) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
68 kv_list->map_destr(elem);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
69 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
70 if (kv_list->map_destr2) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
71 kv_list->map_destr2(kv_list->map_destr_data, elem);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
72 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
73 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
74
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
75 static void cx_kv_list_update_destructors(cx_kv_list *list) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
76 // we copy the destructors to our custom fields and register
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
77 // an own destructor function which invokes all these
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
78 if (list->list.base.collection.simple_destructor != NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
79 list->list_destr = list->list.base.collection.simple_destructor;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
80 list->list.base.collection.simple_destructor = NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
81 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
82 if (list->list.base.collection.advanced_destructor != cx_kv_list_destructor_wrapper) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
83 list->list_destr2 = list->list.base.collection.advanced_destructor;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
84 list->list_destr_data = list->list.base.collection.destructor_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
85 list->list.base.collection.advanced_destructor = cx_kv_list_destructor_wrapper;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
86 list->list.base.collection.destructor_data = list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
87 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
88 if (list->map->map_base.base.collection.simple_destructor != NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
89 list->map_destr = list->map->map_base.base.collection.simple_destructor;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
90 list->map->map_base.base.collection.simple_destructor = NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
91 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
92 if (list->map->map_base.base.collection.advanced_destructor != NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
93 list->map_destr2 = list->map->map_base.base.collection.advanced_destructor;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
94 list->map_destr_data = list->map->map_base.base.collection.destructor_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
95 list->map->map_base.base.collection.advanced_destructor = NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
96 list->map->map_base.base.collection.destructor_data = NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
97 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
98 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
99
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
100 static CxHashKey *cx_kv_list_loc_key(cx_kv_list *list, void *node_data) {
645
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
101 return (CxHashKey*)((char*)node_data - list->list.loc_data + list->list.loc_extra);
622
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
102 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
103
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
104 static void cx_kvl_deallocate(struct cx_list_s *list) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
105 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
106 // patch the destructors
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
107 cx_kv_list_update_destructors(kv_list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
108 kv_list->map_methods->deallocate(&kv_list->map->map_base.base);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
109 // then free the list, now the destructors may be called
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
110 kv_list->list_methods->deallocate(list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
111 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
112
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
113 static void *cx_kvl_insert_element(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
114 struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
115 size_t index,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
116 const void *data
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
117 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
118 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
119 return kv_list->list_methods->insert_element(list, index, data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
120 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
121
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
122 static size_t cx_kvl_insert_array(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
123 struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
124 size_t index,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
125 const void *data,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
126 size_t n
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
127 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
128 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
129 return kv_list->list_methods->insert_array(list, index, data, n);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
130 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
131
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
132 static size_t cx_kvl_insert_sorted(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
133 struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
134 const void *sorted_data,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
135 size_t n
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
136 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
137 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
138 return kv_list->list_methods->insert_sorted(list, sorted_data, n);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
139 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
140
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
141 static size_t cx_kvl_insert_unique(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
142 struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
143 const void *sorted_data,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
144 size_t n
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
145 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
146 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
147 return kv_list->list_methods->insert_unique(list, sorted_data, n);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
148 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
149
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
150 static int cx_kvl_insert_iter(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
151 struct cx_iterator_s *iter,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
152 const void *elem,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
153 int prepend
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
154 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
155 cx_kv_list *kv_list = iter->src_handle;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
156 return kv_list->list_methods->insert_iter(iter, elem, prepend);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
157 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
158
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
159 static size_t cx_kvl_remove(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
160 struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
161 size_t index,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
162 size_t num,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
163 void *targetbuf
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
164 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
165 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
166 // patch the destructors
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
167 // we also have to do that when targetbuf is NULL,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
168 // because we do not want wrong destructors to be called when we remove keys from the map
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
169 cx_kv_list_update_destructors(kv_list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
170 // iterate through the elements first and remove their keys from the map
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
171 CxIterator iter = kv_list->list_methods->iterator(list, index, false);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
172 for (size_t i = 0; i < num && cxIteratorValid(iter); i++) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
173 void *node_data = cxIteratorCurrent(iter);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
174 CxHashKey *key = cx_kv_list_loc_key(kv_list, node_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
175 // when the hash is zero, there is no key assigned to that element
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
176 if (key->hash != 0) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
177 kv_list->map_methods->remove(&kv_list->map->map_base.base, *key, NULL);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
178 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
179 cxIteratorNext(iter);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
180 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
181 return kv_list->list_methods->remove(list, index, num, targetbuf);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
182 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
183
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
184 static void cx_kvl_clear(struct cx_list_s *list) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
185 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
186 // patch the destructors
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
187 cx_kv_list_update_destructors(kv_list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
188 // clear the list
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
189 kv_list->list_methods->clear(list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
190 // then clear the map
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
191 kv_list->map_methods->clear(&kv_list->map->map_base.base);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
192 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
193
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
194 static int cx_kvl_swap(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
195 struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
196 size_t i,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
197 size_t j
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
198 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
199 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
200 return kv_list->list_methods->swap(list, i, j);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
201 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
202
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
203 static void *cx_kvl_at(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
204 const struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
205 size_t index
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
206 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
207 const cx_kv_list *kv_list = (const cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
208 return kv_list->list_methods->at(list, index);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
209 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
210
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
211 static size_t cx_kvl_find_remove(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
212 struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
213 const void *elem,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
214 bool remove
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
215 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
216 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
217 // we do not use the original list methods,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
218 // because that would need two passes for removal
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
219 // (the first to find the index, the second to get a pointer)
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
220 if (list->collection.size == 0) return 0;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
221
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
222 size_t index;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
223 cx_linked_list *ll = &kv_list->list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
224 char *node = cx_linked_list_find(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
225 ll->begin,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
226 ll->loc_next, ll->loc_data,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
227 list->collection.cmpfunc, elem,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
228 &index
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
229 );
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
230 if (node == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
231 return list->collection.size;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
232 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
233 if (remove) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
234 cx_kv_list_update_destructors(kv_list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
235 cx_invoke_advanced_destructor(list, node + ll->loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
236 cx_linked_list_remove(&ll->begin, &ll->end,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
237 ll->loc_prev, ll->loc_next, node);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
238 CxHashKey *key = cx_kv_list_loc_key(kv_list, node + ll->loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
239 if (key->hash != 0) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
240 kv_list->map_methods->remove(&kv_list->map->map_base.base, *key, NULL);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
241 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
242 list->collection.size--;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
243 cxFree(list->collection.allocator, node);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
244 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
245 return index;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
246 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
247
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
248 static void cx_kvl_sort(struct cx_list_s *list) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
249 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
250 kv_list->list_methods->sort(list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
251 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
252
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
253 static void cx_kvl_reverse(struct cx_list_s *list) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
254 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
255 kv_list->list_methods->reverse(list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
256 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
257
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
258 static void cx_kvl_list_iter_next(void *it) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
259 struct cx_iterator_s *iter = it;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
260 if (iter->base.remove) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
261 // remove the assigned key from the map before calling the actual function
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
262 cx_kv_list *kv_list = iter->src_handle;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
263 cx_kv_list_update_destructors(kv_list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
264 char *node = iter->elem_handle;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
265 CxHashKey *key = cx_kv_list_loc_key(kv_list, node + kv_list->list.loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
266 if (key->hash != 0) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
267 kv_list->map_methods->remove(&kv_list->map->map_base.base, *key, NULL);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
268 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
269 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
270 // note that we do not clear the remove flag, because the next_impl will do that
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
271 iter->base.next_impl(it);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
272 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
273
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
274 static struct cx_iterator_s cx_kvl_iterator(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
275 const struct cx_list_s *list,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
276 size_t index,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
277 bool backward
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
278 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
279 const cx_kv_list *kv_list = (const cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
280 struct cx_iterator_s iter = kv_list->list_methods->iterator(list, index, backward);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
281 iter.base.next_impl = iter.base.next;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
282 iter.base.next = cx_kvl_list_iter_next;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
283 return iter;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
284 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
285
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
286 static void cx_kvl_map_deallocate(struct cx_map_s *map) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
287 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
288 kv_list->map_methods->deallocate(map);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
289 kv_list->list_methods->deallocate(&kv_list->list.base);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
290 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
291
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
292 static void cx_kvl_map_clear(struct cx_map_s *map) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
293 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
294 cx_kv_list_update_destructors(kv_list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
295 kv_list->list_methods->clear(&kv_list->list.base);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
296 kv_list->map_methods->clear(map);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
297 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
298
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
299 static void *cx_kvl_map_put(CxMap *map, CxHashKey key, void *value) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
300 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
301 // if the hash has not yet been computed, do it now
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
302 if (key.hash == 0) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
303 cx_hash_murmur(&key);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
304 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
305
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
306 // reserve memory in the map first
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
307 void **map_data = kv_list->map_methods->put(map, key, NULL);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
308 if (map_data == NULL) return NULL; // LCOV_EXCL_LINE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
309
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
310 // insert the data into the list (which most likely destroys the sorted property)
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
311 kv_list->list.base.collection.sorted = false;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
312 void *node_data = kv_list->list_methods->insert_element(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
313 &kv_list->list.base, kv_list->list.base.collection.size,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
314 kv_list->list.base.collection.store_pointer ? &value : value);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
315 if (node_data == NULL) { // LCOV_EXCL_START
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
316 // non-destructively remove the key again
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
317 kv_list->map_methods->remove(&kv_list->map->map_base.base, key, &map_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
318 return NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
319 } // LCOV_EXCL_STOP
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
320
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
321 // write the node pointer to the map entry
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
322 *map_data = node_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
323
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
324 // copy the key to the node data
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
325 CxHashKey *key_ptr = cx_kv_list_loc_key(kv_list, node_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
326 *key_ptr = key;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
327
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
328 // we must return node_data here and not map_data,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
329 // because the node_data is the actual element of this collection
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
330 return node_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
331 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
332
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
333 void *cx_kvl_map_get(const CxMap *map, CxHashKey key) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
334 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
335 void *node_data = kv_list->map_methods->get(map, key);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
336 if (node_data == NULL) return NULL; // LCOV_EXCL_LINE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
337 // return the node data
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
338 return kv_list->list.base.collection.store_pointer ? *(void**)node_data : node_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
339 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
340
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
341 int cx_kvl_map_remove(CxMap *map, CxHashKey key, void *targetbuf) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
342 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
343
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
344 void *node_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
345 if (kv_list->map_methods->remove(map, key, &node_data)) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
346 return 1;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
347 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
348 // we cannot just call a list method (because we don't have the index)
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
349 // and tbh. we also don't want to (because it's not performant when we
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
350 // can have the node ptr directly instead)
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
351 // therefore, we re-implement the logic ourselves
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
352
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
353 // check if the outside caller want's us to return or to destroy the element
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
354 if (targetbuf == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
355 // patch the destructors and invoke them through the wrapper
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
356 cx_kv_list_update_destructors(kv_list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
357 cx_invoke_advanced_destructor(&kv_list->list.base, node_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
358 } else {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
359 // copy the element to the target buffer
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
360 memcpy(targetbuf, node_data, kv_list->list.base.collection.elem_size);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
361 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
362
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
363 // calculate the address of the node
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
364 void *node_ptr = (char*)node_data - kv_list->list.loc_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
365
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
366 // unlink the node
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
367 cx_linked_list_remove(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
368 &kv_list->list.begin,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
369 &kv_list->list.end,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
370 kv_list->list.loc_prev,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
371 kv_list->list.loc_next,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
372 node_ptr
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
373 );
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
374
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
375 // decrement the list's size
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
376 kv_list->list.base.collection.size--;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
377
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
378 // deallocate the node
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
379 cxFree(kv_list->list.base.collection.allocator, node_ptr);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
380
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
381 return 0;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
382 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
383
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
384 static void *cx_kvl_iter_current_entry(const void *it) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
385 const CxMapIterator *iter = it;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
386 return (void*)&iter->entry;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
387 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
388
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
389 static void *cx_kvl_iter_current_key(const void *it) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
390 const CxMapEntry *entry = cx_kvl_iter_current_entry(it);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
391 return (void*)entry->key;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
392 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
393
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
394 static void *cx_kvl_iter_current_value(const void *it) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
395 const CxMapEntry *entry = cx_kvl_iter_current_entry(it);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
396 return entry->value;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
397 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
398
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
399 static void cx_kvl_iter_next(void *it) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
400 CxMapIterator *iter = it;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
401 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)iter->map)->list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
402
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
403 // find the next list entry that has a key assigned
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
404 CxHashKey *key = NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
405 char *next = iter->elem;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
406 while (true) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
407 next = *(char**)(next + kv_list->list.loc_next);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
408 if (next == NULL) break;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
409 key = cx_kv_list_loc_key(kv_list, next + kv_list->list.loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
410 if (key->hash != 0) break;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
411 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
412
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
413 // remove previous element if requested
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
414 if (iter->base.remove) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
415 iter->base.remove = false;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
416 cx_kv_list_update_destructors(kv_list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
417 char *elem = iter->elem;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
418 char *elem_data = elem + kv_list->list.loc_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
419 CxHashKey *elem_key = cx_kv_list_loc_key(kv_list, elem_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
420 // key is guaranteed to exist because iterator only iterates over elems with a key
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
421 kv_list->map_methods->remove(&kv_list->map->map_base.base, *elem_key, NULL);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
422 cx_invoke_advanced_destructor(&kv_list->list.base, elem_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
423 cx_linked_list_remove(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
424 &kv_list->list.begin,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
425 &kv_list->list.end,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
426 kv_list->list.loc_prev,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
427 kv_list->list.loc_next,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
428 elem
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
429 );
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
430 cxFree(kv_list->list.base.collection.allocator, elem);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
431 kv_list->list.base.collection.size--;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
432 iter->index--;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
433 iter->elem_count--;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
434 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
435
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
436 // advance to the next element, if any
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
437 if (next == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
438 iter->index = kv_list->list.base.collection.size;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
439 iter->elem = NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
440 iter->entry = (CxMapEntry){NULL, NULL};
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
441 return;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
442 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
443 iter->index++;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
444 iter->elem = next;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
445 iter->entry.key = key;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
446 if (kv_list->list.base.collection.store_pointer) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
447 iter->entry.value = *(void**)(next + kv_list->list.loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
448 } else {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
449 iter->entry.value = (void*)(next + kv_list->list.loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
450 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
451 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
452
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
453 static bool cx_kvl_iter_valid(const void *it) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
454 const CxMapIterator *iter = it;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
455 return iter->elem != NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
456 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
457
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
458 CxMapIterator cx_kvl_map_iterator(const CxMap *map, enum cx_map_iterator_type type) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
459 CxMapIterator iter = {0};
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
460
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
461 iter.type = type;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
462 iter.map = (CxMap*)map;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
463 // although we iterate over the list, we only report that many elements that have a key in the map
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
464 iter.elem_count = map->collection.size;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
465
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
466 switch (type) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
467 case CX_MAP_ITERATOR_PAIRS:
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
468 iter.elem_size = sizeof(CxMapEntry);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
469 iter.base.current = cx_kvl_iter_current_entry;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
470 break;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
471 case CX_MAP_ITERATOR_KEYS:
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
472 iter.elem_size = sizeof(CxHashKey);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
473 iter.base.current = cx_kvl_iter_current_key;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
474 break;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
475 case CX_MAP_ITERATOR_VALUES:
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
476 iter.elem_size = map->collection.elem_size;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
477 iter.base.current = cx_kvl_iter_current_value;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
478 break;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
479 default:
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
480 assert(false); // LCOV_EXCL_LINE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
481 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
482
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
483 iter.base.allow_remove = true;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
484 iter.base.next = cx_kvl_iter_next;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
485 iter.base.valid = cx_kvl_iter_valid;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
486
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
487 // find the first list entry that has a key assigned
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
488 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
489 CxHashKey *key = NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
490 char *next = kv_list->list.begin;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
491 while (next != NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
492 key = cx_kv_list_loc_key(kv_list, next + kv_list->list.loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
493 if (key->hash != 0) break;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
494 next = *(char**)(next + kv_list->list.loc_next);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
495 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
496 if (next == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
497 iter.elem = NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
498 iter.entry = (CxMapEntry){NULL, NULL};
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
499 } else {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
500 iter.elem = next;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
501 iter.entry.key = key;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
502 if (kv_list->list.base.collection.store_pointer) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
503 iter.entry.value = *(void**)(next + kv_list->list.loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
504 } else {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
505 iter.entry.value = (void*)(next + kv_list->list.loc_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
506 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
507 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
508
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
509 return iter;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
510 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
511
645
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
512 static int cx_kvl_change_capacity(struct cx_list_s *list,
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
513 cx_attr_unused size_t cap) {
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
514 // since our backing list is a linked list, we don't need to do much here,
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
515 // but rehashing the map is quite useful
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
516 cx_kv_list *kv_list = (cx_kv_list*)list;
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
517 cxMapRehash(&kv_list->map->map_base.base);
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
518 return 0;
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
519 }
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
520
622
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
521 static cx_list_class cx_kv_list_class = {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
522 cx_kvl_deallocate,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
523 cx_kvl_insert_element,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
524 cx_kvl_insert_array,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
525 cx_kvl_insert_sorted,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
526 cx_kvl_insert_unique,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
527 cx_kvl_insert_iter,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
528 cx_kvl_remove,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
529 cx_kvl_clear,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
530 cx_kvl_swap,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
531 cx_kvl_at,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
532 cx_kvl_find_remove,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
533 cx_kvl_sort,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
534 NULL,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
535 cx_kvl_reverse,
645
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
536 cx_kvl_change_capacity,
622
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
537 cx_kvl_iterator,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
538 };
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
539
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
540 static cx_map_class cx_kv_map_class = {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
541 cx_kvl_map_deallocate,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
542 cx_kvl_map_clear,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
543 cx_kvl_map_put,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
544 cx_kvl_map_get,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
545 cx_kvl_map_remove,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
546 cx_kvl_map_iterator,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
547 };
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
548
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
549 CxList *cxKvListCreate(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
550 const CxAllocator *allocator,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
551 cx_compare_func comparator,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
552 size_t elem_size
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
553 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
554 if (allocator == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
555 allocator = cxDefaultAllocator;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
556 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
557
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
558 // create a normal linked list and a normal hash map, first
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
559 CxList *list = cxLinkedListCreate(allocator, comparator, elem_size);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
560 if (list == NULL) return NULL; // LCOV_EXCL_LINE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
561 cx_linked_list *ll = (cx_linked_list*)list;
645
0c85c4cd0dd8 update ucx to version 3.2
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 622
diff changeset
562 cx_linked_list_extra_data(ll, sizeof(CxHashKey));
622
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
563 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
564 if (map == NULL) { // LCOV_EXCL_START
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
565 cxListFree(list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
566 return NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
567 } // LCOV_EXCL_STOP
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
568
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
569 // patch the kv-list class with the compare function of the linked list
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
570 // this allows cxListCompare() to optimize comparisons between linked lists and kv-list
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
571 cx_kv_list_class.compare = list->cl->compare;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
572
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
573 // reallocate the map to add memory for the list back-reference
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
574 struct cx_kv_list_map_s *kv_map = cxRealloc(allocator, map, sizeof(struct cx_kv_list_map_s));
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
575
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
576 // reallocate the list to add memory for storing the metadata
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
577 cx_kv_list *kv_list = cxRealloc(allocator, list, sizeof(struct cx_kv_list_s));
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
578
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
579 // if any of the reallocations failed, we bail out
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
580 if (kv_map != NULL && kv_list != NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
581 map = (CxMap*) kv_map;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
582 list = (CxList*) kv_list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
583 } else { // LCOV_EXCL_START
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
584 cxListFree(list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
585 cxMapFree(map);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
586 return NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
587 } // LCOV_EXCL_STOP
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
588
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
589 // zero the custom destructor information
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
590 memset((char*)kv_list + offsetof(cx_kv_list, list_destr), 0, sizeof(void*)*6);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
591
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
592 // combine the list and the map aspect
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
593 kv_list->map = kv_map;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
594 kv_map->list = kv_list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
595
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
596 // remember the base methods and override them
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
597 kv_list->map_methods = map->cl;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
598 map->cl = &cx_kv_map_class;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
599 if (list->climpl == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
600 kv_list->list_methods = list->cl;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
601 list->cl = &cx_kv_list_class;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
602 } else {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
603 kv_list->list_methods = list->climpl;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
604 list->climpl = &cx_kv_list_class;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
605 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
606
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
607 return list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
608 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
609
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
610 CxMap *cxKvListCreateAsMap(
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
611 const CxAllocator *allocator,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
612 cx_compare_func comparator,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
613 size_t elem_size
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
614 ) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
615 CxList *list = cxKvListCreate(allocator, comparator, elem_size);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
616 return list == NULL ? NULL : cxKvListAsMap(list);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
617 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
618
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
619 CxList *cxKvListAsList(CxMap *map) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
620 return &((struct cx_kv_list_map_s*)map)->list->list.base;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
621 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
622
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
623 CxMap *cxKvListAsMap(CxList *list) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
624 return &((cx_kv_list*)list)->map->map_base.base;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
625 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
626
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
627 int cx_kv_list_set_key(CxList *list, size_t index, CxHashKey key) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
628 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
629 void *node_data = kv_list->list_methods->at(list, index);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
630 if (node_data == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
631 return 1;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
632 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
633 // if the hash has not yet been computed, do it now
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
634 if (key.hash == 0) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
635 cx_hash_murmur(&key);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
636 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
637
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
638 // check if the key is already assigned
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
639 void *existing = kv_list->map_methods->get(&kv_list->map->map_base.base, key);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
640 if (existing == node_data) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
641 return 0; // nothing to do
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
642 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
643 if (existing != NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
644 // the key is already assigned to another node, we disallow re-assignment
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
645 return 1;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
646 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
647
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
648 // add the key to the map;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
649 if (NULL == kv_list->map_methods->put(&kv_list->map->map_base.base, key, node_data)) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
650 return 1; // LCOV_EXCL_LINE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
651 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
652
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
653 // write the key to the list's node
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
654 CxHashKey *loc_key = cx_kv_list_loc_key(kv_list, node_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
655 *loc_key = key;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
656
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
657 return 0;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
658 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
659
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
660 int cxKvListRemoveKey(CxList *list, size_t index) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
661 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
662 void *node_data = kv_list->list_methods->at(list, index);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
663 if (node_data == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
664 return 1;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
665 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
666 CxHashKey *loc_key = cx_kv_list_loc_key(kv_list, node_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
667 if (loc_key->hash == 0) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
668 return 0;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
669 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
670 kv_list->map_methods->remove(&kv_list->map->map_base.base, *loc_key, NULL);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
671 // also zero the memory in the list node,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
672 // but don't free the key data (that was done by the map remove)
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
673 memset(loc_key, 0, sizeof(CxHashKey));
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
674 return 0;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
675 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
676
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
677 const CxHashKey *cxKvListGetKey(CxList *list, size_t index) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
678 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
679 void *node_data = kv_list->list_methods->at(list, index);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
680 if (node_data == NULL) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
681 return NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
682 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
683 CxHashKey *key = cx_kv_list_loc_key(kv_list, node_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
684 if (key->hash == 0) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
685 return NULL;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
686 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
687 return key;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
688 }
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
689
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
690 int cx_kv_list_insert(CxList *list, size_t index, CxHashKey key, void *value) {
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
691 // assume we are losing the sorted property
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
692 list->collection.sorted = false;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
693
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
694 cx_kv_list *kv_list = (cx_kv_list*)list;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
695
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
696 // reserve memory in the map
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
697 void **map_data = kv_list->map_methods->put(&kv_list->map->map_base.base, key, NULL);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
698 if (map_data == NULL) return 1; // LCOV_EXCL_LINE
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
699
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
700 // insert the node
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
701 void *node_data = kv_list->list_methods->insert_element(&kv_list->list.base, index,
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
702 kv_list->list.base.collection.store_pointer ? &value : value);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
703 if (node_data == NULL) { // LCOV_EXCL_START
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
704 // non-destructively remove the key again
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
705 kv_list->map_methods->remove(&kv_list->map->map_base.base, key, &map_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
706 return 1;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
707 } // LCOV_EXCL_STOP
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
708 *map_data = node_data;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
709
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
710 // write the key to the node
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
711 CxHashKey *loc_key = cx_kv_list_loc_key(kv_list, node_data);
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
712 *loc_key = key;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
713
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
714 return 0;
6e44c7ce0834 add ucx kv_list
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
715 }

mercurial