| /* Copyright (C) 2011 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_LIST_H |
| #define _ANDROID_UTILS_LIST_H |
| |
| #include <inttypes.h> |
| |
| #include "android/utils/compiler.h" |
| |
| ANDROID_BEGIN_HEADER |
| |
| /* Encapsulates a double-linked, circular list. |
| * The list is organized in the following way: |
| * - List entries contain references to the next, and the previous entry in the |
| * list. |
| * - The list is circular, i.e. the "last" list entry references the "list head" |
| * in its 'next' reference, and the "list head" references the "last" entry in |
| * its 'previous' reference. |
| * - The list is empty if its 'next' and 'previous' references are addressing the |
| * head of the list. |
| */ |
| typedef struct ACList ACList; |
| struct ACList { |
| /* Next entry in the list */ |
| ACList* next; |
| /* Previous entry in the list */ |
| ACList* prev; |
| }; |
| |
| /* Initializes the list. */ |
| AINLINED void |
| alist_init(ACList* list) |
| { |
| list->next = list->prev = list; |
| } |
| |
| /* Checks if the list is empty. */ |
| AINLINED int |
| alist_is_empty(const ACList* list) |
| { |
| return list->next == list; |
| } |
| |
| /* Inserts an entry to the head of the list */ |
| AINLINED void |
| alist_insert_head(ACList* list, ACList* entry) |
| { |
| ACList* const next = list->next; |
| entry->next = next; |
| entry->prev = list; |
| next->prev = entry; |
| list->next = entry; |
| } |
| /* Inserts an entry to the tail of the list */ |
| AINLINED void |
| alist_insert_tail(ACList* list, ACList* entry) |
| { |
| ACList* const prev = list->prev; |
| entry->next = list; |
| entry->prev = prev; |
| prev->next = entry; |
| list->prev = entry; |
| } |
| |
| /* Removes an entry from the list. NOTE: Entry must be in the list when this |
| * routine is called. */ |
| AINLINED void |
| alist_remove(ACList* entry) |
| { |
| ACList* const next = entry->next; |
| ACList* const prev = entry->prev; |
| prev->next = next; |
| next->prev = prev; |
| entry->next = entry->prev = entry; |
| } |
| |
| /* Returns an entry removed from the head of the list. If the list was empty, |
| * this routine returns NULL. */ |
| AINLINED ACList* |
| alist_remove_head(ACList* list) |
| { |
| ACList* entry = NULL; |
| if (!alist_is_empty(list)) { |
| entry = list->next; |
| list->next = entry->next; |
| entry->next->prev = list; |
| entry->next = entry->prev = entry; |
| } |
| return entry; |
| } |
| |
| /* Returns an entry removed from the tail of the list. If the list was empty, |
| * this routine returns NULL. */ |
| AINLINED ACList* |
| alist_remove_tail(ACList* list) |
| { |
| ACList* entry = NULL; |
| if (!alist_is_empty(list)) { |
| entry = list->prev; |
| list->prev = entry->prev; |
| entry->prev->next = list; |
| entry->next = entry->prev = entry; |
| } |
| return entry; |
| } |
| |
| ANDROID_END_HEADER |
| |
| #endif /* _ANDROID_UTILS_LIST_H */ |