00001 /* EGlib "Efficient General Library" provides some basic structures and 00002 * algorithms commons in many optimization algorithms. 00003 * 00004 * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea. 00005 * 00006 * This library is free software; you can redistribute it and/or modify it 00007 * under the terms of the GNU Lesser General Public License as published by the 00008 * Free Software Foundation; either version 2.1 of the License, or (at your 00009 * option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, but 00012 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00013 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00014 * License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this library; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 * */ 00020 /* ========================================================================= */ 00021 /** @defgroup EGeList EGeList 00022 * 00023 * Here we define the basic interface for a circular linked list where the list 00024 * is embeded in some other structure. The ideas come from the Linux Kernel 00025 * implementation of lists. In contrast to the implementation of doubled linked 00026 * list found in @ref EGlist, this implementation is based on the philosophy of 00027 * embeded structures. 00028 * 00029 * 00030 * @version 0.0.1 00031 * @par History: 00032 * - 2005-08-19 00033 * - Add debugging control 00034 * - 2005-05-23 00035 * - First Implementation. 00036 * 00037 * @note In general, the functions described bellow don't perform consistency 00038 * checks. It is asumed that the user does know what is he doing. 00039 * 00040 * @note If you want to have some debugging control try changing the debug level 00041 * at compile time, and lowering the debug level asociated to the list function 00042 * as defined in eg_configure.h. 00043 * 00044 * */ 00045 /** @file 00046 * @ingroup EGeList */ 00047 /** @addtogroup EGeList */ 00048 /** @{ */ 00049 /** @example eg_elist.ex.c 00050 * This is a working (althought useless) example on @ref EGeList. 00051 * */ 00052 /* ========================================================================= */ 00053 #ifndef __EG_ELIST_H__ 00054 #define __EG_ELIST_H__ 00055 #include <stdlib.h> 00056 #include <string.h> 00057 #include <stdio.h> 00058 #include "eg_macros.h" 00059 00060 /* ========================================================================= */ 00061 /** @brief debug level for lists */ 00062 #define __EL_DEBUG_ 100 00063 00064 /* ========================================================================= */ 00065 /** 00066 * @brief List Node Structure. 00067 * @par Description: 00068 * This structure is to store a general node of the list. It is composed by 00069 * two members, that point to the next and previous structures in the list. */ 00070 typedef struct EGeList_t 00071 { 00072 struct EGeList_t *next;/**< Pointer to the next structure in the list */ 00073 struct EGeList_t *prev;/**< Pointer to the previous structure in the list */ 00074 } 00075 EGeList_t; 00076 00077 /* ========================================================================= */ 00078 /** @brief Initialize a given structure to point to itself (in circular 00079 * fashion). 00080 * @param name pointer to the list to initialize. 00081 * @return the pointer to the list. */ 00082 #define EGeListInit(name) ({\ 00083 EGeList_t*const __EGeL_init =(name);\ 00084 __EGeL_init->next = __EGeL_init->prev = __EGeL_init;}) 00085 00086 /* ========================================================================= */ 00087 /** @brief Insert a new entry between two known consecutive entries. 00088 * @par Description: 00089 * This is only for internal list manipulation, where we know the prev/next 00090 * entries already. 00091 * @param new pointer to the list node to insert. 00092 * @param prev_ptr pointer to the node to preceed the new node. 00093 * @param next_ptr pointer to the node to follow the new node. 00094 * @return the address of new. 00095 * */ 00096 #define __EGeListAdd(new,prev_ptr,next_ptr) ({\ 00097 EGeList_t*const __EGeL_add_new = (new);\ 00098 EGeList_t*const __EGeL_add_prev = (prev_ptr);\ 00099 EGeList_t*const __EGeL_add_next = (next_ptr);\ 00100 __EGeL_add_next->prev = __EGeL_add_new;\ 00101 __EGeL_add_prev->next = __EGeL_add_new;\ 00102 __EGeL_add_new->next = __EGeL_add_next;\ 00103 __EGeL_add_new->prev = __EGeL_add_prev;\ 00104 __EGeL_add_new;}) 00105 00106 /* ========================================================================= */ 00107 /** @brief Insert a new entry after the given pointer. 00108 * @param new pointer to the new list node to insert. 00109 * @param head pointer from where the new entry will follow. 00110 * @return the pointer to the new entry in the list. 00111 * */ 00112 #define EGeListAddAfter(new,head) __EGeListAdd(new,head,(head)->next) 00113 00114 /* ========================================================================= */ 00115 /** @brief Insert a new entry before the given pointer. 00116 * @param new pointer to the new list node to insert. 00117 * @param tail pointer that will follow the new entry in the list. 00118 * @return the pointer to the new entry in the list. 00119 * */ 00120 #define EGeListAddBefore(new,tail) __EGeListAdd(new,(tail)->prev,tail) 00121 00122 /* ========================================================================= */ 00123 /** @brief Given two nodes, link them as if they would follow one another in the 00124 * list (used to delete points from a list). 00125 * @param prev_ptr pointer to the guy to be in first in the list. 00126 * @param next_ptr pointer to the guy to follow in the list. 00127 * @par Description: 00128 * This function is intended to be used only internally, where we know what is 00129 * what, if you use it is because you also know what is going on. 00130 * */ 00131 #define __EGeListLink(prev_ptr,next_ptr) ({\ 00132 EGeList_t* __EGeL_lnk_prev = (prev_ptr);\ 00133 EGeList_t* __EGeL_lnk_next = (next_ptr);\ 00134 __EGeL_lnk_prev->next = __EGeL_lnk_next;\ 00135 __EGeL_lnk_next->prev = __EGeL_lnk_prev;\ 00136 0;}) 00137 00138 /* ========================================================================= */ 00139 /** @brief Given a node, eliminate it from the list it bellongs. but don't 00140 * change the internal data in the eliminated list (be carefull, if you will 00141 * use it afterwards, then you MUST initialize it). If debugging is enabled, 00142 * then whenever you delete, the connector is reseted to 0xffffffff. What you 00143 * can count on is that the connector won't be NULL after deleting it from the 00144 * list, but it's values may be lost if we are debugging. 00145 * @param entry entry to eliminate from the list. 00146 * @return pointer to the deleted entry from the list.*/ 00147 #define EGeListDel(entry) ({\ 00148 EGeList_t *const __EGeL_del_entr = (entry);\ 00149 __EGeListLink(__EGeL_del_entr->prev,__EGeL_del_entr->next);\ 00150 if(__EL_DEBUG_ <= DEBUG) \ 00151 (*__EGeL_del_entr) = (EGeList_t){(EGeList_t*)0xffffffffU,\ 00152 (EGeList_t*)0xffffffffU};\ 00153 __EGeL_del_entr;}) 00154 00155 /* ========================================================================= */ 00156 /** @brief Replace one entry with another in a list. 00157 * @param old entry to be replaced, note that the pointers stored in next/prev 00158 * won't be changed, this may possible lead to errors if the entry is used 00159 * afterwards without initialization. 00160 * @param new new entry in the list. 00161 * @return pointer to the old replaced member. 00162 * */ 00163 #define EGeListReplace(old,new) ({\ 00164 EGeList_t* __EGeL_rep_old = (old);\ 00165 EGeList_t* __EGeL_rep_new = (new);\ 00166 __EGeL_rep_new->next = __EGeL_rep_old->next;\ 00167 __EGeL_rep_new->prev = __EGeL_rep_old->prev;\ 00168 __EGeL_rep_new->next->prev = __EGeL_rep_new;\ 00169 __EGeL_rep_new->prev->next = __EGeL_rep_new;\ 00170 __EGeL_rep_old;}) 00171 00172 /* ========================================================================= */ 00173 /** @brief Move an element from one list to another (deleting it from the 00174 * original one). 00175 * @param entry element to be removed from it's current list to a position 00176 * after the given head. 00177 * @param head element to be before the moved element. 00178 * */ 00179 #define EGeListMoveAfter(entry,head) ({\ 00180 __EGeListLink((entry)->prev,(entry)->next);\ 00181 EGeListAddAfter(entry,head);}) 00182 00183 /* ========================================================================= */ 00184 /** @brief Move an element from one list to another (deleting it from the 00185 * original one). 00186 * @param entry element to be removed from it's current list to a position 00187 * before the given tail. 00188 * @param tail element to be after the moved element. 00189 * */ 00190 #define EGeListMoveBefore(entry,tail) ({\ 00191 __EGeListLink((entry)->prev,(entry)->next);\ 00192 EGeListAddBefore(entry,tail);}) 00193 00194 /* ========================================================================= */ 00195 /** @brief test whether a list is empty (i.e. he is its own next pointer) */ 00196 #define EGeListIsEmpty(head) ({\ 00197 EGeList_t* __EGeL_emp_head = (head);\ 00198 (__EGeL_emp_head == __EGeL_emp_head->next);}) 00199 00200 /* ========================================================================= */ 00201 /** @brief move all elements in one list to the given location in a second list. 00202 * Note that this function assumes that the list is represented by a pointer to 00203 * an EGeList_t structure that act as a marker but that don't bellong to the 00204 * list, and thus is not included in the joinded list. 00205 * @param list marker to the list to be joined with the second. Note that the 00206 * fields in list won't be reinitialized, so be carefull with that, because the 00207 * fields are pointing to inconsistent data as it is, if you want to reutilize 00208 * the list you must call EGeListInit before. 00209 * @param head position from where the list will be spliced in. 00210 * @note Note that the original list is left in an undefined status, so before 00211 * use it, it should be re-initialized. 00212 * */ 00213 #define __EGeListSplice(list,head) ({\ 00214 EGeList_t* __EGeL_spl_list = (list);\ 00215 EGeList_t* __EGeL_spl_first = __EGeL_spl_list->next;\ 00216 EGeList_t* __EGeL_spl_last = __EGeL_spl_list->prev;\ 00217 EGeList_t* __EGeL_spl_head = (head);\ 00218 EGeList_t* __EGeL_spl_at = __EGeL_spl_head->next;\ 00219 __EGeL_spl_first->prev = __EGeL_spl_head;\ 00220 __EGeL_spl_head->next = __EGeL_spl_first;\ 00221 __EGeL_spl_last->next = __EGeL_spl_at;\ 00222 __EGeL_spl_at->prev = __EGeL_spl_last;\ 00223 0;}) 00224 #define EGeListSplice(list,head) ({if(!EGeListIsEmpty(list)) __EGeListSplice(list,head);}) 00225 00226 /* ========================================================================= */ 00227 /** @}*/ 00228 /* end of eg_elist.h */ 00229 #endif
1.4.5