2 * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
10 #define GET_ITEM(list, item) ((void *)((uint8_t *)item - list->offset))
11 #define GET_LINK(list, item) ((list_link *)((uint8_t *)item + list->offset))
17 /** Initializes the list with a specified offset to the link
18 * structure in the items that will be part of the list.
22 list_init_etc(struct list
*list
, int32_t offset
)
24 list
->link
.next
= list
->link
.prev
= &list
->link
;
25 list
->offset
= offset
;
30 list_init(struct list
*list
)
32 list_init_etc(list
, 0);
36 /** Adds a link to the head of the list
40 list_add_link_to_head(struct list
*list
, void *_link
)
42 list_link
*link
= (list_link
*)_link
;
44 link
->next
= list
->link
.next
;
45 link
->prev
= &list
->link
;
47 list
->link
.next
->prev
= link
;
48 list
->link
.next
= link
;
52 /** Adds a link to the tail of the list
56 list_add_link_to_tail(struct list
*list
, void *_link
)
58 list_link
*link
= (list_link
*)_link
;
60 link
->next
= &list
->link
;
61 link
->prev
= list
->link
.prev
;
63 list
->link
.prev
->next
= link
;
64 list
->link
.prev
= link
;
68 /** Removes a link from the list it's currently in.
69 * Note: the link has to be in a list when you call this function.
73 list_remove_link(void *_link
)
75 list_link
*link
= (list_link
*)_link
;
77 link
->next
->prev
= link
->prev
;
78 link
->prev
->next
= link
->next
;
82 static inline list_link
*
83 get_next_link(struct list
*list
, list_link
*link
)
85 if (link
->next
== &list
->link
)
92 static inline list_link
*
93 get_prev_link(struct list
*list
, list_link
*link
)
95 if (link
->prev
== &list
->link
)
102 /** Gets the successor for the current item. If the passed
103 * item is NULL, it returns the first entry in the list,
105 * Returns NULL if there aren't any more items in this list.
109 list_get_next_item(struct list
*list
, void *item
)
114 return list_is_empty(list
) ? NULL
: GET_ITEM(list
, list
->link
.next
);
116 link
= get_next_link(list
, GET_LINK(list
, item
));
117 return link
!= NULL
? GET_ITEM(list
, link
) : NULL
;
121 /** Gets the predecessor for the current item. If the passed
122 * item is NULL, it returns the last entry in the list,
124 * Returns NULL if there aren't any previous items in this list.
128 list_get_prev_item(struct list
*list
, void *item
)
133 return list_is_empty(list
) ? NULL
: GET_ITEM(list
, list
->link
.prev
);
135 link
= get_prev_link(list
, GET_LINK(list
, item
));
136 return link
!= NULL
? GET_ITEM(list
, link
) : NULL
;
141 list_get_last_item(struct list
*list
)
143 return list_is_empty(list
) ? NULL
: GET_ITEM(list
, list
->link
.prev
);
147 /** Adds an item to the end of the list.
148 * Similar to list_add_link_to_tail() but works on the item, not the link.
152 list_add_item(struct list
*list
, void *item
)
154 list_add_link_to_tail(list
, GET_LINK(list
, item
));
158 /** Removes an item from the list.
159 * Similar to list_remove_link() but works on the item, not the link.
163 list_remove_item(struct list
*list
, void *item
)
165 list_remove_link(GET_LINK(list
, item
));
169 /** Inserts an item before another item in the list.
170 * If you pass NULL as \a before item, the item is added at the end of
175 list_insert_item_before(struct list
*list
, void *before
, void *item
)
177 list_link
*beforeLink
;
180 if (before
== NULL
) {
181 list_add_item(list
, item
);
185 beforeLink
= GET_LINK(list
, before
);
186 link
= GET_LINK(list
, item
);
188 link
->prev
= beforeLink
->prev
;
189 link
->next
= beforeLink
;
191 beforeLink
->prev
->next
= link
;
192 beforeLink
->prev
= link
;
196 /** Removes the first item in the list and returns it.
197 * Returns NULL if the list is empty.
201 list_remove_head_item(struct list
*list
)
205 if (list_is_empty(list
))
208 list_remove_link(link
= list
->link
.next
);
209 return GET_ITEM(list
, link
);
213 /** Removes the last item in the list and returns it.
214 * Returns NULL if the list is empty.
218 list_remove_tail_item(struct list
*list
)
222 if (list_is_empty(list
))
225 list_remove_link(link
= list
->link
.prev
);
226 return GET_ITEM(list
, link
);
230 /** Moves the contents of the source list to the target list.
231 * The target list will be emptied before the items are moved;
232 * this is a very fast operation.
236 list_move_to_list(struct list
*sourceList
, struct list
*targetList
)
238 if (list_is_empty(sourceList
)) {
239 targetList
->link
.next
= targetList
->link
.prev
= &targetList
->link
;
243 *targetList
= *sourceList
;
245 // correct link pointers to this list
246 targetList
->link
.next
->prev
= &targetList
->link
;
247 targetList
->link
.prev
->next
= &targetList
->link
;
250 sourceList
->link
.next
= sourceList
->link
.prev
= &sourceList
->link
;
253 } // namespace FSShell