Blame list.c

Packit 423ecb
/*
Packit 423ecb
 * list.c: lists handling implementation
Packit 423ecb
 *
Packit 423ecb
 * Copyright (C) 2000 Gary Pennington and Daniel Veillard.
Packit 423ecb
 *
Packit 423ecb
 * Permission to use, copy, modify, and distribute this software for any
Packit 423ecb
 * purpose with or without fee is hereby granted, provided that the above
Packit 423ecb
 * copyright notice and this permission notice appear in all copies.
Packit 423ecb
 *
Packit 423ecb
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
Packit 423ecb
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
Packit 423ecb
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
Packit 423ecb
 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
Packit 423ecb
 *
Packit 423ecb
 * Author: Gary.Pennington@uk.sun.com
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
#define IN_LIBXML
Packit 423ecb
#include "libxml.h"
Packit 423ecb
Packit 423ecb
#include <stdlib.h>
Packit 423ecb
#include <string.h>
Packit 423ecb
#include <libxml/xmlmemory.h>
Packit 423ecb
#include <libxml/list.h>
Packit 423ecb
#include <libxml/globals.h>
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
 * Type definition are kept internal
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
struct _xmlLink
Packit 423ecb
{
Packit 423ecb
    struct _xmlLink *next;
Packit 423ecb
    struct _xmlLink *prev;
Packit 423ecb
    void *data;
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
struct _xmlList
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr sentinel;
Packit 423ecb
    void (*linkDeallocator)(xmlLinkPtr );
Packit 423ecb
    int (*linkCompare)(const void *, const void*);
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *                                    *
Packit 423ecb
 *                Interfaces                *
Packit 423ecb
 *                                    *
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlLinkDeallocator:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @lk:  a link
Packit 423ecb
 *
Packit 423ecb
 * Unlink and deallocate @lk from list @l
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
xmlLinkDeallocator(xmlListPtr l, xmlLinkPtr lk)
Packit 423ecb
{
Packit 423ecb
    (lk->prev)->next = lk->next;
Packit 423ecb
    (lk->next)->prev = lk->prev;
Packit 423ecb
    if(l->linkDeallocator)
Packit 423ecb
        l->linkDeallocator(lk);
Packit 423ecb
    xmlFree(lk);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlLinkCompare:
Packit 423ecb
 * @data0:  first data
Packit 423ecb
 * @data1:  second data
Packit 423ecb
 *
Packit 423ecb
 * Compares two arbitrary data
Packit 423ecb
 *
Packit 423ecb
 * Returns -1, 0 or 1 depending on whether data1 is greater equal or smaller
Packit 423ecb
 *          than data0
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlLinkCompare(const void *data0, const void *data1)
Packit 423ecb
{
Packit 423ecb
    if (data0 < data1)
Packit 423ecb
        return (-1);
Packit 423ecb
    else if (data0 == data1)
Packit 423ecb
	return (0);
Packit 423ecb
    return (1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListLowerSearch:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  a data
Packit 423ecb
 *
Packit 423ecb
 * Search data in the ordered list walking from the beginning
Packit 423ecb
 *
Packit 423ecb
 * Returns the link containing the data or NULL
Packit 423ecb
 */
