RList
|
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 */