/* * 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 #include #include 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; } }