File Coverage

third_party/modest/source/mycore/utils/mctree.c
Criterion Covered Total %
statement 77 137 56.2
branch 31 82 37.8
condition n/a
subroutine n/a
pod n/a
total 108 219 49.3


line stmt bran cond sub pod time code
1             /*
2             Copyright (C) 2015-2017 Alexander Borisov
3            
4             This library is free software; you can redistribute it and/or
5             modify it under the terms of the GNU Lesser General Public
6             License as published by the Free Software Foundation; either
7             version 2.1 of the License, or (at your option) any later version.
8            
9             This library is distributed in the hope that it will be useful,
10             but WITHOUT ANY WARRANTY; without even the implied warranty of
11             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12             Lesser General Public License for more details.
13            
14             You should have received a copy of the GNU Lesser General Public
15             License along with this library; if not, write to the Free Software
16             Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17            
18             Author: lex.borisov@gmail.com (Alexander Borisov)
19             */
20              
21             #include "mycore/utils/resources.h"
22             #include "mycore/utils/mctree.h"
23              
24 145           mctree_t * mctree_create(size_t start_size)
25             {
26 145           mctree_t* mctree = (mctree_t*)mycore_malloc(sizeof(mctree_t));
27            
28 145 50         if(mctree == NULL)
29 0           return NULL;
30            
31 145           mctree->nodes_size = start_size + 512;
32 145           mctree->nodes_length = start_size + 1;
33 145           mctree->nodes = (mctree_node_t*)mycore_calloc(mctree->nodes_size, sizeof(mctree_node_t));
34            
35 145 50         if(mctree->nodes == NULL) {
36 0           mycore_free(mctree);
37 0           return NULL;
38             }
39            
40 145           mctree->start_size = start_size;
41            
42 145           return mctree;
43             }
44              
45 290           void mctree_clean(mctree_t* mctree)
46             {
47 290           mctree->nodes_length = mctree->start_size + 1;
48 290           memset(mctree->nodes, 0, sizeof(mctree_node_t) * mctree->nodes_size);
49 290           }
50              
51 144           mctree_t * mctree_destroy(mctree_t* mctree)
52             {
53 144 50         if(mctree == NULL)
54 0           return NULL;
55            
56 144 50         if(mctree->nodes)
57 144           mycore_free(mctree->nodes);
58            
59 144           mycore_free(mctree);
60            
61 144           return NULL;
62             }
63              
64 8           mctree_index_t __mtree_search_lowercase_to_start(mctree_t* mctree, mctree_index_t idx, const char* key, size_t key_size)
65             {
66 8           mctree_node_t* nodes = mctree->nodes;
67            
68 14 100         while (idx)
69             {
70 11 100         if(key_size == nodes[idx].str_size) {
71 8 100         if(mycore_strncasecmp(key, nodes[idx].str, key_size) == 0) {
72 5           return idx;
73             }
74            
75 3           idx = nodes[idx].child;
76             }
77 3 50         else if(key_size > nodes[idx].str_size)
78             {
79 3 50         if(key_size < nodes[ nodes[idx].next ].str_size) {
80 0           return 0;
81             }
82            
83 3           idx = nodes[idx].next;
84             }
85             else {
86 0 0         if(key_size > nodes[ nodes[idx].prev ].str_size) {
87 0           return 0;
88             }
89            
90 0           idx = nodes[idx].prev;
91             }
92             }
93            
94 3           return 0;
95             }
96              
97 0           mctree_index_t __mtree_search_to_start(mctree_t* mctree, mctree_index_t idx, const char* key, size_t key_size)
98             {
99 0           mctree_node_t* nodes = mctree->nodes;
100            
101 0 0         while (idx)
102             {
103 0 0         if(key_size == nodes[idx].str_size) {
104 0 0         if(memcmp((const void *)key, (const void *)(nodes[idx].str), key_size) == 0) {
105 0           return idx;
106             }
107            
108 0           idx = nodes[idx].child;
109             }
110 0 0         else if(key_size > nodes[idx].str_size)
111             {
112 0 0         if(key_size < nodes[ nodes[idx].next ].str_size) {
113 0           return 0;
114             }
115            
116 0           idx = nodes[idx].next;
117             }
118             else {
119 0 0         if(key_size > nodes[ nodes[idx].prev ].str_size) {
120 0           return 0;
121             }
122            
123 0           idx = nodes[idx].prev;
124             }
125             }
126            
127 0           return 0;
128             }
129              
130 21           mctree_index_t mctree_insert_child(mctree_t* mctree, mctree_index_t idx, const char* key, size_t key_size, void* value)
131             {
132 21           mctree_node_t* nodes = mctree->nodes;
133 21           mctree_index_t new_idx = mctree_node_get_free_id(mctree);
134            
135 21           nodes[idx].child = new_idx;
136            
137 21           nodes[new_idx].str = key;
138 21           nodes[new_idx].str_size = key_size;
139 21           nodes[new_idx].value = value;
140            
141 21 50         mctree_node_add(mctree);
142            
143 21           return new_idx;
144             }
145              
146 1           mctree_index_t mctree_insert_after(mctree_t* mctree, mctree_index_t idx, const char* key, size_t key_size, void* value)
147             {
148 1           mctree_node_t* nodes = mctree->nodes;
149 1           mctree_index_t new_idx = mctree_node_get_free_id(mctree);
150            
151 1 50         if(nodes[idx].next) {
152 0           nodes[ nodes[idx].next ].prev = new_idx;
153 0           nodes[new_idx].next = nodes[idx].next;
154             }
155            
156 1           nodes[idx].next = new_idx;
157 1           nodes[new_idx].prev = idx;
158            
159 1           nodes[new_idx].str = key;
160 1           nodes[new_idx].str_size = key_size;
161 1           nodes[new_idx].value = value;
162            
163 1 50         mctree_node_add(mctree);
164            
165 1           return new_idx;
166             }
167              
168 0           mctree_index_t mctree_insert_before(mctree_t* mctree, mctree_index_t idx, const char* key, size_t key_size, void* value)
169             {
170 0           mctree_node_t* nodes = mctree->nodes;
171 0           mctree_index_t new_idx = mctree_node_get_free_id(mctree);
172            
173 0 0         if(nodes[idx].prev) {
174 0           nodes[ nodes[idx].prev ].next = new_idx;
175 0           nodes[new_idx].prev = nodes[idx].prev;
176             }
177            
178 0           nodes[idx].prev = new_idx;
179 0           nodes[new_idx].next = idx;
180            
181 0           nodes[new_idx].str = key;
182 0           nodes[new_idx].str_size = key_size;
183 0           nodes[new_idx].value = value;
184            
185 0 0         mctree_node_add(mctree);
186            
187 0           return new_idx;
188             }
189              
190 2           mctree_index_t __mtree_insert_to_start(mctree_t* mctree, mctree_index_t idx, const char* key, size_t key_size, void* value, mctree_before_insert_f b_insert)
191             {
192 2           mctree_node_t* nodes = mctree->nodes;
193            
194 2 50         while (idx)
195             {
196 2 100         if(key_size == nodes[idx].str_size) {
197 1 50         if(memcmp((const void *)key, (const void *)nodes[idx].str, key_size) == 0)
198             {
199 0 0         if(value)
200 0           nodes[idx].value = value;
201            
202 0           return idx;
203             }
204            
205 1 50         if(nodes[idx].child == 0) {
206 1 50         if(b_insert)
207 0           b_insert(key, key_size, &value);
208            
209 1           return mctree_insert_child(mctree, idx, key, key_size, value);
210             }
211            
212 0           idx = nodes[idx].child;
213             }
214 1 50         else if(key_size > nodes[idx].str_size)
215             {
216 1 50         if(nodes[idx].next == 0 || key_size < nodes[ nodes[idx].next ].str_size) {
    0          
217 1 50         if(b_insert)
218 0           b_insert(key, key_size, &value);
219            
220 1           return mctree_insert_after(mctree, idx, key, key_size, value);
221             }
222            
223 0           idx = nodes[idx].next;
224             }
225             else {
226 0 0         if(nodes[idx].prev == 0 || key_size > nodes[ nodes[idx].prev ].str_size) {
    0          
227 0 0         if(b_insert)
228 0           b_insert(key, key_size, &value);
229            
230 0           return mctree_insert_before(mctree, idx, key, key_size, value);
231             }
232            
233 0           idx = nodes[idx].prev;
234             }
235             }
236            
237 0           return 0;
238             }
239              
240 22           mctree_index_t mctree_insert(mctree_t* mctree, const char* key, size_t key_size, void* value, mctree_before_insert_f b_insert)
241             {
242 22           mctree_node_t* start = mctree->nodes;
243            
244 22 50         if(key_size > 0) {
245 22           mctree_index_t idx = mctree_make_first_idx(mctree, key, key_size);
246            
247 22 100         if(start[idx].child) {
248 2           return __mtree_insert_to_start(mctree, start[idx].child, key, key_size, value, b_insert);
249             }
250             else {
251 20 50         if(b_insert)
252 0           b_insert(key, key_size, &value);
253            
254 20           return mctree_insert_child(mctree, idx, key, key_size, value);
255             }
256             }
257            
258 0           return 0;
259             }
260              
261 0           mctree_index_t mctree_search(mctree_t* mctree, const char* key, size_t key_size)
262             {
263 0           mctree_node_t* start = mctree->nodes;
264            
265 0 0         if(key_size > 0) {
266 0           mctree_index_t idx = mctree_make_first_idx(mctree, key, key_size);
267            
268 0 0         if(start[idx].child) {
269 0           return __mtree_search_to_start(mctree, start[idx].child, key, key_size);
270             }
271             }
272            
273 0           return 0;
274             }
275              
276 96           mctree_index_t mctree_search_lowercase(mctree_t* mctree, const char* key, size_t key_size)
277             {
278 96           mctree_node_t* start = mctree->nodes;
279            
280 96 50         if(key_size > 0) {
281 96           mctree_index_t idx = mctree_make_first_idx(mctree, key, key_size);
282            
283 96 100         if(start[idx].child) {
284 8           return __mtree_search_lowercase_to_start(mctree, start[idx].child, key, key_size);
285             }
286             }
287            
288 88           return 0;
289             }
290              
291              
292