LCOV - code coverage report
Current view: top level - sql/common - sql_list.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 299 420 71.2 %
Date: 2021-10-13 02:24:04 Functions: 37 47 78.7 %

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

Generated by: LCOV version 1.14