/usr/include/nih/list.h is in libnih-dev 1.0.3-4ubuntu25.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | /* libnih
*
* Copyright © 2009 Scott James Remnant <scott@netsplit.com>.
* Copyright © 2009 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef NIH_LIST_H
#define NIH_LIST_H
/**
* Provides a generic circular doubly-linked list implementation. Like
* all doubly-linked lists, each entry carries both a pointer to the
* previous entry in the list and a pointer to the next entry in the list.
* However this is also circular, so instead of the first entry's previous
* pointer and last entry's next pointers containing NULL, they instead
* point to the last entry and first entry respectively.
*
* A single NihList structure is generally used as the list head, so
* for an empty list, that structure's previous and next pointers point
* to itself.
*
* This has the advantage over other implementations of a constant time
* operation to append or prepend an entry to the list, insert before or
* after a known entry, and remove an entry from the list.
*
* List entries may be created in one of two ways. The most common is to
* embed the NihList structure as the first member of your own structure,
* and initialise it with nih_list_init() after allocating the structure.
* Alternatively you may create NihListEntry structures with
* nih_list_entry_new() and point at your own data from them.
*
* The list head itself may be created with nih_list_new().
*
* Entries are added to the list with nih_list_add(), passing an existing
* entry which is most commonly the list head. This adds the entry "before"
* the given entry, in the list head case this appends the entry to the list.
* To add "after" the given entry (prepending in the list head case) use
* nih_list_add_before().
*
* To remove an entry from the list use nih_list_remove(). The entry
* effectively becomes the list head of an empty list.
*
* Entries may be moved between lists, or rearranged within a list, by
* simply calling nih_list_add() - there's no need to call nih_list_remove()
* first.
*
* List iteration may be performed by following the prev or next pointers
* in a for loop. Since this is an extremely common operation, the
* NIH_LIST_FOREACH() macro is provided that expands to this for loop.
*
* Since this macro only holds a pointer to the entry being iterated, most
* operations that change a list are not safe. To change a list safely
* while iterating, including being able to free the visited node, use
* the NIH_LIST_FOREACH_SAFE() macro. However note that since this macro
* changes the list as it iterates it itself, it is not safe to traverse
* or iterate the list and make assumptions about the type of node being
* seen.
**/
#include <nih/macros.h>
/**
* NihList:
* @prev: previous entry in the list,
* @next: next entry in the list.
*
* This structure can be used both to refer to a linked list and can be
* placed in your own structures to use them as list entries.
*
* The list is circular so the @next pointer of the last entry points to
* the first, and the @prev pointer of the first entry points to the last.
* An empty list simply has the @prev and @next pointers pointing to itself.
**/
typedef struct nih_list {
struct nih_list *prev, *next;
} NihList;
/**
* NihListEntry:
* @entry: list header,
* @data: data pointer,
* @str: string pointer,
* @int_data: integer value.
*
* This structure can be used as a generic NihList node that contains
* a pointer to generic data, a string or contains an integer value.
*
* You should take care of setting the data yourself.
**/
typedef struct nih_list_entry {
NihList entry;
union {
void *data;
char *str;
int int_data;
};
} NihListEntry;
/**
* NIH_LIST_EMPTY:
* @list: entry in the list to check.
*
* Checks whether the given list is empty by comparing the next and
* previous pointers for equality.
*
* Returns: TRUE if empty, FALSE otherwise.
**/
#define NIH_LIST_EMPTY(list) (((list)->prev == (list)) \
&& ((list)->next) == (list))
/**
* NIH_LIST_FOREACH:
* @list: entry in the list to iterate,
* @iter: name of iterator variable.
*
* Expands to a for statement that iterates over each entry in @list
* except @list itself, setting @iter to each entry for the block within
* the loop.
*
* This is the cheapest form of iteration, however it is not safe to perform
* various modifications to the list; most importantly, you must not change
* the member being iterated in any way, including removing it from the list
* or freeing it. If you need to do that, use NIH_LIST_FOREACH_SAFE() instead.
*
* However since it doesn't modify the list being iterated in any way, it
* is safe to traverse or iterate the list again while iterating.
**/
#define NIH_LIST_FOREACH(list, iter) \
for (NihList *iter = (list)->next; iter != (list); iter = iter->next)
/**
* NIH_LIST_FOREACH_SAFE:
* @list: entry in the list to iterate,
* @iter: name of iterator variable.
*
* Expands to a for statement that iterates over each entry in @list
* except @list itself, setting @iter to each entry for the block within
* the loop.
*
* The iteration is performed safely by placing a cursor node after @iter;
* this means that any node including @iter can be removed from the list,
* added to a different list, or entries added before or after it.
*
* Note that if you add an entry directly after @iter and wish it to be
* visited, you would need to use NIH_LIST_FOREACH() instead, as this
* would be placed before the cursor and thus skipped.
*
* Also since the list has an extra node during iteration of a different
* type, it is expressly not safe to traverse or iterate the list while
* iterating. If you need to perform multiple iterations, or reference
* the next or previous pointers of a node, you must use NIH_LIST_FOREACH().
**/
#define NIH_LIST_FOREACH_SAFE(list, iter) \
for (NihList _##iter __attribute__((cleanup(nih_list_destroy))) = \
{ &_##iter, &_##iter }, \
*iter = nih_list_add_after ((list)->next, &_##iter)->prev; \
iter != (list) && iter != &_##iter; \
iter = nih_list_add_after (_##iter.next, &_##iter)->prev)
/**
* NIH_LIST_ITER:
* @iter: iterator variable,
* @type: type of list member,
* @head: name of list head structure member.
*
* Normally the list head is the first member of the structure, so you can
* simply cast an NihList * iterator to the structure you're expecting to
* find.
*
* However when that is not true, you can use this macro to perform the
* cast based on the offset of @head within @type.
*
* Returns: pointer to top of structure being iterated.
**/
#define NIH_LIST_ITER(iter, type, head) \
(type *)((void *)(iter) - offsetof (type, head))
NIH_BEGIN_EXTERN
void nih_list_init (NihList *entry);
NihList * nih_list_new (const void *parent)
__attribute__ ((warn_unused_result));
NihListEntry *nih_list_entry_new (const void *parent)
__attribute__ ((warn_unused_result));
NihList * nih_list_add (NihList *list, NihList *entry);
NihList * nih_list_add_after (NihList *list, NihList *entry);
NihList * nih_list_remove (NihList *entry);
int nih_list_destroy (NihList *entry);
NIH_END_EXTERN
#endif /* NIH_LIST_H */
|