Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlist.c
Go to the documentation of this file.
00001 /* 00002 * list.c: lists handling implementation 00003 * 00004 * Copyright (C) 2000 Gary Pennington and Daniel Veillard. 00005 * 00006 * Permission to use, copy, modify, and distribute this software for any 00007 * purpose with or without fee is hereby granted, provided that the above 00008 * copyright notice and this permission notice appear in all copies. 00009 * 00010 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 00011 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 00012 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND 00013 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. 00014 * 00015 * Author: Gary.Pennington@uk.sun.com 00016 */ 00017 00018 #define IN_LIBXML 00019 #include "libxml.h" 00020 00021 #include <stdlib.h> 00022 #include <string.h> 00023 #include <libxml/xmlmemory.h> 00024 #include <libxml/list.h> 00025 #include <libxml/globals.h> 00026 00027 /* 00028 * Type definition are kept internal 00029 */ 00030 00031 struct _xmlLink 00032 { 00033 struct _xmlLink *next; 00034 struct _xmlLink *prev; 00035 void *data; 00036 }; 00037 00038 struct _xmlList 00039 { 00040 xmlLinkPtr sentinel; 00041 void (*linkDeallocator)(xmlLinkPtr ); 00042 int (*linkCompare)(const void *, const void*); 00043 }; 00044 00045 /************************************************************************ 00046 * * 00047 * Interfaces * 00048 * * 00049 ************************************************************************/ 00050 00058 static void 00059 xmlLinkDeallocator(xmlListPtr l, xmlLinkPtr lk) 00060 { 00061 (lk->prev)->next = lk->next; 00062 (lk->next)->prev = lk->prev; 00063 if(l->linkDeallocator) 00064 l->linkDeallocator(lk); 00065 xmlFree(lk); 00066 } 00067 00078 static int 00079 xmlLinkCompare(const void *data0, const void *data1) 00080 { 00081 if (data0 < data1) 00082 return (-1); 00083 else if (data0 == data1) 00084 return (0); 00085 return (1); 00086 } 00087 00097 static xmlLinkPtr 00098 xmlListLowerSearch(xmlListPtr l, void *data) 00099 { 00100 xmlLinkPtr lk; 00101 00102 if (l == NULL) 00103 return(NULL); 00104 for(lk = l->sentinel->next;lk != l->sentinel && l->linkCompare(lk->data, data) <0 ;lk = lk->next); 00105 return lk; 00106 } 00107 00117 static xmlLinkPtr 00118 xmlListHigherSearch(xmlListPtr l, void *data) 00119 { 00120 xmlLinkPtr lk; 00121 00122 if (l == NULL) 00123 return(NULL); 00124 for(lk = l->sentinel->prev;lk != l->sentinel && l->linkCompare(lk->data, data) >0 ;lk = lk->prev); 00125 return lk; 00126 } 00127 00137 static xmlLinkPtr 00138 xmlListLinkSearch(xmlListPtr l, void *data) 00139 { 00140 xmlLinkPtr lk; 00141 if (l == NULL) 00142 return(NULL); 00143 lk = xmlListLowerSearch(l, data); 00144 if (lk == l->sentinel) 00145 return NULL; 00146 else { 00147 if (l->linkCompare(lk->data, data) ==0) 00148 return lk; 00149 return NULL; 00150 } 00151 } 00152 00162 static xmlLinkPtr 00163 xmlListLinkReverseSearch(xmlListPtr l, void *data) 00164 { 00165 xmlLinkPtr lk; 00166 if (l == NULL) 00167 return(NULL); 00168 lk = xmlListHigherSearch(l, data); 00169 if (lk == l->sentinel) 00170 return NULL; 00171 else { 00172 if (l->linkCompare(lk->data, data) ==0) 00173 return lk; 00174 return NULL; 00175 } 00176 } 00177 00187 xmlListPtr 00188 xmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare) 00189 { 00190 xmlListPtr l; 00191 if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList)))) { 00192 xmlGenericError(xmlGenericErrorContext, 00193 "Cannot initialize memory for list"); 00194 return (NULL); 00195 } 00196 /* Initialize the list to NULL */ 00197 memset(l, 0, sizeof(xmlList)); 00198 00199 /* Add the sentinel */ 00200 if (NULL ==(l->sentinel = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) { 00201 xmlGenericError(xmlGenericErrorContext, 00202 "Cannot initialize memory for sentinel"); 00203 xmlFree(l); 00204 return (NULL); 00205 } 00206 l->sentinel->next = l->sentinel; 00207 l->sentinel->prev = l->sentinel; 00208 l->sentinel->data = NULL; 00209 00210 /* If there is a link deallocator, use it */ 00211 if (deallocator != NULL) 00212 l->linkDeallocator = deallocator; 00213 /* If there is a link comparator, use it */ 00214 if (compare != NULL) 00215 l->linkCompare = compare; 00216 else /* Use our own */ 00217 l->linkCompare = xmlLinkCompare; 00218 return l; 00219 } 00220 00230 void * 00231 xmlListSearch(xmlListPtr l, void *data) 00232 { 00233 xmlLinkPtr lk; 00234 if (l == NULL) 00235 return(NULL); 00236 lk = xmlListLinkSearch(l, data); 00237 if (lk) 00238 return (lk->data); 00239 return NULL; 00240 } 00241 00251 void * 00252 xmlListReverseSearch(xmlListPtr l, void *data) 00253 { 00254 xmlLinkPtr lk; 00255 if (l == NULL) 00256 return(NULL); 00257 lk = xmlListLinkReverseSearch(l, data); 00258 if (lk) 00259 return (lk->data); 00260 return NULL; 00261 } 00262 00272 int 00273 xmlListInsert(xmlListPtr l, void *data) 00274 { 00275 xmlLinkPtr lkPlace, lkNew; 00276 00277 if (l == NULL) 00278 return(1); 00279 lkPlace = xmlListLowerSearch(l, data); 00280 /* Add the new link */ 00281 lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); 00282 if (lkNew == NULL) { 00283 xmlGenericError(xmlGenericErrorContext, 00284 "Cannot initialize memory for new link"); 00285 return (1); 00286 } 00287 lkNew->data = data; 00288 lkPlace = lkPlace->prev; 00289 lkNew->next = lkPlace->next; 00290 (lkPlace->next)->prev = lkNew; 00291 lkPlace->next = lkNew; 00292 lkNew->prev = lkPlace; 00293 return 0; 00294 } 00295 00305 int xmlListAppend(xmlListPtr l, void *data) 00306 { 00307 xmlLinkPtr lkPlace, lkNew; 00308 00309 if (l == NULL) 00310 return(1); 00311 lkPlace = xmlListHigherSearch(l, data); 00312 /* Add the new link */ 00313 lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); 00314 if (lkNew == NULL) { 00315 xmlGenericError(xmlGenericErrorContext, 00316 "Cannot initialize memory for new link"); 00317 return (1); 00318 } 00319 lkNew->data = data; 00320 lkNew->next = lkPlace->next; 00321 (lkPlace->next)->prev = lkNew; 00322 lkPlace->next = lkNew; 00323 lkNew->prev = lkPlace; 00324 return 0; 00325 } 00326 00333 void xmlListDelete(xmlListPtr l) 00334 { 00335 if (l == NULL) 00336 return; 00337 00338 xmlListClear(l); 00339 xmlFree(l->sentinel); 00340 xmlFree(l); 00341 } 00342 00352 int 00353 xmlListRemoveFirst(xmlListPtr l, void *data) 00354 { 00355 xmlLinkPtr lk; 00356 00357 if (l == NULL) 00358 return(0); 00359 /*Find the first instance of this data */ 00360 lk = xmlListLinkSearch(l, data); 00361 if (lk != NULL) { 00362 xmlLinkDeallocator(l, lk); 00363 return 1; 00364 } 00365 return 0; 00366 } 00367 00377 int 00378 xmlListRemoveLast(xmlListPtr l, void *data) 00379 { 00380 xmlLinkPtr lk; 00381 00382 if (l == NULL) 00383 return(0); 00384 /*Find the last instance of this data */ 00385 lk = xmlListLinkReverseSearch(l, data); 00386 if (lk != NULL) { 00387 xmlLinkDeallocator(l, lk); 00388 return 1; 00389 } 00390 return 0; 00391 } 00392 00402 int 00403 xmlListRemoveAll(xmlListPtr l, void *data) 00404 { 00405 int count=0; 00406 00407 if (l == NULL) 00408 return(0); 00409 00410 while(xmlListRemoveFirst(l, data)) 00411 count++; 00412 return count; 00413 } 00414 00421 void 00422 xmlListClear(xmlListPtr l) 00423 { 00424 xmlLinkPtr lk; 00425 00426 if (l == NULL) 00427 return; 00428 lk = l->sentinel->next; 00429 while(lk != l->sentinel) { 00430 xmlLinkPtr next = lk->next; 00431 00432 xmlLinkDeallocator(l, lk); 00433 lk = next; 00434 } 00435 } 00436 00445 int 00446 xmlListEmpty(xmlListPtr l) 00447 { 00448 if (l == NULL) 00449 return(-1); 00450 return (l->sentinel->next == l->sentinel); 00451 } 00452 00461 xmlLinkPtr 00462 xmlListFront(xmlListPtr l) 00463 { 00464 if (l == NULL) 00465 return(NULL); 00466 return (l->sentinel->next); 00467 } 00468 00477 xmlLinkPtr 00478 xmlListEnd(xmlListPtr l) 00479 { 00480 if (l == NULL) 00481 return(NULL); 00482 return (l->sentinel->prev); 00483 } 00484 00493 int 00494 xmlListSize(xmlListPtr l) 00495 { 00496 xmlLinkPtr lk; 00497 int count=0; 00498 00499 if (l == NULL) 00500 return(-1); 00501 /* TODO: keep a counter in xmlList instead */ 00502 for(lk = l->sentinel->next; lk != l->sentinel; lk = lk->next, count++); 00503 return count; 00504 } 00505 00512 void 00513 xmlListPopFront(xmlListPtr l) 00514 { 00515 if(!xmlListEmpty(l)) 00516 xmlLinkDeallocator(l, l->sentinel->next); 00517 } 00518 00525 void 00526 xmlListPopBack(xmlListPtr l) 00527 { 00528 if(!xmlListEmpty(l)) 00529 xmlLinkDeallocator(l, l->sentinel->prev); 00530 } 00531 00541 int 00542 xmlListPushFront(xmlListPtr l, void *data) 00543 { 00544 xmlLinkPtr lkPlace, lkNew; 00545 00546 if (l == NULL) 00547 return(0); 00548 lkPlace = l->sentinel; 00549 /* Add the new link */ 00550 lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); 00551 if (lkNew == NULL) { 00552 xmlGenericError(xmlGenericErrorContext, 00553 "Cannot initialize memory for new link"); 00554 return (0); 00555 } 00556 lkNew->data = data; 00557 lkNew->next = lkPlace->next; 00558 (lkPlace->next)->prev = lkNew; 00559 lkPlace->next = lkNew; 00560 lkNew->prev = lkPlace; 00561 return 1; 00562 } 00563 00573 int 00574 xmlListPushBack(xmlListPtr l, void *data) 00575 { 00576 xmlLinkPtr lkPlace, lkNew; 00577 00578 if (l == NULL) 00579 return(0); 00580 lkPlace = l->sentinel->prev; 00581 /* Add the new link */ 00582 if (NULL ==(lkNew = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) { 00583 xmlGenericError(xmlGenericErrorContext, 00584 "Cannot initialize memory for new link"); 00585 return (0); 00586 } 00587 lkNew->data = data; 00588 lkNew->next = lkPlace->next; 00589 (lkPlace->next)->prev = lkNew; 00590 lkPlace->next = lkNew; 00591 lkNew->prev = lkPlace; 00592 return 1; 00593 } 00594 00603 void * 00604 xmlLinkGetData(xmlLinkPtr lk) 00605 { 00606 if (lk == NULL) 00607 return(NULL); 00608 return lk->data; 00609 } 00610 00617 void 00618 xmlListReverse(xmlListPtr l) 00619 { 00620 xmlLinkPtr lk; 00621 xmlLinkPtr lkPrev; 00622 00623 if (l == NULL) 00624 return; 00625 lkPrev = l->sentinel; 00626 for (lk = l->sentinel->next; lk != l->sentinel; lk = lk->next) { 00627 lkPrev->next = lkPrev->prev; 00628 lkPrev->prev = lk; 00629 lkPrev = lk; 00630 } 00631 /* Fix up the last node */ 00632 lkPrev->next = lkPrev->prev; 00633 lkPrev->prev = lk; 00634 } 00635 00642 void 00643 xmlListSort(xmlListPtr l) 00644 { 00645 xmlListPtr lTemp; 00646 00647 if (l == NULL) 00648 return; 00649 if(xmlListEmpty(l)) 00650 return; 00651 00652 /* I think that the real answer is to implement quicksort, the 00653 * alternative is to implement some list copying procedure which 00654 * would be based on a list copy followed by a clear followed by 00655 * an insert. This is slow... 00656 */ 00657 00658 if (NULL ==(lTemp = xmlListDup(l))) 00659 return; 00660 xmlListClear(l); 00661 xmlListMerge(l, lTemp); 00662 xmlListDelete(lTemp); 00663 return; 00664 } 00665 00675 void 00676 xmlListWalk(xmlListPtr l, xmlListWalker walker, const void *user) { 00677 xmlLinkPtr lk; 00678 00679 if ((l == NULL) || (walker == NULL)) 00680 return; 00681 for(lk = l->sentinel->next; lk != l->sentinel; lk = lk->next) { 00682 if((walker(lk->data, user)) == 0) 00683 break; 00684 } 00685 } 00686 00696 void 00697 xmlListReverseWalk(xmlListPtr l, xmlListWalker walker, const void *user) { 00698 xmlLinkPtr lk; 00699 00700 if ((l == NULL) || (walker == NULL)) 00701 return; 00702 for(lk = l->sentinel->prev; lk != l->sentinel; lk = lk->prev) { 00703 if((walker(lk->data, user)) == 0) 00704 break; 00705 } 00706 } 00707 00716 void 00717 xmlListMerge(xmlListPtr l1, xmlListPtr l2) 00718 { 00719 xmlListCopy(l1, l2); 00720 xmlListClear(l2); 00721 } 00722 00731 xmlListPtr 00732 xmlListDup(const xmlListPtr old) 00733 { 00734 xmlListPtr cur; 00735 00736 if (old == NULL) 00737 return(NULL); 00738 /* Hmmm, how to best deal with allocation issues when copying 00739 * lists. If there is a de-allocator, should responsibility lie with 00740 * the new list or the old list. Surely not both. I'll arbitrarily 00741 * set it to be the old list for the time being whilst I work out 00742 * the answer 00743 */ 00744 if (NULL ==(cur = xmlListCreate(NULL, old->linkCompare))) 00745 return (NULL); 00746 if (0 != xmlListCopy(cur, old)) 00747 return NULL; 00748 return cur; 00749 } 00750 00760 int 00761 xmlListCopy(xmlListPtr cur, const xmlListPtr old) 00762 { 00763 /* Walk the old tree and insert the data into the new one */ 00764 xmlLinkPtr lk; 00765 00766 if ((old == NULL) || (cur == NULL)) 00767 return(1); 00768 for(lk = old->sentinel->next; lk != old->sentinel; lk = lk->next) { 00769 if (0 !=xmlListInsert(cur, lk->data)) { 00770 xmlListDelete(cur); 00771 return (1); 00772 } 00773 } 00774 return (0); 00775 } 00776 /* xmlListUnique() */ 00777 /* xmlListSwap */ 00778 #define bottom_list 00779 #include "elfgcchack.h" Generated on Sat May 26 2012 04:17:40 for ReactOS by
1.7.6.1
|