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 wxT("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() ); }
74 compatibility_iterator
GetNext() const
77 return compatibility_iterator( m_list
, ++i
);
79 compatibility_iterator
GetPrevious() const
81 if ( m_iter
== m_list
->begin() )
82 return compatibility_iterator();
85 return compatibility_iterator( m_list
, --i
);
89 return *this ? std::distance( m_list
->begin(), m_iter
)
94 wxDList() : m_destroy( false ) {}
96 ~wxDList() { Clear(); }
98 compatibility_iterator
Find( const T
* e
) const
100 return compatibility_iterator( this,
101 std::find( const_cast<ListType
*>(this)->begin(), const_cast<ListType
*>(this)->end(), e
) );
105 { return this->empty(); }
106 size_t GetCount() const
107 { return this->size(); }
109 compatibility_iterator
Item( size_t idx
) const
111 iterator i
= const_cast<ListType
*>(this)->begin();
112 std::advance( i
, idx
);
113 return compatibility_iterator( this, i
);
115 T
* operator[](size_t idx
) const
117 return Item(idx
).GetData();
120 compatibility_iterator
GetFirst() const
122 return compatibility_iterator( this, const_cast<ListType
*>(this)->begin() );
124 compatibility_iterator
GetLast() const
126 iterator i
= const_cast<ListType
*>(this)->end();
127 return compatibility_iterator( this, !(this->empty()) ? --i
: i
);
129 compatibility_iterator
Member( T
* e
) const
130 { return Find( e
); }
131 compatibility_iterator
Nth( int n
) const
132 { return Item( n
); }
133 int IndexOf( T
* e
) const
134 { return Find( e
).IndexOf(); }
136 compatibility_iterator
Append( T
* e
)
138 this->push_back( e
);
141 compatibility_iterator
Insert( T
* e
)
143 this->push_front( e
);
144 return compatibility_iterator( this, this->begin() );
146 compatibility_iterator
Insert( compatibility_iterator
& i
, T
* e
)
148 return compatibility_iterator( this, this->insert( i
.m_iter
, e
) );
150 compatibility_iterator
Insert( size_t idx
, T
* e
)
152 return compatibility_iterator( this,
153 this->insert( Item( idx
).m_iter
, e
) );
156 void DeleteContents( bool destroy
)
157 { m_destroy
= destroy
; }
158 bool GetDeleteContents() const
159 { return m_destroy
; }
160 void Erase( const compatibility_iterator
& i
)
164 this->erase( i
.m_iter
);
166 bool DeleteNode( const compatibility_iterator
& i
)
175 bool DeleteObject( T
* e
)
177 return DeleteNode( Find( e
) );
184 for ( it
= this->begin(), en
= this->end(); it
!= en
; ++it
)
199 friend class wxDList
<T
>;
201 Node( wxDList
<T
> *list
= NULL
, Node
*previous
= NULL
, Node
*next
= NULL
, T
*data
= NULL
)
204 m_previous
= previous
;
208 previous
->m_next
= this;
210 next
->m_previous
= this;
215 // handle the case when we're being deleted from the list by
216 // the user (i.e. not by the list itself from DeleteNode) -
217 // we must do it for compatibility with old code
219 m_list
->DetachNode(this);
227 Node
*GetNext() const { return m_next
; }
228 Node
*GetPrevious() const { return m_previous
; }
229 T
*GetData() const { return m_data
; }
230 T
**GetDataPtr() const { return &(wx_const_cast(nodetype
*,this)->m_data
); }
231 void SetData( T
*data
) { m_data
= data
; }
235 wxCHECK_MSG( m_list
, wxNOT_FOUND
, wxT("node doesn't belong to a list in IndexOf"));
238 Node
*prev
= m_previous
;
239 for( i
= 0; prev
; i
++ )
240 prev
= prev
->m_previous
;
245 T
*m_data
; // user data
246 Node
*m_next
, // next and previous nodes in the list
248 wxDList
<T
> *m_list
; // list we belong to
251 typedef Node nodetype
;
253 class compatibility_iterator
256 compatibility_iterator(nodetype
*ptr
= NULL
) : m_ptr(ptr
) { }
257 nodetype
*operator->() const { return m_ptr
; }
258 operator nodetype
*() const { return m_ptr
; }
273 void DoDeleteNode( nodetype
*node
)
277 // so that the node knows that it's being deleted by the list
282 size_t m_count
; // number of elements in the list
283 bool m_destroy
; // destroy user data when deleting list items?
284 nodetype
*m_nodeFirst
, // pointers to the head and tail of the list
294 wxDList( const wxDList
<T
>& list
)
300 wxDList( size_t count
, T
*elements
[] )
304 for (n
= 0; n
< count
; n
++)
305 Append( elements
[n
] );
308 wxDList
& operator=( const wxDList
<T
>& list
)
317 nodetype
*each
= m_nodeFirst
;
318 while ( each
!= NULL
)
320 nodetype
*next
= each
->GetNext();
326 void Assign(const wxDList
<T
> &list
)
328 wxASSERT_MSG( !list
.m_destroy
,
329 wxT("copying list which owns it's elements is a bad idea") );
331 m_destroy
= list
.m_destroy
;
335 for (node
= list
.GetFirst(); node
; node
= node
->GetNext() )
336 Append(node
->GetData());
337 wxASSERT_MSG( m_count
== list
.m_count
, wxT("logic error in Assign()") );
340 nodetype
*Append( T
*object
)
342 nodetype
*node
= new nodetype( this, m_nodeLast
, NULL
, object
);
347 m_nodeLast
= m_nodeFirst
;
351 m_nodeLast
->m_next
= node
;
358 nodetype
*Insert( T
* object
)
360 return Insert( NULL
, object
);
362 nodetype
*Insert( size_t pos
, T
* object
)
365 return Append( object
);
367 return Insert( Item(pos
), object
);
369 nodetype
*Insert( nodetype
*position
, T
* object
)
371 wxCHECK_MSG( !position
|| position
->m_list
== this, NULL
,
372 wxT("can't insert before a node from another list") );
374 // previous and next node for the node being inserted
375 nodetype
*prev
, *next
;
378 prev
= position
->GetPrevious();
383 // inserting in the beginning of the list
387 nodetype
*node
= new nodetype( this, prev
, next
, object
);
397 nodetype
*GetFirst() const
401 nodetype
*GetLast() const
405 size_t GetCount() const
414 void DeleteContents(bool destroy
)
418 bool GetDeleteContents() const
423 nodetype
*Item(size_t index
) const
425 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
430 wxFAIL_MSG( wxT("invalid index in Item()") );
434 T
*operator[](size_t index
) const
436 nodetype
*node
= Item(index
);
437 return node
? node
->GetData() : NULL
;
440 nodetype
*DetachNode( nodetype
*node
)
442 wxCHECK_MSG( node
, NULL
, wxT("detaching NULL wxNodeBase") );
443 wxCHECK_MSG( node
->m_list
== this, NULL
,
444 wxT("detaching node which is not from this list") );
446 nodetype
**prevNext
= node
->GetPrevious() ? &node
->GetPrevious()->m_next
448 nodetype
**nextPrev
= node
->GetNext() ? &node
->GetNext()->m_previous
450 *prevNext
= node
->GetNext();
451 *nextPrev
= node
->GetPrevious();
453 // mark the node as not belonging to this list any more
458 void Erase( nodetype
*node
)
462 bool DeleteNode( nodetype
*node
)
464 if ( !DetachNode(node
) )
470 bool DeleteObject( T
*object
)
472 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
474 if ( current
->GetData() == object
)
484 nodetype
*Find(const T
*object
) const
486 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
488 if ( current
->GetData() == object
)
495 int IndexOf(const T
*object
) const
498 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
500 if ( current
->GetData() == object
)
509 nodetype
*current
= m_nodeFirst
;
512 nodetype
*next
= current
->GetNext();
513 DoDeleteNode(current
);
523 nodetype
* node
= m_nodeFirst
;
527 // swap prev and next pointers
529 node
->m_next
= node
->m_previous
;
530 node
->m_previous
= tmp
;
531 // this is the node that was next before swapping
534 // swap first and last node
535 tmp
= m_nodeFirst
; m_nodeFirst
= m_nodeLast
; m_nodeLast
= tmp
;
540 void DeleteNodes(nodetype
* first
, nodetype
* last
)
542 nodetype
* node
= first
;
545 nodetype
* next
= node
->GetNext();
551 void ForEach(wxListIterateFunction F
)
553 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
554 (*F
)(current
->GetData());
557 T
*FirstThat(wxListIterateFunction F
)
559 for ( nodetype
*current
= GetFirst(); current
; current
= current
->GetNext() )
561 if ( (*F
)(current
->GetData()) )
562 return current
->GetData();
567 T
*LastThat(wxListIterateFunction F
)
569 for ( nodetype
*current
= GetLast(); current
; current
= current
->GetPrevious() )
571 if ( (*F
)(current
->GetData()) )
572 return current
->GetData();
579 typedef size_t size_type
;
580 typedef int difference_type
;
581 typedef T
* value_type
;
582 typedef value_type
& reference
;
583 typedef const value_type
& const_reference
;
588 typedef nodetype Node
;
589 typedef iterator itor
;
590 typedef T
* value_type
;
591 typedef value_type
* ptr_type
;
592 typedef value_type
& reference
;
597 typedef reference reference_type
;
598 typedef ptr_type pointer_type
;
600 iterator(Node
* node
, Node
* init
) : m_node(node
), m_init(init
) {}
601 iterator() : m_node(NULL
), m_init(NULL
) { }
602 reference_type
operator*() const
603 { return *m_node
->GetDataPtr(); }
605 itor
& operator++() { m_node
= m_node
->GetNext(); return *this; }
606 const itor
operator++(int)
607 { itor tmp
= *this; m_node
= m_node
->GetNext(); return tmp
; }
610 m_node
= m_node
? m_node
->GetPrevious() : m_init
;
613 const itor
operator--(int)
616 m_node
= m_node
? m_node
->GetPrevious() : m_init
;
619 bool operator!=(const itor
& it
) const
620 { return it
.m_node
!= m_node
; }
621 bool operator==(const itor
& it
) const
622 { return it
.m_node
== m_node
; }
627 typedef nodetype Node
;
628 typedef T
* value_type
;
629 typedef const value_type
& const_reference
;
630 typedef const_iterator itor
;
631 typedef value_type
* ptr_type
;
636 typedef const_reference reference_type
;
637 typedef const ptr_type pointer_type
;
639 const_iterator(Node
* node
, Node
* init
)
640 : m_node(node
), m_init(init
) { }
641 const_iterator() : m_node(NULL
), m_init(NULL
) { }
642 const_iterator(const iterator
& it
)
643 : m_node(it
.m_node
), m_init(it
.m_init
) { }
644 reference_type
operator*() const
645 { return *m_node
->GetDataPtr(); }
647 itor
& operator++() { m_node
= m_node
->GetNext(); return *this; }
648 const itor
operator++(int)
649 { itor tmp
= *this; m_node
= m_node
->GetNext(); return tmp
; }
652 m_node
= m_node
? m_node
->GetPrevious() : m_init
;
655 const itor
operator--(int)
658 m_node
= m_node
? m_node
->GetPrevious() : m_init
;
661 bool operator!=(const itor
& it
) const
662 { return it
.m_node
!= m_node
; }
663 bool operator==(const itor
& it
) const
664 { return it
.m_node
== m_node
; }
666 class reverse_iterator
669 typedef nodetype Node
;
670 typedef T
* value_type
;
671 typedef reverse_iterator itor
;
672 typedef value_type
* ptr_type
;
673 typedef value_type
& reference
;
678 typedef reference reference_type
;
679 typedef ptr_type pointer_type
;
681 reverse_iterator(Node
* node
, Node
* init
)
682 : m_node(node
), m_init(init
) { }
683 reverse_iterator() : m_node(NULL
), m_init(NULL
) { }
684 reference_type
operator*() const
685 { return *m_node
->GetDataPtr(); }
688 { m_node
= m_node
->GetPrevious(); return *this; }
689 const itor
operator++(int)
690 { itor tmp
= *this; m_node
= m_node
->GetPrevious(); return tmp
; }
692 { m_node
= m_node
? m_node
->GetNext() : m_init
; return *this; }
693 const itor
operator--(int)
696 m_node
= m_node
? m_node
->GetNext() : m_init
;
699 bool operator!=(const itor
& it
) const
700 { return it
.m_node
!= m_node
; }
701 bool operator==(const itor
& it
) const
702 { return it
.m_node
== m_node
; }
704 class const_reverse_iterator
707 typedef nodetype Node
;
708 typedef T
* value_type
;
709 typedef const_reverse_iterator itor
;
710 typedef value_type
* ptr_type
;
711 typedef const value_type
& const_reference
;
716 typedef const_reference reference_type
;
717 typedef const ptr_type pointer_type
;
719 const_reverse_iterator(Node
* node
, Node
* init
)
720 : m_node(node
), m_init(init
) { }
721 const_reverse_iterator() : m_node(NULL
), m_init(NULL
) { }
722 const_reverse_iterator(const reverse_iterator
& it
)
723 : m_node(it
.m_node
), m_init(it
.m_init
) { }
724 reference_type
operator*() const
725 { return *m_node
->GetDataPtr(); }
728 { m_node
= m_node
->GetPrevious(); return *this; }
729 const itor
operator++(int)
730 { itor tmp
= *this; m_node
= m_node
->GetPrevious(); return tmp
; }
732 { m_node
= m_node
? m_node
->GetNext() : m_init
; return *this;}
733 const itor
operator--(int)
736 m_node
= m_node
? m_node
->GetNext() : m_init
;
739 bool operator!=(const itor
& it
) const
740 { return it
.m_node
!= m_node
; }
741 bool operator==(const itor
& it
) const
742 { return it
.m_node
== m_node
; }
745 wxEXPLICIT
wxDList(size_type n
, const_reference v
= value_type())
747 wxDList(const const_iterator
& first
, const const_iterator
& last
)
748 { assign(first
, last
); }
749 iterator
begin() { return iterator(GetFirst(), GetLast()); }
750 const_iterator
begin() const
751 { return const_iterator(GetFirst(), GetLast()); }
752 iterator
end() { return iterator(NULL
, GetLast()); }
753 const_iterator
end() const { return const_iterator(NULL
, GetLast()); }
754 reverse_iterator
rbegin()
755 { return reverse_iterator(GetLast(), GetFirst()); }
756 const_reverse_iterator
rbegin() const
757 { return const_reverse_iterator(GetLast(), GetFirst()); }
758 reverse_iterator
rend() { return reverse_iterator(NULL
, GetFirst()); }
759 const_reverse_iterator
rend() const
760 { return const_reverse_iterator(NULL
, GetFirst()); }
761 void resize(size_type n
, value_type v
= value_type())
768 size_type
size() const { return GetCount(); }
769 size_type
max_size() const { return INT_MAX
; }
770 bool empty() const { return IsEmpty(); }
771 reference
front() { return *begin(); }
772 const_reference
front() const { return *begin(); }
773 reference
back() { iterator tmp
= end(); return *--tmp
; }
774 const_reference
back() const { const_iterator tmp
= end(); return *--tmp
; }
775 void push_front(const_reference v
= value_type())
776 { Insert(GetFirst(), v
); }
777 void pop_front() { DeleteNode(GetFirst()); }
778 void push_back(const_reference v
= value_type())
780 void pop_back() { DeleteNode(GetLast()); }
781 void assign(const_iterator first
, const const_iterator
& last
)
784 for(; first
!= last
; ++first
)
787 void assign(size_type n
, const_reference v
= value_type())
790 for(size_type i
= 0; i
< n
; ++i
)
793 iterator
insert(const iterator
& it
, const_reference v
= value_type())
799 void insert(const iterator
& it
, size_type n
, const_reference v
= value_type())
801 for(size_type i
= 0; i
< n
; ++i
)
802 Insert(it
.m_node
, v
);
804 void insert(const iterator
& it
, const_iterator first
, const const_iterator
& last
)
806 for(; first
!= last
; ++first
)
807 Insert(it
.m_node
, *first
);
809 iterator
erase(const iterator
& it
)
811 iterator next
= iterator(it
.m_node
->GetNext(), GetLast());
812 DeleteNode(it
.m_node
); return next
;
814 iterator
erase(const iterator
& first
, const iterator
& last
)
816 iterator next
= last
; ++next
;
817 DeleteNodes(first
.m_node
, last
.m_node
);
820 void clear() { Clear(); }
821 void splice(const iterator
& it
, wxDList
<T
>& l
, const iterator
& first
, const iterator
& last
)
822 { insert(it
, first
, last
); l
.erase(first
, last
); }
823 void splice(const iterator
& it
, wxDList
<T
>& l
)
824 { splice(it
, l
, l
.begin(), l
.end() ); }
825 void splice(const iterator
& it
, wxDList
<T
>& l
, const iterator
& first
)
827 iterator tmp
= first
; ++tmp
;
828 if(it
== first
|| it
== tmp
) return;
832 void remove(const_reference v
)
836 /* void swap(list<T>& l)
838 { size_t t = m_count; m_count = l.m_count; l.m_count = t; }
839 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }
840 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }
841 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }
842 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }
848 #endif // _WX_DLIST_H_