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