blob: dffaef823e0630f9858c9c9b492c89c59265accf [file] [log] [blame]
/* 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 */