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