1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxDList<T> which is a template version of wxList
4 // Author: Robert Roebling
6 // Copyright: (c) 2008 wxWidgets team
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
18 #include "wx/beforestd.h"
22 #include "wx/afterstd.h"
25 class wxDList
: public std::list
<T
*>
29 typedef std::list
<T
*> BaseListType
;
30 typedef wxDList
<T
> ListType
;
33 typedef typename
BaseListType::iterator iterator
;
35 class compatibility_iterator
38 /* Workaround for broken VC6 nested class name resolution */
39 typedef typename
BaseListType::iterator iterator
;
40 friend class wxDList
<T
>;
46 compatibility_iterator()
47 : m_iter(), m_list( NULL
) {}
48 compatibility_iterator( ListType
* li
, iterator i
)
49 : m_iter( i
), m_list( li
) {}
50 compatibility_iterator( const ListType
* li
, iterator i
)
51 : m_iter( i
), m_list( const_cast<ListType
*>(li
) ) {}
53 compatibility_iterator
* operator->() { return this; }
54 const compatibility_iterator
* operator->() const { return this; }
56 bool operator==(const compatibility_iterator
& i
) const
58 wxASSERT_MSG( m_list
&& i
.m_list
,
59 "comparing invalid iterators is illegal" );
60 return (m_list
== i
.m_list
) && (m_iter
== i
.m_iter
);
62 bool operator!=(const compatibility_iterator
& i
) const
63 { return !( operator==( i
) ); }
65 { return m_list
? m_iter
!= m_list
->end() : false; }
66 bool operator !() const
67 { return !( operator bool() ); }
69 T
* GetData() const { return *m_iter
; }
70 void SetData( T
* e
) { *m_iter
= e
; }
72 compatibility_iterator
GetNext() const
75 return compatibility_iterator( m_list
, ++i
);
78 compatibility_iterator
GetPrevious() const
80 if ( m_iter
== m_list
->begin() )
81 return compatibility_iterator();
84 return compatibility_iterator( m_list
, --i
);
89 return *this ? std::distance( m_list
->begin(), m_iter
)
95 wxDList() : m_destroy( false ) {}
97 ~wxDList() { Clear(); }
99 compatibility_iterator
Find( const T
* e
) const
101 return compatibility_iterator( this,
102 std::find( const_cast<ListType
*>(this)->begin(),
103 const_cast<ListType
*>(this)->end(), e
) );
107 { return this->empty(); }
108 size_t GetCount() const
109 { return this->size(); }
111 compatibility_iterator
Item( size_t idx
) const
113 iterator i
= const_cast<ListType
*>(this)->begin();
114 std::advance( i
, idx
);
115 return compatibility_iterator( this, i
);
118 T
* operator[](size_t idx
) const
120 return Item(idx
).GetData();
123 compatibility_iterator
GetFirst() const
125 return compatibility_iterator( this, const_cast<ListType
*>(this)->begin() );
127 compatibility_iterator
GetLast() const
129 iterator i
= const_cast<ListType
*>(this)->end();
130 return compatibility_iterator( this, !(this->empty()) ? --i
: i
);
132 compatibility_iterator
Member( T
* e
) const
133 { return Find( e
); }
134 compatibility_iterator
Nth( int n
) const
135 { return Item( n
); }
136 int IndexOf( T
* e
) const
137 { return Find( e
).IndexOf(); }
139 compatibility_iterator
Append( T
* e
)
141 this->push_back( e
);
145 compatibility_iterator
Insert( T
* e
)
147 this->push_front( e
);
148 return compatibility_iterator( this, this->begin() );
151 compatibility_iterator
Insert( compatibility_iterator
& i
, T
* e
)
153 return compatibility_iterator( this, this->insert( i
.m_iter
, e
) );
156 compatibility_iterator
Insert( size_t idx
, T
* e
)
158 return compatibility_iterator( this,
159 this->insert( Item( idx
).m_iter
, e
) );
162 void DeleteContents( bool destroy
)
163 { m_destroy
= destroy
; }
165 bool GetDeleteContents() const
166 { return m_destroy
; }
168 void Erase( const compatibility_iterator
& i
)
172 this->erase( i
.m_iter
);
175 bool DeleteNode( const compatibility_iterator
& i
)
185 bool DeleteObject( T
* e
)
187 return DeleteNode( Find( e
) );
195 for ( it
= this->begin(), en
= this->end(); it
!= en
; ++it
)
204 template <typename T
>
211 Node(wxDList
<T
> *list
= NULL
,
212 Node
*previous
= NULL
,
217 m_previous
= previous
;
221 previous
->m_next
= this;
223 next
->m_previous
= this;
228 // handle the case when we're being deleted from the list by
229 // the user (i.e. not by the list itself from DeleteNode) -
230 // we must do it for compatibility with old code
232 m_list
->DetachNode(this);
240 Node
*GetNext() const { return m_next
; }
241 Node
*GetPrevious() const { return m_previous
; }
242 T
*GetData() const { return m_data
; }
243 T
**GetDataPtr() const { return &(wx_const_cast(nodetype
*,this)->m_data
); }
244 void SetData( T
*data
) { m_data
= data
; }
248 wxCHECK_MSG( m_list
, wxNOT_FOUND
,
249 "node doesn't belong to a list in IndexOf" );
252 Node
*prev
= m_previous
;
253 for( i
= 0; prev
; i
++ )
254 prev
= prev
->m_previous
;
259 T
*m_data
; // user data
260 Node
*m_next
, // next and previous nodes in the list
262 wxDList
<T
> *m_list
; // list we belong to
264 friend class wxDList
<T
>;
267 typedef Node nodetype
;
269 class compatibility_iterator
272 compatibility_iterator(nodetype
*ptr
= NULL
) : m_ptr(ptr
) { }
273 nodetype
*operator->() const { return m_ptr
; }
274 operator nodetype
*() const { return m_ptr
; }
289 void DoDeleteNode( nodetype
*node
)
293 // so that the node knows that it's being deleted by the list
298 size_t m_count
; // number of elements in the list
299 bool m_destroy
; // destroy user data when deleting list items?
300 nodetype
*m_nodeFirst
, // pointers to the head and tail of the list
309 wxDList( const wxDList
<T
>& list
)
315 wxDList( size_t count
, T
*elements
[] )
319 for (n
= 0; n
< count
; n
++)
320 Append( elements
[n
] );
323 wxDList
& operator=( const wxDList
<T
>& list
)
332 nodetype
*each
= m_nodeFirst
;
333 while ( each
!= NULL
)
335 nodetype
*next
= each
->GetNext();
341 void Assign(const wxDList
<T
> &list
)
343 wxASSERT_MSG( !list
.m_destroy
,
344 "copying list which owns it's elements is a bad idea" );
346 m_destroy
= list
.m_destroy
;
350 for (node
= list
.GetFirst(); node
; node
= node
->GetNext() )
351 Append(node
->GetData());
352 wxASSERT_MSG( m_count
== list
.m_count
, "logic error in Assign()" );
355 nodetype
*Append( T
*object
)
357 nodetype
*node
= new nodetype( this, m_nodeLast
, NULL
, object
);
362 m_nodeLast
= m_nodeFirst
;
366 m_nodeLast
->m_next
= node
;
373 nodetype
*Insert( T
* object
)
375 return Insert( NULL
, object
);
378 nodetype
*Insert( size_t pos
, T
* object
)
381 return Append( object
);
383 return Insert( Item(pos
), object
);
386 nodetype
*Insert( nodetype
*position
, T
* object
)
388 wxCHECK_MSG( !position
|| position
->m_list
== this, NULL
,
389 "can't insert before a node from another list" );
391 // previous and next node for the node being inserted
392 nodetype
*prev
, *next
;
395 prev
= position
->GetPrevious();
400 // inserting in the beginning of the list
404 nodetype
*node
= new nodetype( this, prev
, next
, object
);
413 nodetype
*GetFirst() const { return m_nodeFirst
; }
414 nodetype
*GetLast() const { return m_nodeLast
; }
415 size_t GetCount() const { return m_count
; }
416 bool IsEmpty() const { return m_count
== 0; }
418 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
419 bool GetDeleteContents() const { return m_destroy
; }
421 nodetype
*Item(size_t index
) const
423 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
428 wxFAIL_MSG( "invalid index in Item()" );
432 T
*operator[](size_t index
) const
434 nodetype
*node
= Item(index
);
435 return node
? node
->GetData() : NULL
;
438 nodetype
*DetachNode( nodetype
*node
)
440 wxCHECK_MSG( node
, NULL
, "detaching NULL wxNodeBase" );
441 wxCHECK_MSG( node
->m_list
== this, NULL
,
442 "detaching node which is not from this list" );
444 nodetype
**prevNext
= node
->GetPrevious() ? &node
->GetPrevious()->m_next
446 nodetype
**nextPrev
= node
->GetNext() ? &node
->GetNext()->m_previous
448 *prevNext
= node
->GetNext();
449 *nextPrev
= node
->GetPrevious();
451 // mark the node as not belonging to this list any more
456 void Erase( nodetype
*node
)
461 bool DeleteNode( nodetype
*node
)
463 if ( !DetachNode(node
) )
469 bool DeleteObject( T
*object
)
471 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
473 if ( current
->GetData() == object
)
483 nodetype
*Find(const T
*object
) const
485 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
487 if ( current
->GetData() == object
)
494 int IndexOf(const T
*object
) const
497 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
499 if ( current
->GetData() == object
)
508 nodetype
*current
= m_nodeFirst
;
511 nodetype
*next
= current
->GetNext();
512 DoDeleteNode(current
);
522 nodetype
* node
= m_nodeFirst
;
526 // swap prev and next pointers
528 node
->m_next
= node
->m_previous
;
529 node
->m_previous
= tmp
;
530 // this is the node that was next before swapping
533 // swap first and last node
534 tmp
= m_nodeFirst
; m_nodeFirst
= m_nodeLast
; m_nodeLast
= tmp
;
537 void DeleteNodes(nodetype
* first
, nodetype
* last
)
539 nodetype
* node
= first
;
542 nodetype
* next
= node
->GetNext();
548 void ForEach(wxListIterateFunction F
)
550 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
551 (*F
)(current
->GetData());
554 T
*FirstThat(wxListIterateFunction F
)
556 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
558 if ( (*F
)(current
->GetData()) )
559 return current
->GetData();
564 T
*LastThat(wxListIterateFunction F
)
566 for ( nodetype
*current
= GetLast(); current
; current
= current
->GetPrevious() )
568 if ( (*F
)(current
->GetData()) )
569 return current
->GetData();
576 typedef size_t size_type
;
577 typedef int difference_type
;
578 typedef T
* value_type
;
579 typedef value_type
& reference
;
580 typedef const value_type
& const_reference
;
585 typedef nodetype Node
;
586 typedef iterator itor
;
587 typedef T
* value_type
;
588 typedef value_type
* ptr_type
;
589 typedef value_type
& reference
;
594 typedef reference reference_type
;
595 typedef ptr_type pointer_type
;
597 iterator(Node
* node
, Node
* init
) : m_node(node
), m_init(init
) {}
598 iterator() : m_node(NULL
), m_init(NULL
) { }
599 reference_type
operator*() const
600 { return *m_node
->GetDataPtr(); }
602 itor
& operator++() { m_node
= m_node
->GetNext(); return *this; }
603 const itor
operator++(int)
604 { itor tmp
= *this; m_node
= m_node
->GetNext(); return tmp
; }
607 m_node
= m_node
? m_node
->GetPrevious() : m_init
;
610 const itor
operator--(int)
613 m_node
= m_node
? m_node
->GetPrevious() : m_init
;
616 bool operator!=(const itor
& it
) const
617 { return it
.m_node
!= m_node
; }
618 bool operator==(const itor
& it
) const
619 { return it
.m_node
== m_node
; }
624 typedef nodetype Node
;
625 typedef T
* value_type
;
626 typedef const value_type
& const_reference
;
627 typedef const_iterator itor
;
628 typedef value_type
* ptr_type
;
633 typedef const_reference reference_type
;
634 typedef const ptr_type pointer_type
;
636 const_iterator(Node
* node
, Node
* init
)
637 : m_node(node
), m_init(init
) { }
638 const_iterator() : m_node(NULL
), m_init(NULL
) { }
639 const_iterator(const iterator
& it
)
640 : m_node(it
.m_node
), m_init(it
.m_init
) { }
641 reference_type
operator*() const
642 { return *m_node
->GetDataPtr(); }
644 itor
& operator++() { m_node
= m_node
->GetNext(); return *this; }
645 const itor
operator++(int)
646 { itor tmp
= *this; m_node
= m_node
->GetNext(); return tmp
; }
649 m_node
= m_node
? m_node
->GetPrevious() : m_init
;
652 const itor
operator--(int)
655 m_node
= m_node
? m_node
->GetPrevious() : m_init
;
658 bool operator!=(const itor
& it
) const
659 { return it
.m_node
!= m_node
; }
660 bool operator==(const itor
& it
) const
661 { return it
.m_node
== m_node
; }
664 class reverse_iterator
667 typedef nodetype Node
;
668 typedef T
* value_type
;
669 typedef reverse_iterator itor
;
670 typedef value_type
* ptr_type
;
671 typedef value_type
& reference
;
676 typedef reference reference_type
;
677 typedef ptr_type pointer_type
;
679 reverse_iterator(Node
* node
, Node
* init
)
680 : m_node(node
), m_init(init
) { }
681 reverse_iterator() : m_node(NULL
), m_init(NULL
) { }
682 reference_type
operator*() const
683 { return *m_node
->GetDataPtr(); }
686 { m_node
= m_node
->GetPrevious(); return *this; }
687 const itor
operator++(int)
688 { itor tmp
= *this; m_node
= m_node
->GetPrevious(); return tmp
; }
690 { m_node
= m_node
? m_node
->GetNext() : m_init
; return *this; }
691 const itor
operator--(int)
694 m_node
= m_node
? m_node
->GetNext() : m_init
;
697 bool operator!=(const itor
& it
) const
698 { return it
.m_node
!= m_node
; }
699 bool operator==(const itor
& it
) const
700 { return it
.m_node
== m_node
; }
703 class const_reverse_iterator
706 typedef nodetype Node
;
707 typedef T
* value_type
;
708 typedef const_reverse_iterator itor
;
709 typedef value_type
* ptr_type
;
710 typedef const value_type
& const_reference
;
715 typedef const_reference reference_type
;
716 typedef const ptr_type pointer_type
;
718 const_reverse_iterator(Node
* node
, Node
* init
)
719 : m_node(node
), m_init(init
) { }
720 const_reverse_iterator() : m_node(NULL
), m_init(NULL
) { }
721 const_reverse_iterator(const reverse_iterator
& it
)
722 : m_node(it
.m_node
), m_init(it
.m_init
) { }
723 reference_type
operator*() const
724 { return *m_node
->GetDataPtr(); }
727 { m_node
= m_node
->GetPrevious(); return *this; }
728 const itor
operator++(int)
729 { itor tmp
= *this; m_node
= m_node
->GetPrevious(); return tmp
; }
731 { m_node
= m_node
? m_node
->GetNext() : m_init
; return *this;}
732 const itor
operator--(int)
735 m_node
= m_node
? m_node
->GetNext() : m_init
;
738 bool operator!=(const itor
& it
) const
739 { return it
.m_node
!= m_node
; }
740 bool operator==(const itor
& it
) const
741 { return it
.m_node
== m_node
; }
744 wxEXPLICIT
wxDList(size_type n
, const_reference v
= value_type())
746 wxDList(const const_iterator
& first
, const const_iterator
& last
)
747 { assign(first
, last
); }
748 iterator
begin() { return iterator(GetFirst(), GetLast()); }
749 const_iterator
begin() const
750 { return const_iterator(GetFirst(), GetLast()); }
751 iterator
end() { return iterator(NULL
, GetLast()); }
752 const_iterator
end() const { return const_iterator(NULL
, GetLast()); }
753 reverse_iterator
rbegin()
754 { return reverse_iterator(GetLast(), GetFirst()); }
755 const_reverse_iterator
rbegin() const
756 { return const_reverse_iterator(GetLast(), GetFirst()); }
757 reverse_iterator
rend() { return reverse_iterator(NULL
, GetFirst()); }
758 const_reverse_iterator
rend() const
759 { return const_reverse_iterator(NULL
, GetFirst()); }
760 void resize(size_type n
, value_type v
= value_type())
767 size_type
size() const { return GetCount(); }
768 size_type
max_size() const { return INT_MAX
; }
769 bool empty() const { return IsEmpty(); }
770 reference
front() { return *begin(); }
771 const_reference
front() const { return *begin(); }
772 reference
back() { iterator tmp
= end(); return *--tmp
; }
773 const_reference
back() const { const_iterator tmp
= end(); return *--tmp
; }
774 void push_front(const_reference v
= value_type())
775 { Insert(GetFirst(), v
); }
776 void pop_front() { DeleteNode(GetFirst()); }
777 void push_back(const_reference v
= value_type())
779 void pop_back() { DeleteNode(GetLast()); }
780 void assign(const_iterator first
, const const_iterator
& last
)
783 for(; first
!= last
; ++first
)
786 void assign(size_type n
, const_reference v
= value_type())
789 for(size_type i
= 0; i
< n
; ++i
)
792 iterator
insert(const iterator
& it
, const_reference v
)
801 void insert(const iterator
& it
, size_type n
, const_reference v
)
803 for(size_type i
= 0; i
< n
; ++i
)
804 Insert(it
.m_node
, v
);
806 void insert(const iterator
& it
, const_iterator first
, const const_iterator
& last
)
808 for(; first
!= last
; ++first
)
809 Insert(it
.m_node
, *first
);
811 iterator
erase(const iterator
& it
)
813 iterator next
= iterator(it
.m_node
->GetNext(), GetLast());
814 DeleteNode(it
.m_node
); return next
;
816 iterator
erase(const iterator
& first
, const iterator
& last
)
818 iterator next
= last
; ++next
;
819 DeleteNodes(first
.m_node
, last
.m_node
);
822 void clear() { Clear(); }
823 void splice(const iterator
& it
, wxDList
<T
>& l
, const iterator
& first
, const iterator
& last
)
824 { insert(it
, first
, last
); l
.erase(first
, last
); }
825 void splice(const iterator
& it
, wxDList
<T
>& l
)
826 { splice(it
, l
, l
.begin(), l
.end() ); }
827 void splice(const iterator
& it
, wxDList
<T
>& l
, const iterator
& first
)
829 iterator tmp
= first
; ++tmp
;
830 if(it
== first
|| it
== tmp
) return;
834 void remove(const_reference v
)
838 /* void swap(list<T>& l)
840 { size_t t = m_count; m_count = l.m_count; l.m_count = t; }
841 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }
842 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }
843 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }
844 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }
848 #endif // wxUSE_STL/!wxUSE_STL
850 #endif // _WX_DLIST_H_