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 #ifndef _ANDROID_UTILS_REFLIST_H
     13 #define _ANDROID_UTILS_REFLIST_H
     14 
     15 #include "android/utils/system.h"
     16 
     17 /* definitions for a smart list of references to generic objects.
     18  * supports safe deletion and addition while they are being iterated
     19  * with AREFLIST_FOREACH() macro
     20  */
     21 
     22 typedef struct ARefList {
     23     uint16_t   count, max;
     24     uint16_t   iteration;
     25     union {
     26         struct ARefList*  next;
     27         void*             item0;
     28         void**            items;
     29     } u;
     30 } ARefList;
     31 
     32 AINLINED void
     33 areflist_init(ARefList*  l)
     34 {
     35     l->count     = 0;
     36     l->max       = 1;
     37     l->iteration = 0;
     38 }
     39 
     40 void  areflist_setEmpty(ARefList*  l);
     41 
     42 AINLINED void
     43 areflist_done(ARefList*  l)
     44 {
     45     areflist_setEmpty(l);
     46 }
     47 
     48 AINLINED ABool
     49 areflist_isEmpty(ARefList*  l)
     50 {
     51     return (l->count == 0);
     52 }
     53 
     54 int    areflist_indexOf(ARefList*  l, void*  item);
     55 
     56 AINLINED ABool
     57 areflist_has(ARefList*  l, void*  item)
     58 {
     59     return areflist_indexOf(l, item) >= 0;
     60 }
     61 
     62 /* if 'item' is not NULL, append it to the list. An item
     63  * can be added several times to a list */
     64 void    areflist_add(ARefList*  l, void*  item);
     65 
     66 /* if 'item' is not NULL, try to remove it from the list */
     67 /* returns TRUE iff the item was found in the list */
     68 ABool   areflist_del(ARefList*  l, void*  item);
     69 
     70 AINLINED void
     71 areflist_push(ARefList*  l, void*  item)
     72 {
     73     areflist_add(l, item);
     74 }
     75 
     76 void*  areflist_pop(ARefList*  l);
     77 
     78 AINLINED void**
     79 areflist_items(ARefList*  l)
     80 {
     81     return (l->max == 1) ? &l->u.item0 : l->u.items;
     82 }
     83 
     84 AINLINED int
     85 areflist_count(ARefList*  l)
     86 {
     87     return l->count;
     88 }
     89 
     90 /* return a pointer to the n-th list array entry,
     91    or NULL in case of invalid index */
     92 void**  areflist_at(ARefList*  l, int  n);
     93 
     94 /* return the n-th array entry, or NULL in case of invalid index */
     95 void*   areflist_get(ARefList*  l, int  n);
     96 
     97 /* used internally */
     98 void    _areflist_remove_deferred(ARefList*  l);
     99 
    100 #define  AREFLIST_FOREACH(list_,item_,statement_) \
    101     ({ ARefList*  _reflist   = (list_); \
    102        int        _reflist_i = 0; \
    103        int        _reflist_n = _reflist->count; \
    104        _reflist->iteration += 2; \
    105        for ( ; _reflist_i < _reflist_n; _reflist_i++ ) { \
    106            void**  __reflist_at   = areflist_at(_reflist, _reflist_i); \
    107            void*  item_ = *__reflist_at; \
    108            if (item_ != NULL) { \
    109                statement_; \
    110            } \
    111        } \
    112        _reflist->iteration -= 2; \
    113        if (_reflist->iteration == 1) \
    114            _areflist_remove_deferred(_reflist); \
    115     })
    116 
    117 /* use this to delete the currently iterated element */
    118 #define  AREFLIST_DEL_ITERATED()  \
    119     ({ *_reflist_at = NULL; \
    120        _reflist->iteration |= 1; })
    121 
    122 /* use this to replace the currently iterated element */
    123 #define  AREFLIST_SET_ITERATED(item) \
    124     ({ *_reflist_at = (item); \
    125        if (item == NULL) _reflist->iteration |= 1; })
    126 
    127 void  areflist_copy(ARefList*  dst, ARefList*  src);
    128 
    129 #endif /* _ANDROID_UTILS_REFLIST_H */
    130