Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "gdk.h" /* for GDKmalloc() & GDKfree() */
15 : #include "sql_list.h"
16 :
17 : static node *
18 56947724 : node_create(sql_allocator *sa, void *data)
19 : {
20 56947724 : node *n = (sa)?SA_NEW(sa, node):MNEW(node);
21 :
22 56945515 : if (n == NULL)
23 : return NULL;
24 56945515 : *n = (node) {
25 : .data = data,
26 : };
27 56945515 : return n;
28 : }
29 :
30 : static list *
31 21280902 : list_init(list *l, sql_allocator *sa, fdestroy destroy)
32 : {
33 21280902 : if (l) {
34 21280902 : *l = (list) {
35 : .sa = sa,
36 : .destroy = destroy,
37 : };
38 : }
39 21280902 : return l;
40 : }
41 :
42 : list *
43 573773 : list_create(fdestroy destroy)
44 : {
45 573773 : return list_init(MNEW(list), NULL, destroy);
46 : }
47 :
48 : list *
49 17687525 : sa_list(sql_allocator *sa)
50 : {
51 17687525 : list *l = (sa)?SA_NEW(sa, list):MNEW(list);
52 17687323 : return list_init(l, sa, NULL);
53 : }
54 :
55 : /*
56 : static void
57 : _free(void *dummy, void *data)
58 : {
59 : (void)dummy;
60 : GDKfree(data);
61 : }
62 : */
63 :
64 : list *
65 219 : sa_list_append(sql_allocator *sa, list *l, void *data)
66 : {
67 219 : if (!l)
68 0 : l = SA_LIST(sa, NULL);
69 219 : return list_append(l, data);
70 : }
71 :
72 : list *
73 705772 : list_add(list *l, void *data)
74 : {
75 705772 : if (!l)
76 66391 : l = list_create(NULL);
77 705772 : return list_append(l, data);
78 : }
79 :
80 : list *
81 3019810 : list_new(sql_allocator *sa, fdestroy destroy)
82 : {
83 3019810 : list *l = (sa)?SA_NEW(sa, list):MNEW(list);
84 3019810 : return list_init(l, sa, destroy);
85 : }
86 :
87 : static list *
88 2641485 : list_new_(list *l)
89 : {
90 2641485 : list *res = NULL;
91 2641485 : if (l->sa)
92 2641485 : res = list_new(l->sa, l->destroy);
93 : else
94 0 : res = list_create(l->destroy);
95 2641485 : return res;
96 : }
97 :
98 : int
99 358073046 : list_empty(list *l)
100 : {
101 358073046 : if (l)
102 304487423 : return list_length(l) == 0;
103 : return 1;
104 : }
105 :
106 : static void
107 5336291 : node_destroy_(list *l, void *data, node *n)
108 : {
109 5336291 : if (n->data && l->destroy) {
110 2616005 : l->destroy(data, n->data);
111 2616003 : n->data = NULL;
112 : }
113 5336289 : if (!l->sa)
114 3120878 : _DELETE(n);
115 5336318 : }
116 :
117 : void
118 3451498 : list_destroy2(list *l, void *data)
119 : {
120 3451498 : if (l) {
121 1279347 : node *n = l->h;
122 :
123 1279347 : l->h = NULL;
124 1279347 : if (l->destroy || l->sa == NULL) {
125 4061799 : while (n) {
126 3102164 : node *t = n;
127 :
128 3102164 : n = t->next;
129 3102164 : node_destroy_(l, data, t);
130 : }
131 : }
132 :
133 1279358 : if (l->ht && !l->ht->sa)
134 38588 : hash_destroy(l->ht);
135 :
136 1279358 : if (!l->sa)
137 816427 : _DELETE(l);
138 : }
139 3451509 : }
140 :
141 : void
142 2810804 : list_destroy(list *l)
143 : {
144 2810804 : list_destroy2(l, NULL);
145 2810792 : }
146 :
147 : int
148 480367014 : list_length(list *l)
149 : {
150 480367014 : if (l)
151 479856985 : return l->cnt;
152 : return 0;
153 : }
154 :
155 : static list *
156 54427811 : list_append_node(list *l, node *n)
157 : {
158 54427811 : if (l->cnt) {
159 35871435 : l->t->next = n;
160 : } else {
161 18556376 : l->h = n;
162 : }
163 54427811 : l->t = n;
164 54427811 : l->cnt++;
165 54427811 : if (n->data) {
166 54386870 : if (l->ht) {
167 1246683 : int key = l->ht->key(n->data);
168 :
169 1246683 : if (hash_add(l->ht, key, n->data) == NULL) {
170 : return NULL;
171 : }
172 : }
173 : }
174 : return l;
175 : }
176 :
177 : list *
178 54428763 : list_append(list *l, void *data)
179 : {
180 54428763 : if (l == NULL)
181 : return NULL;
182 54428763 : node *n = node_create(l->sa, data);
183 :
184 54424883 : if (n == NULL)
185 : return NULL;
186 54424883 : return list_append_node(l, n);
187 : }
188 :
189 : void *
190 206 : list_append_with_validate(list *l, void *data, void *extra, fvalidate cmp)
191 : {
192 206 : node *n = node_create(l->sa, data), *m;
193 206 : void* err = NULL;
194 :
195 206 : if (n == NULL)
196 : return NULL;
197 206 : if (l->cnt) {
198 221 : for (m = l->h; m; m = m->next) {
199 152 : err = cmp(m->data, data, extra);
200 152 : if(err) {
201 43 : n->data = NULL;
202 43 : node_destroy_(l, NULL, n);
203 43 : return err;
204 : }
205 : }
206 69 : l->t->next = n;
207 : } else {
208 94 : l->h = n;
209 : }
210 163 : l->t = n;
211 163 : l->cnt++;
212 163 : if (l->ht) {
213 0 : int key = l->ht->key(data);
214 :
215 0 : if (hash_add(l->ht, key, data) == NULL) {
216 : return NULL;
217 : }
218 : }
219 : return NULL;
220 : }
221 :
222 : void *
223 147 : list_append_sorted(list *l, void *data, void *extra, fcmpvalidate cmp)
224 : {
225 147 : node *n = node_create(l->sa, data), *m, *prev = NULL;
226 147 : int first = 1, comp = 0;
227 147 : void* err = NULL;
228 :
229 147 : if (n == NULL)
230 : return NULL;
231 147 : if (l->cnt == 0) {
232 46 : l->h = n;
233 46 : l->t = n;
234 : } else {
235 273 : for (m = l->h; m; m = m->next) {
236 179 : err = cmp(m->data, data, extra, &comp);
237 179 : if(err) {
238 1 : n->data = NULL;
239 1 : node_destroy_(l, NULL, n);
240 1 : return err;
241 : }
242 178 : if(comp < 0)
243 : break;
244 172 : first = 0;
245 172 : prev = m;
246 : }
247 100 : if(first) {
248 3 : n->next = l->h;
249 3 : l->h = n;
250 97 : } else if(!m) {
251 94 : l->t->next = n;
252 94 : l->t = n;
253 : } else {
254 3 : assert(prev);
255 3 : n->next = m;
256 3 : prev->next = n;
257 : }
258 : }
259 146 : l->cnt++;
260 146 : if (l->ht) {
261 0 : int key = l->ht->key(data);
262 :
263 0 : if (hash_add(l->ht, key, data) == NULL) {
264 : return NULL;
265 : }
266 : }
267 : return NULL;
268 : }
269 :
270 : list *
271 40 : list_append_before(list *l, node *m, void *data)
272 : {
273 40 : node *p = l->h;
274 40 : node *n = node_create(l->sa, data);
275 :
276 40 : if (n == NULL)
277 : return NULL;
278 40 : n->next = m;
279 40 : if (p == m){
280 3 : l->h = n;
281 : } else {
282 60 : while (p->next && p->next != m)
283 : p = p->next;
284 37 : p->next = n;
285 : }
286 40 : l->cnt++;
287 40 : if (l->ht) {
288 17 : int key = l->ht->key(data);
289 :
290 17 : if (hash_add(l->ht, key, data) == NULL) {
291 : return NULL;
292 : }
293 : }
294 : return l;
295 : }
296 :
297 : list *
298 2517622 : list_prepend(list *l, void *data)
299 : {
300 2517622 : node *n = node_create(l->sa, data);
301 :
302 2517622 : if (n == NULL)
303 : return NULL;
304 2517622 : if (!l->cnt) {
305 550252 : l->t = n;
306 : }
307 2517622 : n->next = l->h;
308 2517622 : l->h = n;
309 2517622 : l->cnt++;
310 2517622 : if (l->ht) {
311 3 : int key = l->ht->key(data);
312 :
313 3 : if (hash_add(l->ht, key, data) == NULL) {
314 : return NULL;
315 : }
316 : }
317 : return l;
318 : }
319 :
320 : static void
321 630841 : hash_delete(sql_hash *h, void *data)
322 : {
323 630841 : int key = h->key(data);
324 630841 : sql_hash_e *e, *p = h->buckets[key&(h->size-1)];
325 :
326 630841 : e = p;
327 1090307 : for (; p && p->value != data ; p = p->chain)
328 459466 : e = p;
329 630841 : if (p && p->value == data) {
330 630841 : if (p == e)
331 390882 : h->buckets[key&(h->size-1)] = p->chain;
332 : else
333 239959 : e->chain = p->chain;
334 : }
335 630841 : h->entries--;
336 630841 : }
337 :
338 : static node *
339 2234070 : list_remove_node_(list *l, node *n)
340 : {
341 2234070 : void *data = n->data;
342 2234070 : node *p = l->h;
343 :
344 2234070 : if (p != n)
345 9027814 : while (p && p->next != n)
346 : p = p->next;
347 2234070 : assert(p==n||(p && p->next == n));
348 2234070 : if (p == n) {
349 1119086 : l->h = n->next;
350 1119086 : p = NULL;
351 1114984 : } else if ( p != NULL) {
352 1114984 : p->next = n->next;
353 : }
354 2234070 : if (n == l->t)
355 959460 : l->t = p;
356 2234070 : if (data) {
357 1037309 : if (l->ht && data)
358 630763 : hash_delete(l->ht, data);
359 : }
360 2234070 : l->cnt--;
361 2234070 : assert(l->cnt > 0 || l->h == NULL);
362 2234070 : return p;
363 : }
364 :
365 : node *
366 2234070 : list_remove_node(list *l, void *gdata, node *n)
367 : {
368 2234070 : node *p = list_remove_node_(l, n);
369 :
370 2234067 : node_destroy_(l, gdata, n);
371 2234069 : return p;
372 : }
373 :
374 : void
375 1192014 : list_remove_data(list *s, void *gdata, void *data)
376 : {
377 1192014 : node *n;
378 :
379 : /* maybe use compare func */
380 1192014 : if (s == NULL)
381 : return;
382 2761766 : for (n = s->h; n; n = n->next) {
383 2761766 : if (n->data == data) {
384 1192014 : if (s->ht && n->data)
385 78 : hash_delete(s->ht, n->data);
386 1192014 : n->data = NULL;
387 1192014 : list_remove_node(s, gdata, n);
388 1192014 : break;
389 : }
390 : }
391 : }
392 :
393 : void
394 0 : list_remove_list(list *l, void *gdata, list *data)
395 : {
396 0 : node *n;
397 :
398 0 : for (n=data->h; n; n = n->next)
399 0 : list_remove_data(l, gdata, n->data);
400 0 : }
401 :
402 : list *
403 0 : list_move_data(list *s, list *d, void *data)
404 : {
405 0 : node *n = NULL;
406 :
407 0 : for (n = s->h; n; n = n->next) {
408 0 : if (n->data == data) {
409 0 : if (s->ht && n->data)
410 0 : hash_delete(s->ht, n->data);
411 0 : n->data = NULL; /* make sure data isn't destroyed */
412 0 : (void)list_remove_node_(s, n);
413 0 : n->data = data;
414 0 : break;
415 : }
416 : }
417 0 : if (!n) {
418 0 : return list_append(d, data);
419 : } else {
420 0 : n->next = NULL;
421 0 : return list_append_node(d, n);
422 : }
423 : }
424 :
425 : int
426 1210475 : list_check_prop_all(list *l, prop_check_func f)
427 : {
428 1210475 : int res = 1;
429 1210475 : if (l)
430 7387221 : for (node *n = l->h; n && res; n = n->next)
431 6176746 : res &= f(n->data);
432 1210475 : return res;
433 : }
434 :
435 : void
436 2039 : list_revert(list *l)
437 : {
438 2039 : node *c = NULL;
439 :
440 2039 : l->t = l->h;
441 13766 : for (node *o = l->h; o; ) {
442 11727 : node *nxt = o->next;
443 :
444 11727 : o->next = c;
445 11727 : c = o;
446 :
447 11727 : o = nxt;
448 : }
449 2039 : l->h = c;
450 2039 : }
451 :
452 : int
453 0 : list_traverse(list *l, traverse_func f, void *clientdata)
454 : {
455 0 : int res = 0, seqnr = 0;
456 0 : node *n = l->h;
457 :
458 0 : while (n && !res) {
459 0 : res = f(clientdata, seqnr++, n->data);
460 0 : n = n->next;
461 : }
462 0 : return res;
463 : }
464 :
465 : void *
466 5 : list_transverse_with_validate(list *l, void *data, void *extra, fvalidate cmp)
467 : {
468 5 : void* err = NULL;
469 :
470 14 : for (node *n = l->h; n; n = n->next) {
471 9 : err = cmp(n->data, data, extra);
472 9 : if(err)
473 : break;
474 : }
475 5 : return err;
476 : }
477 :
478 : node *
479 9803956 : list_find(list *l, void *key, fcmp cmp)
480 : {
481 9803956 : node *n = NULL;
482 :
483 9803956 : if (key) {
484 9803956 : if (cmp) {
485 67231458 : for (n = l->h; n; n = n->next) {
486 62676350 : if (cmp(n->data, key) == 0) {
487 5212558 : return n;
488 : }
489 : }
490 : } else {
491 49753 : for (n = l->h; n; n = n->next) {
492 26155 : if (n->data == key)
493 12692 : return n;
494 : }
495 : }
496 : }
497 : return NULL;
498 : }
499 :
500 : int
501 17306694 : list_cmp(list *l1, list *l2, fcmp cmp)
502 : {
503 17306694 : node *n, *m;
504 17306694 : int res = 0;
505 :
506 17306694 : if (l1 == l2)
507 : return 0;
508 17306692 : if (!l1 && l2 && list_empty(l2))
509 : return 0;
510 17306692 : if (!l2 && l1 && list_empty(l1))
511 : return 0;
512 17304377 : if (!l1 || !l2 || (list_length(l1) != list_length(l2)))
513 148471 : return -1;
514 :
515 36303559 : for (n = l1->h, m = l2->h; res == 0 && n; n = n->next, m = m->next) {
516 19147655 : res = cmp(n->data, m->data);
517 : }
518 : return res;
519 : }
520 :
521 : int
522 6384 : list_match(list *l1, list *l2, fcmp cmp)
523 : {
524 6384 : node *n, *m;
525 6384 : ulng chk = 0;
526 :
527 6384 : if (l1 == l2)
528 : return 0;
529 :
530 6384 : if (!l1 || !l2 || (list_length(l1) != list_length(l2)))
531 4316 : return -1;
532 :
533 4413 : for (n = l1->h; n; n = n->next) {
534 2503 : int pos = 0, fnd = 0;
535 8220 : for (m = l2->h; m; m = m->next, pos++) {
536 9891 : if (!(chk & ((ulng) 1 << pos)) &&
537 4174 : cmp(n->data, m->data) == 0) {
538 2345 : chk |= (ulng) 1 << pos;
539 2345 : fnd = 1;
540 : }
541 : }
542 2503 : if (!fnd)
543 : return -1;
544 : }
545 : return 0;
546 : }
547 :
548 : list *
549 0 : list_keysort(list *l, int *keys, fdup dup)
550 : {
551 0 : list *res;
552 0 : node *n = NULL;
553 0 : int i, cnt = list_length(l);
554 0 : void **data;
555 :
556 0 : data = GDKmalloc(cnt*sizeof(void *));
557 0 : if (data == NULL) {
558 : return NULL;
559 : }
560 0 : res = list_new_(l);
561 0 : if (res == NULL) {
562 0 : GDKfree(data);
563 0 : return NULL;
564 : }
565 0 : for (n = l->h, i = 0; n; n = n->next, i++) {
566 0 : data[i] = n->data;
567 : }
568 : /* sort descending */
569 0 : GDKqsort(keys, data, NULL, cnt, sizeof(int), sizeof(void *), TYPE_int, true, true);
570 0 : for(i=0; i<cnt; i++) {
571 0 : list_append(res, dup?dup(data[i]):data[i]);
572 : }
573 0 : GDKfree(data);
574 0 : return res;
575 : }
576 :
577 : list *
578 143213 : list_sort(list *l, fkeyvalue key, fdup dup)
579 : {
580 143213 : list *res;
581 143213 : node *n = NULL;
582 143213 : int i, *keys, cnt = list_length(l);
583 143213 : void **data;
584 :
585 143213 : keys = GDKmalloc(cnt*sizeof(int));
586 143213 : data = GDKmalloc(cnt*sizeof(void *));
587 143213 : if (keys == NULL || data == NULL) {
588 0 : GDKfree(keys);
589 0 : GDKfree(data);
590 0 : return NULL;
591 : }
592 143213 : res = list_new_(l);
593 143213 : if (res == NULL) {
594 0 : GDKfree(keys);
595 0 : GDKfree(data);
596 0 : return NULL;
597 : }
598 561525 : for (n = l->h, i = 0; n; n = n->next, i++) {
599 418312 : keys[i] = key(n->data);
600 418312 : data[i] = n->data;
601 : }
602 : /* sort descending */
603 143213 : GDKqsort(keys, data, NULL, cnt, sizeof(int), sizeof(void *), TYPE_int, true, true);
604 704738 : for(i=0; i<cnt; i++) {
605 418312 : list_append(res, dup?dup(data[i]):data[i]);
606 : }
607 143213 : GDKfree(keys);
608 143213 : GDKfree(data);
609 143213 : return res;
610 : }
611 :
612 : list *
613 1120829 : list_select(list *l, void *key, fcmp cmp, fdup dup)
614 : {
615 1120829 : list *res = NULL;
616 1120829 : node *n = NULL;
617 :
618 1120829 : if (key && l) {
619 1120829 : res = list_new_(l);
620 1120829 : if(res) {
621 4555494 : for (n = l->h; n; n = n->next)
622 3434665 : if (cmp(n->data, key) == 0)
623 1985865 : list_append(res, dup?dup(n->data):n->data);
624 : }
625 : }
626 1120829 : return res;
627 : }
628 :
629 : /* order the list based on the compare function cmp */
630 : list *
631 0 : list_order(list *l, fcmp cmp, fdup dup)
632 : {
633 0 : list *res = list_new_(l);
634 0 : node *m, *n = NULL;
635 :
636 : /* use simple insert sort */
637 0 : if(res) {
638 0 : for (n = l->h; n; n = n->next) {
639 0 : int append = 1;
640 0 : for (m = res->h; m && append; m = m->next) {
641 0 : if (cmp(n->data, m->data) > 0) {
642 0 : list_append_before(res, m, dup ? dup(n->data) : n->data);
643 0 : append = 0;
644 : }
645 : }
646 0 : if (append)
647 0 : list_append(res, dup ? dup(n->data) : n->data);
648 : }
649 : }
650 0 : return res;
651 : }
652 :
653 : list *
654 53443 : list_distinct(list *l, fcmp cmp, fdup dup)
655 : {
656 53443 : list *res = list_new_(l);
657 53443 : node *n = NULL;
658 :
659 53443 : if(res) {
660 192374 : for (n = l->h; n; n = n->next) {
661 138931 : if (!list_find(res, n->data, cmp)) {
662 125116 : list_append(res, dup ? dup(n->data) : n->data);
663 : }
664 : }
665 : }
666 53443 : return res;
667 : }
668 :
669 : int
670 3338167 : list_position(list *l, void *val)
671 : {
672 3338167 : node *n = NULL;
673 3338167 : int i;
674 :
675 40497013 : for (n = l->h, i=0; n && val != n->data; n = n->next, i++)
676 : ;
677 3338167 : if (n && n->data == val)
678 1778374 : return i;
679 : return -1;
680 : }
681 :
682 : void *
683 344272 : list_fetch(list *l, int pos)
684 : {
685 344272 : node *n = NULL;
686 344272 : int i;
687 :
688 1406348 : for (n = l->h, i=0; n && i<pos; n = n->next, i++)
689 : ;
690 344272 : if (n)
691 344272 : return n->data;
692 : return NULL;
693 : }
694 :
695 : void *
696 0 : list_reduce(list *l, freduce red, fdup dup)
697 : {
698 0 : void *res = NULL;
699 0 : node *n = l->h;
700 :
701 0 : if (n) {
702 0 : res = dup?dup(n->data):n->data;
703 0 : for (n = n->next; n; n = n->next) {
704 0 : res = red(res, dup?dup(n->data):n->data);
705 : }
706 : }
707 0 : return res;
708 : }
709 :
710 : void *
711 0 : list_reduce2(list *l, freduce2 red, sql_allocator *sa)
712 : {
713 0 : void *res = NULL;
714 0 : node *n = l->h;
715 :
716 0 : if (n) {
717 0 : res = n->data;
718 0 : for (n = n->next; n; n = n->next)
719 0 : res = red(sa, res, n->data);
720 : }
721 0 : return res;
722 : }
723 :
724 :
725 : list *
726 1241870 : list_map(list *l, void *data, fmap map)
727 : {
728 1241870 : list *res = list_new_(l);
729 :
730 1241870 : node *n = l->h;
731 :
732 1241870 : if(res) {
733 2514060 : while (n) {
734 1272190 : void *v = map(n->data, data);
735 :
736 1272190 : if (v)
737 1256758 : list_append(res, v);
738 1272190 : n = n->next;
739 : }
740 : }
741 1241870 : return res;
742 : }
743 :
744 : list *
745 626519 : list_merge(list *l, list *data, fdup dup)
746 : {
747 626519 : if (data) {
748 483033 : node *n = data->h;
749 :
750 2468738 : while (n) {
751 1985706 : if (dup && n->data)
752 0 : list_append(l, dup(n->data));
753 : else
754 1985706 : list_append(l, n->data);
755 1985705 : n = n->next;
756 : }
757 : }
758 626518 : return l;
759 : }
760 :
761 : list *
762 0 : list_merge_destroy(list *l, list *data, fdup dup)
763 : {
764 0 : if (data) {
765 0 : node *n = data->h;
766 :
767 0 : while (n) {
768 0 : if (dup)
769 0 : list_append(l, dup(n->data));
770 : else
771 0 : list_append(l, n->data);
772 0 : n = n->next;
773 : }
774 : }
775 :
776 0 : list_destroy(data);
777 :
778 0 : return l;
779 : }
780 :
781 : list *
782 81604 : list_dup(list *l, fdup dup)
783 : {
784 81604 : list *res = list_new_(l);
785 81604 : return res ? list_merge(res, l, dup) : NULL;
786 : }
787 :
788 : list *
789 526 : list_flatten(list *l)
790 : {
791 526 : list *res = list_new_(l);
792 526 : if (res) {
793 1355 : for (node *n = l->h ; n ; n = n->next) {
794 829 : list *ll = (list*) n->data;
795 1714 : for (node *m = ll->h ; m ; m = m->next)
796 885 : list_append(res, m->data);
797 : }
798 : }
799 526 : return res;
800 : }
801 :
802 : void
803 0 : list_hash_delete(list *l, void *data, fcmp cmp)
804 : {
805 0 : if (l && data) {
806 0 : node *n = list_find(l, data, cmp);
807 0 : if(n) {
808 0 : if (l->ht && n->data)
809 0 : hash_delete(l->ht, data);
810 : }
811 : }
812 0 : }
813 :
814 : void*
815 0 : list_hash_add(list *l, void *data, fcmp cmp)
816 : {
817 0 : if (l && data) {
818 0 : node *n = list_find(l, data, cmp);
819 0 : if(n) {
820 0 : if (l->ht && n->data) {
821 0 : int nkey = l->ht->key(data);
822 0 : if (hash_add(l->ht, nkey, data) == NULL) {
823 : return NULL;
824 : }
825 : }
826 : }
827 : }
828 : return data;
829 : }
830 :
831 : void
832 586478 : list_hash_clear(list *l)
833 : {
834 586478 : l->ht = NULL;
835 586478 : }
|