Packit 423ecb
static xmlLinkPtr
Packit 423ecb
xmlListLowerSearch(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    for(lk = l->sentinel->next;lk != l->sentinel && l->linkCompare(lk->data, data) <0 ;lk = lk->next);
Packit 423ecb
    return lk;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListHigherSearch:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  a data
Packit 423ecb
 *
Packit 423ecb
 * Search data in the ordered list walking backward from the end
Packit 423ecb
 *
Packit 423ecb
 * Returns the link containing the data or NULL
Packit 423ecb
 */
Packit 423ecb
static xmlLinkPtr
Packit 423ecb
xmlListHigherSearch(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    for(lk = l->sentinel->prev;lk != l->sentinel && l->linkCompare(lk->data, data) >0 ;lk = lk->prev);
Packit 423ecb
    return lk;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListSearch:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  a data
Packit 423ecb
 *
Packit 423ecb
 * Search data in the list
Packit 423ecb
 *
Packit 423ecb
 * Returns the link containing the data or NULL
Packit 423ecb
 */
Packit 423ecb
static xmlLinkPtr
Packit 423ecb
xmlListLinkSearch(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    lk = xmlListLowerSearch(l, data);
Packit 423ecb
    if (lk == l->sentinel)
Packit 423ecb
        return NULL;
Packit 423ecb
    else {
Packit 423ecb
        if (l->linkCompare(lk->data, data) ==0)
Packit 423ecb
            return lk;
Packit 423ecb
        return NULL;
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListLinkReverseSearch:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  a data
Packit 423ecb
 *
Packit 423ecb
 * Search data in the list processing backward
Packit 423ecb
 *
Packit 423ecb
 * Returns the link containing the data or NULL
Packit 423ecb
 */
Packit 423ecb
static xmlLinkPtr
Packit 423ecb
xmlListLinkReverseSearch(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    lk = xmlListHigherSearch(l, data);
Packit 423ecb
    if (lk == l->sentinel)
Packit 423ecb
        return NULL;
Packit 423ecb
    else {
Packit 423ecb
        if (l->linkCompare(lk->data, data) ==0)
Packit 423ecb
            return lk;
Packit 423ecb
        return NULL;
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListCreate:
Packit 423ecb
 * @deallocator:  an optional deallocator function
Packit 423ecb
 * @compare:  an optional comparison function
Packit 423ecb
 *
Packit 423ecb
 * Create a new list
Packit 423ecb
 *
Packit 423ecb
 * Returns the new list or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
xmlListPtr
Packit 423ecb
xmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare)
Packit 423ecb
{
Packit 423ecb
    xmlListPtr l;
Packit 423ecb
    if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList)))) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
		        "Cannot initialize memory for list");
Packit 423ecb
        return (NULL);
Packit 423ecb
    }
Packit 423ecb
    /* Initialize the list to NULL */
Packit 423ecb
    memset(l, 0, sizeof(xmlList));
Packit 423ecb
Packit 423ecb
    /* Add the sentinel */
Packit 423ecb
    if (NULL ==(l->sentinel = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
		        "Cannot initialize memory for sentinel");
Packit 423ecb
	xmlFree(l);
Packit 423ecb
        return (NULL);
Packit 423ecb
    }
Packit 423ecb
    l->sentinel->next = l->sentinel;
Packit 423ecb
    l->sentinel->prev = l->sentinel;
Packit 423ecb
    l->sentinel->data = NULL;
Packit 423ecb
Packit 423ecb
    /* If there is a link deallocator, use it */
Packit 423ecb
    if (deallocator != NULL)
Packit 423ecb
        l->linkDeallocator = deallocator;
Packit 423ecb
    /* If there is a link comparator, use it */
Packit 423ecb
    if (compare != NULL)
Packit 423ecb
        l->linkCompare = compare;
Packit 423ecb
    else /* Use our own */
Packit 423ecb
        l->linkCompare = xmlLinkCompare;
Packit 423ecb
    return l;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListSearch:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  a search value
Packit 423ecb
 *
Packit 423ecb
 * Search the list for an existing value of @data
Packit 423ecb
 *
Packit 423ecb
 * Returns the value associated to @data or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
void *
Packit 423ecb
xmlListSearch(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    lk = xmlListLinkSearch(l, data);
Packit 423ecb
    if (lk)
Packit 423ecb
        return (lk->data);
Packit 423ecb
    return NULL;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListReverseSearch:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  a search value
Packit 423ecb
 *
Packit 423ecb
 * Search the list in reverse order for an existing value of @data
Packit 423ecb
 *
Packit 423ecb
 * Returns the value associated to @data or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
void *
Packit 423ecb
xmlListReverseSearch(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    lk = xmlListLinkReverseSearch(l, data);
Packit 423ecb
    if (lk)
Packit 423ecb
        return (lk->data);
Packit 423ecb
    return NULL;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListInsert:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  the data
Packit 423ecb
 *
Packit 423ecb
 * Insert data in the ordered list at the beginning for this value
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 in case of success, 1 in case of failure
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListInsert(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lkPlace, lkNew;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(1);
Packit 423ecb
    lkPlace = xmlListLowerSearch(l, data);
Packit 423ecb
    /* Add the new link */
Packit 423ecb
    lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
Packit 423ecb
    if (lkNew == NULL) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
		        "Cannot initialize memory for new link");
Packit 423ecb
        return (1);
Packit 423ecb
    }
Packit 423ecb
    lkNew->data = data;
Packit 423ecb
    lkPlace = lkPlace->prev;
Packit 423ecb
    lkNew->next = lkPlace->next;
Packit 423ecb
    (lkPlace->next)->prev = lkNew;
Packit 423ecb
    lkPlace->next = lkNew;
Packit 423ecb
    lkNew->prev = lkPlace;
Packit 423ecb
    return 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListAppend:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  the data
Packit 423ecb
 *
Packit 423ecb
 * Insert data in the ordered list at the end for this value
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 in case of success, 1 in case of failure
Packit 423ecb
 */
Packit 423ecb
int xmlListAppend(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lkPlace, lkNew;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(1);
Packit 423ecb
    lkPlace = xmlListHigherSearch(l, data);
Packit 423ecb
    /* Add the new link */
Packit 423ecb
    lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
Packit 423ecb
    if (lkNew == NULL) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
		        "Cannot initialize memory for new link");
Packit 423ecb
        return (1);
Packit 423ecb
    }
