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
22typedef 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
32AINLINED void
33areflist_init(ARefList*  l)
34{
35    l->count     = 0;
36    l->max       = 1;
37    l->iteration = 0;
38}
39
40void  areflist_setEmpty(ARefList*  l);
41
42AINLINED void
43areflist_done(ARefList*  l)
44{
45    areflist_setEmpty(l);
46}
47
48AINLINED ABool
49areflist_isEmpty(ARefList*  l)
50{
51    return (l->count == 0);
52}
53
54int    areflist_indexOf(ARefList*  l, void*  item);
55
56AINLINED ABool
57areflist_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 */
64void    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 */
68ABool   areflist_del(ARefList*  l, void*  item);
69
70AINLINED void
71areflist_push(ARefList*  l, void*  item)
72{
73    areflist_add(l, item);
74}
75
76void*  areflist_pop(ARefList*  l);
77
78AINLINED void**
79areflist_items(ARefList*  l)
80{
81    return (l->max == 1) ? &l->u.item0 : l->u.items;
82}
83
84AINLINED int
85areflist_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 */
92void**  areflist_at(ARefList*  l, int  n);
93
94/* return the n-th array entry, or NULL in case of invalid index */
95void*   areflist_get(ARefList*  l, int  n);
96
97/* used internally */
98void    _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
127void  areflist_copy(ARefList*  dst, ARefList*  src);
128
129#endif /* _ANDROID_UTILS_REFLIST_H */
130