00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00086 #ifndef ML_INVALID
00087
00088 # define ML_INVALID (MlCargo) 0L
00089 #endif
00090
00091
00092 #ifndef ML_IS_VALID_CARGO
00093
00094 # define ML_IS_VALID_CARGO(a) (a != ML_INVALID)
00095 #endif
00096
00097
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
00106 #ifndef ML_COPY_CARGO
00107
00108 # define ML_COPY_CARGO(dest, source) (dest = source)
00109 #endif
00110
00111
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
00194
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
00203
00204
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
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
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
00508
00509 mlist_assertions;
00510
00511 if (!fn(MLPFX,IsValid)(liste)) return ML_INVALID;
00512
00513
00514
00515 return liste->cur->payload;
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
00594 assert(liste->num_of_clones == 0);
00595
00596
00597 --liste->parent->num_of_clones;
00598
00599
00600
00601 if (liste->is_clone)
00602 {
00603 #endif
00604
00605
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 }
00616 #endif
00617
00618 pd_free(liste->head);
00619 pd_free(liste->tail);
00620 pd_free(liste);
00621
00622 return 0;
00623 }
00624
00625
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