/* 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. */ #include "android/utils/reflist.h" #include #include void areflist_setEmpty(ARefList* l) { if (l->iteration > 0) { /* deferred empty, set all items to NULL * to stop iterations */ void** items = areflist_items(l); memset(items, 0, l->count*sizeof(items[0])); l->iteration |= 1; } else { /* direct empty */ if (l->max > 1) { free(l->u.items); l->max = 1; } } l->count = 0; } int areflist_indexOf(ARefList* l, void* item) { if (item) { void** items = (l->max == 1) ? &l->u.item0 : l->u.items; void** end = items + l->count; void** ii = items; for ( ; ii < end; ii += 1 ) if (*ii == item) return (ii - items); } return -1; } static void areflist_grow(ARefList* l, int count) { int newcount = l->count + count; if (newcount > l->max) { int oldmax = l->max == 1 ? 0 : l->max; int newmax = oldmax; void** olditems = l->max == 1 ? NULL : l->u.items; void** newitems; while (oldmax < newcount) oldmax += (oldmax >> 1) + 4; newitems = realloc(olditems, newmax*sizeof(newitems[0])); l->u.items = newitems; l->max = (uint16_t) newmax; } } void areflist_add(ARefList* l, void* item) { if (item) { void** items; if (l->count >= l->max) { areflist_grow(l, 1); } items = areflist_items(l); items[l->count] = item; l->count += 1; } } void* areflist_pop(ARefList* l) { void* item = NULL; void** items = areflist_items(l); if (l->count > 0) { if (l->iteration > 0) { /* deferred deletion */ int nn; for (nn = l->count-1; nn > 0; nn--) { item = items[nn]; if (item != NULL) { l->count -= 1; return item; } } } else { /* normal pop */ item = items[--l->count]; if (l->count <= 0 && l->max > 1) { free(l->u.items); l->max = 1; } } } return item; } ABool areflist_del(ARefList* l, void* item) { if (item) { int index = areflist_indexOf(l, item); if (index >= 0) { void** items = areflist_items(l); if (l->iteration > 0) { /* deferred deletion */ items[index] = NULL; l->iteration |= 1; } else { /* direct deletion */ if (l->max > 1) { memmove(items + index, items + index + 1, l->count - index - 1); if (--l->count == 0) { free(l->u.items); l->max = 1; } } else { l->u.item0 = NULL; l->count = 0; } } return 1; } } return 0; } void _areflist_remove_deferred(ARefList* l) { if (l->iteration & 1) { /* remove all NULL elements from the array */ void** items = areflist_items(l); int rr = 0; int ww = 0; for ( ; rr < l->count; rr++ ) { if (items[rr] != NULL) items[ww++] = items[rr]; } l->count = (int16_t) ww; /* if the list is empty, release its array */ if (l->count == 0 && l->max > 1) { free(l->u.items); l->max = 1; } } l->iteration = 0; } void areflist_copy(ARefList* dst, ARefList* src) { dst[0] = src[0]; if (src->max > 1) { dst->u.items = malloc( dst->count*sizeof(void*) ); dst->max = dst->count; } } void* areflist_get(ARefList* l, int n) { if ((unsigned)n >= (unsigned)l->count) return NULL; if (l->max == 1) return l->u.item0; return l->u.items[n]; } void** areflist_at(ARefList* l, int n) { void** items; if ((unsigned)n >= (unsigned)l->count) return NULL; items = (l->max == 1) ? &l->u.item0 : l->u.items; return items + n; }