eg_elist.h

Go to the documentation of this file.
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

Generated on Mon Jan 30 08:48:53 2006 for EGlib by  doxygen 1.4.5