📄 list.c
字号:
/* * list.c: lists handling implementation * * Copyright (C) 2000 Gary Pennington and Daniel Veillard. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * * Author: Gary.Pennington@uk.sun.com */#define IN_LIBXML#include "libxml.h"#include <stdlib.h>#include <string.h>#include <libxml/xmlmemory.h>#include <libxml/list.h>#include <libxml/globals.h>/* * Type definition are kept internal */struct _xmlLink{ struct _xmlLink *next; struct _xmlLink *prev; void *data;};struct _xmlList{ xmlLinkPtr sentinel; void (*linkDeallocator)(xmlLinkPtr ); int (*linkCompare)(const void *, const void*);};/************************************************************************ * * * Interfaces * * * ************************************************************************//** * xmlLinkDeallocator: * @l: a list * @lk: a link * * Unlink and deallocate @lk from list @l */static voidxmlLinkDeallocator(xmlListPtr l, xmlLinkPtr lk){ (lk->prev)->next = lk->next; (lk->next)->prev = lk->prev; if(l->linkDeallocator) l->linkDeallocator(lk); xmlFree(lk);}/** * xmlLinkCompare: * @data0: first data * @data1: second data * * Compares two arbitrary data * * Returns -1, 0 or 1 depending on whether data1 is greater equal or smaller * than data0 */static intxmlLinkCompare(const void *data0, const void *data1){ if (data0 < data1) return (-1); else if (data0 == data1) return (0); return (1);}/** * xmlListLowerSearch: * @l: a list * @data: a data * * Search data in the ordered list walking from the beginning * * Returns the link containing the data or NULL */static xmlLinkPtr xmlListLowerSearch(xmlListPtr l, void *data) { xmlLinkPtr lk; if (l == NULL) return(NULL); for(lk = l->sentinel->next;lk != l->sentinel && l->linkCompare(lk->data, data) <0 ;lk = lk->next); return lk; }/** * xmlListHigherSearch: * @l: a list * @data: a data * * Search data in the ordered list walking backward from the end * * Returns the link containing the data or NULL */static xmlLinkPtr xmlListHigherSearch(xmlListPtr l, void *data) { xmlLinkPtr lk; if (l == NULL) return(NULL); for(lk = l->sentinel->prev;lk != l->sentinel && l->linkCompare(lk->data, data) >0 ;lk = lk->prev); return lk; }/** * xmlListSearch: * @l: a list * @data: a data * * Search data in the list * * Returns the link containing the data or NULL */static xmlLinkPtr xmlListLinkSearch(xmlListPtr l, void *data) { xmlLinkPtr lk; if (l == NULL) return(NULL); lk = xmlListLowerSearch(l, data); if (lk == l->sentinel) return NULL; else { if (l->linkCompare(lk->data, data) ==0) return lk; return NULL; }}/** * xmlListLinkReverseSearch: * @l: a list * @data: a data * * Search data in the list processing backward * * Returns the link containing the data or NULL */static xmlLinkPtr xmlListLinkReverseSearch(xmlListPtr l, void *data) { xmlLinkPtr lk; if (l == NULL) return(NULL); lk = xmlListHigherSearch(l, data); if (lk == l->sentinel) return NULL; else { if (l->linkCompare(lk->data, data) ==0) return lk; return NULL; }}/** * xmlListCreate: * @deallocator: an optional deallocator function * @compare: an optional comparison function * * Create a new list * * Returns the new list or NULL in case of error */xmlListPtrxmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare){ xmlListPtr l; if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList)))) { xmlGenericError(xmlGenericErrorContext, "Cannot initialize memory for list"); return (NULL); } /* Initialize the list to NULL */ memset(l, 0, sizeof(xmlList)); /* Add the sentinel */ if (NULL ==(l->sentinel = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) { xmlGenericError(xmlGenericErrorContext, "Cannot initialize memory for sentinel"); xmlFree(l); return (NULL); } l->sentinel->next = l->sentinel; l->sentinel->prev = l->sentinel; l->sentinel->data = NULL; /* If there is a link deallocator, use it */ if (deallocator != NULL) l->linkDeallocator = deallocator; /* If there is a link comparator, use it */ if (compare != NULL) l->linkCompare = compare; else /* Use our own */ l->linkCompare = xmlLinkCompare; return l;} /** * xmlListSearch: * @l: a list * @data: a search value * * Search the list for an existing value of @data * * Returns the value associated to @data or NULL in case of error */void *xmlListSearch(xmlListPtr l, void *data) { xmlLinkPtr lk; if (l == NULL) return(NULL); lk = xmlListLinkSearch(l, data); if (lk) return (lk->data); return NULL;}/** * xmlListReverseSearch: * @l: a list * @data: a search value * * Search the list in reverse order for an existing value of @data * * Returns the value associated to @data or NULL in case of error */void *xmlListReverseSearch(xmlListPtr l, void *data) { xmlLinkPtr lk; if (l == NULL) return(NULL); lk = xmlListLinkReverseSearch(l, data); if (lk) return (lk->data); return NULL;}/** * xmlListInsert: * @l: a list * @data: the data * * Insert data in the ordered list at the beginning for this value * * Returns 0 in case of success, 1 in case of failure */intxmlListInsert(xmlListPtr l, void *data) { xmlLinkPtr lkPlace, lkNew; if (l == NULL) return(1); lkPlace = xmlListLowerSearch(l, data); /* Add the new link */ lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); if (lkNew == NULL) { xmlGenericError(xmlGenericErrorContext, "Cannot initialize memory for new link"); return (1); } lkNew->data = data; lkPlace = lkPlace->prev; lkNew->next = lkPlace->next; (lkPlace->next)->prev = lkNew; lkPlace->next = lkNew; lkNew->prev = lkPlace; return 0;}/** * xmlListAppend: * @l: a list * @data: the data * * Insert data in the ordered list at the end for this value * * Returns 0 in case of success, 1 in case of failure */int xmlListAppend(xmlListPtr l, void *data) { xmlLinkPtr lkPlace, lkNew; if (l == NULL) return(1); lkPlace = xmlListHigherSearch(l, data); /* Add the new link */ lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); if (lkNew == NULL) { xmlGenericError(xmlGenericErrorContext, "Cannot initialize memory for new link"); return (1); } lkNew->data = data; lkNew->next = lkPlace->next; (lkPlace->next)->prev = lkNew; lkPlace->next = lkNew; lkNew->prev = lkPlace; return 0;}/** * xmlListDelete: * @l: a list * * Deletes the list and its associated data */void xmlListDelete(xmlListPtr l){ if (l == NULL) return; xmlListClear(l); xmlFree(l->sentinel); xmlFree(l);}/** * xmlListRemoveFirst: * @l: a list * @data: list data * * Remove the first instance associated to data in the list * * Returns 1 if a deallocation occured, or 0 if not found */intxmlListRemoveFirst(xmlListPtr l, void *data){ xmlLinkPtr lk; if (l == NULL) return(0); /*Find the first instance of this data */ lk = xmlListLinkSearch(l, data); if (lk != NULL) { xmlLinkDeallocator(l, lk); return 1; } return 0;}/** * xmlListRemoveLast: * @l: a list * @data: list data * * Remove the last instance associated to data in the list * * Returns 1 if a deallocation occured, or 0 if not found */intxmlListRemoveLast(xmlListPtr l, void *data){ xmlLinkPtr lk; if (l == NULL) return(0); /*Find the last instance of this data */ lk = xmlListLinkReverseSearch(l, data); if (lk != NULL) { xmlLinkDeallocator(l, lk); return 1; } return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -