blob: b3badc221d4f1d5a172f22159c6a77f855b0a665 [file] [log] [blame]
/*
* Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "DeprecatedPtrListImpl.h"
#include <cstddef>
#include <algorithm>
#include <wtf/Assertions.h>
namespace WebCore {
class DeprecatedListNode
{
public:
DeprecatedListNode(void *d) : data(d), next(0), prev(0) { }
void *data;
DeprecatedListNode *next;
DeprecatedListNode *prev;
};
static DeprecatedListNode *copyList(DeprecatedListNode *l, DeprecatedListNode *&tail)
{
DeprecatedListNode *node = l;
DeprecatedListNode *copyHead = 0;
DeprecatedListNode *last = 0;
while (node != 0) {
DeprecatedListNode *copy = new DeprecatedListNode(node->data);
if (last != 0) {
last->next = copy;
} else {
copyHead = copy;
}
copy->prev = last;
last = copy;
node = node->next;
}
tail = last;
return copyHead;
}
DeprecatedPtrListImpl::DeprecatedPtrListImpl(void (*deleteFunc)(void *)) :
head(0),
tail(0),
cur(0),
nodeCount(0),
deleteItem(deleteFunc),
iterators(0)
{
}
DeprecatedPtrListImpl::DeprecatedPtrListImpl(const DeprecatedPtrListImpl &impl) :
cur(0),
nodeCount(impl.nodeCount),
deleteItem(impl.deleteItem),
iterators(0)
{
head = copyList(impl.head, tail);
}
DeprecatedPtrListImpl::~DeprecatedPtrListImpl()
{
clear(false);
DeprecatedPtrListImplIterator *next;
for (DeprecatedPtrListImplIterator *it = iterators; it; it = next) {
next = it->next;
it->list = 0;
ASSERT(!it->node);
it->next = 0;
it->prev = 0;
}
}
void DeprecatedPtrListImpl::clear(bool deleteItems)
{
DeprecatedListNode *next;
for (DeprecatedListNode *node = head; node; node = next) {
next = node->next;
if (deleteItems)
deleteItem(node->data);
delete node;
}
head = 0;
tail = 0;
cur = 0;
nodeCount = 0;
for (DeprecatedPtrListImplIterator *it = iterators; it; it = it->next)
it->node = 0;
}
void *DeprecatedPtrListImpl::at(unsigned n)
{
DeprecatedListNode *node;
if (n >= nodeCount - 1) {
node = tail;
} else {
node = head;
for (unsigned i = 0; i < n && node; i++) {
node = node->next;
}
}
cur = node;
return node ? node->data : 0;
}
bool DeprecatedPtrListImpl::insert(unsigned n, const void *item)
{
if (n > nodeCount) {
return false;
}
DeprecatedListNode *node = new DeprecatedListNode((void *)item);
if (n == 0) {
// inserting at head
node->next = head;
if (head) {
head->prev = node;
}
head = node;
if (tail == 0) {
tail = node;
}
} else if (n == nodeCount) {
// inserting at tail
node->prev = tail;
if (tail) {
tail->next = node;
}
tail = node;
} else {
// general insertion
// iterate to one node before the insertion point, can't be null
// since we know n > 0 and n < nodeCount
DeprecatedListNode *prevNode = head;
for (unsigned i = 0; i < n - 1; i++) {
prevNode = prevNode->next;
}
node->prev = prevNode;
node->next = prevNode->next;
if (node->next) {
node->next->prev = node;
}
prevNode->next = node;
}
nodeCount++;
cur = node;
return true;
}
bool DeprecatedPtrListImpl::remove(bool shouldDeleteItem)
{
DeprecatedListNode *node = cur;
if (node == 0) {
return false;
}
if (node->prev == 0) {
head = node->next;
} else {
node->prev->next = node->next;
}
if (node->next == 0) {
tail = node->prev;
} else {
node->next->prev = node->prev;
}
if (node->next) {
cur = node->next;
} else {
cur = node->prev;
}
for (DeprecatedPtrListImplIterator *it = iterators; it; it = it->next) {
if (it->node == node) {
it->node = cur;
}
}
if (shouldDeleteItem) {
deleteItem(node->data);
}
delete node;
nodeCount--;
return true;
}
bool DeprecatedPtrListImpl::remove(unsigned n, bool deleteItem)
{
if (n >= nodeCount) {
return false;
}
at(n);
return remove(deleteItem);
}
bool DeprecatedPtrListImpl::removeFirst(bool deleteItem)
{
return remove(0, deleteItem);
}
bool DeprecatedPtrListImpl::removeLast(bool deleteItem)
{
return remove(nodeCount - 1, deleteItem);
}
bool DeprecatedPtrListImpl::removeRef(const void *item, bool deleteItem)
{
DeprecatedListNode *node;
node = head;
while (node && item != node->data) {
node = node->next;
}
if (node == 0) {
return false;
}
cur = node;
return remove(deleteItem);
}
void *DeprecatedPtrListImpl::getFirst() const
{
return head ? head->data : 0;
}
void *DeprecatedPtrListImpl::getLast() const
{
return tail ? tail->data : 0;
}
void *DeprecatedPtrListImpl::getNext() const
{
return cur && cur->next ? cur->next->data : 0;
}
void *DeprecatedPtrListImpl::getPrev() const
{
return cur && cur->prev ? cur->prev->data : 0;
}
void *DeprecatedPtrListImpl::current() const
{
if (cur) {
return cur->data;
} else {
return 0;
}
}
void *DeprecatedPtrListImpl::first()
{
cur = head;
return current();
}
void *DeprecatedPtrListImpl::last()
{
cur = tail;
return current();
}
void *DeprecatedPtrListImpl::next()
{
if (cur) {
cur = cur->next;
}
return current();
}
void *DeprecatedPtrListImpl::prev()
{
if (cur) {
cur = cur->prev;
}
return current();
}
void *DeprecatedPtrListImpl::take(unsigned n)
{
void *retval = at(n);
remove(false);
return retval;
}
void *DeprecatedPtrListImpl::take()
{
void *retval = current();
remove(false);
return retval;
}
void DeprecatedPtrListImpl::append(const void *item)
{
insert(nodeCount, item);
}
void DeprecatedPtrListImpl::prepend(const void *item)
{
insert(0, item);
}
unsigned DeprecatedPtrListImpl::containsRef(const void *item) const
{
unsigned count = 0;
for (DeprecatedListNode *node = head; node; node = node->next) {
if (item == node->data) {
++count;
}
}
return count;
}
int DeprecatedPtrListImpl::findRef(const void *item)
{
DeprecatedListNode *node = head;
int index = 0;
while (node && item != node->data) {
node = node->next;
index++;
}
cur = node;
if (node == 0) {
return -1;
}
return index;
}
DeprecatedPtrListImpl &DeprecatedPtrListImpl::assign(const DeprecatedPtrListImpl &impl, bool deleteItems)
{
clear(deleteItems);
DeprecatedPtrListImpl(impl).swap(*this);
return *this;
}
void DeprecatedPtrListImpl::addIterator(DeprecatedPtrListImplIterator *iter) const
{
iter->next = iterators;
iter->prev = 0;
if (iterators) {
iterators->prev = iter;
}
iterators = iter;
}
void DeprecatedPtrListImpl::removeIterator(DeprecatedPtrListImplIterator *iter) const
{
if (iter->prev == 0) {
iterators = iter->next;
} else {
iter->prev->next = iter->next;
}
if (iter->next) {
iter->next->prev = iter->prev;
}
}
void DeprecatedPtrListImpl::swap(DeprecatedPtrListImpl &other)
{
using std::swap;
ASSERT(iterators == 0);
ASSERT(other.iterators == 0);
swap(head, other.head);
swap(tail, other.tail);
swap(cur, other.cur);
swap(nodeCount, other.nodeCount);
swap(deleteItem, other.deleteItem);
}
DeprecatedPtrListImplIterator::DeprecatedPtrListImplIterator() :
list(0),
node(0)
{
}
DeprecatedPtrListImplIterator::DeprecatedPtrListImplIterator(const DeprecatedPtrListImpl &impl) :
list(&impl),
node(impl.head)
{
impl.addIterator(this);
}
DeprecatedPtrListImplIterator::~DeprecatedPtrListImplIterator()
{
if (list) {
list->removeIterator(this);
}
}
DeprecatedPtrListImplIterator::DeprecatedPtrListImplIterator(const DeprecatedPtrListImplIterator &impl) :
list(impl.list),
node(impl.node)
{
if (list) {
list->addIterator(this);
}
}
unsigned DeprecatedPtrListImplIterator::count() const
{
return list == 0 ? 0 : list->count();
}
void *DeprecatedPtrListImplIterator::toFirst()
{
if (list) {
node = list->head;
}
return current();
}
void *DeprecatedPtrListImplIterator::toLast()
{
if (list) {
node = list->tail;
}
return current();
}
void *DeprecatedPtrListImplIterator::current() const
{
return node == 0 ? 0 : node->data;
}
void *DeprecatedPtrListImplIterator::operator--()
{
if (node) {
node = node->prev;
}
return current();
}
void *DeprecatedPtrListImplIterator::operator++()
{
if (node) {
node = node->next;
}
return current();
}
DeprecatedPtrListImplIterator &DeprecatedPtrListImplIterator::operator=(const DeprecatedPtrListImplIterator &impl)
{
if (list) {
list->removeIterator(this);
}
list = impl.list;
node = impl.node;
if (list) {
list->addIterator(this);
}
return *this;
}
}