Ignore:
File:
1 edited

Legend:

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

    rc14762e r7856d09  
    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;
    52 
    53 
    54 extern int list_member(const link_t *, const list_t *);
    55 extern void list_splice(list_t *, link_t *);
    56 extern unsigned int list_count(const list_t *);
    57 
    5853
    5954/** Declare and initialize statically allocated list.
     
    7166
    7267#define list_get_instance(link, type, member) \
    73         ((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
    74 
    75 #define list_foreach(list, iterator) \
    76         for (link_t *iterator = (list).head.next; \
    77             iterator != &(list).head; iterator = iterator->next)
    78 
    79 /** Unlike list_foreach(), allows removing items while traversing a list.
    80  *
    81  * @code
    82  * list_t mylist;
    83  * typedef struct item {
    84  *     int value;
    85  *     link_t item_link;
    86  * } item_t;
    87  *
    88  * //..
    89  *
    90  * // Print each list element's value and remove the element from the list.
    91  * list_foreach_safe(mylist, cur_link, next_link) {
    92  *     item_t *cur_item = list_get_instance(cur_link, item_t, item_link);
    93  *     printf("%d\n", cur_item->value);
    94  *     list_remove(cur_link);
    95  * }
    96  * @endcode
    97  *
    98  * @param list List to traverse.
    99  * @param iterator Iterator to the current element of the list.
    100  *             The item this iterator points may be safely removed
    101  *             from the list.
    102  * @param next_iter Iterator to the next element of the list.
    103  */
    104 #define list_foreach_safe(list, iterator, next_iter) \
    105         for (link_t *iterator = (list).head.next, \
    106                 *next_iter = iterator->next; \
    107                 iterator != &(list).head; \
    108                 iterator = next_iter, next_iter = iterator->next)
    109 
    110        
     68        ((type *) (((void *)(link)) - list_link_to_void(&(((type *) NULL)->member))))
     69
     70#define list_foreach(list, member, itype, iterator) \
     71        for (itype *iterator = NULL; iterator == NULL; iterator = (itype *) 1) \
     72            for (link_t *_link = (list).head.next; \
     73            iterator = list_get_instance(_link, itype, member), \
     74            _link != &(list).head; _link = _link->next)
     75
     76#define list_foreach_rev(list, member, itype, iterator) \
     77        for (itype *iterator = NULL; iterator == NULL; iterator = (itype *) 1) \
     78            for (link_t *_link = (list).head.prev; \
     79            iterator = list_get_instance(_link, itype, member), \
     80            _link != &(list).head; _link = _link->prev)
     81
    11182#define assert_link_not_used(link) \
    112         ASSERT(((link)->prev == NULL) && ((link)->next == NULL))
     83        ASSERT(!link_used(link))
    11384
    11485/** Initialize doubly-linked circular list link
     
    12394        link->prev = NULL;
    12495        link->next = NULL;
    125 }
    126 
    127 /** Returns true if the initialized link is already in use by any list.
    128  *
    129  * @param link Link to examine whether if belongs to a list or not.
    130  * @return 1 if the link is part of a list.
    131  * @return 0 otherwise.
    132  */
    133 NO_TRACE static inline int link_used(const link_t *link)
    134 {
    135         return link->prev != NULL || link->next != NULL;
    13696}
    13797
     
    253213}
    254214
     215/** Get next item in list.
     216 *
     217 * @param link Current item link
     218 * @param list List containing @a link
     219 *
     220 * @return Next item or NULL if @a link is the last item.
     221 */
     222static inline link_t *list_next(link_t *link, const list_t *list)
     223{
     224        return (link->next == &list->head) ? NULL : link->next;
     225}
     226
     227/** Get previous item in list.
     228 *
     229 * @param link Current item link
     230 * @param list List containing @a link
     231 *
     232 * @return Previous item or NULL if @a link is the first item.
     233 */
     234static inline link_t *list_prev(link_t *link, const list_t *list)
     235{
     236        return (link->prev == &list->head) ? NULL : link->prev;
     237}
     238
    255239/** Split or concatenate headless doubly-linked circular list
    256240 *
     
    307291}
    308292
    309 /** Concatenate two lists
    310  *
    311  * Concatenate lists @a list1 and @a list2, producing a single
    312  * list @a list1 containing items from both (in @a list1, @a list2
    313  * order) and empty list @a list2.
    314  *
    315  * @param list1         First list and concatenated output
    316  * @param list2         Second list and empty output.
    317  *
    318  */
    319 NO_TRACE static inline void list_concat(list_t *list1, list_t *list2)
    320 {
    321         list_splice(list2, list1->head.prev);
    322 }
    323 
    324293/** Get n-th item in a list.
    325294 *
     
    334303{
    335304        unsigned int cnt = 0;
    336        
    337         list_foreach(*list, link) {
     305        link_t *link;
     306       
     307        link = list_first(list);
     308        while (link != NULL) {
    338309                if (cnt == n)
    339310                        return link;
    340311               
    341312                cnt++;
     313                link = list_next(link, list);
    342314        }
    343315       
     
    345317}
    346318
     319/** Verify that argument type is a pointer to link_t (at compile time).
     320 *
     321 * This can be used to check argument type in a macro.
     322 */
     323static inline const void *list_link_to_void(const link_t *link)
     324{
     325        return link;
     326}
     327
     328/** Determine if link is used.
     329 *
     330 * @param link Link
     331 * @return @c true if link is used, @c false if not.
     332 */
     333static inline bool link_used(link_t *link)
     334{
     335        if (link->prev == NULL && link->next == NULL)
     336                return false;
     337
     338        ASSERT(link->prev != NULL && link->next != NULL);
     339        return true;
     340}
     341
     342extern int list_member(const link_t *, const list_t *);
     343extern void list_concat(list_t *, list_t *);
     344extern unsigned int list_count(const list_t *);
     345
    347346#endif
    348347
Note: See TracChangeset for help on using the changeset viewer.