ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

list.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.