00001 /* Part of the culibs project, <http://www.eideticdew.org/culibs/>. 00002 * Copyright (C) 2006--2009 Petter Urkedal <urkedal@nbi.dk> 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef CU_DLINK_H 00019 #define CU_DLINK_H 00020 00021 #include <cu/fwd.h> 00022 #include <cu/debug.h> 00023 00024 CU_BEGIN_DECLARATIONS 00025 /** \defgroup cu_dlink_h cu/dlink.h: Double Link Struct and Functions 00026 ** @{ \ingroup cu_util_mod 00027 ** 00028 ** Defines a simple double link structure and inline functions to manipulate 00029 ** them. This is intended as a low-level functionality used to define higher 00030 ** level structures. 00031 ** 00032 ** These links are represented as cyclic. When used as a list, the cycle is 00033 ** broken by one special head link which is used to refer to the whole list, 00034 ** and which may represent the past-the-end iterator. */ 00035 00036 /** The double link structure. As opposed to most structure in this library, 00037 ** this can be considered transparent. */ 00038 struct cu_dlink 00039 { 00040 cu_dlink_t next; /**< Points to the next element of the link. */ 00041 cu_dlink_t prev; /**< Points to the previous element of the link. */ 00042 }; 00043 00044 #ifdef CU_DEBUG_DLINK 00045 # define cu_debug_dlink_invalidate(l) ((void)((l)->next = NULL)) 00046 # define cu_debug_dlink_assert_valid(l) cu_debug_assert((l)->next != NULL) 00047 #else 00048 # define cu_debug_dlink_invalidate(l_init) ((void)(l_init)) 00049 # define cu_debug_dlink_assert_valid(l) ((void)(l)) 00050 #endif 00051 00052 #define CU_DLINK_SINGLETON_DECL(cuL_var) \ 00053 struct cu_dlink cuL_var = {&cuL_var, &cuL_var} 00054 00055 /** Validate the link integrity of \a l. */ 00056 void cu_dlink_validate(cu_dlink_t l); 00057 00058 /** Initialise \a l_init as a link with next and prev pointing to itself. This 00059 ** is typically used as the head of doubly linked lists. */ 00060 CU_SINLINE void 00061 cu_dlink_init_singleton(cu_dlink_t l_init) 00062 { l_init->next = l_init->prev = l_init; } 00063 00064 /** True iff \a l is a singleton. */ 00065 CU_SINLINE cu_bool_t cu_dlink_is_singleton(cu_dlink_t l) 00066 { return l != NULL && l == l->next; } 00067 00068 /** True iff the cardinality of \a l is at most 1. */ 00069 CU_SINLINE cu_bool_t cu_dlink_card_leq_1(cu_dlink_t l) 00070 { return l == NULL || l->next == l; } 00071 00072 /** True iff the cardinality of \a l is 2. */ 00073 CU_SINLINE cu_bool_t cu_dlink_card_eq_2(cu_dlink_t l) 00074 { return l != NULL && l != l->next && l->prev == l->next; } 00075 00076 /** True iff the cardinality of \a l is at most 2. */ 00077 CU_SINLINE cu_bool_t cu_dlink_card_leq_2(cu_dlink_t l) 00078 { return l == NULL || l->prev == l->next; } 00079 00080 /** Return minimum of the \a limit and the number of elements of \a l. The 00081 ** limit allows quick return if the client is only needs to distinguish cases 00082 ** up to a certain number. Pass \c SIZE_MAX for \a limit for a full count. */ 00083 size_t cu_dlink_card_lim(cu_dlink_t l, size_t limit); 00084 00085 /** Return the number of element of the cycle of which \a l is a member. This 00086 ** takes linear time in the number of nodes. 00087 ** \see cu_dlink_card_lim */ 00088 CU_SINLINE size_t cu_dlink_card(cu_dlink_t l) 00089 { return cu_dlink_card_lim(l, SIZE_MAX); } 00090 00091 /** True iff \a l0 and \a l1 are part of the same cycle. Runs in linear time 00092 ** in the smaller of the cardinalities of the two arguments. 00093 ** \pre Neither argument is \c NULL. */ 00094 cu_bool_t cu_dlink_cocyclic(cu_dlink_t l0, cu_dlink_t l1); 00095 00096 /** Erases and invalidates \a l from the link it is part of. \a l must not be 00097 ** singular. */ 00098 CU_SINLINE void 00099 cu_dlink_erase(cu_dlink_t l) 00100 { 00101 cu_debug_dlink_assert_valid(l); 00102 cu_debug_assert(l->next != l); 00103 l->prev->next = l->next; 00104 l->next->prev = l->prev; 00105 cu_debug_dlink_invalidate(l); 00106 } 00107 00108 /** Removes \a l from its cycle and reconstruct it as an singleton. */ 00109 void cu_dlink_extract(cu_dlink_t l); 00110 00111 /** Initialise \a l_init as the predecessor of \a l. 00112 ** \pre \a l is not \c NULL. */ 00113 CU_SINLINE void 00114 cu_dlink_insert_before(cu_dlink_t l, cu_dlink_t l_init) 00115 { 00116 cu_debug_dlink_assert_valid(l); 00117 l_init->prev = l->prev; 00118 l_init->next = l; 00119 l->prev->next = l_init; 00120 l->prev = l_init; 00121 } 00122 00123 /** Initialise \a l_init as the successor of \a l. 00124 ** \pre \a l is not \c NULL. */ 00125 CU_SINLINE void 00126 cu_dlink_insert_after(cu_dlink_t l, cu_dlink_t l_init) 00127 { 00128 cu_debug_dlink_assert_valid(l); 00129 l_init->prev = l; 00130 l_init->next = l->next; 00131 l->next->prev = l_init; 00132 l->next = l_init; 00133 } 00134 00135 /** Move \a l_mv right before \a l. This works whether they are in the same or 00136 ** in different cycles. 00137 ** \pre Neither argument is \c NULL and \a l != l_mv. */ 00138 void cu_dlink_move_before(cu_dlink_t l, cu_dlink_t l_mv); 00139 00140 /** Move \a l_mv right after \a l. This works whether they are in the same or 00141 ** in different cycles. 00142 ** \pre Neither argument is \c NULL and \a l != l_mv. */ 00143 void cu_dlink_move_after(cu_dlink_t l, cu_dlink_t l_mv); 00144 00145 /** Splice \a l0 and \a l1 right before the given nodes. If \a l0 and \a l1 00146 ** are links of the same cycle, then the cycle is split into two cycles, 00147 ** otherwise the two separate cycles forms a single cycle. This operation can 00148 ** therefore be used as concatenation if sentinel nodes are not used. 00149 ** \pre Neither link is \c NULL. */ 00150 void cu_dlink_splice_before(cu_dlink_t l0, cu_dlink_t l1); 00151 00152 /** Splice \a l0 and \a l1 right after the given nodes, otherwise the same as 00153 ** \ref cu_dlink_splice_before. */ 00154 void cu_dlink_splice_after(cu_dlink_t l0, cu_dlink_t l1); 00155 00156 /** Concatenate \a l0 and \a l1 and return the result. This uses \ref 00157 ** cu_dlink_splice_before if applicable, and in case \a l0 is not \c NULL, it 00158 ** will form the first part of the cycle as seen from the returned link. The 00159 ** arguments shall be considered destructed, as indicated by the \c _d 00160 ** suffix. */ 00161 cu_dlink_t cu_dlink_cat_d(cu_dlink_t l0, cu_dlink_t l1); 00162 00163 /** Drop \a l_excl from its cycle and splice the remaining cycle (the 00164 ** complement) right before \a l. If the two arguments are the EOL sentinel 00165 ** nodes of lists, this concatenates them. 00166 ** \pre Neither of the arguments are \c NULL. 00167 ** \post \a l_excl is invalidated. */ 00168 void cu_dlink_splice_complement_before(cu_dlink_t l, cu_dlink_t l_excl); 00169 00170 /** Erase \a l_excl from its cycle and splice the remaining cycle right after 00171 ** \a l, otherwise works like \ref cu_dlink_splice_complement_before. */ 00172 void cu_dlink_splice_complement_after(cu_dlink_t l, cu_dlink_t l_excl); 00173 00174 CU_END_DECLARATIONS 00175 00176 /** @} */ 00177 00178 #define cu_dlink_cct_singular cu_dlink_init_singleton 00179 #define cu_dlink_is_singular cu_dlink_is_singleton 00180 #define cu_dlink_is_2node cu_dlink_card_eq_2 00181 #define cu_dlink_count_leq_2 cu_dlink_card_leq_2 00182 #define cu_dlink_insert_list_before cu_dlink_splice_complement_before 00183 #define cu_dlink_insert_list_after cu_dlink_splice_complement_after 00184 00185 #endif