RList
src/include/rlist/double.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Stefan Götz <stefan.goetz@web.de>
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
00013  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00044 #ifndef RLIST_DOUBLE_H
00045 #define RLIST_DOUBLE_H
00046 
00047 #include <stddef.h>
00048 #include <stdbool.h>
00049 #include <assert.h>
00050 
00051 #include "rlist/platform.h"
00052 #include "rlist/common.h"
00053 
00054 C_DECLARATIONS_START
00055 
00064 #define DRL_INIT { 0, NULL, NULL, NULL }
00065 
00076 #define DRL_INIT_WITH(free_fn) { 0, free_fn, NULL, NULL }
00077 
00085 struct drl_node_ {
00086     /* The payload data provided by the user */
00087     void *payload;
00088     /* The next node in the list.
00089      * If next is NULL, this node is the last node in the list. */
00090     struct drl_node_ *next;
00091     /* The previous node in the list.
00092      * If prev is NULL, this node is the first node in the list. */
00093     struct drl_node_ *prev;
00094 };
00095 
00106 struct drl_list {
00112     unsigned int node_count;
00119     rl_free_fn free_fn;
00125     struct drl_node_ *head;
00131     struct drl_node_ *tail;
00132 };
00133 
00160 struct drl_iterator {
00167     struct drl_list *list;
00172     struct drl_node_ *node;
00179     enum rl_iterator_state_ state;
00180 };
00181 
00197 typedef int (*drl_map_fn)(struct drl_iterator *const iter,
00198                           void *const context);
00199 
00200 /* The following functions are required by some inline functions here in the
00201  * header file.
00202  * Since they are only called from assert(), i.e. not present in production code, the performance impact of not inlining them, too, can be ignored. */
00211 bool drl_check_list_ ARGS((const struct drl_list *const list));
00212 
00223 bool drl_check_iter_in_list_ ARGS((const struct drl_iterator *const iter));
00224 
00235 bool drl_check_iter_post_delete_ ARGS((const struct drl_iterator *const iter));
00236 
00247 bool drl_check_iter_end_of_list_ ARGS((const struct drl_iterator *const iter));
00248 
00259 bool drl_check_iter_in_list_or_end_of_list_ ARGS((const struct drl_iterator *const iter));
00260 
00271 static inline void *drl_payload(const struct drl_iterator *const iter)
00272 {
00273     assert(iter);
00274     return iter->node->payload;
00275 }
00276 
00291 static inline void drl_init(struct drl_list *const list,
00292                             rl_free_fn free_fn)
00293 {
00294     assert(list);
00295     *list = (struct drl_list) DRL_INIT_WITH(free_fn);
00296     assert(drl_check_list_(list));
00297 }
00298 
00308 static inline unsigned int drl_size(const struct drl_list *const list)
00309 {
00310     assert(drl_check_list_(list));
00311     return list->node_count;
00312 }
00313 
00327 static inline struct drl_iterator *drl_first(struct drl_list *const list,
00328                                              struct drl_iterator *const iter)
00329 {
00330     assert(drl_check_list_(list));
00331     assert(iter);
00332 
00333     *iter = (struct drl_iterator) { list, list->head, list->head ? RL_ISTATE_IN_LIST_ : RL_ISTATE_END_OF_LIST_ };
00334 
00335     return iter;
00336 }
00337 
00351 static inline struct drl_iterator *drl_last(struct drl_list *const list,
00352                                             struct drl_iterator *const iter)
00353 {
00354     assert(drl_check_list_(list));
00355     assert(iter);
00356 
00357     *iter = (struct drl_iterator) { list, list->tail, list->tail ? RL_ISTATE_IN_LIST_ : RL_ISTATE_END_OF_LIST_ };
00358 
00359     return iter;
00360 }
00361 
00378 static inline struct drl_iterator *drl_next ARGS((struct drl_iterator *const iter))
00379 {
00380     assert(iter);
00381 
00382     switch (iter->state) {
00383     case RL_ISTATE_IN_LIST_:
00384         assert(drl_check_iter_in_list_(iter));
00385         iter->node = iter->node->next;
00386         break;
00387     case RL_ISTATE_POST_DELETE_:
00388         assert(drl_check_iter_post_delete_(iter));
00389         break;
00390     case RL_ISTATE_END_OF_LIST_:
00391         assert(drl_check_iter_end_of_list_(iter));
00392         break;
00393     }
00394     
00395     if (iter->node) {
00396         iter->state = RL_ISTATE_IN_LIST_;
00397     } else {
00398         iter->state = RL_ISTATE_END_OF_LIST_;
00399     }
00400 
00401     assert(drl_check_iter_in_list_or_end_of_list_(iter));
00402 
00403     return iter;
00404 }
00405 
00422 static inline struct drl_iterator *drl_prev ARGS((struct drl_iterator *const iter))
00423 {
00424     assert(iter);
00425 
00426     switch (iter->state) {
00427     case RL_ISTATE_IN_LIST_:
00428         assert(drl_check_iter_in_list_(iter));
00429         iter->node = iter->node->prev;
00430         break;
00431     case RL_ISTATE_POST_DELETE_:
00432         assert(drl_check_iter_post_delete_(iter));
00433         break;
00434     case RL_ISTATE_END_OF_LIST_:
00435         assert(drl_check_iter_end_of_list_(iter));
00436         break;
00437     }
00438     
00439     if (iter->node) {
00440         iter->state = RL_ISTATE_IN_LIST_;
00441     } else {
00442         iter->state = RL_ISTATE_END_OF_LIST_;
00443     }
00444 
00445     assert(drl_check_iter_in_list_or_end_of_list_(iter));
00446 
00447     return iter;
00448 }
00449 
00463 static inline bool drl_is_eol(const struct drl_iterator *const iter)
00464 {
00465     return !iter->node;
00466 }
00467 
00486 bool drl_insert_before ARGS((struct drl_iterator *const iter,
00487                              void *const payload));
00488 
00511 void *drl_del ARGS((struct drl_iterator *const iter));
00512 
00523 void drl_del_all ARGS((struct drl_list *const list));
00524 
00546 struct drl_iterator *drl_find ARGS((struct drl_iterator *const iter,
00547                                     rl_match_fn match_fn,
00548                                     void *const match_context));
00549 
00567 struct drl_iterator *drl_find_payload ARGS((struct drl_iterator *const iter,
00568                                             void *const payload));
00569 
00597 int drl_map ARGS((struct drl_iterator *const iter,
00598                   drl_map_fn map_fn,
00599                   void *const map_context,
00600                   rl_match_fn match_fn,
00601                   void *const match_context));
00602 
00603 C_DECLARATIONS_END
00604 
00605 #endif /* RLIST_DOUBLE_H */