2008-09-21 08:44:24 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name: dlist.h
|
|
|
|
// Purpose: wxDList<T> which is a template version of wxList
|
|
|
|
// Author: Robert Roebling
|
|
|
|
// Created: 18.09.2008
|
|
|
|
// Copyright: (c) 2008 wxWidgets team
|
|
|
|
// Licence: wxWindows licence
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#ifndef _WX_DLIST_H_
|
|
|
|
#define _WX_DLIST_H_
|
|
|
|
|
|
|
|
#include "wx/defs.h"
|
|
|
|
#include "wx/utils.h"
|
|
|
|
|
|
|
|
#if wxUSE_STL
|
|
|
|
|
|
|
|
#include "wx/beforestd.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <iterator>
|
|
|
|
#include <list>
|
|
|
|
#include "wx/afterstd.h"
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class wxDList: public std::list<T*>
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
bool m_destroy;
|
|
|
|
typedef std::list<T*> BaseListType;
|
|
|
|
typedef wxDList<T> ListType;
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
public:
|
2008-09-21 10:27:24 +00:00
|
|
|
typedef typename BaseListType::iterator iterator;
|
|
|
|
|
|
|
|
class compatibility_iterator
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
/* Workaround for broken VC6 nested class name resolution */
|
2008-09-21 08:44:24 +00:00
|
|
|
typedef typename BaseListType::iterator iterator;
|
2008-09-21 10:27:24 +00:00
|
|
|
friend class wxDList<T>;
|
|
|
|
|
|
|
|
iterator m_iter;
|
|
|
|
ListType *m_list;
|
|
|
|
|
|
|
|
public:
|
|
|
|
compatibility_iterator()
|
|
|
|
: m_iter(), m_list( NULL ) {}
|
|
|
|
compatibility_iterator( ListType* li, iterator i )
|
|
|
|
: m_iter( i ), m_list( li ) {}
|
|
|
|
compatibility_iterator( const ListType* li, iterator i )
|
|
|
|
: m_iter( i ), m_list( const_cast<ListType*>(li) ) {}
|
|
|
|
|
|
|
|
compatibility_iterator* operator->() { return this; }
|
|
|
|
const compatibility_iterator* operator->() const { return this; }
|
|
|
|
|
|
|
|
bool operator==(const compatibility_iterator& i) const
|
2008-09-21 08:44:24 +00:00
|
|
|
{
|
2008-09-21 10:27:24 +00:00
|
|
|
wxASSERT_MSG( m_list && i.m_list,
|
|
|
|
"comparing invalid iterators is illegal" );
|
|
|
|
return (m_list == i.m_list) && (m_iter == i.m_iter);
|
|
|
|
}
|
|
|
|
bool operator!=(const compatibility_iterator& i) const
|
|
|
|
{ return !( operator==( i ) ); }
|
|
|
|
operator bool() const
|
|
|
|
{ return m_list ? m_iter != m_list->end() : false; }
|
|
|
|
bool operator !() const
|
|
|
|
{ return !( operator bool() ); }
|
|
|
|
|
|
|
|
T* GetData() const { return *m_iter; }
|
|
|
|
void SetData( T* e ) { *m_iter = e; }
|
|
|
|
|
|
|
|
compatibility_iterator GetNext() const
|
|
|
|
{
|
|
|
|
iterator i = m_iter;
|
|
|
|
return compatibility_iterator( m_list, ++i );
|
|
|
|
}
|
|
|
|
|
|
|
|
compatibility_iterator GetPrevious() const
|
|
|
|
{
|
|
|
|
if ( m_iter == m_list->begin() )
|
|
|
|
return compatibility_iterator();
|
|
|
|
|
|
|
|
iterator i = m_iter;
|
|
|
|
return compatibility_iterator( m_list, --i );
|
|
|
|
}
|
|
|
|
|
|
|
|
int IndexOf() const
|
|
|
|
{
|
|
|
|
return *this ? std::distance( m_list->begin(), m_iter )
|
|
|
|
: wxNOT_FOUND;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
wxDList() : m_destroy( false ) {}
|
|
|
|
|
|
|
|
~wxDList() { Clear(); }
|
|
|
|
|
|
|
|
compatibility_iterator Find( const T* e ) const
|
|
|
|
{
|
|
|
|
return compatibility_iterator( this,
|
|
|
|
std::find( const_cast<ListType*>(this)->begin(),
|
|
|
|
const_cast<ListType*>(this)->end(), e ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsEmpty() const
|
|
|
|
{ return this->empty(); }
|
|
|
|
size_t GetCount() const
|
|
|
|
{ return this->size(); }
|
|
|
|
|
|
|
|
compatibility_iterator Item( size_t idx ) const
|
|
|
|
{
|
|
|
|
iterator i = const_cast<ListType*>(this)->begin();
|
|
|
|
std::advance( i, idx );
|
|
|
|
return compatibility_iterator( this, i );
|
|
|
|
}
|
|
|
|
|
|
|
|
T* operator[](size_t idx) const
|
|
|
|
{
|
|
|
|
return Item(idx).GetData();
|
|
|
|
}
|
|
|
|
|
|
|
|
compatibility_iterator GetFirst() const
|
|
|
|
{
|
|
|
|
return compatibility_iterator( this, const_cast<ListType*>(this)->begin() );
|
|
|
|
}
|
|
|
|
compatibility_iterator GetLast() const
|
|
|
|
{
|
|
|
|
iterator i = const_cast<ListType*>(this)->end();
|
|
|
|
return compatibility_iterator( this, !(this->empty()) ? --i : i );
|
|
|
|
}
|
|
|
|
compatibility_iterator Member( T* e ) const
|
|
|
|
{ return Find( e ); }
|
|
|
|
compatibility_iterator Nth( int n ) const
|
|
|
|
{ return Item( n ); }
|
|
|
|
int IndexOf( T* e ) const
|
|
|
|
{ return Find( e ).IndexOf(); }
|
|
|
|
|
|
|
|
compatibility_iterator Append( T* e )
|
|
|
|
{
|
|
|
|
this->push_back( e );
|
|
|
|
return GetLast();
|
|
|
|
}
|
|
|
|
|
|
|
|
compatibility_iterator Insert( T* e )
|
|
|
|
{
|
|
|
|
this->push_front( e );
|
|
|
|
return compatibility_iterator( this, this->begin() );
|
|
|
|
}
|
|
|
|
|
|
|
|
compatibility_iterator Insert( compatibility_iterator & i, T* e )
|
|
|
|
{
|
|
|
|
return compatibility_iterator( this, this->insert( i.m_iter, e ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
compatibility_iterator Insert( size_t idx, T* e )
|
|
|
|
{
|
|
|
|
return compatibility_iterator( this,
|
|
|
|
this->insert( Item( idx ).m_iter, e ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeleteContents( bool destroy )
|
|
|
|
{ m_destroy = destroy; }
|
|
|
|
|
|
|
|
bool GetDeleteContents() const
|
|
|
|
{ return m_destroy; }
|
|
|
|
|
|
|
|
void Erase( const compatibility_iterator& i )
|
|
|
|
{
|
|
|
|
if ( m_destroy )
|
|
|
|
delete i->GetData();
|
|
|
|
this->erase( i.m_iter );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeleteNode( const compatibility_iterator& i )
|
|
|
|
{
|
|
|
|
if( i )
|
|
|
|
{
|
|
|
|
Erase( i );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeleteObject( T* e )
|
|
|
|
{
|
|
|
|
return DeleteNode( Find( e ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Clear()
|
|
|
|
{
|
|
|
|
if ( m_destroy )
|
|
|
|
{
|
|
|
|
iterator it, en;
|
|
|
|
for ( it = this->begin(), en = this->end(); it != en; ++it )
|
|
|
|
delete *it;
|
|
|
|
}
|
|
|
|
this->clear();
|
|
|
|
}
|
2008-09-21 08:44:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#else // STL
|
2008-09-21 10:27:24 +00:00
|
|
|
|
|
|
|
template <typename T>
|
2008-09-21 08:44:24 +00:00
|
|
|
class wxDList
|
|
|
|
{
|
2008-09-21 10:27:24 +00:00
|
|
|
public:
|
2008-09-21 08:44:24 +00:00
|
|
|
class Node
|
|
|
|
{
|
|
|
|
public:
|
2008-09-21 10:27:24 +00:00
|
|
|
Node(wxDList<T> *list = NULL,
|
|
|
|
Node *previous = NULL,
|
|
|
|
Node *next = NULL,
|
|
|
|
T *data = NULL)
|
2008-09-21 08:44:24 +00:00
|
|
|
{
|
|
|
|
m_list = list;
|
|
|
|
m_previous = previous;
|
|
|
|
m_next = next;
|
|
|
|
m_data = data;
|
|
|
|
if (previous)
|
|
|
|
previous->m_next = this;
|
|
|
|
if (next)
|
|
|
|
next->m_previous = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~Node()
|
|
|
|
{
|
|
|
|
// handle the case when we're being deleted from the list by
|
2008-09-21 10:27:24 +00:00
|
|
|
// the user (i.e. not by the list itself from DeleteNode) -
|
2008-09-21 08:44:24 +00:00
|
|
|
// we must do it for compatibility with old code
|
|
|
|
if (m_list != NULL)
|
|
|
|
m_list->DetachNode(this);
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
void DeleteData()
|
|
|
|
{
|
|
|
|
delete m_data;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
Node *GetNext() const { return m_next; }
|
|
|
|
Node *GetPrevious() const { return m_previous; }
|
|
|
|
T *GetData() const { return m_data; }
|
|
|
|
T **GetDataPtr() const { return &(wx_const_cast(nodetype*,this)->m_data); }
|
|
|
|
void SetData( T *data ) { m_data = data; }
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
int IndexOf() const
|
|
|
|
{
|
2008-09-21 10:27:24 +00:00
|
|
|
wxCHECK_MSG( m_list, wxNOT_FOUND,
|
|
|
|
"node doesn't belong to a list in IndexOf" );
|
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
int i;
|
|
|
|
Node *prev = m_previous;
|
|
|
|
for( i = 0; prev; i++ )
|
|
|
|
prev = prev->m_previous;
|
|
|
|
return i;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
private:
|
|
|
|
T *m_data; // user data
|
|
|
|
Node *m_next, // next and previous nodes in the list
|
|
|
|
*m_previous;
|
|
|
|
wxDList<T> *m_list; // list we belong to
|
2008-09-21 10:27:24 +00:00
|
|
|
|
|
|
|
friend class wxDList<T>;
|
2008-09-21 08:44:24 +00:00
|
|
|
};
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
typedef Node nodetype;
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
class compatibility_iterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
compatibility_iterator(nodetype *ptr = NULL) : m_ptr(ptr) { }
|
|
|
|
nodetype *operator->() const { return m_ptr; }
|
|
|
|
operator nodetype *() const { return m_ptr; }
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
private:
|
|
|
|
nodetype *m_ptr;
|
2008-09-21 10:27:24 +00:00
|
|
|
};
|
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
private:
|
|
|
|
void Init()
|
|
|
|
{
|
|
|
|
m_nodeFirst =
|
|
|
|
m_nodeLast = NULL;
|
|
|
|
m_count = 0;
|
|
|
|
m_destroy = false;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
void DoDeleteNode( nodetype *node )
|
|
|
|
{
|
|
|
|
if ( m_destroy )
|
|
|
|
node->DeleteData();
|
|
|
|
// so that the node knows that it's being deleted by the list
|
|
|
|
node->m_list = NULL;
|
|
|
|
delete node;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t m_count; // number of elements in the list
|
|
|
|
bool m_destroy; // destroy user data when deleting list items?
|
|
|
|
nodetype *m_nodeFirst, // pointers to the head and tail of the list
|
|
|
|
*m_nodeLast;
|
2008-09-21 10:27:24 +00:00
|
|
|
|
|
|
|
public:
|
2008-09-21 08:44:24 +00:00
|
|
|
wxDList()
|
|
|
|
{
|
|
|
|
Init();
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
wxDList( const wxDList<T>& list )
|
2008-09-21 10:27:24 +00:00
|
|
|
{
|
2008-09-21 08:44:24 +00:00
|
|
|
Init();
|
2008-09-21 10:27:24 +00:00
|
|
|
Assign(list);
|
2008-09-21 08:44:24 +00:00
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
wxDList( size_t count, T *elements[] )
|
|
|
|
{
|
|
|
|
Init();
|
|
|
|
size_t n;
|
|
|
|
for (n = 0; n < count; n++)
|
|
|
|
Append( elements[n] );
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
wxDList& operator=( const wxDList<T>& list )
|
2008-09-21 10:27:24 +00:00
|
|
|
{
|
|
|
|
if (&list != this)
|
|
|
|
Assign(list);
|
2008-09-21 08:44:24 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
~wxDList()
|
|
|
|
{
|
|
|
|
nodetype *each = m_nodeFirst;
|
|
|
|
while ( each != NULL )
|
|
|
|
{
|
|
|
|
nodetype *next = each->GetNext();
|
|
|
|
DoDeleteNode(each);
|
|
|
|
each = next;
|
|
|
|
}
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
void Assign(const wxDList<T> &list)
|
|
|
|
{
|
|
|
|
wxASSERT_MSG( !list.m_destroy,
|
2008-09-21 10:27:24 +00:00
|
|
|
"copying list which owns it's elements is a bad idea" );
|
2008-09-21 08:44:24 +00:00
|
|
|
Clear();
|
|
|
|
m_destroy = list.m_destroy;
|
|
|
|
m_nodeFirst = NULL;
|
|
|
|
m_nodeLast = NULL;
|
|
|
|
nodetype* node;
|
|
|
|
for (node = list.GetFirst(); node; node = node->GetNext() )
|
|
|
|
Append(node->GetData());
|
2008-09-21 10:27:24 +00:00
|
|
|
wxASSERT_MSG( m_count == list.m_count, "logic error in Assign()" );
|
2008-09-21 08:44:24 +00:00
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
nodetype *Append( T *object )
|
|
|
|
{
|
|
|
|
nodetype *node = new nodetype( this, m_nodeLast, NULL, object );
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
if ( !m_nodeFirst )
|
|
|
|
{
|
|
|
|
m_nodeFirst = node;
|
|
|
|
m_nodeLast = m_nodeFirst;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_nodeLast->m_next = node;
|
|
|
|
m_nodeLast = node;
|
|
|
|
}
|
|
|
|
m_count++;
|
|
|
|
return node;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
nodetype *Insert( T* object )
|
2008-09-21 10:27:24 +00:00
|
|
|
{
|
2008-09-21 08:44:24 +00:00
|
|
|
return Insert( NULL, object );
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
nodetype *Insert( size_t pos, T* object )
|
|
|
|
{
|
|
|
|
if (pos == m_count)
|
|
|
|
return Append( object );
|
|
|
|
else
|
|
|
|
return Insert( Item(pos), object );
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
nodetype *Insert( nodetype *position, T* object )
|
|
|
|
{
|
|
|
|
wxCHECK_MSG( !position || position->m_list == this, NULL,
|
2008-09-21 10:27:24 +00:00
|
|
|
"can't insert before a node from another list" );
|
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
// previous and next node for the node being inserted
|
|
|
|
nodetype *prev, *next;
|
|
|
|
if ( position )
|
|
|
|
{
|
|
|
|
prev = position->GetPrevious();
|
|
|
|
next = position;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// inserting in the beginning of the list
|
|
|
|
prev = NULL;
|
|
|
|
next = m_nodeFirst;
|
|
|
|
}
|
|
|
|
nodetype *node = new nodetype( this, prev, next, object );
|
|
|
|
if ( !m_nodeFirst )
|
|
|
|
m_nodeLast = node;
|
|
|
|
if ( prev == NULL )
|
|
|
|
m_nodeFirst = node;
|
|
|
|
m_count++;
|
|
|
|
return node;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
|
|
|
nodetype *GetFirst() const { return m_nodeFirst; }
|
|
|
|
nodetype *GetLast() const { return m_nodeLast; }
|
|
|
|
size_t GetCount() const { return m_count; }
|
|
|
|
bool IsEmpty() const { return m_count == 0; }
|
|
|
|
|
|
|
|
void DeleteContents(bool destroy) { m_destroy = destroy; }
|
|
|
|
bool GetDeleteContents() const { return m_destroy; }
|
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
nodetype *Item(size_t index) const
|
2008-09-21 10:27:24 +00:00
|
|
|
{
|
2008-09-21 08:44:24 +00:00
|
|
|
for ( nodetype *current = GetFirst(); current; current = current->GetNext() )
|
|
|
|
{
|
|
|
|
if ( index-- == 0 )
|
|
|
|
return current;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
wxFAIL_MSG( "invalid index in Item()" );
|
2008-09-21 08:44:24 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
|
|
|
T *operator[](size_t index) const
|
|
|
|
{
|
|
|
|
nodetype *node = Item(index);
|
2008-09-21 08:44:24 +00:00
|
|
|
return node ? node->GetData() : NULL;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
nodetype *DetachNode( nodetype *node )
|
|
|
|
{
|
2008-09-21 10:27:24 +00:00
|
|
|
wxCHECK_MSG( node, NULL, "detaching NULL wxNodeBase" );
|
2008-09-21 08:44:24 +00:00
|
|
|
wxCHECK_MSG( node->m_list == this, NULL,
|
2008-09-21 10:27:24 +00:00
|
|
|
"detaching node which is not from this list" );
|
2008-09-21 08:44:24 +00:00
|
|
|
// update the list
|
|
|
|
nodetype **prevNext = node->GetPrevious() ? &node->GetPrevious()->m_next
|
|
|
|
: &m_nodeFirst;
|
|
|
|
nodetype **nextPrev = node->GetNext() ? &node->GetNext()->m_previous
|
|
|
|
: &m_nodeLast;
|
|
|
|
*prevNext = node->GetNext();
|
|
|
|
*nextPrev = node->GetPrevious();
|
|
|
|
m_count--;
|
|
|
|
// mark the node as not belonging to this list any more
|
|
|
|
node->m_list = NULL;
|
|
|
|
return node;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
void Erase( nodetype *node )
|
2008-09-21 10:27:24 +00:00
|
|
|
{
|
2008-09-21 08:44:24 +00:00
|
|
|
DeleteNode(node);
|
2008-09-21 10:27:24 +00:00
|
|
|
}
|
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
bool DeleteNode( nodetype *node )
|
|
|
|
{
|
|
|
|
if ( !DetachNode(node) )
|
|
|
|
return false;
|
|
|
|
DoDeleteNode(node);
|
|
|
|
return true;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
bool DeleteObject( T *object )
|
|
|
|
{
|
|
|
|
for ( nodetype *current = GetFirst(); current; current = current->GetNext() )
|
|
|
|
{
|
|
|
|
if ( current->GetData() == object )
|
|
|
|
{
|
|
|
|
DeleteNode(current);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// not found
|
|
|
|
return false;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
nodetype *Find(const T *object) const
|
|
|
|
{
|
|
|
|
for ( nodetype *current = GetFirst(); current; current = current->GetNext() )
|
|
|
|
{
|
|
|
|
if ( current->GetData() == object )
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
// not found
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
int IndexOf(const T *object) const
|
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
for ( nodetype *current = GetFirst(); current; current = current->GetNext() )
|
|
|
|
{
|
|
|
|
if ( current->GetData() == object )
|
|
|
|
return n;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
return wxNOT_FOUND;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
void Clear()
|
|
|
|
{
|
|
|
|
nodetype *current = m_nodeFirst;
|
|
|
|
while ( current )
|
|
|
|
{
|
|
|
|
nodetype *next = current->GetNext();
|
|
|
|
DoDeleteNode(current);
|
|
|
|
current = next;
|
|
|
|
}
|
|
|
|
m_nodeFirst =
|
|
|
|
m_nodeLast = NULL;
|
|
|
|
m_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Reverse()
|
|
|
|
{
|
|
|
|
nodetype * node = m_nodeFirst;
|
|
|
|
nodetype* tmp;
|
|
|
|
while (node)
|
|
|
|
{
|
|
|
|
// swap prev and next pointers
|
|
|
|
tmp = node->m_next;
|
|
|
|
node->m_next = node->m_previous;
|
|
|
|
node->m_previous = tmp;
|
|
|
|
// this is the node that was next before swapping
|
|
|
|
node = tmp;
|
|
|
|
}
|
|
|
|
// swap first and last node
|
|
|
|
tmp = m_nodeFirst; m_nodeFirst = m_nodeLast; m_nodeLast = tmp;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
2008-09-21 08:44:24 +00:00
|
|
|
void DeleteNodes(nodetype* first, nodetype* last)
|
|
|
|
{
|
|
|
|
nodetype * node = first;
|
|
|
|
while (node != last)
|
|
|
|
{
|
|
|
|
nodetype* next = node->GetNext();
|
|
|
|
DeleteNode(node);
|
|
|
|
node = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ForEach(wxListIterateFunction F)
|
|
|
|
{
|
|
|
|
for ( nodetype *current = GetFirst(); current; current = current->GetNext() )
|
|
|
|
(*F)(current->GetData());
|
|
|
|
}
|
|
|
|
|
|
|
|
T *FirstThat(wxListIterateFunction F)
|
|
|
|
{
|
|
|
|
for ( nodetype *current = GetFirst(); current; current = current->GetNext() )
|
|
|
|
{
|
|
|
|
if ( (*F)(current->GetData()) )
|
|
|
|
return current->GetData();
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
T *LastThat(wxListIterateFunction F)
|
|
|
|
{
|
|
|
|
for ( nodetype *current = GetLast(); current; current = current->GetPrevious() )
|
|
|
|
{
|
|
|
|
if ( (*F)(current->GetData()) )
|
|
|
|
return current->GetData();
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-21 10:27:24 +00:00
|
|
|
|
|
|
|
/* STL interface */
|
|
|
|
public:
|
|
|
|
typedef size_t size_type;
|
|
|
|
typedef int difference_type;
|
|
|
|
typedef T* value_type;
|
|
|
|
typedef value_type& reference;
|
|
|
|
typedef const value_type& const_reference;
|
|
|
|
|
|
|
|
class iterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef nodetype Node;
|
|
|
|
typedef iterator itor;
|
|
|
|
typedef T* value_type;
|
|
|
|
typedef value_type* ptr_type;
|
|
|
|
typedef value_type& reference;
|
|
|
|
|
|
|
|
Node* m_node;
|
|
|
|
Node* m_init;
|
|
|
|
public:
|
|
|
|
typedef reference reference_type;
|
|
|
|
typedef ptr_type pointer_type;
|
|
|
|
|
|
|
|
iterator(Node* node, Node* init) : m_node(node), m_init(init) {}
|
|
|
|
iterator() : m_node(NULL), m_init(NULL) { }
|
|
|
|
reference_type operator*() const
|
|
|
|
{ return *m_node->GetDataPtr(); }
|
|
|
|
// ptrop
|
|
|
|
itor& operator++() { m_node = m_node->GetNext(); return *this; }
|
|
|
|
const itor operator++(int)
|
|
|
|
{ itor tmp = *this; m_node = m_node->GetNext(); return tmp; }
|
|
|
|
itor& operator--()
|
|
|
|
{
|
|
|
|
m_node = m_node ? m_node->GetPrevious() : m_init;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
const itor operator--(int)
|
|
|
|
{
|
|
|
|
itor tmp = *this;
|
|
|
|
m_node = m_node ? m_node->GetPrevious() : m_init;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
bool operator!=(const itor& it) const
|
|
|
|
{ return it.m_node != m_node; }
|
|
|
|
bool operator==(const itor& it) const
|
|
|
|
{ return it.m_node == m_node; }
|
|
|
|
};
|
|
|
|
class const_iterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef nodetype Node;
|
|
|
|
typedef T* value_type;
|
|
|
|
typedef const value_type& const_reference;
|
|
|
|
typedef const_iterator itor;
|
|
|
|
typedef value_type* ptr_type;
|
|
|
|
|
|
|
|
Node* m_node;
|
|
|
|
Node* m_init;
|
|
|
|
public:
|
|
|
|
typedef const_reference reference_type;
|
|
|
|
typedef const ptr_type pointer_type;
|
|
|
|
|
|
|
|
const_iterator(Node* node, Node* init)
|
|
|
|
: m_node(node), m_init(init) { }
|
|
|
|
const_iterator() : m_node(NULL), m_init(NULL) { }
|
|
|
|
const_iterator(const iterator& it)
|
|
|
|
: m_node(it.m_node), m_init(it.m_init) { }
|
|
|
|
reference_type operator*() const
|
|
|
|
{ return *m_node->GetDataPtr(); }
|
|
|
|
// ptrop
|
|
|
|
itor& operator++() { m_node = m_node->GetNext(); return *this; }
|
|
|
|
const itor operator++(int)
|
|
|
|
{ itor tmp = *this; m_node = m_node->GetNext(); return tmp; }
|
|
|
|
itor& operator--()
|
|
|
|
{
|
|
|
|
m_node = m_node ? m_node->GetPrevious() : m_init;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
const itor operator--(int)
|
|
|
|
{
|
|
|
|
itor tmp = *this;
|
|
|
|
m_node = m_node ? m_node->GetPrevious() : m_init;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
bool operator!=(const itor& it) const
|
|
|
|
{ return it.m_node != m_node; }
|
|
|
|
bool operator==(const itor& it) const
|
|
|
|
{ return it.m_node == m_node; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class reverse_iterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef nodetype Node;
|
|
|
|
typedef T* value_type;
|
|
|
|
typedef reverse_iterator itor;
|
|
|
|
typedef value_type* ptr_type;
|
|
|
|
typedef value_type& reference;
|
|
|
|
|
|
|
|
Node* m_node;
|
|
|
|
Node* m_init;
|
|
|
|
public:
|
|
|
|
typedef reference reference_type;
|
|
|
|
typedef ptr_type pointer_type;
|
|
|
|
|
|
|
|
reverse_iterator(Node* node, Node* init)
|
|
|
|
: m_node(node), m_init(init) { }
|
|
|
|
reverse_iterator() : m_node(NULL), m_init(NULL) { }
|
|
|
|
reference_type operator*() const
|
|
|
|
{ return *m_node->GetDataPtr(); }
|
|
|
|
// ptrop
|
|
|
|
itor& operator++()
|
|
|
|
{ m_node = m_node->GetPrevious(); return *this; }
|
|
|
|
const itor operator++(int)
|
|
|
|
{ itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }
|
|
|
|
itor& operator--()
|
|
|
|
{ m_node = m_node ? m_node->GetNext() : m_init; return *this; }
|
|
|
|
const itor operator--(int)
|
|
|
|
{
|
|
|
|
itor tmp = *this;
|
|
|
|
m_node = m_node ? m_node->GetNext() : m_init;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
bool operator!=(const itor& it) const
|
|
|
|
{ return it.m_node != m_node; }
|
|
|
|
bool operator==(const itor& it) const
|
|
|
|
{ return it.m_node == m_node; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class const_reverse_iterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef nodetype Node;
|
|
|
|
typedef T* value_type;
|
|
|
|
typedef const_reverse_iterator itor;
|
|
|
|
typedef value_type* ptr_type;
|
|
|
|
typedef const value_type& const_reference;
|
|
|
|
|
|
|
|
Node* m_node;
|
|
|
|
Node* m_init;
|
|
|
|
public:
|
|
|
|
typedef const_reference reference_type;
|
|
|
|
typedef const ptr_type pointer_type;
|
|
|
|
|
|
|
|
const_reverse_iterator(Node* node, Node* init)
|
|
|
|
: m_node(node), m_init(init) { }
|
|
|
|
const_reverse_iterator() : m_node(NULL), m_init(NULL) { }
|
|
|
|
const_reverse_iterator(const reverse_iterator& it)
|
|
|
|
: m_node(it.m_node), m_init(it.m_init) { }
|
|
|
|
reference_type operator*() const
|
|
|
|
{ return *m_node->GetDataPtr(); }
|
|
|
|
// ptrop
|
|
|
|
itor& operator++()
|
|
|
|
{ m_node = m_node->GetPrevious(); return *this; }
|
|
|
|
const itor operator++(int)
|
|
|
|
{ itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }
|
|
|
|
itor& operator--()
|
|
|
|
{ m_node = m_node ? m_node->GetNext() : m_init; return *this;}
|
|
|
|
const itor operator--(int)
|
|
|
|
{
|
|
|
|
itor tmp = *this;
|
|
|
|
m_node = m_node ? m_node->GetNext() : m_init;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
bool operator!=(const itor& it) const
|
|
|
|
{ return it.m_node != m_node; }
|
|
|
|
bool operator==(const itor& it) const
|
|
|
|
{ return it.m_node == m_node; }
|
|
|
|
};
|
|
|
|
|
|
|
|
wxEXPLICIT wxDList(size_type n, const_reference v = value_type())
|
|
|
|
{ assign(n, v); }
|
|
|
|
wxDList(const const_iterator& first, const const_iterator& last)
|
|
|
|
{ assign(first, last); }
|
|
|
|
iterator begin() { return iterator(GetFirst(), GetLast()); }
|
|
|
|
const_iterator begin() const
|
|
|
|
{ return const_iterator(GetFirst(), GetLast()); }
|
|
|
|
iterator end() { return iterator(NULL, GetLast()); }
|
|
|
|
const_iterator end() const { return const_iterator(NULL, GetLast()); }
|
|
|
|
reverse_iterator rbegin()
|
|
|
|
{ return reverse_iterator(GetLast(), GetFirst()); }
|
|
|
|
const_reverse_iterator rbegin() const
|
|
|
|
{ return const_reverse_iterator(GetLast(), GetFirst()); }
|
|
|
|
reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }
|
|
|
|
const_reverse_iterator rend() const
|
|
|
|
{ return const_reverse_iterator(NULL, GetFirst()); }
|
|
|
|
void resize(size_type n, value_type v = value_type())
|
|
|
|
{
|
|
|
|
while (n < size())
|
|
|
|
pop_back();
|
|
|
|
while (n > size())
|
|
|
|
push_back(v);
|
|
|
|
}
|
|
|
|
size_type size() const { return GetCount(); }
|
|
|
|
size_type max_size() const { return INT_MAX; }
|
|
|
|
bool empty() const { return IsEmpty(); }
|
|
|
|
reference front() { return *begin(); }
|
|
|
|
const_reference front() const { return *begin(); }
|
|
|
|
reference back() { iterator tmp = end(); return *--tmp; }
|
|
|
|
const_reference back() const { const_iterator tmp = end(); return *--tmp; }
|
|
|
|
void push_front(const_reference v = value_type())
|
|
|
|
{ Insert(GetFirst(), v); }
|
|
|
|
void pop_front() { DeleteNode(GetFirst()); }
|
|
|
|
void push_back(const_reference v = value_type())
|
|
|
|
{ Append( v ); }
|
|
|
|
void pop_back() { DeleteNode(GetLast()); }
|
|
|
|
void assign(const_iterator first, const const_iterator& last)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
for(; first != last; ++first)
|
|
|
|
Append(*first);
|
|
|
|
}
|
|
|
|
void assign(size_type n, const_reference v = value_type())
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
for(size_type i = 0; i < n; ++i)
|
|
|
|
Append(v);
|
|
|
|
}
|
2008-10-14 09:43:53 +00:00
|
|
|
iterator insert(const iterator& it, const_reference v)
|
2008-09-21 10:27:24 +00:00
|
|
|
{
|
2008-10-14 09:43:53 +00:00
|
|
|
if (it == end())
|
|
|
|
Append( v );
|
|
|
|
else
|
|
|
|
Insert(it.m_node,v);
|
2008-09-21 10:27:24 +00:00
|
|
|
iterator itprev(it);
|
|
|
|
return itprev--;
|
|
|
|
}
|
2008-10-14 09:43:53 +00:00
|
|
|
void insert(const iterator& it, size_type n, const_reference v)
|
2008-09-21 10:27:24 +00:00
|
|
|
{
|
|
|
|
for(size_type i = 0; i < n; ++i)
|
|
|
|
Insert(it.m_node, v);
|
|
|
|
}
|
|
|
|
void insert(const iterator& it, const_iterator first, const const_iterator& last)
|
|
|
|
{
|
|
|
|
for(; first != last; ++first)
|
|
|
|
Insert(it.m_node, *first);
|
|
|
|
}
|
|
|
|
iterator erase(const iterator& it)
|
|
|
|
{
|
|
|
|
iterator next = iterator(it.m_node->GetNext(), GetLast());
|
|
|
|
DeleteNode(it.m_node); return next;
|
|
|
|
}
|
|
|
|
iterator erase(const iterator& first, const iterator& last)
|
|
|
|
{
|
|
|
|
iterator next = last; ++next;
|
|
|
|
DeleteNodes(first.m_node, last.m_node);
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
void clear() { Clear(); }
|
|
|
|
void splice(const iterator& it, wxDList<T>& l, const iterator& first, const iterator& last)
|
|
|
|
{ insert(it, first, last); l.erase(first, last); }
|
|
|
|
void splice(const iterator& it, wxDList<T>& l)
|
|
|
|
{ splice(it, l, l.begin(), l.end() ); }
|
|
|
|
void splice(const iterator& it, wxDList<T>& l, const iterator& first)
|
|
|
|
{
|
|
|
|
iterator tmp = first; ++tmp;
|
|
|
|
if(it == first || it == tmp) return;
|
|
|
|
insert(it, *first);
|
|
|
|
l.erase(first);
|
|
|
|
}
|
|
|
|
void remove(const_reference v)
|
|
|
|
{ DeleteObject(v); }
|
|
|
|
void reverse()
|
|
|
|
{ Reverse(); }
|
|
|
|
/* void swap(list<T>& l)
|
|
|
|
{
|
|
|
|
{ size_t t = m_count; m_count = l.m_count; l.m_count = t; }
|
|
|
|
{ bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }
|
|
|
|
{ wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }
|
|
|
|
{ wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }
|
|
|
|
{ wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }
|
|
|
|
} */
|
2008-09-21 08:44:24 +00:00
|
|
|
};
|
|
|
|
|
2008-09-21 10:27:24 +00:00
|
|
|
#endif // wxUSE_STL/!wxUSE_STL
|
2008-09-21 08:44:24 +00:00
|
|
|
|
|
|
|
#endif // _WX_DLIST_H_
|