vfs: check userland buffers before reading them.
[haiku.git] / src / system / kernel / util / list.cpp
blobce7cc1d8535a2e023ac8339ea6a4d691efed7064
1 /*
2 * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <util/list.h>
10 #define GET_ITEM(list, item) ((void *)((uint8 *)item - list->offset))
11 #define GET_LINK(list, item) ((list_link *)((uint8 *)item + list->offset))
14 /** Initializes the list with a specified offset to the link
15 * structure in the items that will be part of the list.
18 void
19 list_init_etc(struct list *list, int32 offset)
21 list->link.next = list->link.prev = &list->link;
22 list->offset = offset;
26 void
27 list_init(struct list *list)
29 list_init_etc(list, 0);
33 /** Adds a link to the head of the list
36 void
37 list_add_link_to_head(struct list *list, void *_link)
39 list_link *link = (list_link *)_link;
41 link->next = list->link.next;
42 link->prev = &list->link;
44 list->link.next->prev = link;
45 list->link.next = link;
49 /** Adds a link to the tail of the list
52 void
53 list_add_link_to_tail(struct list *list, void *_link)
55 list_link *link = (list_link *)_link;
57 link->next = &list->link;
58 link->prev = list->link.prev;
60 list->link.prev->next = link;
61 list->link.prev = link;
65 /** Removes a link from the list it's currently in.
66 * Note: the link has to be in a list when you call this function.
69 void
70 list_remove_link(void *_link)
72 list_link *link = (list_link *)_link;
74 link->next->prev = link->prev;
75 link->prev->next = link->next;
79 static inline list_link *
80 get_next_link(struct list *list, list_link *link)
82 if (link->next == &list->link)
83 return NULL;
85 return link->next;
89 static inline list_link *
90 get_prev_link(struct list *list, list_link *link)
92 if (link->prev == &list->link)
93 return NULL;
95 return link->prev;
99 /** Gets the successor for the current item. If the passed
100 * item is NULL, it returns the first entry in the list,
101 * if there is one.
102 * Returns NULL if there aren't any more items in this list.
105 void *
106 list_get_next_item(struct list *list, void *item)
108 list_link *link;
110 if (item == NULL)
111 return list_is_empty(list) ? NULL : GET_ITEM(list, list->link.next);
113 link = get_next_link(list, GET_LINK(list, item));
114 return link != NULL ? GET_ITEM(list, link) : NULL;
118 /** Gets the predecessor for the current item. If the passed
119 * item is NULL, it returns the last entry in the list,
120 * if there is one.
121 * Returns NULL if there aren't any previous items in this list.
124 void *
125 list_get_prev_item(struct list *list, void *item)
127 list_link *link;
129 if (item == NULL)
130 return list_is_empty(list) ? NULL : GET_ITEM(list, list->link.prev);
132 link = get_prev_link(list, GET_LINK(list, item));
133 return link != NULL ? GET_ITEM(list, link) : NULL;
137 void *
138 list_get_last_item(struct list *list)
140 return list_is_empty(list) ? NULL : GET_ITEM(list, list->link.prev);
144 /** Adds an item to the end of the list.
145 * Similar to list_add_link_to_tail() but works on the item, not the link.
148 void
149 list_add_item(struct list *list, void *item)
151 list_add_link_to_tail(list, GET_LINK(list, item));
155 /** Removes an item from the list.
156 * Similar to list_remove_link() but works on the item, not the link.
159 void
160 list_remove_item(struct list *list, void *item)
162 list_remove_link(GET_LINK(list, item));
166 /** Inserts an item before another item in the list.
167 * If you pass NULL as \a before item, the item is added at the end of
168 * the list.
171 void
172 list_insert_item_before(struct list *list, void *before, void *item)
174 list_link *beforeLink;
175 list_link *link;
177 if (before == NULL) {
178 list_add_item(list, item);
179 return;
182 beforeLink = GET_LINK(list, before);
183 link = GET_LINK(list, item);
185 link->prev = beforeLink->prev;
186 link->next = beforeLink;
188 beforeLink->prev->next = link;
189 beforeLink->prev = link;
193 /** Removes the first item in the list and returns it.
194 * Returns NULL if the list is empty.
197 void *
198 list_remove_head_item(struct list *list)
200 list_link *link;
202 if (list_is_empty(list))
203 return NULL;
205 list_remove_link(link = list->link.next);
206 return GET_ITEM(list, link);
210 /** Removes the last item in the list and returns it.
211 * Returns NULL if the list is empty.
214 void *
215 list_remove_tail_item(struct list *list)
217 list_link *link;
219 if (list_is_empty(list))
220 return NULL;
222 list_remove_link(link = list->link.prev);
223 return GET_ITEM(list, link);
227 /** Moves the contents of the source list to the target list.
228 * The target list will be emptied before the items are moved;
229 * this is a very fast operation.
232 void
233 list_move_to_list(struct list *sourceList, struct list *targetList)
235 if (list_is_empty(sourceList)) {
236 targetList->link.next = targetList->link.prev = &targetList->link;
237 return;
240 *targetList = *sourceList;
242 // correct link pointers to this list
243 targetList->link.next->prev = &targetList->link;
244 targetList->link.prev->next = &targetList->link;
246 // empty source list
247 sourceList->link.next = sourceList->link.prev = &sourceList->link;