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

Generated by: LCOV version 1.14