diff options
Diffstat (limited to 'android/utils/reflist.h')
-rw-r--r-- | android/utils/reflist.h | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/android/utils/reflist.h b/android/utils/reflist.h new file mode 100644 index 0000000..dffaef8 --- /dev/null +++ b/android/utils/reflist.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2007-2008 The Android Open Source Project +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** 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 + +#include "android/utils/system.h" + +/* definitions for a smart list of references to generic objects. + * supports safe deletion and addition while they are being iterated + * with AREFLIST_FOREACH() macro + */ + +typedef struct ARefList { + uint16_t count, max; + uint16_t iteration; + union { + struct ARefList* next; + void* item0; + void** items; + } u; +} ARefList; + +AINLINED void +areflist_init(ARefList* l) +{ + l->count = 0; + l->max = 1; + l->iteration = 0; +} + +void areflist_setEmpty(ARefList* l); + +AINLINED void +areflist_done(ARefList* l) +{ + areflist_setEmpty(l); +} + +AINLINED ABool +areflist_isEmpty(ARefList* l) +{ + return (l->count == 0); +} + +int areflist_indexOf(ARefList* l, void* item); + +AINLINED ABool +areflist_has(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 */ +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); + +AINLINED void +areflist_push(ARefList* l, void* item) +{ + areflist_add(l, item); +} + +void* areflist_pop(ARefList* l); + +AINLINED void** +areflist_items(ARefList* l) +{ + return (l->max == 1) ? &l->u.item0 : l->u.items; +} + +AINLINED int +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); + +/* used internally */ +void _areflist_remove_deferred(ARefList* l); + +#define AREFLIST_FOREACH(list_,item_,statement_) \ + ({ ARefList* _reflist = (list_); \ + int _reflist_i = 0; \ + int _reflist_n = _reflist->count; \ + _reflist->iteration += 2; \ + for ( ; _reflist_i < _reflist_n; _reflist_i++ ) { \ + void** __reflist_at = areflist_at(_reflist, _reflist_i); \ + void* item_ = *__reflist_at; \ + if (item_ != NULL) { \ + statement_; \ + } \ + } \ + _reflist->iteration -= 2; \ + if (_reflist->iteration == 1) \ + _areflist_remove_deferred(_reflist); \ + }) + +/* use this to delete the currently iterated element */ +#define AREFLIST_DEL_ITERATED() \ + ({ *_reflist_at = NULL; \ + _reflist->iteration |= 1; }) + +/* use this to replace the currently iterated element */ +#define AREFLIST_SET_ITERATED(item) \ + ({ *_reflist_at = (item); \ + if (item == NULL) _reflist->iteration |= 1; }) + +void areflist_copy(ARefList* dst, ARefList* src); + +#endif /* _ANDROID_UTILS_REFLIST_H */ |