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 "android/utils/system.h"
     14 #include "android/utils/assert.h"
     15 #include <stdlib.h>
     16 #include <string.h>
     17 
     18 static void** _areflist_items(const ARefList*  l)
     19 {
     20     if (l->max == 1)
     21         return (void**)&l->u.item0;
     22     else
     23         return l->u.items;
     24 }
     25 
     26 static void
     27 _areflist_checkSize0(ARefList*  l)
     28 {
     29     if (l->size == 0 && l->max > 1) {
     30         AFREE(l->u.items);
     31         l->max     = 1;
     32         l->u.item0 = NULL;
     33     }
     34 }
     35 
     36 void
     37 areflist_setEmpty(ARefList*  l)
     38 {
     39     if (l->iteration > 0) {
     40         /* deferred empty, set all items to NULL
     41          * to stop iterations */
     42         void**  items = _areflist_items(l);
     43         AARRAY_ZERO(items, l->count);
     44         l->iteration |= 1;
     45     } else {
     46         /* direct empty */
     47         l->size = 0;
     48         _areflist_checkSize0(l);
     49     }
     50     l->count = 0;
     51 }
     52 
     53 int
     54 areflist_indexOf(const ARefList*  l, void*  item)
     55 {
     56     if (item) {
     57         void**  items = _areflist_items(l);
     58         void**  end   = items + l->count;
     59         void**  ii    = items;
     60 
     61         for ( ; ii < end; ii += 1 )
     62             if (*ii == item)
     63                 return (ii - items);
     64     }
     65     return -1;
     66 }
     67 
     68 static void
     69 areflist_grow(ARefList*  l, int  count)
     70 {
     71     int   newcount = l->size + count;
     72     if (newcount > l->max) {
     73         int  oldmax = l->max;
     74         int  newmax;
     75         void**  items;
     76 
     77         if (oldmax == 1) {
     78             oldmax   = 0;
     79             items    = NULL;
     80         } else {
     81             items = l->u.items;
     82         }
     83         newmax = oldmax;
     84         while (newmax < newcount)
     85             newmax += (newmax >> 1) + 4;
     86 
     87         AARRAY_RENEW(items, newmax);
     88 
     89         if (l->max == 1)
     90             items[0] = l->u.item0;
     91 
     92         l->u.items = items;
     93         l->max     = (uint16_t) newmax;
     94     }
     95 }
     96 
     97 
     98 void
     99 areflist_add(ARefList*  l, void*  item)
    100 {
    101     if (item) {
    102         void**  items;
    103 
    104         if (l->size >= l->max) {
    105             areflist_grow(l, 1);
    106         }
    107         items = _areflist_items(l);
    108         items[l->size] = item;
    109         l->size  += 1;
    110         l->count += 1;
    111     }
    112 }
    113 
    114 void
    115 areflist_append(ARefList*  l, const ARefList*  l2)
    116 {
    117     AREFLIST_FOREACH_CONST(l2, item, {
    118         areflist_add(l, item);
    119     });
    120 }
    121 
    122 void*
    123 areflist_popLast(ARefList*  l)
    124 {
    125     void*   item = NULL;
    126     void**  items = _areflist_items(l);
    127     int     nn;
    128 
    129     if (l->count == 0)
    130         return NULL;
    131 
    132     for (nn = l->size; nn > 0; nn--) {
    133         item = items[nn-1];
    134         if (item != NULL)
    135             goto FOUND_LAST;
    136     }
    137     return NULL;
    138 
    139 FOUND_LAST:
    140     /* we found the last non-NULL item in the array */
    141     l->count   -= 1;
    142     items[nn-1] = NULL;
    143 
    144     if (l->iteration == 0) {
    145         l->size = nn;
    146         _areflist_checkSize0(l);
    147     }
    148     return item;
    149 }
    150 
    151 ABool
    152 areflist_delFirst(ARefList*  l, void*  item)
    153 {
    154     if (item == NULL)
    155         return 0;
    156 
    157     int  index = areflist_indexOf(l, item);
    158     if (index < 0)
    159         return 0;
    160 
    161     void** items = _areflist_items(l);
    162 
    163     if (l->iteration > 0) {
    164         /* deferred deletion */
    165         items[index]  = NULL;
    166         l->iteration |= 1;
    167         l->count     -= 1;
    168     } else {
    169         /* direct deletion */
    170         if (l->max > 1) {
    171             AARRAY_MOVE(items + index, items + index + 1, l->size - index - 1);
    172             l->size -= 1;
    173     l->count -= 1;
    174             _areflist_checkSize0(l);
    175         } else {
    176             l->u.item0 = NULL;
    177             l->size    = 0;
    178             l->count   = 0;
    179         }
    180     }
    181     return 1;
    182 }
    183 
    184 ABool
    185 areflist_delAll(ARefList*  l, void*  item)
    186 {
    187     ABool   result = 0;
    188 
    189     if (item == NULL)
    190         return 0;
    191 
    192     void**  items    = _areflist_items(l);
    193     int     readPos  = 0;
    194     int     writePos = 0;
    195 
    196     /* don't modify the list until we find the item
    197      * or an EMPTY slot */
    198     for ( ; readPos < l->size; readPos++ ) {
    199         if (items[readPos] == NULL || items[readPos] == item)
    200             goto COPY_LIST;
    201     }
    202     return 0;
    203 
    204 COPY_LIST:
    205     writePos = readPos;
    206     for ( ; readPos < l->size; readPos++ ) {
    207         if (items[readPos] == NULL) {
    208             continue;
    209         }
    210         if (items[readPos] == item) {
    211             result = 1;
    212             continue;
    213         }
    214         items[writePos] = items[readPos];
    215         writePos++;
    216     }
    217     l->count = l->size = (uint16_t) writePos;
    218     _areflist_checkSize0(l);
    219 
    220     return result;
    221 }
    222 
    223 
    224 void
    225 _areflist_remove_deferred(ARefList*  l)
    226 {
    227     if (l->iteration & 1) {
    228         /* remove all NULL elements from the array */
    229         void**  items = _areflist_items(l);
    230         int     rr = 0;
    231         int     ww = 0;
    232         for ( ; rr < l->size; rr++ ) {
    233             if (items[rr] != NULL)
    234                 items[ww++] = items[rr];
    235         }
    236         l->count = l->size = (uint16_t) ww;
    237         _areflist_checkSize0(l);
    238     }
    239     l->iteration = 0;
    240 }
    241 
    242 void
    243 areflist_copy(ARefList*  dst, const ARefList*  src)
    244 {
    245     dst[0] = src[0];
    246 
    247     if (src->max > 1) {
    248         dst->max  = dst->count;
    249         AARRAY_NEW(dst->u.items, dst->max);
    250 
    251         void**  ritems = src->u.items;
    252         void**  witems = _areflist_items(dst);
    253         int  rr = 0;
    254         int  ww = 0;
    255         for ( ; rr < src->size; rr++ ) {
    256             if (ritems[rr] != NULL) {
    257                 witems[ww++] = ritems[rr];
    258             }
    259         }
    260         dst->size = ww;
    261         AASSERT_TRUE(ww == dst->count);
    262         _areflist_checkSize0(dst);
    263     }
    264 }
    265 
    266 void*
    267 areflist_get(const ARefList*  l, int  n)
    268 {
    269     if ((unsigned)n >= (unsigned)l->count)
    270         return NULL;
    271 
    272     if (l->max == 1)
    273         return l->u.item0;
    274 
    275     return l->u.items[n];
    276 }
    277 
    278 void**
    279 _areflist_at(const ARefList*  l, int  n)
    280 {
    281     void**  items;
    282 
    283     if ((unsigned)n >= (unsigned)l->size)
    284         return NULL;
    285 
    286     items = _areflist_items(l);
    287     return items + n;
    288 }
    289