blob: 66b77ac56e7cfca733acac96fb7fbf88fa11153c [file] [log] [blame]
/*
* Copyright (C) 2001 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 <KWQValueListImpl.h>
#ifndef USING_BORROWED_QVALUELIST
#include <stdlib.h>
KWQValueListNodeImpl::KWQValueListNodeImpl() :
prev(NULL),
next(NULL)
{
}
KWQValueListNodeImpl::~KWQValueListNodeImpl()
{
}
KWQValueListIteratorImpl::KWQValueListIteratorImpl() :
nodeImpl(NULL)
{
}
KWQValueListIteratorImpl::KWQValueListIteratorImpl(const KWQValueListIteratorImpl &other) :
nodeImpl(other.nodeImpl)
{
}
KWQValueListIteratorImpl::~KWQValueListIteratorImpl()
{
}
KWQValueListIteratorImpl &KWQValueListIteratorImpl::operator=(const KWQValueListIteratorImpl &other)
{
nodeImpl = other.nodeImpl;
return *this;
}
bool KWQValueListIteratorImpl::operator==(const KWQValueListIteratorImpl &other)
{
return nodeImpl == other.nodeImpl;
}
bool KWQValueListIteratorImpl::operator!=(const KWQValueListIteratorImpl &other)
{
return nodeImpl != other.nodeImpl;
}
KWQValueListNodeImpl *KWQValueListIteratorImpl::node()
{
return nodeImpl;
}
const KWQValueListNodeImpl *KWQValueListIteratorImpl::node() const
{
return nodeImpl;
}
KWQValueListIteratorImpl& KWQValueListIteratorImpl::operator++()
{
if (nodeImpl != NULL) {
nodeImpl = nodeImpl->next;
}
return *this;
}
KWQValueListIteratorImpl KWQValueListIteratorImpl::operator++(int)
{
KWQValueListIteratorImpl tmp(*this);
if (nodeImpl != NULL) {
nodeImpl = nodeImpl->next;
}
return tmp;
}
KWQValueListIteratorImpl& KWQValueListIteratorImpl::operator--()
{
if (nodeImpl != NULL) {
nodeImpl = nodeImpl->prev;
}
return *this;
}
KWQValueListIteratorImpl::KWQValueListIteratorImpl(const KWQValueListNodeImpl *n) :
nodeImpl((KWQValueListNodeImpl *)n)
{
}
class KWQValueListImpl::KWQValueListPrivate
{
public:
KWQValueListPrivate(void (*deleteFunc)(KWQValueListNodeImpl *), KWQValueListNodeImpl *(*copyFunc)(KWQValueListNodeImpl *));
KWQValueListPrivate(const KWQValueListPrivate &other);
~KWQValueListPrivate();
KWQValueListNodeImpl *copyList(KWQValueListNodeImpl *l) const;
void deleteList(KWQValueListNodeImpl *l);
KWQValueListNodeImpl *head;
void (*deleteNode)(KWQValueListNodeImpl *);
KWQValueListNodeImpl *(*copyNode)(KWQValueListNodeImpl *);
uint count;
uint refCount;
};
KWQValueListImpl::KWQValueListPrivate::KWQValueListPrivate(void (*deleteFunc)(KWQValueListNodeImpl *),
KWQValueListNodeImpl *(*copyFunc)(KWQValueListNodeImpl *)) :
head(NULL),
deleteNode(deleteFunc),
copyNode(copyFunc),
count(0),
refCount(0)
{
}
KWQValueListImpl::KWQValueListPrivate::KWQValueListPrivate(const KWQValueListPrivate &other) :
head(other.copyList(other.head)),
deleteNode(other.deleteNode),
copyNode(other.copyNode),
count(other.count),
refCount(0)
{
}
KWQValueListImpl::KWQValueListPrivate::~KWQValueListPrivate()
{
deleteList(head);
}
KWQValueListNodeImpl *KWQValueListImpl::KWQValueListPrivate::copyList(KWQValueListNodeImpl *l) const
{
KWQValueListNodeImpl *prev = NULL;
KWQValueListNodeImpl *node = l;
KWQValueListNodeImpl *head = NULL;
while (node != NULL) {
KWQValueListNodeImpl *copy = copyNode(node);
if (prev == NULL) {
head = copy;
} else {
prev->next = copy;
}
copy->prev = prev;
copy->next = NULL;
prev = copy;
node = node->next;
}
return head;
}
void KWQValueListImpl::KWQValueListPrivate::deleteList(KWQValueListNodeImpl *l)
{
KWQValueListNodeImpl *p = l;
while (p != NULL) {
KWQValueListNodeImpl *next = p->next;
deleteNode(p);
p = next;
}
}
KWQValueListImpl::KWQValueListImpl(void (*deleteFunc)(KWQValueListNodeImpl *), KWQValueListNodeImpl *(*copyFunc)(KWQValueListNodeImpl *)) :
d(new KWQValueListImpl::KWQValueListPrivate(deleteFunc, copyFunc))
{
}
KWQValueListImpl::KWQValueListImpl(const KWQValueListImpl &other) :
d(other.d)
{
}
KWQValueListImpl::~KWQValueListImpl()
{
}
void KWQValueListImpl::clear()
{
d->deleteList(d->head);
d->head = NULL;
d->count = 0;
}
uint KWQValueListImpl::count() const
{
return d->count;
}
bool KWQValueListImpl::isEmpty() const
{
return d->count == 0;
}
void KWQValueListImpl::appendNode(KWQValueListNodeImpl *node)
{
copyOnWrite();
// FIXME: maintain tail pointer to make this fast
if (d->head == NULL) {
d->head = node;
} else {
KWQValueListNodeImpl *p = d->head;
while (p->next != NULL) {
p = p->next;
}
p->next = node;
node->prev = p;
node->next = NULL;
}
d->count++;
}
void KWQValueListImpl::prependNode(KWQValueListNodeImpl *node)
{
copyOnWrite();
node->next = d->head;
node->prev = NULL;
d->head = node;
if (node->next != NULL) {
node->next->prev = node;
}
d->count++;
}
void KWQValueListImpl::removeEqualNodes(KWQValueListNodeImpl *node, bool (*equalFunc)(const KWQValueListNodeImpl *, const KWQValueListNodeImpl *))
{
copyOnWrite();
KWQValueListNodeImpl *p = d->head;
while (p != NULL) {
KWQValueListNodeImpl *next = p->next;
if (equalFunc(node, p)) {
if (p->next != NULL) {
p->next->prev = p->prev;
}
if (p->prev != NULL) {
p->prev->next = p->next;
} else {
d->head = p->next;
}
d->deleteNode(p);
d->count--;
}
p = next;
}
}
uint KWQValueListImpl::containsEqualNodes(KWQValueListNodeImpl *node, bool (*equalFunc)(const KWQValueListNodeImpl *, const KWQValueListNodeImpl *)) const
{
KWQValueListNodeImpl *p = d->head;
unsigned contains = 0;
while (p != NULL) {
if (equalFunc(node, p)) {
++contains;
}
p = p->next;
}
return contains;
}
KWQValueListIteratorImpl KWQValueListImpl::removeIterator(KWQValueListIteratorImpl &iterator)
{
copyOnWrite();
if (iterator.nodeImpl == NULL) {
return iterator;
}
KWQValueListNodeImpl *next = iterator.nodeImpl->next;
// detach node
if (iterator.nodeImpl->next != NULL) {
iterator.nodeImpl->next->prev = iterator.nodeImpl->prev;
}
if (iterator.nodeImpl->prev != NULL) {
iterator.nodeImpl->prev->next = iterator.nodeImpl->next;
} else {
d->head = iterator.nodeImpl->next;
}
d->deleteNode(iterator.nodeImpl);
d->count--;
return KWQValueListIteratorImpl(next);
}
KWQValueListIteratorImpl KWQValueListImpl::fromLast()
{
return KWQValueListIteratorImpl(lastNode());
}
KWQValueListNodeImpl *KWQValueListImpl::firstNode()
{
copyOnWrite();
return ((const KWQValueListImpl *)this)->firstNode();
}
KWQValueListNodeImpl *KWQValueListImpl::lastNode()
{
copyOnWrite();
return ((const KWQValueListImpl *)this)->lastNode();
}
KWQValueListNodeImpl *KWQValueListImpl::firstNode() const
{
return d->head;
}
KWQValueListNodeImpl *KWQValueListImpl::lastNode() const
{
// FIXME: use tail pointer
KWQValueListNodeImpl *p = d->head;
if (p == NULL) {
return NULL;
}
while (p->next != NULL) {
p = p->next;
}
return p;
}
KWQValueListIteratorImpl KWQValueListImpl::begin()
{
copyOnWrite();
return ((const KWQValueListImpl *)this)->begin();
}
KWQValueListIteratorImpl KWQValueListImpl::end()
{
copyOnWrite();
return ((const KWQValueListImpl *)this)->end();
}
KWQValueListIteratorImpl KWQValueListImpl::begin() const
{
return KWQValueListIteratorImpl(firstNode());
}
KWQValueListIteratorImpl KWQValueListImpl::end() const
{
return KWQValueListIteratorImpl(NULL);
}
KWQValueListNodeImpl *KWQValueListImpl::nodeAt(uint index)
{
copyOnWrite();
if (d->count <= index) {
return NULL;
}
KWQValueListNodeImpl *p = d->head;
for (uint i = 0; i < index; i++) {
p = p->next;
}
return p;
}
KWQValueListNodeImpl *KWQValueListImpl::nodeAt(uint index) const
{
if (d->count <= index) {
return NULL;
}
KWQValueListNodeImpl *p = d->head;
for (uint i = 0; i < index; i++) {
p = p->next;
}
return p;
}
KWQValueListImpl KWQValueListImpl::operator=(const KWQValueListImpl &other)
{
KWQValueListImpl tmp(other);
KWQRefPtr<KWQValueListImpl::KWQValueListPrivate> tmpD = tmp.d;
tmp.d = d;
d = tmpD;
return *this;
}
void KWQValueListImpl::copyOnWrite()
{
if (d->refCount > 1) {
d = KWQRefPtr<KWQValueListImpl::KWQValueListPrivate>(new KWQValueListImpl::KWQValueListPrivate(*d));
}
}
#endif