aboutsummaryrefslogtreecommitdiffstats
path: root/android/utils/reflist.h
diff options
context:
space:
mode:
Diffstat (limited to 'android/utils/reflist.h')
-rw-r--r--android/utils/reflist.h155
1 files changed, 117 insertions, 38 deletions
diff --git a/android/utils/reflist.h b/android/utils/reflist.h
index dffaef8..7275f54 100644
--- a/android/utils/reflist.h
+++ b/android/utils/reflist.h
@@ -9,77 +9,111 @@
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
-#ifndef _ANDROID_UTILS_REFLIST_H
-#define _ANDROID_UTILS_REFLIST_H
+#ifndef _ANDROID_GRAPHICS_REFLIST_H
+#define _ANDROID_GRAPHICS_REFLIST_H
-#include "android/utils/system.h"
+#include <inttypes.h>
+#include <android/utils/system.h>
-/* definitions for a smart list of references to generic objects.
+/* Definitions for a smart list of references to generic objects.
* supports safe deletion and addition while they are being iterated
- * with AREFLIST_FOREACH() macro
+ * with AREFLIST_FOREACH() macro.
+ *
+ * note that you cannot add NULL to an ARefList.
*/
+/* Clients should ignore these implementation details, which
+ * we're going to explain there:
+ * - 'count' is the number of items in the list
+ * - 'size' is the number of slots in the list's array. It is
+ * always >= 'count'. Some slots correspond to deleted items
+ * and will hold a NULL value.
+ * - 'max' is the size of the slots array
+ * - 'u.item0' is used when 'max' is 1
+ * - 'u.items' is the slot array if 'max > 1'
+ * - 'u.next' is only used for free-list storage.
+ */
typedef struct ARefList {
- uint16_t count, max;
+ /* XXX: should we use uint32_t instead ? */
+ uint16_t count, size, max;
uint16_t iteration;
union {
- struct ARefList* next;
- void* item0;
- void** items;
+ void* item0;
+ void** items;
} u;
} ARefList;
-AINLINED void
+/* Initialize an empty ARefList */
+AINLINED void
areflist_init(ARefList* l)
{
l->count = 0;
+ l->size = 0;
l->max = 1;
l->iteration = 0;
}
+/* Return the number of items in a list */
+AINLINED int
+areflist_getCount(const ARefList* l)
+{
+ return l->count;
+}
+
+/* Clear an ARefList */
void areflist_setEmpty(ARefList* l);
+/* Finalize, i.e. clear, an ARefList */
AINLINED void
areflist_done(ARefList* l)
{
areflist_setEmpty(l);
}
+/* Return TRUE iff an ARefList has no item */
AINLINED ABool
-areflist_isEmpty(ARefList* l)
+areflist_isEmpty(const ARefList* l)
{
- return (l->count == 0);
+ return (areflist_getCount(l) == 0);
}
-int areflist_indexOf(ARefList* l, void* item);
+/* Return the index of 'item' in the ARefList, or -1.
+ * This returns -1 if 'item' is NULL.
+ */
+int areflist_indexOf(const ARefList* l, void* item);
-AINLINED ABool
-areflist_has(ARefList* l, void* item)
+/* Return TRUE iff an ARefList contains 'item' */
+AINLINED ABool
+areflist_has(const ARefList* l, void* item)
{
return areflist_indexOf(l, item) >= 0;
}
-/* if 'item' is not NULL, append it to the list. An item
- * can be added several times to a list */
+/* Append 'item' to a list. An item can be added several
+ * times to the same list. Do nothing if 'item' is NULL. */
void areflist_add(ARefList* l, void* item);
-/* if 'item' is not NULL, try to remove it from the list */
-/* returns TRUE iff the item was found in the list */
-ABool areflist_del(ARefList* l, void* item);
+/* Remove first instance of 'item' from an ARefList.
+ * Returns TRUE iff the item was found in the list. */
+ABool areflist_delFirst(ARefList* l, void* item);
+/* Remove all instances of 'item' from an ARefList.
+ * returns TRUE iff the item was found in the list */
+ABool areflist_delAll(ARefList* l, void* item);
+
+/* Same as areflist_add() */
AINLINED void
areflist_push(ARefList* l, void* item)
{
areflist_add(l, item);
}
-void* areflist_pop(ARefList* l);
+/* Remove last item from an ARefList and return it.
+ * NULL is returned if the list is empty */
+void* areflist_popLast(ARefList* l);
-AINLINED void**
-areflist_items(ARefList* l)
-{
- return (l->max == 1) ? &l->u.item0 : l->u.items;
-}
+/* Return the n-th array entry, or NULL in case of invalid index */
+void* areflist_get(const ARefList* l, int n);
AINLINED int
areflist_count(ARefList* l)
@@ -87,23 +121,55 @@ areflist_count(ARefList* l)
return l->count;
}
-/* return a pointer to the n-th list array entry,
- or NULL in case of invalid index */
-void** areflist_at(ARefList* l, int n);
-
-/* return the n-th array entry, or NULL in case of invalid index */
-void* areflist_get(ARefList* l, int n);
+void areflist_append(ARefList* l, const ARefList* src);
/* used internally */
void _areflist_remove_deferred(ARefList* l);
+void** _areflist_at(const ARefList* l, int n);
+
+#define AREFLIST_LOOP(list_,itemvar_) \
+ do { \
+ ARefList* _reflist_loop = (list_); \
+ int _reflist_loop_i = 0; \
+ int _reflist_loop_n = _reflist_loop->size; \
+ _reflist_loop->iteration += 2; \
+ for ( ; _reflist_loop_i < _reflist_loop_n; _reflist_loop_i++ ) { \
+ void** _reflist_loop_at = _areflist_at(_reflist_loop, _reflist_loop_i); \
+ (itemvar_) = *(_reflist_loop_at); \
+ if ((itemvar_) != NULL) {
+
+#define AREFLIST_LOOP_END \
+ } \
+ } \
+ if (_reflist_loop->iteration & 1) \
+ _areflist_remove_deferred(_reflist_loop); \
+ } while (0);
+
+#define AREFLIST_LOOP_CONST(list_,itemvar_) \
+ do { \
+ const ARefList* _reflist_loop = (list_); \
+ int _reflist_loop_i = 0; \
+ int _reflist_loop_n = _reflist_loop->size; \
+ for ( ; _reflist_loop_i < _reflist_loop_n; _reflist_loop_i++ ) { \
+ void** _reflist_loop_at = _areflist_at(_reflist_loop, _reflist_loop_i); \
+ (itemvar_) = *(_reflist_loop_at); \
+ if ((itemvar_) != NULL) {
+
+#define AREFLIST_LOOP_DEL() \
+ (_reflist_loop->iteration |= 1, *_reflist_loop_at = NULL)
+
+#define AREFLIST_LOOP_SET(val) \
+ (_reflist_loop->iteration |= 1, *_reflist_loop_at = (val))
+
+
#define AREFLIST_FOREACH(list_,item_,statement_) \
({ ARefList* _reflist = (list_); \
int _reflist_i = 0; \
- int _reflist_n = _reflist->count; \
+ int _reflist_n = _reflist->size; \
_reflist->iteration += 2; \
for ( ; _reflist_i < _reflist_n; _reflist_i++ ) { \
- void** __reflist_at = areflist_at(_reflist, _reflist_i); \
+ void** __reflist_at = _areflist_at(_reflist, _reflist_i); \
void* item_ = *__reflist_at; \
if (item_ != NULL) { \
statement_; \
@@ -114,16 +180,29 @@ void _areflist_remove_deferred(ARefList* l);
_areflist_remove_deferred(_reflist); \
})
+#define AREFLIST_FOREACH_CONST(list_,item_,statement_) \
+ ({ const ARefList* _reflist = (list_); \
+ int _reflist_i = 0; \
+ int _reflist_n = _reflist->size; \
+ for ( ; _reflist_i < _reflist_n; _reflist_i++ ) { \
+ void** __reflist_at = _areflist_at(_reflist, _reflist_i); \
+ void* item_ = *__reflist_at; \
+ if (item_ != NULL) { \
+ statement_; \
+ } \
+ } \
+ })
+
/* use this to delete the currently iterated element */
#define AREFLIST_DEL_ITERATED() \
- ({ *_reflist_at = NULL; \
+ ({ *__reflist_at = NULL; \
_reflist->iteration |= 1; })
/* use this to replace the currently iterated element */
#define AREFLIST_SET_ITERATED(item) \
- ({ *_reflist_at = (item); \
+ ({ *__reflist_at = (item); \
if (item == NULL) _reflist->iteration |= 1; })
-void areflist_copy(ARefList* dst, ARefList* src);
+void areflist_copy(ARefList* dst, const ARefList* src);
-#endif /* _ANDROID_UTILS_REFLIST_H */
+#endif /* _ANDROID_GRAPHICS_REFLIST_H */