Annotation of embedaddon/libxml2/list.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * list.c: lists handling implementation
        !             3:  *
        !             4:  * Copyright (C) 2000 Gary Pennington and Daniel Veillard.
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            11:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            12:  * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
        !            13:  * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
        !            14:  *
        !            15:  * Author: Gary.Pennington@uk.sun.com
        !            16:  */
        !            17: 
        !            18: #define IN_LIBXML
        !            19: #include "libxml.h"
        !            20: 
        !            21: #include <stdlib.h>
        !            22: #include <string.h>
        !            23: #include <libxml/xmlmemory.h>
        !            24: #include <libxml/list.h>
        !            25: #include <libxml/globals.h>
        !            26: 
        !            27: /*
        !            28:  * Type definition are kept internal
        !            29:  */
        !            30: 
        !            31: struct _xmlLink
        !            32: {
        !            33:     struct _xmlLink *next;
        !            34:     struct _xmlLink *prev;
        !            35:     void *data;
        !            36: };
        !            37: 
        !            38: struct _xmlList
        !            39: {
        !            40:     xmlLinkPtr sentinel;
        !            41:     void (*linkDeallocator)(xmlLinkPtr );
        !            42:     int (*linkCompare)(const void *, const void*);
        !            43: };
        !            44: 
        !            45: /************************************************************************
        !            46:  *                                    *
        !            47:  *                Interfaces                *
        !            48:  *                                    *
        !            49:  ************************************************************************/
        !            50: 
        !            51: /**
        !            52:  * xmlLinkDeallocator:
        !            53:  * @l:  a list
        !            54:  * @lk:  a link
        !            55:  *
        !            56:  * Unlink and deallocate @lk from list @l
        !            57:  */
        !            58: static void
        !            59: xmlLinkDeallocator(xmlListPtr l, xmlLinkPtr lk)
        !            60: {
        !            61:     (lk->prev)->next = lk->next;
        !            62:     (lk->next)->prev = lk->prev;
        !            63:     if(l->linkDeallocator)
        !            64:         l->linkDeallocator(lk);
        !            65:     xmlFree(lk);
        !            66: }
        !            67: 
        !            68: /**
        !            69:  * xmlLinkCompare:
        !            70:  * @data0:  first data
        !            71:  * @data1:  second data
        !            72:  *
        !            73:  * Compares two arbitrary data
        !            74:  *
        !            75:  * Returns -1, 0 or 1 depending on whether data1 is greater equal or smaller
        !            76:  *          than data0
        !            77:  */
        !            78: static int
        !            79: xmlLinkCompare(const void *data0, const void *data1)
        !            80: {
        !            81:     if (data0 < data1)
        !            82:         return (-1);
        !            83:     else if (data0 == data1)
        !            84:        return (0);
        !            85:     return (1);
        !            86: }
        !            87: 
        !            88: /**
        !            89:  * xmlListLowerSearch:
        !            90:  * @l:  a list
        !            91:  * @data:  a data
        !            92:  *
        !            93:  * Search data in the ordered list walking from the beginning
        !            94:  *
        !            95:  * Returns the link containing the data or NULL
        !            96:  */
        !            97: static xmlLinkPtr 
        !            98: xmlListLowerSearch(xmlListPtr l, void *data) 
        !            99: {
        !           100:     xmlLinkPtr lk;
        !           101: 
        !           102:     if (l == NULL)
        !           103:         return(NULL);
        !           104:     for(lk = l->sentinel->next;lk != l->sentinel && l->linkCompare(lk->data, data) <0 ;lk = lk->next);
        !           105:     return lk;    
        !           106: }
        !           107: 
        !           108: /**
        !           109:  * xmlListHigherSearch:
        !           110:  * @l:  a list
        !           111:  * @data:  a data
        !           112:  *
        !           113:  * Search data in the ordered list walking backward from the end
        !           114:  *
        !           115:  * Returns the link containing the data or NULL
        !           116:  */
        !           117: static xmlLinkPtr 
        !           118: xmlListHigherSearch(xmlListPtr l, void *data) 
        !           119: {
        !           120:     xmlLinkPtr lk;
        !           121: 
        !           122:     if (l == NULL)
        !           123:         return(NULL);
        !           124:     for(lk = l->sentinel->prev;lk != l->sentinel && l->linkCompare(lk->data, data) >0 ;lk = lk->prev);
        !           125:     return lk;    
        !           126: }
        !           127: 
        !           128: /**
        !           129:  * xmlListSearch:
        !           130:  * @l:  a list
        !           131:  * @data:  a data
        !           132:  *
        !           133:  * Search data in the list
        !           134:  *
        !           135:  * Returns the link containing the data or NULL
        !           136:  */
        !           137: static xmlLinkPtr 
        !           138: xmlListLinkSearch(xmlListPtr l, void *data) 
        !           139: {
        !           140:     xmlLinkPtr lk;
        !           141:     if (l == NULL)
        !           142:         return(NULL);
        !           143:     lk = xmlListLowerSearch(l, data);
        !           144:     if (lk == l->sentinel)
        !           145:         return NULL;
        !           146:     else {
        !           147:         if (l->linkCompare(lk->data, data) ==0)
        !           148:             return lk;
        !           149:         return NULL;
        !           150:     }
        !           151: }
        !           152: 
        !           153: /**
        !           154:  * xmlListLinkReverseSearch:
        !           155:  * @l:  a list
        !           156:  * @data:  a data
        !           157:  *
        !           158:  * Search data in the list processing backward
        !           159:  *
        !           160:  * Returns the link containing the data or NULL
        !           161:  */
        !           162: static xmlLinkPtr 
        !           163: xmlListLinkReverseSearch(xmlListPtr l, void *data) 
        !           164: {
        !           165:     xmlLinkPtr lk;
        !           166:     if (l == NULL)
        !           167:         return(NULL);
        !           168:     lk = xmlListHigherSearch(l, data);
        !           169:     if (lk == l->sentinel)
        !           170:         return NULL;
        !           171:     else {
        !           172:         if (l->linkCompare(lk->data, data) ==0)
        !           173:             return lk;
        !           174:         return NULL;
        !           175:     }
        !           176: }
        !           177: 
        !           178: /**
        !           179:  * xmlListCreate:
        !           180:  * @deallocator:  an optional deallocator function
        !           181:  * @compare:  an optional comparison function
        !           182:  *
        !           183:  * Create a new list
        !           184:  *
        !           185:  * Returns the new list or NULL in case of error
        !           186:  */
        !           187: xmlListPtr
        !           188: xmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare)
        !           189: {
        !           190:     xmlListPtr l;
        !           191:     if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList)))) {
        !           192:         xmlGenericError(xmlGenericErrorContext, 
        !           193:                        "Cannot initialize memory for list");
        !           194:         return (NULL);
        !           195:     }
        !           196:     /* Initialize the list to NULL */
        !           197:     memset(l, 0, sizeof(xmlList));
        !           198:     
        !           199:     /* Add the sentinel */
        !           200:     if (NULL ==(l->sentinel = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) {
        !           201:         xmlGenericError(xmlGenericErrorContext, 
        !           202:                        "Cannot initialize memory for sentinel");
        !           203:        xmlFree(l);
        !           204:         return (NULL);
        !           205:     }
        !           206:     l->sentinel->next = l->sentinel;
        !           207:     l->sentinel->prev = l->sentinel;
        !           208:     l->sentinel->data = NULL;
        !           209:     
        !           210:     /* If there is a link deallocator, use it */
        !           211:     if (deallocator != NULL)
        !           212:         l->linkDeallocator = deallocator;
        !           213:     /* If there is a link comparator, use it */
        !           214:     if (compare != NULL)
        !           215:         l->linkCompare = compare;
        !           216:     else /* Use our own */
        !           217:         l->linkCompare = xmlLinkCompare;
        !           218:     return l;
        !           219: }
        !           220:     
        !           221: /**
        !           222:  * xmlListSearch:
        !           223:  * @l:  a list
        !           224:  * @data:  a search value
        !           225:  *
        !           226:  * Search the list for an existing value of @data
        !           227:  *
        !           228:  * Returns the value associated to @data or NULL in case of error
        !           229:  */
        !           230: void *
        !           231: xmlListSearch(xmlListPtr l, void *data) 
        !           232: {
        !           233:     xmlLinkPtr lk;
        !           234:     if (l == NULL)
        !           235:         return(NULL);
        !           236:     lk = xmlListLinkSearch(l, data);
        !           237:     if (lk)
        !           238:         return (lk->data);
        !           239:     return NULL;
        !           240: }
        !           241: 
        !           242: /**
        !           243:  * xmlListReverseSearch:
        !           244:  * @l:  a list
        !           245:  * @data:  a search value
        !           246:  *
        !           247:  * Search the list in reverse order for an existing value of @data
        !           248:  *
        !           249:  * Returns the value associated to @data or NULL in case of error
        !           250:  */
        !           251: void *
        !           252: xmlListReverseSearch(xmlListPtr l, void *data) 
        !           253: {
        !           254:     xmlLinkPtr lk;
        !           255:     if (l == NULL)
        !           256:         return(NULL);
        !           257:     lk = xmlListLinkReverseSearch(l, data);
        !           258:     if (lk)
        !           259:         return (lk->data);
        !           260:     return NULL;
        !           261: }
        !           262: 
        !           263: /**
        !           264:  * xmlListInsert:
        !           265:  * @l:  a list
        !           266:  * @data:  the data
        !           267:  *
        !           268:  * Insert data in the ordered list at the beginning for this value
        !           269:  *
        !           270:  * Returns 0 in case of success, 1 in case of failure
        !           271:  */
        !           272: int
        !           273: xmlListInsert(xmlListPtr l, void *data) 
        !           274: {
        !           275:     xmlLinkPtr lkPlace, lkNew;
        !           276: 
        !           277:     if (l == NULL)
        !           278:         return(1);
        !           279:     lkPlace = xmlListLowerSearch(l, data);
        !           280:     /* Add the new link */
        !           281:     lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
        !           282:     if (lkNew == NULL) {
        !           283:         xmlGenericError(xmlGenericErrorContext, 
        !           284:                        "Cannot initialize memory for new link");
        !           285:         return (1);
        !           286:     }
        !           287:     lkNew->data = data;
        !           288:     lkPlace = lkPlace->prev;
        !           289:     lkNew->next = lkPlace->next;
        !           290:     (lkPlace->next)->prev = lkNew;
        !           291:     lkPlace->next = lkNew;
        !           292:     lkNew->prev = lkPlace;
        !           293:     return 0;
        !           294: }
        !           295: 
        !           296: /**
        !           297:  * xmlListAppend:
        !           298:  * @l:  a list
        !           299:  * @data:  the data
        !           300:  *
        !           301:  * Insert data in the ordered list at the end for this value
        !           302:  *
        !           303:  * Returns 0 in case of success, 1 in case of failure
        !           304:  */
        !           305: int xmlListAppend(xmlListPtr l, void *data) 
        !           306: {
        !           307:     xmlLinkPtr lkPlace, lkNew;
        !           308: 
        !           309:     if (l == NULL)
        !           310:         return(1);
        !           311:     lkPlace = xmlListHigherSearch(l, data);
        !           312:     /* Add the new link */
        !           313:     lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
        !           314:     if (lkNew == NULL) {
        !           315:         xmlGenericError(xmlGenericErrorContext, 
        !           316:                        "Cannot initialize memory for new link");
        !           317:         return (1);
        !           318:     }
        !           319:     lkNew->data = data;
        !           320:     lkNew->next = lkPlace->next;
        !           321:     (lkPlace->next)->prev = lkNew;
        !           322:     lkPlace->next = lkNew;
        !           323:     lkNew->prev = lkPlace;
        !           324:     return 0;
        !           325: }
        !           326: 
        !           327: /**
        !           328:  * xmlListDelete:
        !           329:  * @l:  a list
        !           330:  *
        !           331:  * Deletes the list and its associated data
        !           332:  */
        !           333: void xmlListDelete(xmlListPtr l)
        !           334: {
        !           335:     if (l == NULL)
        !           336:         return;
        !           337: 
        !           338:     xmlListClear(l);
        !           339:     xmlFree(l->sentinel);
        !           340:     xmlFree(l);
        !           341: }
        !           342: 
        !           343: /**
        !           344:  * xmlListRemoveFirst:
        !           345:  * @l:  a list
        !           346:  * @data:  list data
        !           347:  *
        !           348:  * Remove the first instance associated to data in the list
        !           349:  *
        !           350:  * Returns 1 if a deallocation occured, or 0 if not found
        !           351:  */
        !           352: int
        !           353: xmlListRemoveFirst(xmlListPtr l, void *data)
        !           354: {
        !           355:     xmlLinkPtr lk;
        !           356:     
        !           357:     if (l == NULL)
        !           358:         return(0);
        !           359:     /*Find the first instance of this data */
        !           360:     lk = xmlListLinkSearch(l, data);
        !           361:     if (lk != NULL) {
        !           362:         xmlLinkDeallocator(l, lk);
        !           363:         return 1;
        !           364:     }
        !           365:     return 0;
        !           366: }
        !           367: 
        !           368: /**
        !           369:  * xmlListRemoveLast:
        !           370:  * @l:  a list
        !           371:  * @data:  list data
        !           372:  *
        !           373:  * Remove the last instance associated to data in the list
        !           374:  *
        !           375:  * Returns 1 if a deallocation occured, or 0 if not found
        !           376:  */
        !           377: int
        !           378: xmlListRemoveLast(xmlListPtr l, void *data)
        !           379: {
        !           380:     xmlLinkPtr lk;
        !           381:     
        !           382:     if (l == NULL)
        !           383:         return(0);
        !           384:     /*Find the last instance of this data */
        !           385:     lk = xmlListLinkReverseSearch(l, data);
        !           386:     if (lk != NULL) {
        !           387:        xmlLinkDeallocator(l, lk);
        !           388:         return 1;
        !           389:     }
        !           390:     return 0;
        !           391: }
        !           392: 
        !           393: /**
        !           394:  * xmlListRemoveAll:
        !           395:  * @l:  a list
        !           396:  * @data:  list data
        !           397:  *
        !           398:  * Remove the all instance associated to data in the list
        !           399:  *
        !           400:  * Returns the number of deallocation, or 0 if not found
        !           401:  */
        !           402: int
        !           403: xmlListRemoveAll(xmlListPtr l, void *data)
        !           404: {
        !           405:     int count=0;
        !           406:     
        !           407:     if (l == NULL)
        !           408:         return(0);
        !           409: 
        !           410:     while(xmlListRemoveFirst(l, data))
        !           411:         count++;
        !           412:     return count;
        !           413: }
        !           414: 
        !           415: /**
        !           416:  * xmlListClear:
        !           417:  * @l:  a list
        !           418:  *
        !           419:  * Remove the all data in the list
        !           420:  */
        !           421: void
        !           422: xmlListClear(xmlListPtr l)
        !           423: {
        !           424:     xmlLinkPtr  lk;
        !           425:     
        !           426:     if (l == NULL)
        !           427:         return;
        !           428:     lk = l->sentinel->next;
        !           429:     while(lk != l->sentinel) {
        !           430:         xmlLinkPtr next = lk->next;
        !           431: 
        !           432:         xmlLinkDeallocator(l, lk);
        !           433:         lk = next;
        !           434:     }
        !           435: }
        !           436: 
        !           437: /**
        !           438:  * xmlListEmpty:
        !           439:  * @l:  a list
        !           440:  *
        !           441:  * Is the list empty ?
        !           442:  *
        !           443:  * Returns 1 if the list is empty, 0 if not empty and -1 in case of error
        !           444:  */
        !           445: int
        !           446: xmlListEmpty(xmlListPtr l)
        !           447: {
        !           448:     if (l == NULL)
        !           449:         return(-1);
        !           450:     return (l->sentinel->next == l->sentinel);
        !           451: }
        !           452: 
        !           453: /**
        !           454:  * xmlListFront:
        !           455:  * @l:  a list
        !           456:  *
        !           457:  * Get the first element in the list
        !           458:  *
        !           459:  * Returns the first element in the list, or NULL
        !           460:  */
        !           461: xmlLinkPtr 
        !           462: xmlListFront(xmlListPtr l)
        !           463: {
        !           464:     if (l == NULL)
        !           465:         return(NULL);
        !           466:     return (l->sentinel->next);
        !           467: }
        !           468:     
        !           469: /**
        !           470:  * xmlListEnd:
        !           471:  * @l:  a list
        !           472:  *
        !           473:  * Get the last element in the list
        !           474:  *
        !           475:  * Returns the last element in the list, or NULL
        !           476:  */
        !           477: xmlLinkPtr 
        !           478: xmlListEnd(xmlListPtr l)
        !           479: {
        !           480:     if (l == NULL)
        !           481:         return(NULL);
        !           482:     return (l->sentinel->prev);
        !           483: }
        !           484:     
        !           485: /**
        !           486:  * xmlListSize:
        !           487:  * @l:  a list
        !           488:  *
        !           489:  * Get the number of elements in the list
        !           490:  *
        !           491:  * Returns the number of elements in the list or -1 in case of error
        !           492:  */
        !           493: int
        !           494: xmlListSize(xmlListPtr l)
        !           495: {
        !           496:     xmlLinkPtr lk;
        !           497:     int count=0;
        !           498: 
        !           499:     if (l == NULL)
        !           500:         return(-1);
        !           501:     /* TODO: keep a counter in xmlList instead */
        !           502:     for(lk = l->sentinel->next; lk != l->sentinel; lk = lk->next, count++);
        !           503:     return count;
        !           504: }
        !           505: 
        !           506: /**
        !           507:  * xmlListPopFront:
        !           508:  * @l:  a list
        !           509:  *
        !           510:  * Removes the first element in the list
        !           511:  */
        !           512: void
        !           513: xmlListPopFront(xmlListPtr l)
        !           514: {
        !           515:     if(!xmlListEmpty(l))
        !           516:         xmlLinkDeallocator(l, l->sentinel->next);
        !           517: }
        !           518: 
        !           519: /**
        !           520:  * xmlListPopBack:
        !           521:  * @l:  a list
        !           522:  *
        !           523:  * Removes the last element in the list
        !           524:  */
        !           525: void
        !           526: xmlListPopBack(xmlListPtr l)
        !           527: {
        !           528:     if(!xmlListEmpty(l))
        !           529:         xmlLinkDeallocator(l, l->sentinel->prev);
        !           530: }
        !           531: 
        !           532: /**
        !           533:  * xmlListPushFront:
        !           534:  * @l:  a list
        !           535:  * @data:  new data
        !           536:  *
        !           537:  * add the new data at the beginning of the list
        !           538:  *
        !           539:  * Returns 1 if successful, 0 otherwise
        !           540:  */
        !           541: int
        !           542: xmlListPushFront(xmlListPtr l, void *data) 
        !           543: {
        !           544:     xmlLinkPtr lkPlace, lkNew;
        !           545: 
        !           546:     if (l == NULL)
        !           547:         return(0);
        !           548:     lkPlace = l->sentinel;
        !           549:     /* Add the new link */
        !           550:     lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
        !           551:     if (lkNew == NULL) {
        !           552:         xmlGenericError(xmlGenericErrorContext, 
        !           553:                        "Cannot initialize memory for new link");
        !           554:         return (0);
        !           555:     }
        !           556:     lkNew->data = data;
        !           557:     lkNew->next = lkPlace->next;
        !           558:     (lkPlace->next)->prev = lkNew;
        !           559:     lkPlace->next = lkNew;
        !           560:     lkNew->prev = lkPlace;
        !           561:     return 1;
        !           562: }
        !           563: 
        !           564: /**
        !           565:  * xmlListPushBack:
        !           566:  * @l:  a list
        !           567:  * @data:  new data
        !           568:  *
        !           569:  * add the new data at the end of the list
        !           570:  *
        !           571:  * Returns 1 if successful, 0 otherwise
        !           572:  */
        !           573: int
        !           574: xmlListPushBack(xmlListPtr l, void *data) 
        !           575: {
        !           576:     xmlLinkPtr lkPlace, lkNew;
        !           577: 
        !           578:     if (l == NULL)
        !           579:         return(0);
        !           580:     lkPlace = l->sentinel->prev;
        !           581:     /* Add the new link */
        !           582:     if (NULL ==(lkNew = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) {
        !           583:         xmlGenericError(xmlGenericErrorContext, 
        !           584:                        "Cannot initialize memory for new link");
        !           585:         return (0);
        !           586:     }
        !           587:     lkNew->data = data;
        !           588:     lkNew->next = lkPlace->next;
        !           589:     (lkPlace->next)->prev = lkNew;
        !           590:     lkPlace->next = lkNew;
        !           591:     lkNew->prev = lkPlace;
        !           592:     return 1;
        !           593: }
        !           594: 
        !           595: /**
        !           596:  * xmlLinkGetData:
        !           597:  * @lk:  a link
        !           598:  *
        !           599:  * See Returns.
        !           600:  *
        !           601:  * Returns a pointer to the data referenced from this link
        !           602:  */
        !           603: void *
        !           604: xmlLinkGetData(xmlLinkPtr lk)
        !           605: {
        !           606:     if (lk == NULL)
        !           607:         return(NULL);
        !           608:     return lk->data;
        !           609: }
        !           610: 
        !           611: /**
        !           612:  * xmlListReverse:
        !           613:  * @l:  a list
        !           614:  *
        !           615:  * Reverse the order of the elements in the list
        !           616:  */
        !           617: void
        !           618: xmlListReverse(xmlListPtr l)
        !           619: {
        !           620:     xmlLinkPtr lk;
        !           621:     xmlLinkPtr lkPrev;
        !           622: 
        !           623:     if (l == NULL)
        !           624:         return;
        !           625:     lkPrev = l->sentinel;
        !           626:     for (lk = l->sentinel->next; lk != l->sentinel; lk = lk->next) {
        !           627:         lkPrev->next = lkPrev->prev;
        !           628:         lkPrev->prev = lk;
        !           629:         lkPrev = lk;
        !           630:     }
        !           631:     /* Fix up the last node */
        !           632:     lkPrev->next = lkPrev->prev;
        !           633:     lkPrev->prev = lk;
        !           634: }
        !           635: 
        !           636: /**
        !           637:  * xmlListSort:
        !           638:  * @l:  a list
        !           639:  *
        !           640:  * Sort all the elements in the list
        !           641:  */
        !           642: void
        !           643: xmlListSort(xmlListPtr l)
        !           644: {
        !           645:     xmlListPtr lTemp;
        !           646:     
        !           647:     if (l == NULL)
        !           648:         return;
        !           649:     if(xmlListEmpty(l))
        !           650:         return;
        !           651: 
        !           652:     /* I think that the real answer is to implement quicksort, the
        !           653:      * alternative is to implement some list copying procedure which
        !           654:      * would be based on a list copy followed by a clear followed by
        !           655:      * an insert. This is slow...
        !           656:      */
        !           657: 
        !           658:     if (NULL ==(lTemp = xmlListDup(l)))
        !           659:         return;
        !           660:     xmlListClear(l);
        !           661:     xmlListMerge(l, lTemp);
        !           662:     xmlListDelete(lTemp);
        !           663:     return;
        !           664: }
        !           665: 
        !           666: /**
        !           667:  * xmlListWalk:
        !           668:  * @l:  a list
        !           669:  * @walker:  a processing function
        !           670:  * @user:  a user parameter passed to the walker function
        !           671:  *
        !           672:  * Walk all the element of the first from first to last and
        !           673:  * apply the walker function to it
        !           674:  */
        !           675: void
        !           676: xmlListWalk(xmlListPtr l, xmlListWalker walker, const void *user) {
        !           677:     xmlLinkPtr lk;
        !           678: 
        !           679:     if ((l == NULL) || (walker == NULL))
        !           680:         return;
        !           681:     for(lk = l->sentinel->next; lk != l->sentinel; lk = lk->next) {
        !           682:         if((walker(lk->data, user)) == 0)
        !           683:                 break;
        !           684:     }
        !           685: }
        !           686: 
        !           687: /**
        !           688:  * xmlListReverseWalk:
        !           689:  * @l:  a list
        !           690:  * @walker:  a processing function
        !           691:  * @user:  a user parameter passed to the walker function
        !           692:  *
        !           693:  * Walk all the element of the list in reverse order and
        !           694:  * apply the walker function to it
        !           695:  */
        !           696: void
        !           697: xmlListReverseWalk(xmlListPtr l, xmlListWalker walker, const void *user) {
        !           698:     xmlLinkPtr lk;
        !           699: 
        !           700:     if ((l == NULL) || (walker == NULL))
        !           701:         return;
        !           702:     for(lk = l->sentinel->prev; lk != l->sentinel; lk = lk->prev) {
        !           703:         if((walker(lk->data, user)) == 0)
        !           704:                 break;
        !           705:     }
        !           706: }
        !           707: 
        !           708: /**
        !           709:  * xmlListMerge:
        !           710:  * @l1:  the original list
        !           711:  * @l2:  the new list
        !           712:  *
        !           713:  * include all the elements of the second list in the first one and
        !           714:  * clear the second list
        !           715:  */
        !           716: void
        !           717: xmlListMerge(xmlListPtr l1, xmlListPtr l2)
        !           718: {
        !           719:     xmlListCopy(l1, l2);
        !           720:     xmlListClear(l2);
        !           721: }
        !           722: 
        !           723: /**
        !           724:  * xmlListDup:
        !           725:  * @old:  the list
        !           726:  *
        !           727:  * Duplicate the list
        !           728:  * 
        !           729:  * Returns a new copy of the list or NULL in case of error
        !           730:  */
        !           731: xmlListPtr 
        !           732: xmlListDup(const xmlListPtr old)
        !           733: {
        !           734:     xmlListPtr cur;
        !           735: 
        !           736:     if (old == NULL)
        !           737:         return(NULL);
        !           738:     /* Hmmm, how to best deal with allocation issues when copying
        !           739:      * lists. If there is a de-allocator, should responsibility lie with
        !           740:      * the new list or the old list. Surely not both. I'll arbitrarily
        !           741:      * set it to be the old list for the time being whilst I work out
        !           742:      * the answer
        !           743:      */
        !           744:     if (NULL ==(cur = xmlListCreate(NULL, old->linkCompare)))
        !           745:         return (NULL);
        !           746:     if (0 != xmlListCopy(cur, old))
        !           747:         return NULL;
        !           748:     return cur;
        !           749: }
        !           750: 
        !           751: /**
        !           752:  * xmlListCopy:
        !           753:  * @cur:  the new list
        !           754:  * @old:  the old list
        !           755:  *
        !           756:  * Move all the element from the old list in the new list
        !           757:  * 
        !           758:  * Returns 0 in case of success 1 in case of error
        !           759:  */
        !           760: int
        !           761: xmlListCopy(xmlListPtr cur, const xmlListPtr old)
        !           762: {
        !           763:     /* Walk the old tree and insert the data into the new one */
        !           764:     xmlLinkPtr lk;
        !           765: 
        !           766:     if ((old == NULL) || (cur == NULL))
        !           767:         return(1);
        !           768:     for(lk = old->sentinel->next; lk != old->sentinel; lk = lk->next) {
        !           769:         if (0 !=xmlListInsert(cur, lk->data)) {
        !           770:             xmlListDelete(cur);
        !           771:             return (1);
        !           772:         }
        !           773:     }
        !           774:     return (0);    
        !           775: }
        !           776: /* xmlListUnique() */
        !           777: /* xmlListSwap */
        !           778: #define bottom_list
        !           779: #include "elfgcchack.h"

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>