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-04-26 00:35:57 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    52700489 : node_create(allocator *sa, void *data)
      19             : {
      20    52700489 :         node *n = (sa)?SA_NEW(sa, node):MNEW(node);
      21             : 
      22    52700982 :         if (n == NULL)
      23             :                 return NULL;
      24    52700982 :         *n = (node) {
      25             :                 .data = data,
      26             :         };
      27    52700982 :         return n;
      28             : }
      29             : 
      30             : static list *
      31    20000155 : list_init(list *l, allocator *sa, fdestroy destroy)
      32             : {
      33    20000155 :         if (l) {
      34    20000155 :                 *l = (list) {
      35             :                         .sa = sa,
      36             :                         .destroy = destroy,
      37             :                 };
      38             :         }
      39    20000155 :         return l;
      40             : }
      41             : 
      42             : list *
      43      590179 : list_create(fdestroy destroy)
      44             : {
      45      590179 :         return list_init(MNEW(list), NULL, destroy);
      46             : }
      47             : 
      48             : list *
      49    16771154 : sa_list(allocator *sa)
      50             : {
      51    16771154 :         list *l = (sa)?SA_NEW(sa, list):MNEW(list);
      52    16771260 :         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      715137 : list_add(list *l, void *data)
      74             : {
      75      715137 :         if (!l)
      76       65655 :                 l = list_create(NULL);
      77      715150 :         return list_append(l, data);
      78             : }
      79             : 
      80             : list *
      81     2638663 : list_new(allocator *sa, fdestroy destroy)
      82             : {
      83     2638663 :         list *l = (sa)?SA_NEW(sa, list):MNEW(list);
      84     2638663 :         return list_init(l, sa, destroy);
      85             : }
      86             : 
      87             : static list *
      88     2260627 : list_new_(list *l)
      89             : {
      90     2260627 :         list *res = NULL;
      91     2260627 :         if (l->sa)
      92     2260627 :                 res = list_new(l->sa, l->destroy);
      93             :         else
      94           0 :                 res = list_create(l->destroy);
      95     2260627 :         return res;
      96             : }
      97             : 
      98             : int
      99   249632002 : list_empty(list *l)
     100             : {
     101   249632002 :         if (l)
     102   218697299 :                 return list_length(l) == 0;
     103             :         return 1;
     104             : }
     105             : 
     106             : static void
     107     5193256 : node_destroy_(list *l, void *data, node *n)
     108             : {
     109     5193256 :         if (n->data && l->destroy) {
     110     2585494 :                 l->destroy(data, n->data);
     111     2585582 :                 n->data = NULL;
     112             :         }
     113     5193344 :         if (!l->sa)
     114     3162446 :                 _DELETE(n);
     115     5193739 : }
     116             : 
     117             : void
     118     3450103 : list_destroy2(list *l, void *data)
     119             : {
     120     3450103 :         if (l) {
     121     1274177 :                 node *n = l->h;
     122             : 
     123     1274177 :                 l->h = NULL;
     124     1274177 :                 if (l->destroy || l->sa == NULL) {
     125     4024277 :                         while (n) {
     126     3079657 :                                 node *t = n;
     127             : 
     128     3079657 :                                 n = t->next;
     129     3079657 :                                 node_destroy_(l, data, t);
     130             :                         }
     131             :                 }
     132             : 
     133     1274239 :                 if (l->ht && !l->ht->sa)
     134       38370 :                         hash_destroy(l->ht);
     135             : 
     136     1274239 :                 if (!l->sa)
     137      834168 :                         _DELETE(l);
     138             :         }
     139     3450162 : }
     140             : 
     141             : void
     142     2791122 : list_destroy(list *l)
     143             : {
     144     2791122 :         list_destroy2(l, NULL);
     145     2791229 : }
     146             : 
     147             : int
     148   330964364 : list_length(list *l)
     149             : {
     150   330964364 :         if (l)
     151   330416639 :                 return l->cnt;
     152             :         return 0;
     153             : }
     154             : 
     155             : static list *
     156    50159010 : list_append_node(list *l, node *n)
     157             : {
     158    50159010 :         if (l->cnt) {
     159    32813139 :                 l->t->next = n;
     160             :         } else {
     161    17345871 :                 l->h = n;
     162             :         }
     163    50159010 :         l->t = n;
     164    50159010 :         l->cnt++;
     165    50159010 :         if (n->data) {
     166    50106063 :                 if (l->ht) {
     167     1170977 :                         int key = l->ht->key(n->data);
     168             : 
     169     1170977 :                         if (hash_add(l->ht, key, n->data) == NULL) {
     170             :                                 return NULL;
     171             :                         }
     172             :                 }
     173             :         }
     174             :         return l;
     175             : }
     176             : 
     177             : list *
     178    50148011 : list_append(list *l, void *data)
     179             : {
     180    50148011 :         if (l == NULL)
     181             :                 return NULL;
     182    50148011 :         node *n = node_create(l->sa, data);
     183             : 
     184    50145926 :         if (n == NULL)
     185             :                 return NULL;
     186    50145926 :         return list_append_node(l, n);
     187             : }
     188             : 
     189             : void *
     190         222 : list_append_with_validate(list *l, void *data, void *extra, fvalidate cmp)
     191             : {
     192         222 :         node *n = node_create(l->sa, data), *m;
     193         222 :         void* err = NULL;
     194             : 
     195         222 :         if (n == NULL)
     196             :                 return NULL;
     197         222 :         if (l->cnt) {
     198         245 :                 for (m = l->h; m; m = m->next) {
     199         166 :                         err = cmp(m->data, data, extra);
     200         166 :                         if(err) {
     201          43 :                                 n->data = NULL;
     202          43 :                                 node_destroy_(l, NULL, n);
     203          43 :                                 return err;
     204             :                         }
     205             :                 }
     206          79 :                 l->t->next = n;
     207             :         } else {
     208         100 :                 l->h = n;
     209             :         }
     210         179 :         l->t = n;
     211         179 :         l->cnt++;
     212         179 :         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         162 : list_append_sorted(list *l, void *data, void *extra, fcmpvalidate cmp)
     224             : {
     225         162 :         node *n = node_create(l->sa, data), *m, *prev = NULL;
     226         162 :         int first = 1, comp = 0;
     227         162 :         void* err = NULL;
     228             : 
     229         162 :         if (n == NULL)
     230             :                 return NULL;
     231         162 :         if (l->cnt == 0) {
     232          51 :                 l->h = n;
     233          51 :                 l->t = n;
     234             :         } else {
     235         298 :                 for (m = l->h; m; m = m->next) {
     236         194 :                         err = cmp(m->data, data, extra, &comp);
     237         194 :                         if(err) {
     238           1 :                                 n->data = NULL;
     239           1 :                                 node_destroy_(l, NULL, n);
     240           1 :                                 return err;
     241             :                         }
     242         193 :                         if(comp < 0)
     243             :                                 break;
     244         187 :                         first = 0;
     245         187 :                         prev = m;
     246             :                 }
     247         110 :                 if(first) {
     248           3 :                         n->next = l->h;
     249           3 :                         l->h = n;
     250         107 :                 } else if(!m) {
     251         104 :                         l->t->next = n;
     252         104 :                         l->t = n;
     253             :                 } else {
     254           3 :                         assert(prev);
     255           3 :                         n->next = m;
     256           3 :                         prev->next = n;
     257             :                 }
     258             :         }
     259         161 :         l->cnt++;
     260         161 :         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          26 : list_append_before(list *l, node *m, void *data)
     272             : {
     273          26 :         node *p = l->h;
     274          26 :         node *n = node_create(l->sa, data);
     275             : 
     276          26 :         if (n == NULL)
     277             :                 return NULL;
     278          26 :         n->next = m;
     279          26 :         if (p == m){
     280           3 :                 l->h = n;
     281             :         } else {
     282          26 :                 while (p->next && p->next != m)
     283             :                         p = p->next;
     284          23 :                 p->next = n;
     285             :         }
     286          26 :         l->cnt++;
     287          26 :         if (l->ht) {
     288           5 :                 int key = l->ht->key(data);
     289             : 
     290           5 :                 if (hash_add(l->ht, key, data) == NULL) {
     291             :                         return NULL;
     292             :                 }
     293             :         }
     294             :         return l;
     295             : }
     296             : 
     297             : list *
     298     2543762 : list_prepend(list *l, void *data)
     299             : {
     300     2543762 :         node *n = node_create(l->sa, data);
     301             : 
     302     2543762 :         if (n == NULL)
     303             :                 return NULL;
     304     2543762 :         if (!l->cnt) {
     305      558547 :                 l->t = n;
     306             :         }
     307     2543762 :         n->next = l->h;
     308     2543762 :         l->h = n;
     309     2543762 :         l->cnt++;
     310     2543762 :         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      638409 : hash_delete(sql_hash *h, void *data)
     322             : {
     323      638409 :         int key = h->key(data);
     324      638424 :         sql_hash_e *e, *p = h->buckets[key&(h->size-1)];
     325             : 
     326      638424 :         e = p;
     327     1105560 :         for (;  p && p->value != data ; p = p->chain)
     328      467136 :                 e = p;
     329      638424 :         if (p && p->value == data) {
     330      638424 :                 if (p == e)
     331      394512 :                         h->buckets[key&(h->size-1)] = p->chain;
     332             :                 else
     333      243912 :                         e->chain = p->chain;
     334             :         }
     335      638424 :         h->entries--;
     336      638424 : }
     337             : 
     338             : static node *
     339     2113592 : list_remove_node_(list *l, node *n)
     340             : {
     341     2113592 :         void *data = n->data;
     342     2113592 :         node *p = l->h;
     343             : 
     344     2113592 :         if (p != n)
     345     8243487 :                 while (p && p->next != n)
     346             :                         p = p->next;
     347     2113592 :         assert(p==n||(p && p->next == n));
     348     2113592 :         if (p == n) {
     349     1071127 :                 l->h = n->next;
     350     1071127 :                 p = NULL;
     351     1042465 :         } else if ( p != NULL)  {
     352     1042465 :                 p->next = n->next;
     353             :         }
     354     2113592 :         if (n == l->t)
     355      827462 :                 l->t = p;
     356     2113592 :         if (data) {
     357     1049700 :                 if (l->ht && data)
     358      638339 :                         hash_delete(l->ht, data);
     359             :         }
     360     2113600 :         l->cnt--;
     361     2113600 :         assert(l->cnt > 0 || l->h == NULL);
     362     2113600 :         return p;
     363             : }
     364             : 
     365             : node *
     366     2113567 : list_remove_node(list *l, void *gdata, node *n)
     367             : {
     368     2113567 :         node *p = list_remove_node_(l, n);
     369             : 
     370     2113591 :         node_destroy_(l, gdata, n);
     371     2113577 :         return p;
     372             : }
     373             : 
     374             : void
     375     1058897 : list_remove_data(list *s, void *gdata, void *data)
     376             : {
     377     1058897 :         node *n;
     378             : 
     379             :         /* maybe use compare func */
     380     1058897 :         if (s == NULL)
     381             :                 return;
     382     2402811 :         for (n = s->h; n; n = n->next) {
     383     2402811 :                 if (n->data == data) {
     384     1058897 :                         if (s->ht && n->data)
     385          78 :                                 hash_delete(s->ht, n->data);
     386     1058897 :                         n->data = NULL;
     387     1058897 :                         list_remove_node(s, gdata, n);
     388     1058897 :                         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     1240324 : list_check_prop_all(list *l, prop_check_func f)
     427             : {
     428     1240324 :         int res = 1;
     429     1240324 :         if (l)
     430     7015595 :                 for (node *n = l->h; n && res; n = n->next)
     431     5775270 :                         res &= f(n->data);
     432     1240325 :         return res;
     433             : }
     434             : 
     435             : void
     436        1515 : list_revert(list *l)
     437             : {
     438        1515 :         node *c = NULL;
     439             : 
     440        1515 :         l->t = l->h;
     441       11742 :         for (node *o = l->h; o; ) {
     442       10227 :                 node *nxt = o->next;
     443             : 
     444       10227 :                 o->next = c;
     445       10227 :                 c = o;
     446             : 
     447       10227 :                 o = nxt;
     448             :         }
     449        1515 :         l->h = c;
     450        1515 : }
     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     7314834 : list_find(list *l, void *key, fcmp cmp)
     480             : {
     481     7314834 :         node *n = NULL;
     482             : 
     483     7314834 :         if (key) {
     484     7314834 :                 if (cmp) {
     485    36557981 :                         for (n = l->h; n; n = n->next) {
     486    32670933 :                                 if (cmp(n->data, key) == 0) {
     487     3404877 :                                         return n;
     488             :                                 }
     489             :                         }
     490             :                 } else {
     491       37079 :                         for (n = l->h; n; n = n->next) {
     492       22422 :                                 if (n->data == key)
     493        8252 :                                         return n;
     494             :                         }
     495             :                 }
     496             :         }
     497             :         return NULL;
     498             : }
     499             : 
     500             : int
     501     3983686 : list_cmp(list *l1, list *l2, fcmp cmp)
     502             : {
     503     3983686 :         node *n, *m;
     504     3983686 :         int res = 0;
     505             : 
     506     3983686 :         if (l1 == l2)
     507             :                 return 0;
     508     3983684 :         if (!l1 && l2 && list_empty(l2))
     509             :                 return 0;
     510     3983684 :         if (!l2 && l1 && list_empty(l1))
     511             :                 return 0;
     512     3981363 :         if (!l1 || !l2 || (list_length(l1) != list_length(l2)))
     513       87217 :                 return -1;
     514             : 
     515     8283452 :         for (n = l1->h, m = l2->h; res == 0 && n; n = n->next, m = m->next) {
     516     4389211 :                 res = cmp(n->data, m->data);
     517             :         }
     518             :         return res;
     519             : }
     520             : 
     521             : int
     522        6307 : list_match(list *l1, list *l2, fcmp cmp)
     523             : {
     524        6307 :         node *n, *m;
     525        6307 :         ulng chk = 0;
     526             : 
     527        6307 :         if (l1 == l2)
     528             :                 return 0;
     529             : 
     530        6307 :         if (!l1 || !l2 || (list_length(l1) != list_length(l2)))
     531        4262 :                 return -1;
     532             : 
     533        4376 :         for (n = l1->h; n; n = n->next) {
     534        2481 :                 int pos = 0, fnd = 0;
     535        8170 :                 for (m = l2->h; m; m = m->next, pos++) {
     536        9834 :                         if (!(chk & ((ulng) 1 << pos)) &&
     537        4145 :                             cmp(n->data, m->data) == 0) {
     538        2331 :                                 chk |= (ulng) 1 << pos;
     539        2331 :                                 fnd = 1;
     540             :                         }
     541             :                 }
     542        2481 :                 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      110454 : list_sort(list *l, fkeyvalue key, fdup dup)
     579             : {
     580      110454 :         list *res;
     581      110454 :         node *n = NULL;
     582      110454 :         int i, *keys, cnt = list_length(l);
     583      110454 :         void **data;
     584             : 
     585      110454 :         keys = GDKmalloc(cnt*sizeof(int));
     586      110454 :         data = GDKmalloc(cnt*sizeof(void *));
     587      110454 :         if (keys == NULL || data == NULL) {
     588           0 :                 GDKfree(keys);
     589           0 :                 GDKfree(data);
     590           0 :                 return NULL;
     591             :         }
     592      110454 :         res = list_new_(l);
     593      110454 :         if (res == NULL) {
     594           0 :                 GDKfree(keys);
     595           0 :                 GDKfree(data);
     596           0 :                 return NULL;
     597             :         }
     598      463366 :         for (n = l->h, i = 0; n; n = n->next, i++) {
     599      352912 :                 keys[i] = key(n->data);
     600      352912 :                 data[i] = n->data;
     601             :         }
     602             :         /* sort descending */
     603      110454 :         GDKqsort(keys, data, NULL, cnt, sizeof(int), sizeof(void *), TYPE_int, true, true);
     604      573820 :         for(i=0; i<cnt; i++) {
     605      352912 :                 list_append(res, dup?dup(data[i]):data[i]);
     606             :         }
     607      110454 :         GDKfree(keys);
     608      110454 :         GDKfree(data);
     609      110454 :         return res;
     610             : }
     611             : 
     612             : list *
     613      950627 : list_select(list *l, void *key, fcmp cmp, fdup dup)
     614             : {
     615      950627 :         list *res = NULL;
     616      950627 :         node *n = NULL;
     617             : 
     618      950627 :         if (key && l) {
     619      950627 :                 res = list_new_(l);
     620      950627 :                 if(res) {
     621     4216434 :                         for (n = l->h; n; n = n->next)
     622     3265807 :                                 if (cmp(n->data, key) == 0)
     623     1812707 :                                         list_append(res, dup?dup(n->data):n->data);
     624             :                 }
     625             :         }
     626      950627 :         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       52862 : list_distinct(list *l, fcmp cmp, fdup dup)
     655             : {
     656       52862 :         list *res = list_new_(l);
     657       52862 :         node *n = NULL;
     658             : 
     659       52862 :         if(res) {
     660      188953 :                 for (n = l->h; n; n = n->next) {
     661      136091 :                         if (!list_find(res, n->data, cmp)) {
     662      122925 :                                 list_append(res, dup ? dup(n->data) : n->data);
     663             :                         }
     664             :                 }
     665             :         }
     666       52862 :         return res;
     667             : }
     668             : 
     669             : int
     670     1841499 : list_position(list *l, void *val)
     671             : {
     672     1841499 :         node *n = NULL;
     673     1841499 :         int i;
     674             : 
     675    27802272 :         for (n = l->h, i=0; n && val != n->data; n = n->next, i++)
     676             :                 ;
     677     1841499 :         if (n && n->data == val)
     678     1114086 :                 return i;
     679             :         return -1;
     680             : }
     681             : 
     682             : void *
     683      396811 : list_fetch(list *l, int pos)
     684             : {
     685      396811 :         node *n = NULL;
     686      396811 :         int i;
     687             : 
     688     1533886 :         for (n = l->h, i=0; n && i<pos; n = n->next, i++)
     689             :                 ;
     690      396811 :         if (n)
     691      396811 :                 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     1065243 : list_map(list *l, void *data, fmap map)
     727             : {
     728     1065243 :         list *res = list_new_(l);
     729             : 
     730     1065243 :         node *n = l->h;
     731             : 
     732     1065243 :         if(res) {
     733     2157940 :                 while (n) {
     734     1092697 :                         void *v = map(n->data, data);
     735             : 
     736     1092697 :                         if (v)
     737     1081798 :                                 list_append(res, v);
     738     1092697 :                         n = n->next;
     739             :                 }
     740             :         }
     741     1065243 :         return res;
     742             : }
     743             : 
     744             : list *
     745      574302 : list_merge(list *l, list *data, fdup dup)
     746             : {
     747      574302 :         if (data) {
     748      463564 :                 node *n = data->h;
     749             : 
     750     2343042 :                 while (n) {
     751     1879475 :                         if (dup && n->data)
     752           0 :                                 list_append(l, dup(n->data));
     753             :                         else
     754     1879475 :                                 list_append(l, n->data);
     755     1879478 :                         n = n->next;
     756             :                 }
     757             :         }
     758      574305 :         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       80927 : list_dup(list *l, fdup dup)
     783             : {
     784       80927 :         list *res = list_new_(l);
     785       80927 :         return res ? list_merge(res, l, dup) : NULL;
     786             : }
     787             : 
     788             : list *
     789         514 : list_flatten(list *l)
     790             : {
     791         514 :         list *res = list_new_(l);
     792         514 :         if (res) {
     793        1337 :                 for (node *n = l->h ; n ; n = n->next) {
     794         823 :                         list *ll = (list*) n->data;
     795        1702 :                         for (node *m = ll->h ; m ; m = m->next)
     796         879 :                                 list_append(res, m->data);
     797             :                 }
     798             :         }
     799         514 :         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      513119 : list_hash_clear(list *l)
     833             : {
     834      513119 :         l->ht = NULL;
     835      513119 : }

Generated by: LCOV version 1.14