Main Page   Data Structures   File List   Data Fields   Globals   Related Pages  

mlist_tmpl_c.inc

Go to the documentation of this file.
00001 /***************************************************************************
00002                                mlist_tmpl_c.inc
00003                              --------------------
00004     begin                : Tue Nov 20 2001
00005     copyright            : (C) 2001-2002 by Christian Hoenig & Gunter Ohrner
00006     email                : pdepp@CustomCDROM.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00053 #ifdef ML_LIST_NAME
00054 
00055 #include "common.h"
00056 
00057 #include <stdlib.h>
00058 
00059 #include "xmalloc.h"
00060 #include "assert.h"
00061 
00062 #ifndef MLPFX
00063 # define MLPFX ML_FUNC_PFX
00064 #endif
00065 
00066 #ifdef DOXYGEN_PREPROCESSING
00067 # include "mlist_tmpl_h.inc"
00068 #endif
00069 
00071 #define mlist_assertions    assert(liste != NULL                  \
00072                             && liste->head->next != NULL          \
00073                             && liste->tail->prev != NULL          \
00074                             && liste->cur != NULL                 \
00075                             && liste->head->prev == liste->head   \
00076                             && liste->tail->next == liste->tail);
00077 
00079 #define no_clone_assertion  assert(                               \
00080                               liste->is_clone == false ||         \
00081                               liste->num_of_clones != 0           \
00082                             )
00083 
00084 
00085 // define element returned to indicate an "invalid" state / result
00086 #ifndef ML_INVALID
00087 
00088 # define ML_INVALID (MlCargo) 0L
00089 #endif
00090 
00091 // define a way to tell if a given MlCargo object is valid
00092 #ifndef ML_IS_VALID_CARGO
00093 
00094 # define ML_IS_VALID_CARGO(a) (a != ML_INVALID)
00095 #endif
00096 
00097 // define a facility to create an MlCargo object
00098 #ifndef ML_CREATE_CARGO
00099 
00100 # define ML_CREATE_CARGOI(new)
00101 #else
00102 # define ML_CREATE_CARGOI(new) ML_CREATE_CARGO(new)
00103 #endif
00104 
00105 // define a way to dublicate an MlCargo object
00106 #ifndef ML_COPY_CARGO
00107 
00108 # define ML_COPY_CARGO(dest, source) (dest = source)
00109 #endif
00110 
00111 // give a possibility to free a Cargo object
00112 #ifndef ML_FREE_CARGO
00113 
00114 # define ML_FREE_CARGOI(a)
00115 #else
00116 # define ML_FREE_CARGOI(a) ML_FREE_CARGO(a)
00117 #endif
00118 
00119 
00121 #define MlNode fn(ML_LIST_NAME, Node)
00122 
00124 struct MlNode
00125 {
00126   struct MlNode* next; 
00127   struct MlNode* prev; 
00128   MlCargo payload;     
00129 };
00130 
00132 struct ML_LIST_NAME
00133 {
00134   struct MlNode* head; 
00135   struct MlNode* tail; 
00136   struct MlNode* cur;  
00137 #ifndef NDEBUG
00138   int num_of_clones;   
00139   int is_clone;        
00140   ML_LIST_NAME parent;
00141 #endif
00142 };
00143 
00145 typedef struct MlNode MlNode;
00146 
00154 ML_LIST_NAME fn(MLPFX,Init)()
00155 {
00156   ML_LIST_NAME new_list = (ML_LIST_NAME) pd_malloc(sizeof(struct ML_LIST_NAME));
00157   new_list->head = (MlNode*) pd_malloc(sizeof(MlNode));
00158   new_list->head->prev = new_list->head;
00159 
00160   new_list->tail = (MlNode*) pd_malloc(sizeof(MlNode));
00161   new_list->tail->next = new_list->tail;
00162 
00163   new_list->head->next = new_list->tail;
00164   new_list->tail->prev = new_list->head;
00165 
00166   new_list->cur  = new_list->head;
00167 
00168 #ifndef NDEBUG
00169   new_list->num_of_clones = 0;
00170   new_list->is_clone = false;
00171   new_list->parent = new_list;
00172 #endif
00173 
00174   return new_list;
00175 }
00176 
00190 ML_LIST_NAME fn(MLPFX,Dublicate)(ML_LIST_NAME liste)
00191 {
00192   struct MlNode* tmp_cur_node = NULL;
00193   // Create a working copy of liste's control block so we do not
00194   // change the state of the original list.
00195   ML_LIST_NAME tmp_list = fn(MLPFX,Clone)(liste);
00196   ML_LIST_NAME new_list = fn(MLPFX,Init)();
00197 
00198   fn(MLPFX,First)(tmp_list);
00199   while(!fn(MLPFX,IsTail)(tmp_list))
00200   {
00201     fn(MLPFX,Append)(new_list, fn(MLPFX,GetPayload)(tmp_list));
00202     /* If we're just visiting the original list's "current" node,
00203        remeber the current position in the new list - it will become
00204        the current node in the new_list as well. */
00205     if (tmp_list->cur == liste->cur)
00206       tmp_cur_node = new_list->cur;
00207     fn(MLPFX,Next)(tmp_list);
00208     fn(MLPFX,Next)(new_list);
00209   }
00210 
00211 #ifndef NDEBUG
00212   assert(tmp_cur_node != NULL);
00213 #endif  
00214   new_list->cur = tmp_cur_node;
00215 
00216   return new_list;
00217 }
00218 
00233 ML_LIST_NAME fn(MLPFX,Clone)(ML_LIST_NAME liste)
00234 {
00235   ML_LIST_NAME clone_list = (ML_LIST_NAME) pd_malloc(sizeof(struct ML_LIST_NAME));
00236   clone_list->head = liste->head;
00237   clone_list->tail = liste->tail;
00238   clone_list->cur  = liste->cur;
00239 
00240 #ifndef NDEBUG
00241   clone_list->num_of_clones = 0;
00242   clone_list->is_clone = true;
00243   clone_list->parent = liste->parent;
00244   ++clone_list->parent->num_of_clones;
00245 #endif
00246 
00247   return clone_list;
00248 }
00249 
00263 int fn(MLPFX,InsertAfter)(ML_LIST_NAME liste, MlCargo new_load)
00264 {
00265   MlNode* new_node;
00266 
00267   mlist_assertions;
00268 
00269   // you cannot modify a clone or a list having living clones
00270   assert(liste->is_clone == false || liste->num_of_clones != 0);
00271 
00272   if (fn(MLPFX,IsTail(liste))) return -1;
00273 
00274   new_node = (MlNode*) pd_malloc(sizeof(MlNode));
00275   new_node->payload = ML_INVALID;
00276 
00277   new_node->next = liste->cur->next;
00278   new_node->prev = liste->cur;
00279 
00280   liste->cur->next = new_node;
00281   new_node->next->prev = new_node;
00282 
00283   liste->cur = new_node;
00284 
00285   fn(MLPFX,SetPayload)(liste, new_load);
00286 
00287   return 0;
00288 }
00289 
00303 int fn(MLPFX,InsertBefore)(ML_LIST_NAME liste, MlCargo new_load)
00304 {
00305   MlNode* new_node;
00306 
00307   mlist_assertions;
00308 
00309   no_clone_assertion;
00310 
00311   if (fn(MLPFX,IsHead(liste))) return -1;
00312 
00313   new_node = (MlNode*) pd_malloc(sizeof(MlNode));
00314   new_node->payload = ML_INVALID;
00315 
00316   new_node->next = liste->cur;
00317   new_node->prev = liste->cur->prev;
00318 
00319   liste->cur->prev->next = new_node;
00320   liste->cur->prev = new_node;
00321 
00322   liste->cur = new_node;
00323 
00324   fn(MLPFX,SetPayload)(liste, new_load);
00325 
00326   return 0;
00327 }
00328 
00340 void fn(MLPFX,Append)(ML_LIST_NAME liste, MlCargo new_load)
00341 {
00342   mlist_assertions;
00343 
00344   no_clone_assertion; 
00345 
00346   fn(MLPFX,Last)(liste);
00347   fn(MLPFX,InsertAfter)(liste, new_load);
00348 }
00349 
00362 void fn(MLPFX,Prepend)(ML_LIST_NAME liste, MlCargo new_load)
00363 {
00364   mlist_assertions;
00365 
00366   no_clone_assertion;
00367 
00368   fn(MLPFX,First)(liste);
00369   fn(MLPFX,InsertBefore)(liste, new_load);
00370 }
00371 
00383 int fn(MLPFX,Delete)(ML_LIST_NAME liste)
00384 {
00385   MlNode* to_delete;
00386 
00387   mlist_assertions;
00388 
00389   no_clone_assertion;
00390 
00391   if (!fn(MLPFX,IsValid(liste))) return -1;
00392 
00393   liste->cur->prev->next = liste->cur->next;
00394   liste->cur->next->prev = liste->cur->prev;
00395 
00396   to_delete = liste->cur;
00397   liste->cur = liste->cur->next;
00398 
00399   ML_FREE_CARGOI(to_delete->payload);
00400   pd_free(to_delete);
00401 
00402   return 0;
00403 }
00404 
00414 void fn(MLPFX,Next)(ML_LIST_NAME liste)
00415 {
00416   mlist_assertions;
00417 
00418   liste->cur = liste->cur->next;
00419 }
00420 
00430 void fn(MLPFX,Prev)(ML_LIST_NAME liste)
00431 {
00432   mlist_assertions;
00433 
00434   liste->cur = liste->cur->prev;
00435 }
00436 
00446 void fn(MLPFX,First)(ML_LIST_NAME liste)
00447 {
00448   mlist_assertions;
00449 
00450   liste->cur = liste->head->next;
00451 }
00452 
00462 void fn(MLPFX,Last)(ML_LIST_NAME liste)
00463 {
00464   mlist_assertions;
00465 
00466   liste->cur = liste->tail->prev;
00467 }
00468 
00479 int fn(MLPFX,SetPayload)(ML_LIST_NAME liste, MlCargo new_load)
00480 {
00481   mlist_assertions;
00482 
00483   if (!fn(MLPFX,IsValid)(liste)) return -1;
00484 
00485   // If ML_FREE_CARGO is defined, ML_FREE_CARGOI must be used as well.
00486 #ifdef ML_FREE_CARGO
00487   if (ML_IS_VALID_CARGO(liste->cur->payload))
00488     ML_FREE_CARGOI(liste->cur->payload);
00489 #endif
00490 
00491   ML_CREATE_CARGOI(liste->cur->payload);
00492   ML_COPY_CARGO(liste->cur->payload, new_load);
00493   return 0;
00494 }
00495 
00505 MlCargo fn(MLPFX,GetPayload)(ML_LIST_NAME liste)
00506 {
00507 //  MlCargo cur_load;
00508 
00509   mlist_assertions;
00510 
00511   if (!fn(MLPFX,IsValid)(liste)) return ML_INVALID;
00512 
00513 //  ML_CREATE_CARGOI(cur_load);
00514 //  ML_COPY_CARGO(cur_load, liste->cur->payload);
00515   return liste->cur->payload; // cur_load;
00516 }
00517 
00523 int fn(MLPFX,IsEmpty)(ML_LIST_NAME liste)
00524 {
00525   mlist_assertions;
00526 
00527   return (liste->head->next == liste->tail);
00528 }
00529 
00535 int fn(MLPFX,IsHead)(ML_LIST_NAME liste)
00536 {
00537   mlist_assertions;
00538 
00539   return (liste->cur == liste->head);
00540 }
00541 
00547 int fn(MLPFX,IsTail)(ML_LIST_NAME liste)
00548 {
00549   mlist_assertions;
00550 
00551   return (liste->cur == liste->tail);
00552 }
00553 
00560 int fn(MLPFX,IsValid)(ML_LIST_NAME liste)
00561 {
00562   mlist_assertions;
00563 
00564   return !fn(MLPFX,IsHead)(liste) && !fn(MLPFX,IsTail)(liste);
00565 }
00566 
00572 int fn(MLPFX,IsValidValue)(MlCargo load)
00573 {
00574   return ML_IS_VALID_CARGO(load);
00575 }
00576 
00588 int fn(MLPFX,Terminate)(ML_LIST_NAME liste)
00589 {
00590   mlist_assertions;
00591 
00592 #ifndef NDEBUG
00593   /* we can't die if our clones still live */
00594   assert(liste->num_of_clones == 0);
00595 
00596   /* inform the parent (if any) that a clone died */
00597   --liste->parent->num_of_clones;
00598 
00599   /* If we're clone, it's not our data in this list.
00600      We must not touch it.                          */
00601   if (liste->is_clone)
00602   {
00603 #endif
00604 
00605 // has ML_FREE_CARGO any meaningful content?
00606 #ifdef ML_FREE_CARGO
00607     fn(MLPFX,First)(liste);
00608     while (!fn(MLPFX,IsTail)(liste))
00609       fn(MLPFX,Delete)(liste);
00610 #else
00611     if (liste->head->next != liste->tail) return -1;
00612 #endif
00613 
00614 #ifndef NDEBUG
00615   } /* liste->is_clone */
00616 #endif
00617   
00618   pd_free(liste->head);
00619   pd_free(liste->tail);
00620   pd_free(liste);
00621 
00622   return 0;
00623 }
00624 
00625 // clean up
00626 #undef ML_INVALID
00627 #undef ML_IS_VALID_CARGO
00628 #undef ML_FUNC_PFX
00629 #undef MLPFX
00630 #undef MlNode
00631 #undef ML_LIST_NAME
00632 #undef MlCargo
00633 #undef ML_CREATE_CARGO
00634 #undef ML_CREATE_CARGOI
00635 #undef ML_COPY_CARGO
00636 #undef ML_FREE_CARGO
00637 #undef ML_FREE_CARGOI
00638 #undef ML_EMPTY_DEF
00639 
00640 #endif

Generated on Fri Jan 25 22:40:31 2002 for PDepp Webserver by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001