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-11-12 19:36:54 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    56834345 : node_create(allocator *sa, void *data)
      19             : {
      20    56834345 :         node *n = (sa)?SA_NEW(sa, node):MNEW(node);
      21             : 
      22    56834469 :         if (n == NULL)
      23             :                 return NULL;
      24    56834469 :         *n = (node) {
      25             :                 .data = data,
      26             :         };
      27    56834469 :         return n;
      28             : }
      29             : 
      30             : static list *
      31    21248282 : list_init(list *l, allocator *sa, fdestroy destroy)
      32             : {
      33    21248282 :         if (l) {
      34    21248282 :                 *l = (list) {
      35             :                         .sa = sa,
      36             :                         .destroy = destroy,
      37             :                 };
      38             :         }
      39    21248282 :         return l;
      40             : }
      41             : 
      42             : list *
      43      583513 : list_create(fdestroy destroy)
      44             : {
      45      583513 :         return list_init(MNEW(list), NULL, destroy);
      46             : }
      47             : 
      48             : list *
      49    17697958 : sa_list(allocator *sa)
      50             : {
      51    17697958 :         list *l = (sa)?SA_NEW(sa, list):MNEW(list);
      52    17698180 :         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      734757 : list_add(list *l, void *data)
      74             : {
      75      734757 :         if (!l)
      76       67813 :                 l = list_create(NULL);
      77      734771 :         return list_append(l, data);
      78             : }
      79             : 
      80             : list *
      81     2966514 : list_new(allocator *sa, fdestroy destroy)
      82             : {
      83     2966514 :         list *l = (sa)?SA_NEW(sa, list):MNEW(list);
      84     2966514 :         return list_init(l, sa, destroy);
      85             : }
      86             : 
      87             : static list *
      88     2586271 : list_new_(list *l)
      89             : {
      90     2586271 :         list *res = NULL;
      91     2586271 :         if (l->sa)
      92     2586271 :                 res = list_new(l->sa, l->destroy);
      93             :         else
      94           0 :                 res = list_create(l->destroy);
      95     2586271 :         return res;
      96             : }
      97             : 
      98             : int
      99   254632520 : list_empty(list *l)
     100             : {
     101   254632520 :         if (l)
     102   223247284 :                 return list_length(l) == 0;
     103             :         return 1;
     104             : }
     105             : 
     106             : static void
     107     5455193 : node_destroy_(list *l, void *data, node *n)
     108             : {
     109     5455193 :         if (n->data && l->destroy) {
     110     2645867 :                 l->destroy(data, n->data);
     111     2645920 :                 n->data = NULL;
     112             :         }
     113     5455246 :         if (!l->sa)
     114     3173543 :                 _DELETE(n);
     115     5455697 : }
     116             : 
     117             : void
     118     3558164 : list_destroy2(list *l, void *data)
     119             : {
     120     3558164 :         if (l) {
     121     1319201 :                 node *n = l->h;
     122             : 
     123     1319201 :                 l->h = NULL;
     124     1319201 :                 if (l->destroy || l->sa == NULL) {
     125     4137704 :                         while (n) {
     126     3159317 :                                 node *t = n;
     127             : 
     128     3159317 :                                 n = t->next;
     129     3159317 :                                 node_destroy_(l, data, t);
     130             :                         }
     131             :                 }
     132             : 
     133     1319247 :                 if (l->ht && !l->ht->sa)
     134       37738 :                         hash_destroy(l->ht);
     135             : 
     136     1319247 :                 if (!l->sa)
     137      825143 :                         _DELETE(l);
     138             :         }
     139     3558215 : }
     140             : 
     141             : void
     142     2912884 : list_destroy(list *l)
     143             : {
     144     2912884 :         list_destroy2(l, NULL);
     145     2912978 : }
     146             : 
     147             : int
     148   302497360 : list_length(list *l)
     149             : {
     150   302497360 :         if (l)
     151   301963734 :                 return l->cnt;
     152             :         return 0;
     153             : }
     154             : 
     155             : static list *
     156    54243233 : list_append_node(list *l, node *n)
     157             : {
     158    54243233 :         if (l->cnt) {
     159    35800628 :                 l->t->next = n;
     160             :         } else {
     161    18442605 :                 l->h = n;
     162             :         }
     163    54243233 :         l->t = n;
     164    54243233 :         l->cnt++;
     165    54243233 :         if (n->data) {
     166    54190679 :                 if (l->ht) {
     167      936297 :                         int key = l->ht->key(n->data);
     168             : 
     169      936297 :                         if (hash_add(l->ht, key, n->data) == NULL) {
     170             :                                 return NULL;
     171             :                         }
     172             :                 }
     173             :         }
     174             :         return l;
     175             : }
     176             : 
     177             : list *
     178    54232852 : list_append(list *l, void *data)
     179             : {
     180    54232852 :         if (l == NULL)
     181             :                 return NULL;
     182    54232852 :         node *n = node_create(l->sa, data);
     183             : 
     184    54228645 :         if (n == NULL)
     185             :                 return NULL;
     186    54228645 :         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     2592929 : list_prepend(list *l, void *data)
     299             : {
     300     2592929 :         node *n = node_create(l->sa, data);
     301             : 
     302     2592929 :         if (n == NULL)
     303             :                 return NULL;
     304     2592929 :         if (!l->cnt) {
     305      580947 :                 l->t = n;
     306             :         }
     307     2592929 :         n->next = l->h;
     308     2592929 :         l->h = n;
     309     2592929 :         l->cnt++;
     310     2592929 :         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       24726 : hash_delete(sql_hash *h, void *data)
     322             : {
     323       24726 :         int key = h->key(data);
     324       24726 :         sql_hash_e *e, *p = h->buckets[key&(h->size-1)];
     325             : 
     326       24726 :         e = p;
     327       31953 :         for (;  p && p->value != data ; p = p->chain)
     328        7227 :                 e = p;
     329       24726 :         if (p && p->value == data) {
     330       24726 :                 if (p == e)
     331       19106 :                         h->buckets[key&(h->size-1)] = p->chain;
     332             :                 else
     333        5620 :                         e->chain = p->chain;
     334             :         }
     335       24726 :         h->entries--;
     336       24726 : }
     337             : 
     338             : static node *
     339     2295928 : list_remove_node_(list *l, node *n)
     340             : {
     341     2295928 :         void *data = n->data;
     342     2295928 :         node *p = l->h;
     343             : 
     344     2295928 :         if (p != n)
     345     8665911 :                 while (p && p->next != n)
     346             :                         p = p->next;
     347     2295928 :         assert(p==n||(p && p->next == n));
     348     2295928 :         if (p == n) {
     349     1206232 :                 l->h = n->next;
     350     1206232 :                 p = NULL;
     351     1089696 :         } else if ( p != NULL)  {
     352     1089696 :                 p->next = n->next;
     353             :         }
     354     2295928 :         if (n == l->t)
     355      972059 :                 l->t = p;
     356     2295928 :         if (data) {
     357     1088905 :                 if (l->ht && data)
     358       24648 :                         hash_delete(l->ht, data);
     359             :         }
     360     2295928 :         l->cnt--;
     361     2295928 :         assert(l->cnt > 0 || l->h == NULL);
     362     2295928 :         return p;
     363             : }
     364             : 
     365             : node *
     366     2295907 : list_remove_node(list *l, void *gdata, node *n)
     367             : {
     368     2295907 :         node *p = list_remove_node_(l, n);
     369             : 
     370     2295921 :         node_destroy_(l, gdata, n);
     371     2295910 :         return p;
     372             : }
     373             : 
     374             : void
     375     1202236 : list_remove_data(list *s, void *gdata, void *data)
     376             : {
     377     1202236 :         node *n;
     378             : 
     379             :         /* maybe use compare func */
     380     1202236 :         if (s == NULL)
     381             :                 return;
     382     2535067 :         for (n = s->h; n; n = n->next) {
     383     2535067 :                 if (n->data == data) {
     384     1202236 :                         if (s->ht && n->data)
     385          78 :                                 hash_delete(s->ht, n->data);
     386     1202236 :                         n->data = NULL;
     387     1202236 :                         list_remove_node(s, gdata, n);
     388     1202236 :                         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     1084014 : list_check_prop_all(list *l, prop_check_func f)
     427             : {
     428     1084014 :         int res = 1;
     429     1084014 :         if (l)
     430     6836079 :                 for (node *n = l->h; n && res; n = n->next)
     431     5752065 :                         res &= f(n->data);
     432     1084014 :         return res;
     433             : }
     434             : 
     435             : void
     436        2190 : list_revert(list *l)
     437             : {
     438        2190 :         node *c = NULL;
     439             : 
     440        2190 :         l->t = l->h;
     441       14124 :         for (node *o = l->h; o; ) {
     442       11934 :                 node *nxt = o->next;
     443             : 
     444       11934 :                 o->next = c;
     445       11934 :                 c = o;
     446             : 
     447       11934 :                 o = nxt;
     448             :         }
     449        2190 :         l->h = c;
     450        2190 : }
     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     7277333 : list_find(list *l, void *key, fcmp cmp)
     480             : {
     481     7277333 :         node *n = NULL;
     482             : 
     483     7277333 :         if (key) {
     484     7277333 :                 if (cmp) {
     485    36185907 :                         for (n = l->h; n; n = n->next) {
     486    32426604 :                                 if (cmp(n->data, key) == 0) {
     487     3470545 :                                         return n;
     488             :                                 }
     489             :                         }
     490             :                 } else {
     491       64178 :                         for (n = l->h; n; n = n->next) {
     492       30997 :                                 if (n->data == key)
     493       14304 :                                         return n;
     494             :                         }
     495             :                 }
     496             :         }
     497             :         return NULL;
     498             : }
     499             : 
     500             : int
     501     3987010 : list_cmp(list *l1, list *l2, fcmp cmp)
     502             : {
     503     3987010 :         node *n, *m;
     504     3987010 :         int res = 0;
     505             : 
     506     3987010 :         if (l1 == l2)
     507             :                 return 0;
     508     3987008 :         if (!l1 && l2 && list_empty(l2))
     509             :                 return 0;
     510     3987008 :         if (!l2 && l1 && list_empty(l1))
     511             :                 return 0;
     512     3984744 :         if (!l1 || !l2 || (list_length(l1) != list_length(l2)))
     513      107092 :                 return -1;
     514             : 
     515     8257746 :         for (n = l1->h, m = l2->h; res == 0 && n; n = n->next, m = m->next) {
     516     4380018 :                 res = cmp(n->data, m->data);
     517             :         }
     518             :         return res;
     519             : }
     520             : 
     521             : int
     522        6360 : list_match(list *l1, list *l2, fcmp cmp)
     523             : {
     524        6360 :         node *n, *m;
     525        6360 :         ulng chk = 0;
     526             : 
     527        6360 :         if (l1 == l2)
     528             :                 return 0;
     529             : 
     530        6360 :         if (!l1 || !l2 || (list_length(l1) != list_length(l2)))
     531        4227 :                 return -1;
     532             : 
     533        4551 :         for (n = l1->h; n; n = n->next) {
     534        2574 :                 int pos = 0, fnd = 0;
     535        8388 :                 for (m = l2->h; m; m = m->next, pos++) {
     536       10068 :                         if (!(chk & ((ulng) 1 << pos)) &&
     537        4254 :                             cmp(n->data, m->data) == 0) {
     538        2418 :                                 chk |= (ulng) 1 << pos;
     539        2418 :                                 fnd = 1;
     540             :                         }
     541             :                 }
     542        2574 :                 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      153252 : list_sort(list *l, fkeyvalue key, fdup dup)
     579             : {
     580      153252 :         list *res;
     581      153252 :         node *n = NULL;
     582      153252 :         int i, *keys, cnt = list_length(l);
     583      153252 :         void **data;
     584             : 
     585      153252 :         keys = GDKmalloc(cnt*sizeof(int));
     586      153252 :         data = GDKmalloc(cnt*sizeof(void *));
     587      153252 :         if (keys == NULL || data == NULL) {
     588           0 :                 GDKfree(keys);
     589           0 :                 GDKfree(data);
     590           0 :                 return NULL;
     591             :         }
     592      153252 :         res = list_new_(l);
     593      153252 :         if (res == NULL) {
     594           0 :                 GDKfree(keys);
     595           0 :                 GDKfree(data);
     596           0 :                 return NULL;
     597             :         }
     598      580509 :         for (n = l->h, i = 0; n; n = n->next, i++) {
     599      427257 :                 keys[i] = key(n->data);
     600      427257 :                 data[i] = n->data;
     601             :         }
     602             :         /* sort descending */
     603      153252 :         GDKqsort(keys, data, NULL, cnt, sizeof(int), sizeof(void *), TYPE_int, true, true);
     604      733761 :         for(i=0; i<cnt; i++) {
     605      427257 :                 list_append(res, dup?dup(data[i]):data[i]);
     606             :         }
     607      153252 :         GDKfree(keys);
     608      153252 :         GDKfree(data);
     609      153252 :         return res;
     610             : }
     611             : 
     612             : list *
     613     1081115 : list_select(list *l, void *key, fcmp cmp, fdup dup)
     614             : {
     615     1081115 :         list *res = NULL;
     616     1081115 :         node *n = NULL;
     617             : 
     618     1081115 :         if (key && l) {
     619     1081115 :                 res = list_new_(l);
     620     1081115 :                 if(res) {
     621     4435676 :                         for (n = l->h; n; n = n->next)
     622     3354561 :                                 if (cmp(n->data, key) == 0)
     623     1948250 :                                         list_append(res, dup?dup(n->data):n->data);
     624             :                 }
     625             :         }
     626     1081115 :         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       54446 : list_distinct(list *l, fcmp cmp, fdup dup)
     655             : {
     656       54446 :         list *res = list_new_(l);
     657       54446 :         node *n = NULL;
     658             : 
     659       54446 :         if(res) {
     660      194729 :                 for (n = l->h; n; n = n->next) {
     661      140283 :                         if (!list_find(res, n->data, cmp)) {
     662      126603 :                                 list_append(res, dup ? dup(n->data) : n->data);
     663             :                         }
     664             :                 }
     665             :         }
     666       54446 :         return res;
     667             : }
     668             : 
     669             : int
     670     4278610 : list_position(list *l, void *val)
     671             : {
     672     4278610 :         node *n = NULL;
     673     4278610 :         int i;
     674             : 
     675    47673630 :         for (n = l->h, i=0; n && val != n->data; n = n->next, i++)
     676             :                 ;
     677     4278610 :         if (n && n->data == val)
     678     1959502 :                 return i;
     679             :         return -1;
     680             : }
     681             : 
     682             : void *
     683      567657 : list_fetch(list *l, int pos)
     684             : {
     685      567657 :         node *n = NULL;
     686      567657 :         int i;
     687             : 
     688     4543205 :         for (n = l->h, i=0; n && i<pos; n = n->next, i++)
     689             :                 ;
     690      567657 :         if (n)
     691      567657 :                 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     1213811 : list_map(list *l, void *data, fmap map)
     727             : {
     728     1213811 :         list *res = list_new_(l);
     729             : 
     730     1213811 :         node *n = l->h;
     731             : 
     732     1213811 :         if(res) {
     733     2449587 :                 while (n) {
     734     1235776 :                         void *v = map(n->data, data);
     735             : 
     736     1235776 :                         if (v)
     737     1217398 :                                 list_append(res, v);
     738     1235776 :                         n = n->next;
     739             :                 }
     740             :         }
     741     1213811 :         return res;
     742             : }
     743             : 
     744             : list *
     745      650217 : list_merge(list *l, list *data, fdup dup)
     746             : {
     747      650217 :         if (data) {
     748      496900 :                 node *n = data->h;
     749             : 
     750     2575930 :                 while (n) {
     751     2079030 :                         if (dup && n->data)
     752           4 :                                 list_append(l, dup(n->data));
     753             :                         else
     754     2079026 :                                 list_append(l, n->data);
     755     2079030 :                         n = n->next;
     756             :                 }
     757             :         }
     758      650217 :         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       83121 : list_dup(list *l, fdup dup)
     783             : {
     784       83121 :         list *res = list_new_(l);
     785       83121 :         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      685706 : list_hash_clear(list *l)
     833             : {
     834      685706 :         l->ht = NULL;
     835      685706 : }

Generated by: LCOV version 1.14