blob: fa0998b43f74db714e8acd74b730c00ef1f20a0e [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Matthew Hoyt (mhoyt@ca.ibm.com)
*/
#if !defined(XALANLIST_HEADER_GUARD_1357924680)
#define XALANLIST_HEADER_GUARD_1357924680
// Base include file. Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>
#include <cstddef>
#include <algorithm>
#include <cassert>
#include <new>
#include <iterator>
#include <stdexcept>
#include <xalanc/Include/XalanMemoryManagement.hpp>
XALAN_CPP_NAMESPACE_BEGIN
template <class Value>
struct XalanListIteratorTraits
{
typedef Value value_type;
typedef Value& reference;
typedef Value* pointer;
};
template <class Value>
struct XalanListConstIteratorTraits
{
typedef Value value_type;
typedef const Value& reference;
typedef const Value* pointer;
};
template<class XalanListTraits, class Node>
struct XalanListIteratorBase
{
typedef typename XalanListTraits::value_type value_type;
typedef typename XalanListTraits::reference reference;
typedef typename XalanListTraits::pointer pointer;
typedef ptrdiff_t difference_type;
typedef XALAN_STD_QUALIFIER bidirectional_iterator_tag iterator_category;
typedef XalanListIteratorBase<XalanListIteratorTraits<value_type>, Node> iterator;
XalanListIteratorBase(Node& node) :
currentNode(&node)
{
}
XalanListIteratorBase(const iterator& theRhs) :
currentNode(theRhs.currentNode)
{
}
XalanListIteratorBase operator++()
{
currentNode = currentNode->next;
return *this;
}
XalanListIteratorBase operator++(int)
{
Node& origNode = *currentNode;
currentNode = currentNode->next;
return XalanListIteratorBase(origNode);
}
XalanListIteratorBase operator--()
{
currentNode = currentNode->prev;
return *this;
}
XalanListIteratorBase operator-(difference_type decrement) const
{
Node* node = currentNode;
while (decrement > 0)
{
node = node->prev;
--decrement;
};
return XalanListIteratorBase(*node);
}
reference operator*() const
{
return currentNode->value;
}
pointer operator->() const
{
return &currentNode->value;
}
const XalanListIteratorBase & operator=(const XalanListIteratorBase& theRhs)
{
currentNode = theRhs.currentNode;
return *this;
}
bool operator!=(const XalanListIteratorBase& theRhs) const
{
return !operator==(theRhs);
}
bool operator==(const XalanListIteratorBase& theRhs) const
{
return currentNode == theRhs.currentNode;
}
Node& node()
{
return *currentNode;
}
Node* currentNode;
};
/**
* Xalan implementation of a doubly linked list
*/
template <class Type>
class XalanList
{
public:
typedef Type value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
typedef XalanList<value_type> ThisType;
struct Node
{
Node(
const value_type & theValue,
Node& prevNode,
Node& nextNode) :
value(theValue),
prev(&prevNode),
next(&nextNode)
{
}
value_type value;
Node* prev;
Node* next;
};
typedef XalanListIteratorBase<XalanListIteratorTraits<value_type>, Node> iterator;
typedef XalanListIteratorBase<XalanListConstIteratorTraits<value_type>, Node> const_iterator;
#if defined(XALAN_HAS_STD_ITERATORS)
typedef XALAN_STD_QUALIFIER reverse_iterator<iterator> reverse_iterator_;
typedef XALAN_STD_QUALIFIER reverse_iterator<const_iterator> const_reverse_iterator_;
#elif defined(XALAN_RW_NO_CLASS_PARTIAL_SPEC)
typedef XALAN_STD_QUALIFIER reverse_iterator<
iterator,
XALAN_STD_QUALIFIER bidirectional_iterator_tag,
value_type> reverse_iterator_;
typedef XALAN_STD_QUALIFIER reverse_iterator<
const_iterator,
XALAN_STD_QUALIFIER bidirectional_iterator_tag,
const value_type> const_reverse_iterator_;
#else
typedef XALAN_STD_QUALIFIER reverse_iterator<iterator, value_type> reverse_iterator_;
typedef XALAN_STD_QUALIFIER reverse_iterator<const_iterator, value_type, const_reference> const_reverse_iterator_;
#endif
typedef reverse_iterator_ reverse_iterator;
typedef const_reverse_iterator_ const_reverse_iterator;
typedef typename MemoryManagedConstructionTraits<value_type>::Constructor Constructor;
XalanList(
MemoryManagerType* theManager = 0) :
m_memoryManager(theManager),
m_listHead(0),
m_freeListHeadPtr(0)
{
}
~XalanList()
{
if (m_listHead != 0)
{
iterator pos = begin();
while (pos != end())
{
destroyNode(pos++.node());
}
Node * freeNode = m_freeListHeadPtr;
while (freeNode != 0)
{
Node * nextNode = freeNode->next;
deallocate(freeNode);
freeNode = nextNode;
}
deallocate(m_listHead);
}
}
iterator
begin()
{
return iterator(*(getListHead().next));
}
const_iterator
begin() const
{
return const_iterator(*(getListHead().next));
}
iterator
end()
{
return iterator(getListHead());
}
const_iterator
end() const
{
return const_iterator(getListHead());
}
reverse_iterator
rbegin()
{
return reverse_iterator(end());
}
const_reverse_iterator
rbegin() const
{
return const_reverse_iterator(end());
}
reverse_iterator
rend()
{
return reverse_iterator(begin());
}
const_reverse_iterator
rend() const
{
return const_reverse_iterator(begin());
}
reference
front()
{
return *begin();
}
reference
back()
{
return *(--end());
}
size_type
size() const
{
size_type size = 0;
const_iterator item = begin();
while (item != end())
{
++size;
++item;
}
return size;
}
bool
empty() const
{
return (begin() == end()) != 0;
}
void
push_back(const value_type& data)
{
constructNode(data, end());
}
void
push_front(const value_type& data)
{
constructNode(data, begin());
}
void
pop_front()
{
erase(begin());
}
iterator
insert(const iterator& pos, const value_type& value)
{
return iterator(constructNode(value,pos));
}
void
erase(iterator pos)
{
assert(pos != end());
freeNode(pos.node());
}
void
splice(
iterator pos,
#if defined(NDEBUG)
ThisType& /* list */,
#else
ThisType& list,
#endif
iterator toInsert)
{
assert(m_memoryManager == list.m_memoryManager);
if (pos != toInsert)
{
Node & posNode = pos.node();
Node & toInsertNode = toInsert.node();
toInsertNode.prev->next = toInsertNode.next;
toInsertNode.next->prev = toInsertNode.prev;
toInsertNode.prev = posNode.prev;
toInsertNode.next = &posNode;
posNode.prev->next = &toInsertNode;
posNode.prev = &toInsertNode;
}
}
void
splice(
iterator pos,
#if defined(NDEBUG)
ThisType& /* list */,
#else
ThisType& list,
#endif
iterator toInsertFirst,
iterator toInsertLast)
{
assert(m_memoryManager == list.m_memoryManager);
if (toInsertFirst != toInsertLast)
{
Node & posNode = pos.node();
Node & toInsertFirstNode = toInsertFirst.node();
Node & toInsertLastNode = *(toInsertLast.node().prev);
toInsertFirstNode.prev->next = toInsertLastNode.next;
toInsertLastNode.next->prev = toInsertFirstNode.prev;
toInsertFirstNode.prev = posNode.prev;
toInsertLastNode.next = &posNode;
posNode.prev->next = &toInsertFirstNode;
posNode.prev = &toInsertLastNode;
}
}
void
clear()
{
iterator pos = begin();
while (pos != end())
{
freeNode(pos++.node());
}
}
void swap(ThisType& theRHS)
{
#if defined(XALAN_NO_STD_NAMESPACE)
::swap(m_memoryManager, theRHS.m_memoryManager);
::swap(m_listHead, theRHS.m_listHead);
::swap(m_freeListHeadPtr, theRHS.m_freeListHeadPtr);
#else
XALAN_STD_QUALIFIER swap(m_memoryManager, theRHS.m_memoryManager);
XALAN_STD_QUALIFIER swap(m_listHead, theRHS.m_listHead);
XALAN_STD_QUALIFIER swap(m_freeListHeadPtr, theRHS.m_freeListHeadPtr);
#endif
}
protected:
Node& constructNode(const value_type& data, iterator pos)
{
Node * newNode = 0;
Node * nextFreeNode = 0;
if (m_freeListHeadPtr != 0)
{
newNode = m_freeListHeadPtr;
nextFreeNode = m_freeListHeadPtr->next;
}
else
{
m_freeListHeadPtr = allocate(1);
newNode = m_freeListHeadPtr;
}
Constructor::construct(&newNode->value, data, *m_memoryManager);
new (&newNode->prev) Node*(pos.node().prev);
new (&newNode->next) Node*(&(pos.node()));
pos.node().prev->next = newNode;
pos.node().prev = newNode;
m_freeListHeadPtr = nextFreeNode;
return *newNode;
}
void freeNode(Node& node)
{
node.prev->next = node.next;
node.next->prev = node.prev;
node.~Node();
node.prev = 0;
node.next = m_freeListHeadPtr;
m_freeListHeadPtr = &node;
}
void destroyNode(Node& node)
{
assert(&node != m_listHead);
node.~Node();
deallocate(&node);
}
Node& getListHead()
{
if (0 == m_listHead)
{
m_listHead = allocate(1);
m_listHead->next = m_listHead;
m_listHead->prev = m_listHead;
}
return *m_listHead;
}
Node& getListHead() const
{
return const_cast<XalanList*>(this)->getListHead();
}
Node*
allocate(size_type size)
{
const size_type theBytesNeeded = size * sizeof(Node);
void* pointer = m_memoryManager == 0 ?
::operator new (theBytesNeeded) :
m_memoryManager->allocate(theBytesNeeded);
assert(pointer != 0);
return (Node*) pointer;
}
void
deallocate(Node* pointer)
{
if (m_memoryManager == 0)
{
::operator delete(pointer);
}
else
{
m_memoryManager->deallocate(pointer);
}
}
MemoryManagerType * m_memoryManager;
Node* m_listHead;
Node* m_freeListHeadPtr;
private:
XalanList(const XalanList& theRhs);
XalanList& operator=(const XalanList& theRhs);
};
XALAN_CPP_NAMESPACE_END
#endif // XALANLIST_HEADER_GUARD_1357924680