1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxList, wxStringList classes
4 // Author: Julian Smart
5 // Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 All this is quite ugly but serves two purposes:
14 1. Be almost 100% compatible with old, untyped, wxList class
15 2. Ensure compile-time type checking for the linked lists
17 The idea is to have one base class (wxListBase) working with "void *" data,
18 but to hide these untyped functions - i.e. make them protected, so they
19 can only be used from derived classes which have inline member functions
20 working with right types. This achieves the 2nd goal. As for the first one,
21 we provide a special derivation of wxListBase called wxList which looks just
28 // -----------------------------------------------------------------------------
30 // -----------------------------------------------------------------------------
33 #include "wx/object.h"
34 #include "wx/string.h"
36 #if wxUSE_STD_CONTAINERS
37 #include "wx/beforestd.h"
41 #include "wx/afterstd.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 class WXDLLIMPEXP_FWD_BASE wxObjectListNode
;
49 typedef wxObjectListNode wxNode
;
51 #if wxUSE_STD_CONTAINERS
53 #define wxLIST_COMPATIBILITY
55 #define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
56 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
57 #define WX_DECLARE_LIST_PTR_3(elT, dummy1, liT, dummy2, decl) \
58 WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl)
60 #define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
61 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
62 #define WX_DECLARE_LIST_PTR_2(elT, liT, dummy, decl) \
63 WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
65 #define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
66 WX_DECLARE_LIST_XO(elT*, liT, decl)
68 #if !defined(__VISUALC__) || __VISUALC__ >= 1300 // == !VC6
71 class wxList_SortFunction
74 wxList_SortFunction(wxSortCompareFunction f
) : m_f(f
) { }
75 bool operator()(const T
& i1
, const T
& i2
)
76 { return m_f((T
*)&i1
, (T
*)&i2
) < 0; }
78 wxSortCompareFunction m_f
;
81 #define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
82 #define WX_LIST_VC6_WORKAROUND(elT, liT, decl)
84 #else // if defined( __VISUALC__ ) && __VISUALC__ < 1300 // == VC6
86 #define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
87 #define WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
90 /* Workaround for broken VC6 STL incorrectly requires a std::greater<> */ \
91 /* to be passed into std::list::sort() */ \
93 struct std::greater<elT> \
96 wxSortCompareFunction m_CompFunc; \
98 greater( wxSortCompareFunction compfunc = NULL ) \
99 : m_CompFunc( compfunc ) {} \
100 bool operator()(const elT X, const elT Y) const \
102 return m_CompFunc ? \
103 ( m_CompFunc( wxListCastElementToVoidPtr(X), \
104 wxListCastElementToVoidPtr(Y) ) < 0 ) : \
109 // helper for std::greater<elT> above:
111 inline const void *wxListCastElementToVoidPtr(const T
* ptr
) { return ptr
; }
112 inline const void *wxListCastElementToVoidPtr(const wxString
& str
)
113 { return (const char*)str
; }
118 Note 1: the outer helper class _WX_LIST_HELPER_##liT below is a workaround
119 for mingw 3.2.3 compiler bug that prevents a static function of liT class
120 from being exported into dll. A minimal code snippet reproducing the bug:
122 struct WXDLLIMPEXP_CORE Foo
125 struct SomeInnerClass
127 friend class Foo; // comment this out to make it link
135 The program does not link under mingw_gcc 3.2.3 producing undefined
136 reference to Foo::Bar() function
139 Note 2: the EmptyList is needed to allow having a NULL pointer-like
140 invalid iterator. We used to use just an uninitialized iterator object
141 instead but this fails with some debug/checked versions of STL, notably the
142 glibc version activated with _GLIBCXX_DEBUG, so we need to have a separate
146 // the real wxList-class declaration
147 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
148 decl _WX_LIST_HELPER_##liT \
150 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
151 typedef std::list<elT> BaseListType; \
153 static BaseListType EmptyList; \
154 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
157 WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
158 class liT : public std::list<elT> \
161 typedef std::list<elT> BaseListType; \
166 class compatibility_iterator \
169 /* Workaround for broken VC6 nested class name resolution */ \
170 typedef std::list<elT>::iterator iterator; \
177 compatibility_iterator() \
178 : m_iter(_WX_LIST_HELPER_##liT::EmptyList.end()), m_list( NULL ) {} \
179 compatibility_iterator( liT* li, iterator i ) \
180 : m_iter( i ), m_list( li ) {} \
181 compatibility_iterator( const liT* li, iterator i ) \
182 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
184 compatibility_iterator* operator->() { return this; } \
185 const compatibility_iterator* operator->() const { return this; } \
187 bool operator==(const compatibility_iterator& i) const \
189 wxASSERT_MSG( m_list && i.m_list, \
190 wxT("comparing invalid iterators is illegal") ); \
191 return (m_list == i.m_list) && (m_iter == i.m_iter); \
193 bool operator!=(const compatibility_iterator& i) const \
194 { return !( operator==( i ) ); } \
195 operator bool() const \
196 { return m_list ? m_iter != m_list->end() : false; } \
197 bool operator !() const \
198 { return !( operator bool() ); } \
200 elT GetData() const \
201 { return *m_iter; } \
202 void SetData( elT e ) \
205 compatibility_iterator GetNext() const \
207 iterator i = m_iter; \
208 return compatibility_iterator( m_list, ++i ); \
210 compatibility_iterator GetPrevious() const \
212 if ( m_iter == m_list->begin() ) \
213 return compatibility_iterator(); \
215 iterator i = m_iter; \
216 return compatibility_iterator( m_list, --i ); \
218 int IndexOf() const \
220 return *this ? std::distance( m_list->begin(), m_iter ) \
225 liT() : m_destroy( false ) {} \
227 compatibility_iterator Find( const elT e ) const \
229 liT* _this = const_cast< liT* >( this ); \
230 return compatibility_iterator( _this, \
231 std::find( _this->begin(), _this->end(), e ) ); \
234 bool IsEmpty() const \
235 { return empty(); } \
236 size_t GetCount() const \
239 { return static_cast< int >( GetCount() ); } \
241 compatibility_iterator Item( size_t idx ) const \
243 iterator i = const_cast< liT* >(this)->begin(); \
244 std::advance( i, idx ); \
245 return compatibility_iterator( this, i ); \
247 elT operator[](size_t idx) const \
249 return Item(idx).GetData(); \
252 compatibility_iterator GetFirst() const \
254 return compatibility_iterator( this, \
255 const_cast< liT* >(this)->begin() ); \
257 compatibility_iterator GetLast() const \
259 iterator i = const_cast< liT* >(this)->end(); \
260 return compatibility_iterator( this, !empty() ? --i : i ); \
262 bool Member( elT e ) const \
263 { return Find( e ); } \
264 compatibility_iterator Nth( int n ) const \
265 { return Item( n ); } \
266 int IndexOf( elT e ) const \
267 { return Find( e ).IndexOf(); } \
269 compatibility_iterator Append( elT e ) \
274 compatibility_iterator Insert( elT e ) \
277 return compatibility_iterator( this, begin() ); \
279 compatibility_iterator Insert(const compatibility_iterator & i, elT e)\
281 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
283 compatibility_iterator Insert( size_t idx, elT e ) \
285 return compatibility_iterator( this, \
286 insert( Item( idx ).m_iter, e ) ); \
289 void DeleteContents( bool destroy ) \
290 { m_destroy = destroy; } \
291 bool GetDeleteContents() const \
292 { return m_destroy; } \
293 void Erase( const compatibility_iterator& i ) \
296 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
299 bool DeleteNode( const compatibility_iterator& i ) \
308 bool DeleteObject( elT e ) \
310 return DeleteNode( Find( e ) ); \
315 std::for_each( begin(), end(), \
316 _WX_LIST_HELPER_##liT::DeleteFunction ); \
319 /* Workaround for broken VC6 std::list::sort() see above */ \
320 void Sort( wxSortCompareFunction compfunc ) \
321 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
322 ~liT() { Clear(); } \
324 /* It needs access to our EmptyList */ \
325 friend class compatibility_iterator; \
328 #define WX_DECLARE_LIST(elementtype, listname) \
329 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
330 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
331 WX_DECLARE_LIST(elementtype, listname)
333 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
334 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLIMPEXP_CORE)
335 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
336 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
338 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
339 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
340 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
341 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
343 // this macro must be inserted in your program after
344 // #include "wx/listimpl.cpp"
345 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
347 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
348 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
350 #else // if !wxUSE_STD_CONTAINERS
353 // undef it to get rid of old, deprecated functions
354 #define wxLIST_COMPATIBILITY
356 // -----------------------------------------------------------------------------
357 // key stuff: a list may be optionally keyed on integer or string key
358 // -----------------------------------------------------------------------------
366 // a struct which may contain both types of keys
368 // implementation note: on one hand, this class allows to have only one function
369 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
370 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
371 // wxList::Find(const char *).
372 class WXDLLIMPEXP_BASE wxListKey
376 wxListKey() : m_keyType(wxKEY_NONE
)
378 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
379 { m_key
.integer
= i
; }
380 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
381 { m_key
.string
= new wxString(s
); }
382 wxListKey(const char *s
) : m_keyType(wxKEY_STRING
)
383 { m_key
.string
= new wxString(s
); }
384 wxListKey(const wchar_t *s
) : m_keyType(wxKEY_STRING
)
385 { m_key
.string
= new wxString(s
); }
388 wxKeyType
GetKeyType() const { return m_keyType
; }
389 const wxString
GetString() const
390 { wxASSERT( m_keyType
== wxKEY_STRING
); return *m_key
.string
; }
391 long GetNumber() const
392 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
395 // Note: implementation moved to list.cpp to prevent BC++ inline
396 // expansion warning.
397 bool operator==(wxListKeyValue value
) const ;
402 if ( m_keyType
== wxKEY_STRING
)
408 wxListKeyValue m_key
;
411 // -----------------------------------------------------------------------------
412 // wxNodeBase class is a (base for) node in a double linked list
413 // -----------------------------------------------------------------------------
415 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
417 class WXDLLIMPEXP_FWD_BASE wxListBase
;
419 class WXDLLIMPEXP_BASE wxNodeBase
421 friend class wxListBase
;
424 wxNodeBase(wxListBase
*list
= NULL
,
425 wxNodeBase
*previous
= NULL
,
426 wxNodeBase
*next
= NULL
,
428 const wxListKey
& key
= wxDefaultListKey
);
430 virtual ~wxNodeBase();
432 // FIXME no check is done that the list is really keyed on strings
433 wxString
GetKeyString() const { return *m_key
.string
; }
434 long GetKeyInteger() const { return m_key
.integer
; }
436 // Necessary for some existing code
437 void SetKeyString(const wxString
& s
) { m_key
.string
= new wxString(s
); }
438 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
440 #ifdef wxLIST_COMPATIBILITY
441 // compatibility methods, use Get* instead.
442 wxDEPRECATED( wxNode
*Next() const );
443 wxDEPRECATED( wxNode
*Previous() const );
444 wxDEPRECATED( wxObject
*Data() const );
445 #endif // wxLIST_COMPATIBILITY
448 // all these are going to be "overloaded" in the derived classes
449 wxNodeBase
*GetNext() const { return m_next
; }
450 wxNodeBase
*GetPrevious() const { return m_previous
; }
452 void *GetData() const { return m_data
; }
453 void SetData(void *data
) { m_data
= data
; }
455 // get 0-based index of this node within the list or wxNOT_FOUND
458 virtual void DeleteData() { }
460 // for wxList::iterator
461 void** GetDataPtr() const { return &(const_cast<wxNodeBase
*>(this)->m_data
); }
463 // optional key stuff
464 wxListKeyValue m_key
;
466 void *m_data
; // user data
467 wxNodeBase
*m_next
, // next and previous nodes in the list
470 wxListBase
*m_list
; // list we belong to
472 wxDECLARE_NO_COPY_CLASS(wxNodeBase
);
475 // -----------------------------------------------------------------------------
476 // a double-linked list class
477 // -----------------------------------------------------------------------------
479 class WXDLLIMPEXP_FWD_BASE wxList
;
481 class WXDLLIMPEXP_BASE wxListBase
483 friend class wxNodeBase
; // should be able to call DetachNode()
484 friend class wxHashTableBase
; // should be able to call untyped Find()
487 // default ctor & dtor
488 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
490 virtual ~wxListBase();
493 // count of items in the list
494 size_t GetCount() const { return m_count
; }
496 // return true if this list is empty
497 bool IsEmpty() const { return m_count
== 0; }
504 // instruct it to destroy user data when deleting nodes
505 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
507 // query if to delete
508 bool GetDeleteContents() const
509 { return m_destroy
; }
512 wxKeyType
GetKeyType() const
513 { return m_keyType
; }
515 // set the keytype (required by the serial code)
516 void SetKeyType(wxKeyType keyType
)
517 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
519 #ifdef wxLIST_COMPATIBILITY
520 // compatibility methods from old wxList
521 wxDEPRECATED( int Number() const ); // use GetCount instead.
522 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
523 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
524 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
526 // kludge for typesafe list migration in core classes.
527 wxDEPRECATED( operator wxList
&() const );
528 #endif // wxLIST_COMPATIBILITY
532 // all methods here are "overloaded" in derived classes to provide compile
533 // time type checking
535 // create a node for the list of this type
536 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
538 const wxListKey
& key
= wxDefaultListKey
) = 0;
543 wxListBase(size_t count
, void *elements
[]);
544 // from a sequence of objects
545 wxListBase(void *object
, ... /* terminate with NULL */);
548 void Assign(const wxListBase
& list
)
549 { Clear(); DoCopy(list
); }
551 // get list head/tail
552 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
553 wxNodeBase
*GetLast() const { return m_nodeLast
; }
555 // by (0-based) index
556 wxNodeBase
*Item(size_t index
) const;
558 // get the list item's data
559 void *operator[](size_t n
) const
561 wxNodeBase
*node
= Item(n
);
563 return node
? node
->GetData() : NULL
;
567 // append to end of list
568 wxNodeBase
*Prepend(void *object
)
569 { return (wxNodeBase
*)wxListBase::Insert(object
); }
570 // append to beginning of list
571 wxNodeBase
*Append(void *object
);
572 // insert a new item at the beginning of the list
573 wxNodeBase
*Insert(void *object
)
574 { return Insert(static_cast<wxNodeBase
*>(NULL
), object
); }
575 // insert a new item at the given position
576 wxNodeBase
*Insert(size_t pos
, void *object
)
577 { return pos
== GetCount() ? Append(object
)
578 : Insert(Item(pos
), object
); }
579 // insert before given node or at front of list if prev == NULL
580 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
583 wxNodeBase
*Append(long key
, void *object
);
584 wxNodeBase
*Append(const wxString
& key
, void *object
);
586 // removes node from the list but doesn't delete it (returns pointer
587 // to the node or NULL if it wasn't found in the list)
588 wxNodeBase
*DetachNode(wxNodeBase
*node
);
589 // delete element from list, returns false if node not found
590 bool DeleteNode(wxNodeBase
*node
);
591 // finds object pointer and deletes node (and object if DeleteContents
592 // is on), returns false if object not found
593 bool DeleteObject(void *object
);
595 // search (all return NULL if item not found)
597 wxNodeBase
*Find(const void *object
) const;
600 wxNodeBase
*Find(const wxListKey
& key
) const;
602 // get 0-based index of object or wxNOT_FOUND
603 int IndexOf( void *object
) const;
605 // this function allows the sorting of arbitrary lists by giving
606 // a function to compare two list elements. The list is sorted in place.
607 void Sort(const wxSortCompareFunction compfunc
);
609 // functions for iterating over the list
610 void *FirstThat(wxListIterateFunction func
);
611 void ForEach(wxListIterateFunction func
);
612 void *LastThat(wxListIterateFunction func
);
614 // for STL interface, "last" points to one after the last node
615 // of the controlled sequence (NULL for the end of the list)
617 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
620 // common part of all ctors
621 void Init(wxKeyType keyType
= wxKEY_NONE
);
624 // common part of copy ctor and assignment operator
625 void DoCopy(const wxListBase
& list
);
626 // common part of all Append()s
627 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
628 // free node's data and node itself
629 void DoDeleteNode(wxNodeBase
*node
);
631 size_t m_count
; // number of elements in the list
632 bool m_destroy
; // destroy user data when deleting list items?
633 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
636 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
639 // -----------------------------------------------------------------------------
640 // macros for definition of "template" list type
641 // -----------------------------------------------------------------------------
643 // and now some heavy magic...
645 // declare a list type named 'name' and containing elements of type 'T *'
646 // (as a by product of macro expansion you also get wx##name##Node
647 // wxNode-derived type)
649 // implementation details:
650 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
651 // for the list of given type - this allows us to pass only the list name
652 // to WX_DEFINE_LIST() even if it needs both the name and the type
654 // 2. We redefine all non-type-safe wxList functions with type-safe versions
655 // which don't take any space (everything is inline), but bring compile
656 // time error checking.
658 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
659 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
660 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
661 // interesting capability to store polymorphic objects in the list and is
662 // particularly useful with, for example, "wxWindow *" list where the
663 // wxWindowBase pointers are put into the list, but wxWindow pointers are
664 // retrieved from it.
666 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
667 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
668 // it results in compiler warnings when this operator doesn't make sense
669 // (i.e. stored elements are not pointers)
671 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
672 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
673 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
675 classexp nodetype : public wxNodeBase \
678 nodetype(wxListBase *list = NULL, \
679 nodetype *previous = NULL, \
680 nodetype *next = NULL, \
682 const wxListKey& key = wxDefaultListKey) \
683 : wxNodeBase(list, previous, next, data, key) { } \
685 nodetype *GetNext() const \
686 { return (nodetype *)wxNodeBase::GetNext(); } \
687 nodetype *GetPrevious() const \
688 { return (nodetype *)wxNodeBase::GetPrevious(); } \
691 { return (T *)wxNodeBase::GetData(); } \
692 void SetData(T *data) \
693 { wxNodeBase::SetData(data); } \
696 virtual void DeleteData(); \
698 DECLARE_NO_COPY_CLASS(nodetype) \
701 classexp name : public wxListBase \
704 typedef nodetype Node; \
705 classexp compatibility_iterator \
708 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
710 Node *operator->() const { return m_ptr; } \
711 operator Node *() const { return m_ptr; } \
717 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
719 name(const name& list) : wxListBase(list.GetKeyType()) \
721 name(size_t count, T *elements[]) \
722 : wxListBase(count, (void **)elements) { } \
724 name& operator=(const name& list) \
725 { if (&list != this) Assign(list); return *this; } \
727 nodetype *GetFirst() const \
728 { return (nodetype *)wxListBase::GetFirst(); } \
729 nodetype *GetLast() const \
730 { return (nodetype *)wxListBase::GetLast(); } \
732 nodetype *Item(size_t index) const \
733 { return (nodetype *)wxListBase::Item(index); } \
735 T *operator[](size_t index) const \
737 nodetype *node = Item(index); \
738 return node ? (T*)(node->GetData()) : NULL; \
741 nodetype *Append(Tbase *object) \
742 { return (nodetype *)wxListBase::Append(object); } \
743 nodetype *Insert(Tbase *object) \
744 { return (nodetype *)Insert(static_cast<nodetype *>(NULL), \
746 nodetype *Insert(size_t pos, Tbase *object) \
747 { return (nodetype *)wxListBase::Insert(pos, object); } \
748 nodetype *Insert(nodetype *prev, Tbase *object) \
749 { return (nodetype *)wxListBase::Insert(prev, object); } \
751 nodetype *Append(long key, void *object) \
752 { return (nodetype *)wxListBase::Append(key, object); } \
753 nodetype *Append(const wxChar *key, void *object) \
754 { return (nodetype *)wxListBase::Append(key, object); } \
756 nodetype *DetachNode(nodetype *node) \
757 { return (nodetype *)wxListBase::DetachNode(node); } \
758 bool DeleteNode(nodetype *node) \
759 { return wxListBase::DeleteNode(node); } \
760 bool DeleteObject(Tbase *object) \
761 { return wxListBase::DeleteObject(object); } \
762 void Erase(nodetype *it) \
763 { DeleteNode(it); } \
765 nodetype *Find(const Tbase *object) const \
766 { return (nodetype *)wxListBase::Find(object); } \
768 virtual nodetype *Find(const wxListKey& key) const \
769 { return (nodetype *)wxListBase::Find(key); } \
771 bool Member(const Tbase *object) const \
772 { return Find(object) != NULL; } \
774 int IndexOf(Tbase *object) const \
775 { return wxListBase::IndexOf(object); } \
777 void Sort(wxSortCompareFunction func) \
778 { wxListBase::Sort(func); } \
779 void Sort(wxSortFuncFor_##name func) \
780 { Sort((wxSortCompareFunction)func); } \
783 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
785 const wxListKey& key = wxDefaultListKey) \
787 return new nodetype(this, \
788 (nodetype *)prev, (nodetype *)next, \
791 /* STL interface */ \
793 typedef size_t size_type; \
794 typedef int difference_type; \
795 typedef T* value_type; \
796 typedef Tbase* base_value_type; \
797 typedef value_type& reference; \
798 typedef const value_type& const_reference; \
799 typedef base_value_type& base_reference; \
800 typedef const base_value_type& const_base_reference; \
806 typedef nodetype Node; \
807 typedef iterator itor; \
808 typedef T* value_type; \
809 typedef value_type* ptr_type; \
810 typedef value_type& reference; \
815 typedef reference reference_type; \
816 typedef ptr_type pointer_type; \
818 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
819 iterator() : m_node(NULL), m_init(NULL) { } \
820 reference_type operator*() const \
821 { return *(pointer_type)m_node->GetDataPtr(); } \
825 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
826 m_node = m_node->GetNext(); \
829 const itor operator++(int) \
832 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
833 m_node = m_node->GetNext(); \
838 m_node = m_node ? m_node->GetPrevious() : m_init; \
841 const itor operator--(int) \
844 m_node = m_node ? m_node->GetPrevious() : m_init; \
847 bool operator!=(const itor& it) const \
848 { return it.m_node != m_node; } \
849 bool operator==(const itor& it) const \
850 { return it.m_node == m_node; } \
852 classexp const_iterator \
856 typedef nodetype Node; \
857 typedef T* value_type; \
858 typedef const value_type& const_reference; \
859 typedef const_iterator itor; \
860 typedef value_type* ptr_type; \
865 typedef const_reference reference_type; \
866 typedef const ptr_type pointer_type; \
868 const_iterator(Node* node, Node* init) \
869 : m_node(node), m_init(init) { } \
870 const_iterator() : m_node(NULL), m_init(NULL) { } \
871 const_iterator(const iterator& it) \
872 : m_node(it.m_node), m_init(it.m_init) { } \
873 reference_type operator*() const \
874 { return *(pointer_type)m_node->GetDataPtr(); } \
878 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
879 m_node = m_node->GetNext(); \
882 const itor operator++(int) \
885 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
886 m_node = m_node->GetNext(); \
891 m_node = m_node ? m_node->GetPrevious() : m_init; \
894 const itor operator--(int) \
897 m_node = m_node ? m_node->GetPrevious() : m_init; \
900 bool operator!=(const itor& it) const \
901 { return it.m_node != m_node; } \
902 bool operator==(const itor& it) const \
903 { return it.m_node == m_node; } \
905 classexp reverse_iterator \
909 typedef nodetype Node; \
910 typedef T* value_type; \
911 typedef reverse_iterator itor; \
912 typedef value_type* ptr_type; \
913 typedef value_type& reference; \
918 typedef reference reference_type; \
919 typedef ptr_type pointer_type; \
921 reverse_iterator(Node* node, Node* init) \
922 : m_node(node), m_init(init) { } \
923 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
924 reference_type operator*() const \
925 { return *(pointer_type)m_node->GetDataPtr(); } \
928 { m_node = m_node->GetPrevious(); return *this; } \
929 const itor operator++(int) \
930 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
932 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
933 const itor operator--(int) \
936 m_node = m_node ? m_node->GetNext() : m_init; \
939 bool operator!=(const itor& it) const \
940 { return it.m_node != m_node; } \
941 bool operator==(const itor& it) const \
942 { return it.m_node == m_node; } \
944 classexp const_reverse_iterator \
948 typedef nodetype Node; \
949 typedef T* value_type; \
950 typedef const_reverse_iterator itor; \
951 typedef value_type* ptr_type; \
952 typedef const value_type& const_reference; \
957 typedef const_reference reference_type; \
958 typedef const ptr_type pointer_type; \
960 const_reverse_iterator(Node* node, Node* init) \
961 : m_node(node), m_init(init) { } \
962 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
963 const_reverse_iterator(const reverse_iterator& it) \
964 : m_node(it.m_node), m_init(it.m_init) { } \
965 reference_type operator*() const \
966 { return *(pointer_type)m_node->GetDataPtr(); } \
969 { m_node = m_node->GetPrevious(); return *this; } \
970 const itor operator++(int) \
971 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
973 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
974 const itor operator--(int) \
977 m_node = m_node ? m_node->GetNext() : m_init; \
980 bool operator!=(const itor& it) const \
981 { return it.m_node != m_node; } \
982 bool operator==(const itor& it) const \
983 { return it.m_node == m_node; } \
986 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
988 name(const const_iterator& first, const const_iterator& last) \
989 { assign(first, last); } \
990 iterator begin() { return iterator(GetFirst(), GetLast()); } \
991 const_iterator begin() const \
992 { return const_iterator(GetFirst(), GetLast()); } \
993 iterator end() { return iterator(NULL, GetLast()); } \
994 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
995 reverse_iterator rbegin() \
996 { return reverse_iterator(GetLast(), GetFirst()); } \
997 const_reverse_iterator rbegin() const \
998 { return const_reverse_iterator(GetLast(), GetFirst()); } \
999 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
1000 const_reverse_iterator rend() const \
1001 { return const_reverse_iterator(NULL, GetFirst()); } \
1002 void resize(size_type n, value_type v = value_type()) \
1004 while (n < size()) \
1006 while (n > size()) \
1009 size_type size() const { return GetCount(); } \
1010 size_type max_size() const { return INT_MAX; } \
1011 bool empty() const { return IsEmpty(); } \
1012 reference front() { return *begin(); } \
1013 const_reference front() const { return *begin(); } \
1014 reference back() { iterator tmp = end(); return *--tmp; } \
1015 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
1016 void push_front(const_reference v = value_type()) \
1017 { Insert(GetFirst(), (const_base_reference)v); } \
1018 void pop_front() { DeleteNode(GetFirst()); } \
1019 void push_back(const_reference v = value_type()) \
1020 { Append((const_base_reference)v); } \
1021 void pop_back() { DeleteNode(GetLast()); } \
1022 void assign(const_iterator first, const const_iterator& last) \
1025 for(; first != last; ++first) \
1026 Append((const_base_reference)*first); \
1028 void assign(size_type n, const_reference v = value_type()) \
1031 for(size_type i = 0; i < n; ++i) \
1032 Append((const_base_reference)v); \
1034 iterator insert(const iterator& it, const_reference v) \
1036 if ( it == end() ) \
1038 Append((const_base_reference)v); \
1040 note that this is the new end(), the old one was \
1041 invalidated by the Append() call, and this is why we \
1042 can't use the same code as in the normal case below \
1044 iterator itins(end()); \
1049 Insert(it.m_node, (const_base_reference)v); \
1050 iterator itins(it); \
1054 void insert(const iterator& it, size_type n, const_reference v) \
1056 for(size_type i = 0; i < n; ++i) \
1059 void insert(const iterator& it, \
1060 const_iterator first, const const_iterator& last) \
1062 for(; first != last; ++first) \
1063 insert(it, *first); \
1065 iterator erase(const iterator& it) \
1067 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1068 DeleteNode(it.m_node); return next; \
1070 iterator erase(const iterator& first, const iterator& last) \
1072 iterator next = last; \
1073 if ( next != end() ) \
1075 DeleteNodes(first.m_node, last.m_node); \
1078 void clear() { Clear(); } \
1079 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1080 { insert(it, first, last); l.erase(first, last); } \
1081 void splice(const iterator& it, name& l) \
1082 { splice(it, l, l.begin(), l.end() ); } \
1083 void splice(const iterator& it, name& l, const iterator& first) \
1085 if ( it != first ) \
1087 insert(it, *first); \
1091 void remove(const_reference v) \
1092 { DeleteObject((const_base_reference)v); } \
1095 /* void swap(name& l) \
1097 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1098 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1099 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1100 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1101 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1105 #define WX_LIST_PTROP \
1106 pointer_type operator->() const \
1107 { return (pointer_type)m_node->GetDataPtr(); }
1108 #define WX_LIST_PTROP_NONE
1110 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1111 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1112 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1113 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1115 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1116 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1117 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1118 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1120 #define WX_DECLARE_LIST(elementtype, listname) \
1121 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1122 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1123 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1124 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1125 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1127 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1128 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1129 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1131 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1132 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLIMPEXP_CORE)
1134 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1135 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1136 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLIMPEXP_CORE)
1138 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1139 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1140 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1141 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1142 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1143 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1145 // this macro must be inserted in your program after
1146 // #include "wx/listimpl.cpp"
1147 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1149 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1150 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1152 #endif // !wxUSE_STD_CONTAINERS
1154 // ============================================================================
1155 // now we can define classes 100% compatible with the old ones
1156 // ============================================================================
1158 // ----------------------------------------------------------------------------
1159 // commonly used list classes
1160 // ----------------------------------------------------------------------------
1162 #if defined(wxLIST_COMPATIBILITY)
1164 // inline compatibility functions
1166 #if !wxUSE_STD_CONTAINERS
1168 // ----------------------------------------------------------------------------
1169 // wxNodeBase deprecated methods
1170 // ----------------------------------------------------------------------------
1172 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1173 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1174 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1176 // ----------------------------------------------------------------------------
1177 // wxListBase deprecated methods
1178 // ----------------------------------------------------------------------------
1180 inline int wxListBase::Number() const { return (int)GetCount(); }
1181 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1182 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1183 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1184 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1188 // define this to make a lot of noise about use of the old wxList classes.
1189 //#define wxWARN_COMPAT_LIST_USE
1191 // ----------------------------------------------------------------------------
1192 // wxList compatibility class: in fact, it's a list of wxObjects
1193 // ----------------------------------------------------------------------------
1195 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1196 class WXDLLIMPEXP_BASE
);
1198 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1201 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STD_CONTAINERS
1203 wxDEPRECATED( wxList(int key_type
) );
1204 #elif !wxUSE_STD_CONTAINERS
1205 wxList(int key_type
= wxKEY_NONE
);
1208 // this destructor is required for Darwin
1211 #if !wxUSE_STD_CONTAINERS
1212 wxList
& operator=(const wxList
& list
)
1213 { if (&list
!= this) Assign(list
); return *this; }
1215 // compatibility methods
1216 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1217 #endif // !wxUSE_STD_CONTAINERS
1220 #if !wxUSE_STD_CONTAINERS
1222 // -----------------------------------------------------------------------------
1223 // wxStringList class for compatibility with the old code
1224 // -----------------------------------------------------------------------------
1225 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1227 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1232 #ifdef wxWARN_COMPAT_LIST_USE
1234 wxDEPRECATED( wxStringList(const wxChar
*first
...) ); // FIXME-UTF8
1237 wxStringList(const wxChar
*first
...); // FIXME-UTF8
1240 // copying the string list: the strings are copied, too (extremely
1242 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1243 wxStringList
& operator=(const wxStringList
& other
)
1254 // makes a copy of the string
1255 wxNode
*Add(const wxChar
*s
);
1257 // Append to beginning of list
1258 wxNode
*Prepend(const wxChar
*s
);
1260 bool Delete(const wxChar
*s
);
1262 wxChar
**ListToArray(bool new_copies
= false) const;
1263 bool Member(const wxChar
*s
) const;
1269 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1272 #else // if wxUSE_STD_CONTAINERS
1274 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1276 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1279 compatibility_iterator
Append(wxChar
* s
)
1280 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1281 compatibility_iterator
Insert(wxChar
* s
)
1282 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1283 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1287 return wxStringListBase::Insert(pos
, tmp
);
1289 compatibility_iterator
Add(const wxChar
* s
)
1290 { push_back(s
); return GetLast(); }
1291 compatibility_iterator
Prepend(const wxChar
* s
)
1292 { push_front(s
); return GetFirst(); }
1295 #endif // wxUSE_STD_CONTAINERS
1297 #endif // wxLIST_COMPATIBILITY
1299 // delete all list elements
1301 // NB: the class declaration of the list elements must be visible from the
1302 // place where you use this macro, otherwise the proper destructor may not
1303 // be called (a decent compiler should give a warning about it, but don't
1305 #define WX_CLEAR_LIST(type, list) \
1307 type::iterator it, en; \
1308 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1313 // append all element of one list to another one
1314 #define WX_APPEND_LIST(list, other) \
1316 wxList::compatibility_iterator node = other->GetFirst(); \
1319 (list)->push_back(node->GetData()); \
1320 node = node->GetNext(); \
1324 #endif // _WX_LISTH__