Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/adt/list.h

    r9d58539 re98f1c3e  
    11/*
    22 * Copyright (c) 2001-2004 Jakub Jermar
    3  * Copyright (c) 2011 Jiri Svoboda
     3 * Copyright (c) 2013 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    3737#define KERN_LIST_H_
    3838
     39#include <debug.h>
    3940#include <typedefs.h>
    4041#include <trace.h>
     
    5051        link_t head;  /**< List head. Does not have any data. */
    5152} list_t;
     53
     54
     55extern bool list_member(const link_t *, const list_t *);
     56extern void list_splice(list_t *, link_t *);
     57extern unsigned long list_count(const list_t *);
     58
    5259
    5360/** Declare and initialize statically allocated list.
     
    6572
    6673#define list_get_instance(link, type, member) \
    67         ((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
    68 
    69 #define list_foreach(list, iterator) \
    70         for (link_t *iterator = (list).head.next; \
    71             iterator != &(list).head; iterator = iterator->next)
    72 
     74        ((type *) (((void *)(link)) - list_link_to_void(&(((type *) NULL)->member))))
     75
     76#define list_foreach(list, member, itype, iterator) \
     77        for (itype *iterator = NULL; iterator == NULL; iterator = (itype *) 1) \
     78                for (link_t *_link = (list).head.next; \
     79                    iterator = list_get_instance(_link, itype, member), \
     80                    _link != &(list).head; _link = _link->next)
     81
     82#define list_foreach_rev(list, member, itype, iterator) \
     83        for (itype *iterator = NULL; iterator == NULL; iterator = (itype *) 1) \
     84                for (link_t *_link = (list).head.prev; \
     85                    iterator = list_get_instance(_link, itype, member), \
     86                    _link != &(list).head; _link = _link->prev)
     87
     88/** Unlike list_foreach(), allows removing items while traversing a list.
     89 *
     90 * @code
     91 * list_t mylist;
     92 * typedef struct item {
     93 *     int value;
     94 *     link_t item_link;
     95 * } item_t;
     96 *
     97 * //..
     98 *
     99 * // Print each list element's value and remove the element from the list.
     100 * list_foreach_safe(mylist, cur_link, next_link) {
     101 *     item_t *cur_item = list_get_instance(cur_link, item_t, item_link);
     102 *     printf("%d\n", cur_item->value);
     103 *     list_remove(cur_link);
     104 * }
     105 * @endcode
     106 *
     107 * @param list List to traverse.
     108 * @param iterator Iterator to the current element of the list.
     109 *             The item this iterator points may be safely removed
     110 *             from the list.
     111 * @param next_iter Iterator to the next element of the list.
     112 */
     113#define list_foreach_safe(list, iterator, next_iter) \
     114        for (link_t *iterator = (list).head.next, \
     115            *next_iter = iterator->next; \
     116            iterator != &(list).head; \
     117            iterator = next_iter, next_iter = iterator->next)
     118
     119       
    73120#define assert_link_not_used(link) \
    74         ASSERT(((link)->prev == NULL) && ((link)->next == NULL))
     121        ASSERT(!link_used(link))
    75122
    76123/** Initialize doubly-linked circular list link
     
    173220 *
    174221 */
    175 NO_TRACE static inline int list_empty(const list_t *list)
     222NO_TRACE static inline bool list_empty(const list_t *list)
    176223{
    177224        return (list->head.next == &list->head);
     
    202249{
    203250        return ((list->head.prev == &list->head) ? NULL : list->head.prev);
     251}
     252
     253/** Get next item in list.
     254 *
     255 * @param link Current item link
     256 * @param list List containing @a link
     257 *
     258 * @return Next item or NULL if @a link is the last item.
     259 */
     260static inline link_t *list_next(link_t *link, const list_t *list)
     261{
     262        return (link->next == &list->head) ? NULL : link->next;
     263}
     264
     265/** Get previous item in list.
     266 *
     267 * @param link Current item link
     268 * @param list List containing @a link
     269 *
     270 * @return Previous item or NULL if @a link is the first item.
     271 */
     272static inline link_t *list_prev(link_t *link, const list_t *list)
     273{
     274        return (link->prev == &list->head) ? NULL : link->prev;
    204275}
    205276
     
    258329}
    259330
     331/** Concatenate two lists
     332 *
     333 * Concatenate lists @a list1 and @a list2, producing a single
     334 * list @a list1 containing items from both (in @a list1, @a list2
     335 * order) and empty list @a list2.
     336 *
     337 * @param list1         First list and concatenated output
     338 * @param list2         Second list and empty output.
     339 *
     340 */
     341NO_TRACE static inline void list_concat(list_t *list1, list_t *list2)
     342{
     343        list_splice(list2, list1->head.prev);
     344}
     345
    260346/** Get n-th item in a list.
    261347 *
     
    267353 *
    268354 */
    269 static inline link_t *list_nth(list_t *list, unsigned int n)
    270 {
    271         unsigned int cnt = 0;
    272        
    273         list_foreach(*list, link) {
     355static inline link_t *list_nth(list_t *list, unsigned long n)
     356{
     357        unsigned long cnt = 0;
     358        link_t *link;
     359       
     360        link = list_first(list);
     361        while (link != NULL) {
    274362                if (cnt == n)
    275363                        return link;
    276364               
    277365                cnt++;
     366                link = list_next(link, list);
    278367        }
    279368       
     
    281370}
    282371
    283 extern int list_member(const link_t *, const list_t *);
    284 extern void list_concat(list_t *, list_t *);
    285 extern unsigned int list_count(const list_t *);
     372/** Verify that argument type is a pointer to link_t (at compile time).
     373 *
     374 * This can be used to check argument type in a macro.
     375 */
     376static inline const void *list_link_to_void(const link_t *link)
     377{
     378        return link;
     379}
     380
     381/** Determine if link is used.
     382 *
     383 * @param link Link
     384 * @return @c true if link is used, @c false if not.
     385 */
     386static inline bool link_used(link_t *link)
     387{
     388        if (link->prev == NULL && link->next == NULL)
     389                return false;
     390
     391        ASSERT(link->prev != NULL && link->next != NULL);
     392        return true;
     393}
    286394
    287395#endif
Note: See TracChangeset for help on using the changeset viewer.