📄 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 void
xmlLinkDeallocator(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 int
xmlLinkCompare(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
*/
xmlListPtr
xmlListCreate(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
*/
int
xmlListInsert(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 (0);
}
lkNew->data = data;
lkNew->next = lkPlace->next;
(lkPlace->next)->prev = lkNew;
lkPlace->next = lkNew;
lkNew->prev = lkPlace;
return 1;
}
/**
* 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
*/
int
xmlListRemoveFirst(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
*/
int
xmlListRemoveLast(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 + -