LCOV - code coverage report
Current view: top level - sql/common - sql_list.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 322 434 74.2 %
Date: 2024-12-20 20:06:10 Functions: 38 48 79.2 %

          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    56891794 : node_create(allocator *sa, void *data)
      19             : {
      20    56891794 :         node *n = (sa)?SA_NEW(sa, node):MNEW(node);
      21             : 
      22    56889898 :         if (n == NULL)
      23             :                 return NULL;
      24    56889898 :         *n = (node) {
      25             :                 .data = data,
      26             :         };
      27    56889898 :         return n;
      28             : }
      29             : 
      30             : static list *
      31    21269615 : list_init(list *l, allocator *sa, fdestroy destroy)
      32             : {
      33    21269615 :         if (l) {
      34    21269615 :                 *l = (list) {
      35             :                         .sa = sa,
      36             :                         .destroy = destroy,
      37             :                 };
      38             :         }
      39    21269615 :         return l;
      40             : }
      41             : 
      42             : list *
      43      588630 : list_create(fdestroy destroy)
      44             : {
      45      588630 :         return list_init(MNEW(list), NULL, destroy);
      46             : }
      47             : 
      48             : list *
      49    17713226 : sa_list(allocator *sa)
      50             : {
      51    17713226 :         list *l = (sa)?SA_NEW(sa, list):MNEW(list);
      52    17713046 :         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         218 : sa_list_append(allocator *sa, list *l, void *data)
      66             : {
      67         218 :         if (!l)
      68           0 :                 l = SA_LIST(sa, NULL);
      69         218 :         return list_append(l, data);
      70             : }
      71             : 
      72             : list *
      73      736403 : list_add(list *l, void *data)
      74             : {
      75      736403 :         if (!l)
      76       67717 :                 l = list_create(NULL);
      77      736403 :         return list_append(l, data);
      78             : }
      79             : 
      80             : list *
      81     2967940 : list_new(allocator *sa, fdestroy destroy)
      82             : {
      83     2967940 :         list *l = (sa)?SA_NEW(sa, list):MNEW(list);
      84     2967940 :         return list_init(l, sa, destroy);
      85             : }
      86             : 
      87             : static list *
      88     2585049 : list_new_(list *l)
      89             : {
      90     2585049 :         list *res = NULL;
      91     2585049 :         if (l->sa)
      92     2585049 :                 res = list_new(l->sa, l->destroy);
      93             :         else
      94           0 :                 res = list_create(l->destroy);
      95     2585049 :         return res;
      96             : }
      97             : 
      98             : int
      99   254789405 : list_empty(list *l)
     100             : {
     101   254789405 :         if (l)
     102   223390857 :                 return list_length(l) == 0;
     103             :         return 1;
     104             : }
     105             : 
     106             : static void
     107     5472446 : node_destroy_(list *l, void *data, node *n)
     108             : {
     109     5472446 :         if (n->data && l->destroy) {
     110     2661224 :                 l->destroy(data, n->data);
     111     2661231 :                 n->data = NULL;
     112             :         }
     113     5472453 :         if (!l->sa)
     114     3191562 :                 _DELETE(n);
     115     5472536 : }
     116             : 
     117             : void
     118     3567794 : list_destroy2(list *l, void *data)
     119             : {
     120     3567794 :         if (l) {
     121     1326790 :                 node *n = l->h;
     122             : 
     123     1326790 :                 l->h = NULL;
     124     1326790 :                 if (l->destroy || l->sa == NULL) {
     125     4163917 :                         while (n) {
     126     3177965 :                                 node *t = n;
     127             : 
     128     3177965 :                                 n = t->next;
     129     3177965 :                                 node_destroy_(l, data, t);
     130             :                         }
     131             :                 }
     132             : 
     133     1326804 :                 if (l->ht && !l->ht->sa)
     134       37874 :                         hash_destroy(l->ht);
     135             : 
     136     1326804 :                 if (!l->sa)
     137      832798 :                         _DELETE(l);
     138             :         }
     139     3567808 : }
     140             : 
     141             : void
     142     2914371 : list_destroy(list *l)
     143             : {
     144     2914371 :         list_destroy2(l, NULL);
     145     2914357 : }
     146             : 
     147             : int
     148   302801933 : list_length(list *l)
     149             : {
     150   302801933 :         if (l)
     151   302267956 :                 return l->cnt;
     152             :         return 0;
     153             : }
     154             : 
     155             : static list *
     156    54297519 : list_append_node(list *l, node *n)
     157             : {
     158    54297519 :         if (l->cnt) {
     159    35834072 :                 l->t->next = n;
     160             :         } else {
     161    18463447 :                 l->h = n;
     162             :         }
     163    54297519 :         l->t = n;
     164    54297519 :         l->cnt++;
     165    54297519 :         if (n->data) {
     166    54256342 :                 if (l->ht) {
     167      941402 :                         int key = l->ht->key(n->data);
     168             : 
     169      941402 :                         if (hash_add(l->ht, key, n->data) == NULL) {
     170             :                                 return NULL;
     171             :                         }
     172             :                 }
     173             :         }
     174             :         return l;
     175             : }
     176             : 
     177             : list *
     178    54298055 : list_append(list *l, void *data)
     179             : {
     180    54298055 :         if (l == NULL)
     181             :                 return NULL;
     182    54298055 :         node *n = node_create(l->sa, data);
     183             : 
     184    54295244 :         if (n == NULL)
     185             :                 return NULL;
     186    54295244 :         return list_append_node(l, n);
     187             : }
     188             : 
     189             : void *
     190         234 : list_append_with_validate(list *l, void *data, void *extra, fvalidate cmp)
     191             : {
     192         234 :         node *n = node_create(l->sa, data), *m;
     193         234 :         void* err = NULL;
     194             : 
     195         234 :         if (n == NULL)
     196             :                 return NULL;
     197         234 :         if (l->cnt) {
     198         255 :                 for (m = l->h; m; m = m->next) {
     199         171 :                         err = cmp(m->data, data, extra);
     200         171 :                         if(err) {
     201          43 :                                 n->data = NULL;
     202          43 :                                 node_destroy_(l, NULL, n);
     203          43 :                                 return err;
     204             :                         }
     205             :                 }
     206          84 :                 l->t->next = n;
     207             :         } else {
     208         107 :                 l->h = n;
     209             :         }
     210         191 :         l->t = n;
     211         191 :         l->cnt++;
     212         191 :         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         165 : list_append_sorted(list *l, void *data, void *extra, fcmpvalidate cmp)
     224             : {
     225         165 :         node *n = node_create(l->sa, data), *m, *prev = NULL;
     226         165 :         int first = 1, comp = 0;
     227         165 :         void* err = NULL;
     228             : 
     229         165 :         if (n == NULL)
     230             :                 return NULL;
     231         165 :         if (l->cnt == 0) {
     232          52 :                 l->h = n;
     233          52 :                 l->t = n;
     234             :         } else {
     235         303 :                 for (m = l->h; m; m = m->next) {
     236         197 :                         err = cmp(m->data, data, extra, &comp);
     237         197 :                         if(err) {
     238           1 :                                 n->data = NULL;
     239           1 :                                 node_destroy_(l, NULL, n);
     240           1 :                                 return err;
     241             :                         }
     242         196 :                         if(comp < 0)
     243             :                                 break;
     244         190 :                         first = 0;
     245         190 :                         prev = m;
     246             :                 }
     247         112 :                 if(first) {
     248           3 :                         n->next = l->h;
     249           3 :                         l->h = n;
     250         109 :                 } else if(!m) {
     251         106 :                         l->t->next = n;
     252         106 :                         l->t = n;
     253             :                 } else {
     254           3 :                         assert(prev);
     255           3 :                         n->next = m;
     256           3 :                         prev->next = n;
     257             :                 }
     258             :         }
     259         164 :         l->cnt++;
     260         164 :         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          35 : list_append_before(list *l, node *m, void *data)
     272             : {
     273          35 :         node *p = l->h;
     274          35 :         node *n = node_create(l->sa, data);
     275             : 
     276          35 :         if (n == NULL)
     277             :                 return NULL;
     278          35 :         n->next = m;
     279          35 :         if (p == m){
     280           0 :                 l->h = n;
     281             :         } else {
     282          57 :                 while (p->next && p->next != m)
     283             :                         p = p->next;
     284          35 :                 p->next = n;
     285             :         }
     286          35 :         l->cnt++;
     287          35 :         if (l->ht) {
     288          14 :                 int key = l->ht->key(data);
     289             : 
     290          14 :                 if (hash_add(l->ht, key, data) == NULL) {
     291             :                         return NULL;
     292             :                 }
     293             :         }
     294             :         return l;
     295             : }
     296             : 
     297             : list *
     298     2592440 : list_prepend(list *l, void *data)
     299             : {
     300     2592440 :         node *n = node_create(l->sa, data);
     301             : 
     302     2592440 :         if (n == NULL)
     303             :                 return NULL;
     304     2592440 :         if (!l->cnt) {
     305      580828 :                 l->t = n;
     306             :         }
     307     2592440 :         n->next = l->h;
     308     2592440 :         l->h = n;
     309     2592440 :         l->cnt++;
     310     2592440 :         if (l->ht) {
     311           0 :                 int key = l->ht->key(data);
     312             : 
     313           0 :                 if (hash_add(l->ht, key, data) == NULL) {
     314             :                         return NULL;
     315             :                 }
     316             :         }
     317             :         return l;
     318             : }
     319             : 
     320             : static void
     321       24706 : hash_delete(sql_hash *h, void *data)
     322             : {
     323       24706 :         int key = h->key(data);
     324       24706 :         sql_hash_e *e, *p = h->buckets[key&(h->size-1)];
     325             : 
     326       24706 :         e = p;
     327       31915 :         for (;  p && p->value != data ; p = p->chain)
     328        7209 :                 e = p;
     329       24706 :         if (p && p->value == data) {
     330       24706 :                 if (p == e)
     331       19095 :                         h->buckets[key&(h->size-1)] = p->chain;
     332             :                 else
     333        5611 :                         e->chain = p->chain;
     334             :         }
     335       24706 :         h->entries--;
     336       24706 : }
     337             : 
     338             : static node *
     339     2294395 : list_remove_node_(list *l, node *n)
     340             : {
     341     2294395 :         void *data = n->data;
     342     2294395 :         node *p = l->h;
     343             : 
     344     2294395 :         if (p != n)
     345     9299550 :                 while (p && p->next != n)
     346             :                         p = p->next;
     347     2294395 :         assert(p==n||(p && p->next == n));
     348     2294395 :         if (p == n) {
     349     1161932 :                 l->h = n->next;
     350     1161932 :                 p = NULL;
     351     1132463 :         } else if ( p != NULL)  {
     352     1132463 :                 p->next = n->next;
     353             :         }
     354     2294395 :         if (n == l->t)
     355      984569 :                 l->t = p;
     356     2294395 :         if (data) {
     357     1087510 :                 if (l->ht && data)
     358       24628 :                         hash_delete(l->ht, data);
     359             :         }
     360     2294395 :         l->cnt--;
     361     2294395 :         assert(l->cnt > 0 || l->h == NULL);
     362     2294395 :         return p;
     363             : }
     364             : 
     365             : node *
     366     2294395 : list_remove_node(list *l, void *gdata, node *n)
     367             : {
     368     2294395 :         node *p = list_remove_node_(l, n);
     369             : 
     370     2294395 :         node_destroy_(l, gdata, n);
     371     2294392 :         return p;
     372             : }
     373             : 
     374             : void
     375     1202117 : list_remove_data(list *s, void *gdata, void *data)
     376             : {
     377     1202117 :         node *n;
     378             : 
     379             :         /* maybe use compare func */
     380     1202117 :         if (s == NULL)
     381             :                 return;
     382     2534103 :         for (n = s->h; n; n = n->next) {
     383     2534103 :                 if (n->data == data) {
     384     1202117 :                         if (s->ht && n->data)
     385          78 :                                 hash_delete(s->ht, n->data);
     386     1202117 :                         n->data = NULL;
     387     1202117 :                         list_remove_node(s, gdata, n);
     388     1202117 :                         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     1084104 : list_check_prop_all(list *l, prop_check_func f)
     427             : {
     428     1084104 :         int res = 1;
     429     1084104 :         if (l)
     430     6835642 :                 for (node *n = l->h; n && res; n = n->next)
     431     5751538 :                         res &= f(n->data);
     432     1084104 :         return res;
     433             : }
     434             : 
     435             : void
     436        2138 : list_revert(list *l)
     437             : {
     438        2138 :         node *c = NULL;
     439             : 
     440        2138 :         l->t = l->h;
     441       14023 :         for (node *o = l->h; o; ) {
     442       11885 :                 node *nxt = o->next;
     443             : 
     444       11885 :                 o->next = c;
     445       11885 :                 c = o;
     446             : 
     447       11885 :                 o = nxt;
     448             :         }
     449        2138 :         l->h = c;
     450        2138 : }
     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     7274871 : list_find(list *l, void *key, fcmp cmp)
     480             : {
     481     7274871 :         node *n = NULL;
     482             : 
     483     7274871 :         if (key) {
     484     7274871 :                 if (cmp) {
     485    36179709 :                         for (n = l->h; n; n = n->next) {
     486    32420868 :                                 if (cmp(n->data, key) == 0) {
     487     3468513 :                                         return n;
     488             :                                 }
     489             :                         }
     490             :                 } else {
     491       64212 :                         for (n = l->h; n; n = n->next) {
     492       31007 :                                 if (n->data == key)
     493       14312 :                                         return n;
     494             :                         }
     495             :                 }
     496             :         }
     497             :         return NULL;
     498             : }
     499             : 
     500             : int
     501     3987567 : list_cmp(list *l1, list *l2, fcmp cmp)
     502             : {
     503     3987567 :         node *n, *m;
     504     3987567 :         int res = 0;
     505             : 
     506     3987567 :         if (l1 == l2)
     507             :                 return 0;
     508     3987565 :         if (!l1 && l2 && list_empty(l2))
     509             :                 return 0;
     510     3987565 :         if (!l2 && l1 && list_empty(l1))
     511             :                 return 0;
     512     3985301 :         if (!l1 || !l2 || (list_length(l1) != list_length(l2)))
     513      107234 :                 return -1;
     514             : 
     515     8258723 :         for (n = l1->h, m = l2->h; res == 0 && n; n = n->next, m = m->next) {
     516     4380656 :                 res = cmp(n->data, m->data);
     517             :         }
     518             :         return res;
     519             : }
     520             : 
     521             : int
     522        6349 : list_match(list *l1, list *l2, fcmp cmp)
     523             : {
     524        6349 :         node *n, *m;
     525        6349 :         ulng chk = 0;
     526             : 
     527        6349 :         if (l1 == l2)
     528             :                 return 0;
     529             : 
     530        6349 :         if (!l1 || !l2 || (list_length(l1) != list_length(l2)))
     531        4227 :                 return -1;
     532             : 
     533        4518 :         for (n = l1->h; n; n = n->next) {
     534        2552 :                 int pos = 0, fnd = 0;
     535        8322 :                 for (m = l2->h; m; m = m->next, pos++) {
     536        9991 :                         if (!(chk & ((ulng) 1 << pos)) &&
     537        4221 :                             cmp(n->data, m->data) == 0) {
     538        2396 :                                 chk |= (ulng) 1 << pos;
     539        2396 :                                 fnd = 1;
     540             :                         }
     541             :                 }
     542        2552 :                 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      153153 : list_sort(list *l, fkeyvalue key, fdup dup)
     579             : {
     580      153153 :         list *res;
     581      153153 :         node *n = NULL;
     582      153153 :         int i, *keys, cnt = list_length(l);
     583      153153 :         void **data;
     584             : 
     585      153153 :         keys = GDKmalloc(cnt*sizeof(int));
     586      153153 :         data = GDKmalloc(cnt*sizeof(void *));
     587      153153 :         if (keys == NULL || data == NULL) {
     588           0 :                 GDKfree(keys);
     589           0 :                 GDKfree(data);
     590           0 :                 return NULL;
     591             :         }
     592      153153 :         res = list_new_(l);
     593      153153 :         if (res == NULL) {
     594           0 :                 GDKfree(keys);
     595           0 :                 GDKfree(data);
     596           0 :                 return NULL;
     597             :         }
     598      580122 :         for (n = l->h, i = 0; n; n = n->next, i++) {
     599      426969 :                 keys[i] = key(n->data);
     600      426969 :                 data[i] = n->data;
     601             :         }
     602             :         /* sort descending */
     603      153153 :         GDKqsort(keys, data, NULL, cnt, sizeof(int), sizeof(void *), TYPE_int, true, true);
     604      733275 :         for(i=0; i<cnt; i++) {
     605      426969 :                 list_append(res, dup?dup(data[i]):data[i]);
     606             :         }
     607      153153 :         GDKfree(keys);
     608      153153 :         GDKfree(data);
     609      153153 :         return res;
     610             : }
     611             : 
     612             : list *
     613     1080609 : list_select(list *l, void *key, fcmp cmp, fdup dup)
     614             : {
     615     1080609 :         list *res = NULL;
     616     1080609 :         node *n = NULL;
     617             : 
     618     1080609 :         if (key && l) {
     619     1080609 :                 res = list_new_(l);
     620     1080609 :                 if(res) {
     621     4434344 :                         for (n = l->h; n; n = n->next)
     622     3353735 :                                 if (cmp(n->data, key) == 0)
     623     1947864 :                                         list_append(res, dup?dup(n->data):n->data);
     624             :                 }
     625             :         }
     626     1080609 :         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       54450 : list_distinct(list *l, fcmp cmp, fdup dup)
     655             : {
     656       54450 :         list *res = list_new_(l);
     657       54450 :         node *n = NULL;
     658             : 
     659       54450 :         if(res) {
     660      194750 :                 for (n = l->h; n; n = n->next) {
     661      140300 :                         if (!list_find(res, n->data, cmp)) {
     662      126620 :                                 list_append(res, dup ? dup(n->data) : n->data);
     663             :                         }
     664             :                 }
     665             :         }
     666       54450 :         return res;
     667             : }
     668             : 
     669             : int
     670     4281618 : list_position(list *l, void *val)
     671             : {
     672     4281618 :         node *n = NULL;
     673     4281618 :         int i;
     674             : 
     675    47692500 :         for (n = l->h, i=0; n && val != n->data; n = n->next, i++)
     676             :                 ;
     677     4281618 :         if (n && n->data == val)
     678     1961618 :                 return i;
     679             :         return -1;
     680             : }
     681             : 
     682             : void *
     683      568016 : list_fetch(list *l, int pos)
     684             : {
     685      568016 :         node *n = NULL;
     686      568016 :         int i;
     687             : 
     688     4543449 :         for (n = l->h, i=0; n && i<pos; n = n->next, i++)
     689             :                 ;
     690      568016 :         if (n)
     691      568016 :                 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, 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     1213192 : list_map(list *l, void *data, fmap map)
     727             : {
     728     1213192 :         list *res = list_new_(l);
     729             : 
     730     1213192 :         node *n = l->h;
     731             : 
     732     1213192 :         if(res) {
     733     2448358 :                 while (n) {
     734     1235166 :                         void *v = map(n->data, data);
     735             : 
     736     1235166 :                         if (v)
     737     1216774 :                                 list_append(res, v);
     738     1235166 :                         n = n->next;
     739             :                 }
     740             :         }
     741     1213192 :         return res;
     742             : }
     743             : 
     744             : list *
     745      650014 : list_merge(list *l, list *data, fdup dup)
     746             : {
     747      650014 :         if (data) {
     748      496796 :                 node *n = data->h;
     749             : 
     750     2575819 :                 while (n) {
     751     2079023 :                         if (dup && n->data)
     752           4 :                                 list_append(l, dup(n->data));
     753             :                         else
     754     2079019 :                                 list_append(l, n->data);
     755     2079023 :                         n = n->next;
     756             :                 }
     757             :         }
     758      650014 :         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       83119 : list_dup(list *l, fdup dup)
     783             : {
     784       83119 :         list *res = list_new_(l);
     785       83119 :         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      686167 : list_hash_clear(list *l)
     833             : {
     834      686167 :         l->ht = NULL;
     835      686167 : }

Generated by: LCOV version 1.14