Packit 423ecb
    lkNew->data = data;
Packit 423ecb
    lkNew->next = lkPlace->next;
Packit 423ecb
    (lkPlace->next)->prev = lkNew;
Packit 423ecb
    lkPlace->next = lkNew;
Packit 423ecb
    lkNew->prev = lkPlace;
Packit 423ecb
    return 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListDelete:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Deletes the list and its associated data
Packit 423ecb
 */
Packit 423ecb
void xmlListDelete(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return;
Packit 423ecb
Packit 423ecb
    xmlListClear(l);
Packit 423ecb
    xmlFree(l->sentinel);
Packit 423ecb
    xmlFree(l);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListRemoveFirst:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  list data
Packit 423ecb
 *
Packit 423ecb
 * Remove the first instance associated to data in the list
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if a deallocation occurred, or 0 if not found
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListRemoveFirst(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(0);
Packit 423ecb
    /*Find the first instance of this data */
Packit 423ecb
    lk = xmlListLinkSearch(l, data);
Packit 423ecb
    if (lk != NULL) {
Packit 423ecb
        xmlLinkDeallocator(l, lk);
Packit 423ecb
        return 1;
Packit 423ecb
    }
Packit 423ecb
    return 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListRemoveLast:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  list data
Packit 423ecb
 *
Packit 423ecb
 * Remove the last instance associated to data in the list
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if a deallocation occurred, or 0 if not found
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListRemoveLast(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(0);
Packit 423ecb
    /*Find the last instance of this data */
Packit 423ecb
    lk = xmlListLinkReverseSearch(l, data);
Packit 423ecb
    if (lk != NULL) {
Packit 423ecb
	xmlLinkDeallocator(l, lk);
Packit 423ecb
        return 1;
Packit 423ecb
    }
Packit 423ecb
    return 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListRemoveAll:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  list data
Packit 423ecb
 *
Packit 423ecb
 * Remove the all instance associated to data in the list
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of deallocation, or 0 if not found
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListRemoveAll(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    int count=0;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(0);
Packit 423ecb
Packit 423ecb
    while(xmlListRemoveFirst(l, data))
Packit 423ecb
        count++;
Packit 423ecb
    return count;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListClear:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Remove the all data in the list
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlListClear(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr  lk;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return;
Packit 423ecb
    lk = l->sentinel->next;
Packit 423ecb
    while(lk != l->sentinel) {
Packit 423ecb
        xmlLinkPtr next = lk->next;
Packit 423ecb
Packit 423ecb
        xmlLinkDeallocator(l, lk);
Packit 423ecb
        lk = next;
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListEmpty:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Is the list empty ?
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if the list is empty, 0 if not empty and -1 in case of error
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListEmpty(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(-1);
Packit 423ecb
    return (l->sentinel->next == l->sentinel);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListFront:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Get the first element in the list
Packit 423ecb
 *
Packit 423ecb
 * Returns the first element in the list, or NULL
Packit 423ecb
 */
Packit 423ecb
xmlLinkPtr
Packit 423ecb
xmlListFront(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    return (l->sentinel->next);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListEnd:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Get the last element in the list
Packit 423ecb
 *
Packit 423ecb
 * Returns the last element in the list, or NULL
Packit 423ecb
 */
Packit 423ecb
xmlLinkPtr
Packit 423ecb
xmlListEnd(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    return (l->sentinel->prev);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListSize:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Get the number of elements in the list
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of elements in the list or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListSize(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
    int count=0;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(-1);
Packit 423ecb
    /* TODO: keep a counter in xmlList instead */
Packit 423ecb
    for(lk = l->sentinel->next; lk != l->sentinel; lk = lk->next, count++);
Packit 423ecb
    return count;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListPopFront:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Removes the first element in the list
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlListPopFront(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    if(!xmlListEmpty(l))
Packit 423ecb
        xmlLinkDeallocator(l, l->sentinel->next);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListPopBack:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Removes the last element in the list
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlListPopBack(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    if(!xmlListEmpty(l))
Packit 423ecb
        xmlLinkDeallocator(l, l->sentinel->prev);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListPushFront:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  new data
Packit 423ecb
 *
Packit 423ecb
 * add the new data at the beginning of the list
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if successful, 0 otherwise
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListPushFront(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lkPlace, lkNew;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(0);
Packit 423ecb
    lkPlace = l->sentinel;
Packit 423ecb
    /* Add the new link */
Packit 423ecb
    lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink));
Packit 423ecb
    if (lkNew == NULL) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
		        "Cannot initialize memory for new link");
Packit 423ecb
        return (0);
Packit 423ecb
    }
Packit 423ecb
    lkNew->data = data;
Packit 423ecb
    lkNew->next = lkPlace->next;
Packit 423ecb
    (lkPlace->next)->prev = lkNew;
Packit 423ecb
    lkPlace->next = lkNew;
Packit 423ecb
    lkNew->prev = lkPlace;
Packit 423ecb
    return 1;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListPushBack:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @data:  new data
Packit 423ecb
 *
Packit 423ecb
 * add the new data at the end of the list
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if successful, 0 otherwise
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListPushBack(xmlListPtr l, void *data)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lkPlace, lkNew;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return(0);
Packit 423ecb
    lkPlace = l->sentinel->prev;
Packit 423ecb
    /* Add the new link */
Packit 423ecb
    if (NULL ==(lkNew = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
		        "Cannot initialize memory for new link");
Packit 423ecb
        return (0);
Packit 423ecb
    }
Packit 423ecb
    lkNew->data = data;
Packit 423ecb
    lkNew->next = lkPlace->next;
Packit 423ecb
    (lkPlace->next)->prev = lkNew;
Packit 423ecb
    lkPlace->next = lkNew;
Packit 423ecb
    lkNew->prev = lkPlace;
Packit 423ecb
    return 1;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlLinkGetData:
Packit 423ecb
 * @lk:  a link
Packit 423ecb
 *
Packit 423ecb
 * See Returns.
Packit 423ecb
 *
Packit 423ecb
 * Returns a pointer to the data referenced from this link
Packit 423ecb
 */
Packit 423ecb
void *
Packit 423ecb
xmlLinkGetData(xmlLinkPtr lk)
Packit 423ecb
{
Packit 423ecb
    if (lk == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    return lk->data;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListReverse:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Reverse the order of the elements in the list
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlListReverse(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
    xmlLinkPtr lkPrev;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return;
Packit 423ecb
    lkPrev = l->sentinel;
Packit 423ecb
    for (lk = l->sentinel->next; lk != l->sentinel; lk = lk->next) {
Packit 423ecb
        lkPrev->next = lkPrev->prev;
Packit 423ecb
        lkPrev->prev = lk;
Packit 423ecb
        lkPrev = lk;
Packit 423ecb
    }
Packit 423ecb
    /* Fix up the last node */
Packit 423ecb
    lkPrev->next = lkPrev->prev;
Packit 423ecb
    lkPrev->prev = lk;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListSort:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 *
Packit 423ecb
 * Sort all the elements in the list
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlListSort(xmlListPtr l)
Packit 423ecb
{
Packit 423ecb
    xmlListPtr lTemp;
Packit 423ecb
Packit 423ecb
    if (l == NULL)
Packit 423ecb
        return;
Packit 423ecb
    if(xmlListEmpty(l))
Packit 423ecb
        return;
Packit 423ecb
Packit 423ecb
    /* I think that the real answer is to implement quicksort, the
Packit 423ecb
     * alternative is to implement some list copying procedure which
Packit 423ecb
     * would be based on a list copy followed by a clear followed by
Packit 423ecb
     * an insert. This is slow...
Packit 423ecb
     */
Packit 423ecb
Packit 423ecb
    if (NULL ==(lTemp = xmlListDup(l)))
Packit 423ecb
        return;
Packit 423ecb
    xmlListClear(l);
Packit 423ecb
    xmlListMerge(l, lTemp);
Packit 423ecb
    xmlListDelete(lTemp);
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListWalk:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @walker:  a processing function
Packit 423ecb
 * @user:  a user parameter passed to the walker function
Packit 423ecb
 *
Packit 423ecb
 * Walk all the element of the first from first to last and
Packit 423ecb
 * apply the walker function to it
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlListWalk(xmlListPtr l, xmlListWalker walker, const void *user) {
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
Packit 423ecb
    if ((l == NULL) || (walker == NULL))
Packit 423ecb
        return;
Packit 423ecb
    for(lk = l->sentinel->next; lk != l->sentinel; lk = lk->next) {
Packit 423ecb
        if((walker(lk->data, user)) == 0)
Packit 423ecb
                break;
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListReverseWalk:
Packit 423ecb
 * @l:  a list
Packit 423ecb
 * @walker:  a processing function
Packit 423ecb
 * @user:  a user parameter passed to the walker function
Packit 423ecb
 *
Packit 423ecb
 * Walk all the element of the list in reverse order and
Packit 423ecb
 * apply the walker function to it
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlListReverseWalk(xmlListPtr l, xmlListWalker walker, const void *user) {
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
Packit 423ecb
    if ((l == NULL) || (walker == NULL))
Packit 423ecb
        return;
Packit 423ecb
    for(lk = l->sentinel->prev; lk != l->sentinel; lk = lk->prev) {
Packit 423ecb
        if((walker(lk->data, user)) == 0)
Packit 423ecb
                break;
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListMerge:
Packit 423ecb
 * @l1:  the original list
Packit 423ecb
 * @l2:  the new list
Packit 423ecb
 *
Packit 423ecb
 * include all the elements of the second list in the first one and
Packit 423ecb
 * clear the second list
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlListMerge(xmlListPtr l1, xmlListPtr l2)
Packit 423ecb
{
Packit 423ecb
    xmlListCopy(l1, l2);
Packit 423ecb
    xmlListClear(l2);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListDup:
Packit 423ecb
 * @old:  the list
Packit 423ecb
 *
Packit 423ecb
 * Duplicate the list
Packit 423ecb
 *
Packit 423ecb
 * Returns a new copy of the list or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
xmlListPtr
Packit 423ecb
xmlListDup(const xmlListPtr old)
Packit 423ecb
{
Packit 423ecb
    xmlListPtr cur;
Packit 423ecb
Packit 423ecb
    if (old == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
    /* Hmmm, how to best deal with allocation issues when copying
Packit 423ecb
     * lists. If there is a de-allocator, should responsibility lie with
Packit 423ecb
     * the new list or the old list. Surely not both. I'll arbitrarily
Packit 423ecb
     * set it to be the old list for the time being whilst I work out
Packit 423ecb
     * the answer
Packit 423ecb
     */
Packit 423ecb
    if (NULL ==(cur = xmlListCreate(NULL, old->linkCompare)))
Packit 423ecb
        return (NULL);
Packit 423ecb
    if (0 != xmlListCopy(cur, old))
Packit 423ecb
        return NULL;
Packit 423ecb
    return cur;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlListCopy:
Packit 423ecb
 * @cur:  the new list
Packit 423ecb
 * @old:  the old list
Packit 423ecb
 *
Packit 423ecb
 * Move all the element from the old list in the new list
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 in case of success 1 in case of error
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlListCopy(xmlListPtr cur, const xmlListPtr old)
Packit 423ecb
{
Packit 423ecb
    /* Walk the old tree and insert the data into the new one */
Packit 423ecb
    xmlLinkPtr lk;
Packit 423ecb
Packit 423ecb
    if ((old == NULL) || (cur == NULL))
Packit 423ecb
        return(1);
Packit 423ecb
    for(lk = old->sentinel->next; lk != old->sentinel; lk = lk->next) {
Packit 423ecb
        if (0 !=xmlListInsert(cur, lk->data)) {
Packit 423ecb
            xmlListDelete(cur);
Packit 423ecb
            return (1);
Packit 423ecb
        }
Packit 423ecb
    }
Packit 423ecb
    return (0);
Packit 423ecb
}
Packit 423ecb
/* xmlListUnique() */
Packit 423ecb
/* xmlListSwap */
Packit 423ecb
#define bottom_list
Packit 423ecb
#include "elfgcchack.h"