Home | History | Annotate | Download | only in utils
      1 /* Copyright (C) 2007-2008 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 #include "android/utils/reflist.h"
     13 #include <stdlib.h>
     14 #include <string.h>
     15 
     16 void
     17 areflist_setEmpty(ARefList*  l)
     18 {
     19     if (l->iteration > 0) {
     20         /* deferred empty, set all items to NULL
     21          * to stop iterations */
     22         void**  items = areflist_items(l);
     23         memset(items, 0, l->count*sizeof(items[0]));
     24         l->iteration |= 1;
     25     } else {
     26         /* direct empty */
     27         if (l->max > 1) {
     28             free(l->u.items);
     29             l->max = 1;
     30         }
     31     }
     32     l->count = 0;
     33 }
     34 
     35 int
     36 areflist_indexOf(ARefList*  l, void*  item)
     37 {
     38     if (item) {
     39         void**  items = (l->max == 1) ? &l->u.item0 : l->u.items;
     40         void**  end   = items + l->count;
     41         void**  ii    = items;
     42 
     43         for ( ; ii < end; ii += 1 )
     44             if (*ii == item)
     45                 return (ii - items);
     46     }
     47     return -1;
     48 }
     49 
     50 static void
     51 areflist_grow(ARefList*  l, int  count)
     52 {
     53     int   newcount = l->count + count;
     54     if (newcount > l->max) {
     55         int  oldmax = l->max == 1 ? 0 : l->max;
     56         int  newmax = oldmax;
     57         void**  olditems = l->max == 1 ? NULL : l->u.items;
     58         void**  newitems;
     59 
     60         while (oldmax < newcount)
     61             oldmax += (oldmax >> 1) + 4;
     62 
     63         newitems = realloc(olditems, newmax*sizeof(newitems[0]));
     64 
     65         l->u.items = newitems;
     66         l->max     = (uint16_t) newmax;
     67     }
     68 }
     69 
     70 
     71 void
     72 areflist_add(ARefList*  l, void*  item)
     73 {
     74     if (item) {
     75         void**  items;
     76 
     77         if (l->count >= l->max) {
     78             areflist_grow(l, 1);
     79         }
     80         items = areflist_items(l);
     81         items[l->count] = item;
     82         l->count += 1;
     83     }
     84 }
     85 
     86 void*
     87 areflist_pop(ARefList*  l)
     88 {
     89     void*   item = NULL;
     90     void**  items = areflist_items(l);
     91 
     92     if (l->count > 0) {
     93         if (l->iteration > 0) {
     94             /* deferred deletion */
     95             int  nn;
     96             for (nn = l->count-1; nn > 0; nn--) {
     97                 item = items[nn];
     98                 if (item != NULL) {
     99                     l->count -= 1;
    100                     return item;
    101                 }
    102             }
    103         } else {
    104             /* normal pop */
    105             item = items[--l->count];
    106             if (l->count <= 0 && l->max > 1) {
    107                 free(l->u.items);
    108                 l->max = 1;
    109             }
    110         }
    111     }
    112     return item;
    113 }
    114 
    115 ABool
    116 areflist_del(ARefList*  l, void*  item)
    117 {
    118     if (item) {
    119         int  index = areflist_indexOf(l, item);
    120         if (index >= 0) {
    121             void** items = areflist_items(l);
    122 
    123             if (l->iteration > 0) {
    124                 /* deferred deletion */
    125                 items[index]  = NULL;
    126                 l->iteration |= 1;
    127             } else {
    128                 /* direct deletion */
    129                 if (l->max > 1) {
    130                     memmove(items + index, items + index + 1, l->count - index - 1);
    131                     if (--l->count == 0) {
    132                         free(l->u.items);
    133                         l->max = 1;
    134                     }
    135                 } else {
    136                     l->u.item0 = NULL;
    137                     l->count   = 0;
    138                 }
    139             }
    140             return 1;
    141         }
    142     }
    143     return 0;
    144 }
    145 
    146 void
    147 _areflist_remove_deferred(ARefList*  l)
    148 {
    149     if (l->iteration & 1) {
    150         /* remove all NULL elements from the array */
    151         void**  items = areflist_items(l);
    152         int     rr = 0;
    153         int     ww = 0;
    154         for ( ; rr < l->count; rr++ ) {
    155             if (items[rr] != NULL)
    156                 items[ww++] = items[rr];
    157         }
    158         l->count = (int16_t) ww;
    159 
    160         /* if the list is empty, release its array */
    161         if (l->count == 0 && l->max > 1) {
    162             free(l->u.items);
    163             l->max = 1;
    164         }
    165     }
    166     l->iteration = 0;
    167 }
    168 
    169 void
    170 areflist_copy(ARefList*  dst, ARefList*  src)
    171 {
    172     dst[0] = src[0];
    173 
    174     if (src->max > 1) {
    175         dst->u.items = malloc( dst->count*sizeof(void*) );
    176         dst->max     = dst->count;
    177     }
    178 }
    179 
    180 void*
    181 areflist_get(ARefList*  l, int  n)
    182 {
    183     if ((unsigned)n >= (unsigned)l->count)
    184         return NULL;
    185 
    186     if (l->max == 1)
    187         return l->u.item0;
    188 
    189     return l->u.items[n];
    190 }
    191 
    192 void**
    193 areflist_at(ARefList*  l, int  n)
    194 {
    195     void**  items;
    196 
    197     if ((unsigned)n >= (unsigned)l->count)
    198         return NULL;
    199 
    200     items = (l->max == 1) ? &l->u.item0 : l->u.items;
    201 
    202     return items + n;
    203 }
    204