]>
git.saurik.com Git - wxWidgets.git/blob - include/wx/dynarray.h
1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: auto-resizable (i.e. dynamic) array support
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
15 #if defined(__GNUG__) && !defined(__APPLE__) && \
16 !(defined(__MINGW32__) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
17 #pragma interface "dynarray.h"
23 #include "wx/beforestd.h"
26 #include "wx/afterstd.h"
27 #if defined(__WXMSW__) && defined(__MINGW32__)
28 #include "wx/msw/winundef.h"
33 This header defines the dynamic arrays and object arrays (i.e. arrays which
34 own their elements). Dynamic means that the arrays grow automatically as
37 These macros are ugly (especially if you look in the sources ;-), but they
38 allow us to define "template" classes without actually using templates and so
39 this works with all compilers (and may be also much faster to compile even
40 with a compiler which does support templates). The arrays defined with these
43 Range checking is performed in debug build for both arrays and objarrays but
44 not in release build - so using an invalid index will just lead to a crash
47 Note about memory usage: arrays never shrink automatically (although you may
48 use Shrink() function explicitly), they only grow, so loading 10 millions in
49 an array only to delete them 2 lines below might be a bad idea if the array
50 object is not going to be destroyed soon. However, as it does free memory
51 when destroyed, it is ok if the array is a local variable.
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
59 The initial size by which an array grows when an element is added default
60 value avoids allocate one or two bytes when the array is created which is
63 #define WX_ARRAY_DEFAULT_INITIAL_SIZE (16)
65 // ----------------------------------------------------------------------------
67 // ----------------------------------------------------------------------------
70 Callback compare function for quick sort.
72 It must return negative value, 0 or positive value if the first item is
73 less than, equal to or greater than the second one.
77 typedef int (wxCMPFUNC_CONV
*CMPFUNC
)(const void* pItem1
, const void* pItem2
);
80 // ----------------------------------------------------------------------------
81 // Base class managing data having size of type 'long' (not used directly)
83 // NB: for efficiency this often used class has no virtual functions (hence no
84 // virtual table), even dtor is *not* virtual. If used as expected it
85 // won't create any problems because ARRAYs from DEFINE_ARRAY have no dtor
86 // at all, so it's not too important if it's not called (this happens when
87 // you cast "SomeArray *" as "BaseArray *" and then delete it)
88 // ----------------------------------------------------------------------------
92 #define _WX_DECLARE_BASEARRAY(T, name, classexp) \
93 classexp name : public std::vector<T> \
96 void Empty() { clear(); } \
97 void Clear() { clear(); } \
98 void Alloc(size_t uiSize) { reserve(uiSize); } \
101 size_t GetCount() const { return size(); } \
102 void SetCount(size_t n, T v = T()) { resize(n, v); } \
103 bool IsEmpty() const { return empty(); } \
104 size_t Count() const { return size(); } \
106 typedef T base_type; \
109 T& Item(size_t uiIndex) const \
110 { wxASSERT( uiIndex < size() ); return (T&)operator[](uiIndex); } \
112 int Index(T e, bool bFromEnd = FALSE) const; \
113 int Index(T lItem, CMPFUNC fnCompare) const; \
114 size_t IndexForInsert(T lItem, CMPFUNC fnCompare) const; \
115 void Add(T lItem, size_t nInsert = 1) \
116 { insert(end(), nInsert, lItem); } \
117 void Add(T lItem, CMPFUNC fnCompare); \
118 void Insert(T lItem, size_t uiIndex, size_t nInsert = 1) \
119 { insert(begin() + uiIndex, nInsert, lItem); } \
120 void Remove(T lItem); \
121 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
122 { erase(begin() + uiIndex, begin() + uiIndex + nRemove); } \
124 void Sort(CMPFUNC fCmp) \
127 std::sort(begin(), end(), p); \
132 typedef CMPFUNC fnc; \
135 Predicate(fnc f) : m_f(f) { } \
136 bool operator()(const T& i1, const T& i2) \
137 { return m_f((T*)&i1, (T*)&i2) < 0; /* const cast */ } \
141 #else // if !wxUSE_STL
143 #define _WX_DECLARE_BASEARRAY(T, name, classexp) \
148 name(const name& array); \
149 name& operator=(const name& src); \
152 void Empty() { m_nCount = 0; } \
154 void Alloc(size_t uiSize); \
157 size_t GetCount() const { return m_nCount; } \
158 void SetCount(size_t n, T defval = T(0)); \
159 bool IsEmpty() const { return m_nCount == 0; } \
160 size_t Count() const { return m_nCount; } \
162 typedef T base_type; \
165 T& Item(size_t uiIndex) const \
166 { wxASSERT( uiIndex < m_nCount ); return m_pItems[uiIndex]; } \
167 T& operator[](size_t uiIndex) const { return Item(uiIndex); } \
169 int Index(T lItem, bool bFromEnd = FALSE) const; \
170 int Index(T lItem, CMPFUNC fnCompare) const; \
171 size_t IndexForInsert(T lItem, CMPFUNC fnCompare) const; \
172 void Add(T lItem, size_t nInsert = 1); \
173 void Add(T lItem, CMPFUNC fnCompare); \
174 void Insert(T lItem, size_t uiIndex, size_t nInsert = 1); \
175 void Remove(T lItem); \
176 void RemoveAt(size_t uiIndex, size_t nRemove = 1); \
178 void Sort(CMPFUNC fnCompare); \
180 /* *minimal* STL-ish interface, for derived classes */ \
181 typedef T value_type; \
182 typedef value_type* iterator; \
183 typedef const value_type* const_iterator; \
184 typedef value_type& reference; \
185 typedef const value_type& const_reference; \
186 typedef int difference_type; \
187 typedef size_t size_type; \
189 void assign(const_iterator first, const_iterator last); \
190 void assign(size_type n, const_reference v); \
191 size_type capacity() const { return m_nSize; } \
192 void clear() { Clear(); } \
193 bool empty() const { return IsEmpty(); } \
194 iterator erase(iterator first, iterator last) \
196 size_type idx = first - begin(); \
197 RemoveAt(idx, last - first); \
198 return begin() + idx; \
200 iterator erase(iterator it) { return erase(it, it + 1); } \
201 void insert(iterator it, size_type n, const value_type& v) \
202 { Insert(v, it - begin(), n); } \
203 iterator insert(iterator it, const value_type& v = value_type()) \
205 size_type idx = it - begin(); \
207 return begin() + idx; \
209 void insert(iterator it, const_iterator first, const_iterator last);\
210 size_type max_size() const { return INT_MAX; } \
211 void pop_back() { RemoveAt(size() - 1); } \
212 void push_back(const value_type& v) { Add(v); } \
213 void reserve(size_type n) { if(n > m_nSize) Realloc(n); } \
214 void resize(size_type n, value_type v = value_type()); \
215 size_type size() const { return GetCount(); } \
217 iterator begin() { return m_pItems; } \
218 iterator end() { return m_pItems + m_nCount; } \
219 const_iterator begin() const { return m_pItems; } \
220 const_iterator end() const { return m_pItems + m_nCount; } \
222 void Grow(size_t nIncrement = 0); \
223 bool Realloc(size_t nSize); \
233 // ============================================================================
234 // The private helper macros containing the core of the array classes
235 // ============================================================================
237 // Implementation notes:
239 // JACS: Salford C++ doesn't like 'var->operator=' syntax, as in:
240 // { ((wxBaseArray *)this)->operator=((const wxBaseArray&)src);
241 // so using a temporary variable instead.
243 // The classes need a (even trivial) ~name() to link under Mac X
245 // _WX_ERROR_REMOVE is needed to resolve the name conflict between the wxT()
246 // macro and T typedef: we can't use wxT() inside WX_DEFINE_ARRAY!
248 #define _WX_ERROR_REMOVE wxT("removing inexisting element in wxArray::Remove")
250 // ----------------------------------------------------------------------------
251 // _WX_DEFINE_TYPEARRAY: array for simple types
252 // ----------------------------------------------------------------------------
256 #define _WX_DEFINE_TYPEARRAY(T, name, base, classexp) \
257 typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2); \
258 classexp name : public base \
261 T& operator[](size_t uiIndex) const \
262 { return (T&)(base::operator[](uiIndex)); } \
263 T& Item(size_t uiIndex) const \
264 { return (T&)/*const cast*/base::operator[](uiIndex); } \
266 { return Item(Count() - 1); } \
268 int Index(T e, bool bFromEnd = FALSE) const \
269 { return base::Index(e, bFromEnd); } \
271 void Add(T Item, size_t nInsert = 1) \
272 { insert(end(), nInsert, Item); } \
273 void Insert(T Item, size_t uiIndex, size_t nInsert = 1) \
274 { insert(begin() + uiIndex, nInsert, Item); } \
276 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
277 { base::RemoveAt(uiIndex, nRemove); } \
278 void Remove(T Item) \
279 { int iIndex = Index(Item); \
280 wxCHECK2_MSG( iIndex != wxNOT_FOUND, return, \
282 RemoveAt((size_t)iIndex); } \
284 void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC)fCmp); } \
287 #else // if !wxUSE_STL
289 #define _WX_DEFINE_TYPEARRAY(T, name, base, classexp) \
290 wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type), \
291 TypeTooBigToBeStoredIn##base, \
293 typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2); \
294 classexp name : public base \
300 name& operator=(const name& src) \
301 { base* temp = (base*) this; \
302 (*temp) = ((const base&)src); \
305 T& operator[](size_t uiIndex) const \
306 { return (T&)(base::operator[](uiIndex)); } \
307 T& Item(size_t uiIndex) const \
308 { return (T&)(base::operator[](uiIndex)); } \
310 { return (T&)(base::operator[](Count() - 1)); } \
312 int Index(T Item, bool bFromEnd = FALSE) const \
313 { return base::Index((base_type)Item, bFromEnd); } \
315 void Add(T Item, size_t nInsert = 1) \
316 { base::Add((base_type)Item, nInsert); } \
317 void Insert(T Item, size_t uiIndex, size_t nInsert = 1) \
318 { base::Insert((base_type)Item, uiIndex, nInsert) ; } \
320 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
321 { base::RemoveAt(uiIndex, nRemove); } \
322 void Remove(T Item) \
323 { int iIndex = Index(Item); \
324 wxCHECK2_MSG( iIndex != wxNOT_FOUND, return, \
326 base::RemoveAt((size_t)iIndex); } \
328 void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC)fCmp); } \
330 /* STL-like interface */ \
332 typedef base::iterator biterator; \
333 typedef base::const_iterator bconst_iterator; \
334 typedef base::value_type bvalue_type; \
335 typedef base::const_reference bconst_reference; \
337 typedef T value_type; \
338 typedef value_type* pointer; \
339 typedef const value_type* const_pointer; \
340 typedef value_type* iterator; \
341 typedef const value_type* const_iterator; \
342 typedef value_type& reference; \
343 typedef const value_type& const_reference; \
344 typedef base::difference_type difference_type; \
345 typedef base::size_type size_type; \
347 class reverse_iterator \
349 typedef T value_type; \
350 typedef value_type& reference; \
351 typedef value_type* pointer; \
352 typedef reverse_iterator itor; \
353 friend itor operator+(int o, const itor& it); \
354 friend itor operator+(const itor& it, int o); \
355 friend itor operator-(const itor& it, int o); \
356 friend difference_type operator -(const itor& i1, const itor& i2);\
359 reverse_iterator() : m_ptr(NULL) { } \
360 reverse_iterator(pointer ptr) : m_ptr(ptr) { } \
361 reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { } \
362 reference operator*() const { return *m_ptr; } \
363 pointer operator->() const { return m_ptr; } \
364 itor operator++() { --m_ptr; return *this; } \
365 itor operator++(int) \
366 { reverse_iterator tmp = *this; --m_ptr; return tmp; } \
367 itor operator--() { ++m_ptr; return *this; } \
368 itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } \
369 bool operator ==(const itor& it) { return m_ptr == it.m_ptr; } \
370 bool operator !=(const itor& it) { return m_ptr != it.m_ptr; } \
373 class const_reverse_iterator \
375 typedef T value_type; \
376 typedef const value_type& reference; \
377 typedef const value_type* pointer; \
378 typedef const_reverse_iterator itor; \
379 friend itor operator+(int o, const itor& it); \
380 friend itor operator+(const itor& it, int o); \
381 friend itor operator-(const itor& it, int o); \
382 friend difference_type operator -(const itor& i1, const itor& i2);\
385 const_reverse_iterator() : m_ptr(NULL) { } \
386 const_reverse_iterator(pointer ptr) : m_ptr(ptr) { } \
387 const_reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { } \
388 const_reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { }\
389 reference operator*() const { return *m_ptr; } \
390 pointer operator->() const { return m_ptr; } \
391 itor operator++() { --m_ptr; return *this; } \
392 itor operator++(int) \
393 { itor tmp = *this; --m_ptr; return tmp; } \
394 itor operator--() { ++m_ptr; return *this; } \
395 itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } \
396 bool operator ==(const itor& it) { return m_ptr == it.m_ptr; } \
397 bool operator !=(const itor& it) { return m_ptr != it.m_ptr; } \
400 void assign(const_iterator first, const_iterator last) \
401 { base::assign((bconst_iterator)first, (bconst_iterator)last); } \
402 void assign(size_type n, const_reference v) \
403 { base::assign(n, (bconst_reference)v); } \
404 reference back() { return *(end() - 1); } \
405 const_reference back() const { return *(end() - 1); } \
406 iterator begin() { return (iterator)base::begin(); } \
407 const_iterator begin() const { return (const_iterator)base::begin(); }\
408 size_type capacity() const { return base::capacity(); } \
409 void clear() { base::clear(); } \
410 bool empty() const { return base::empty(); } \
411 iterator end() { return (iterator)base::end(); } \
412 const_iterator end() const { return (const_iterator)base::end(); } \
413 iterator erase(iterator first, iterator last) \
414 { return (iterator)base::erase((biterator)first, (biterator)last); }\
415 iterator erase(iterator it) \
416 { return (iterator)base::erase((biterator)it); } \
417 reference front() { return *begin(); } \
418 const_reference front() const { return *begin(); } \
419 void insert(iterator it, size_type n, const_reference v) \
420 { base::insert((biterator)it, n, (bconst_reference)v); } \
421 iterator insert(iterator it, const_reference v = value_type()) \
422 { return (iterator)base::insert((biterator)it, (bconst_reference)v); }\
423 void insert(iterator it, const_iterator first, const_iterator last) \
424 { base::insert((biterator)it, (bconst_iterator)first, \
425 (bconst_iterator)last); } \
426 size_type max_size() const { return base::max_size(); } \
427 void pop_back() { base::pop_back(); } \
428 void push_back(const_reference v) \
429 { base::push_back((bconst_reference)v); } \
430 reverse_iterator rbegin() { return reverse_iterator(end() - 1); } \
431 const_reverse_iterator rbegin() const; \
432 reverse_iterator rend() { return reverse_iterator(begin() - 1); } \
433 const_reverse_iterator rend() const; \
434 void reserve(size_type n) { base::reserve(n); }; \
435 void resize(size_type n, value_type v = value_type()); \
436 size_type size() const { return base::size(); } \
439 inline name::reverse_iterator operator+(int o, const name::reverse_iterator& it) { return it.m_ptr - o; } \
440 inline name::reverse_iterator operator+(const name::reverse_iterator& it, int o) { return it.m_ptr - o; } \
441 inline name::reverse_iterator operator-(const name::reverse_iterator& it, int o) { return it.m_ptr + o; } \
442 inline name::difference_type operator -(const name::reverse_iterator& i1, \
443 const name::reverse_iterator& i2) \
444 { return i1.m_ptr - i2.m_ptr; } \
446 inline name::const_reverse_iterator operator+(int o, const name::const_reverse_iterator& it) { return it.m_ptr - o; } \
447 inline name::const_reverse_iterator operator+(const name::const_reverse_iterator& it, int o) { return it.m_ptr - o; } \
448 inline name::const_reverse_iterator operator-(const name::const_reverse_iterator& it, int o) { return it.m_ptr + o; } \
449 inline name::difference_type operator -(const name::const_reverse_iterator& i1,\
450 const name::const_reverse_iterator& i2) \
451 { return i1.m_ptr - i2.m_ptr; } \
455 // ----------------------------------------------------------------------------
456 // _WX_DEFINE_SORTED_TYPEARRAY: sorted array for simple data types
457 // cannot handle types with size greater than pointer because of sorting
458 // ----------------------------------------------------------------------------
460 #define _WX_DEFINE_SORTED_TYPEARRAY(T, name, base, defcomp, classexp) \
461 typedef int (CMPFUNC_CONV *SCMPFUNC##T)(T pItem1, T pItem2); \
462 _WX_DEFINE_SORTED_TYPEARRAY_2(T, name, base, defcomp, classexp, SCMPFUNC##T)
464 #define _WX_DEFINE_SORTED_TYPEARRAY_2(T, name, base, defcomp, classexp, comptype)\
465 wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(void *), \
466 TypeTooBigToBeStoredInSorted##base, \
468 classexp name : public base \
471 name(comptype fn defcomp) { m_fnCompare = fn; } \
473 name& operator=(const name& src) \
474 { base* temp = (base*) this; \
475 (*temp) = ((const base&)src); \
476 m_fnCompare = src.m_fnCompare; \
479 T& operator[](size_t uiIndex) const \
480 { return (T&)(base::operator[](uiIndex)); } \
481 T& Item(size_t uiIndex) const \
482 { return (T&)(base::operator[](uiIndex)); } \
484 { return (T&)(base::operator[](size() - 1)); } \
486 int Index(T Item) const \
487 { return base::Index(Item, (CMPFUNC)m_fnCompare); } \
489 size_t IndexForInsert(T Item) const \
490 { return base::IndexForInsert(Item, (CMPFUNC)m_fnCompare); } \
492 void AddAt(T item, size_t index) \
493 { base::insert(begin() + index, item); } \
496 { base::Add(Item, (CMPFUNC)m_fnCompare); } \
498 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
499 { base::erase(begin() + uiIndex, begin() + uiIndex + nRemove); } \
500 void Remove(T Item) \
501 { int iIndex = Index(Item); \
502 wxCHECK2_MSG( iIndex != wxNOT_FOUND, return, \
503 _WX_ERROR_REMOVE ); \
504 base::erase(begin() + iIndex); } \
507 comptype m_fnCompare; \
511 // ----------------------------------------------------------------------------
512 // _WX_DECLARE_OBJARRAY: an array for pointers to type T with owning semantics
513 // ----------------------------------------------------------------------------
515 #define _WX_DECLARE_OBJARRAY(T, name, base, classexp) \
516 typedef int (CMPFUNC_CONV *CMPFUNC##T)(T **pItem1, T **pItem2); \
517 classexp name : protected base \
519 typedef int (CMPFUNC_CONV *CMPFUNC##base)(void **pItem1, void **pItem2); \
520 typedef base base_array; \
523 name(const name& src); \
524 name& operator=(const name& src); \
528 void Alloc(size_t count) { reserve(count); } \
529 size_t GetCount() const { return base_array::size(); } \
530 size_t size() const { return base_array::size(); } \
531 bool IsEmpty() const { return base_array::empty(); } \
532 size_t Count() const { return base_array::size(); } \
533 void Shrink() { base::Shrink(); } \
535 T& operator[](size_t uiIndex) const \
536 { return *(T*)base::operator[](uiIndex); } \
537 T& Item(size_t uiIndex) const \
538 { return *(T*)base::operator[](uiIndex); } \
540 { return *(T*)(base::operator[](size() - 1)); } \
542 int Index(const T& Item, bool bFromEnd = FALSE) const; \
544 void Add(const T& Item, size_t nInsert = 1); \
545 void Add(const T* pItem) \
546 { base::push_back((T*)pItem); } \
547 void push_back(const T* pItem) \
548 { base::push_back((T*)pItem); } \
549 void push_back(const T& Item) \
552 void Insert(const T& Item, size_t uiIndex, size_t nInsert = 1); \
553 void Insert(const T* pItem, size_t uiIndex) \
554 { base::insert(begin() + uiIndex, (T*)pItem); } \
556 void Empty() { DoEmpty(); base::clear(); } \
557 void Clear() { DoEmpty(); base::clear(); } \
559 T* Detach(size_t uiIndex) \
560 { T* p = (T*)base::operator[](uiIndex); \
561 base::erase(begin() + uiIndex); return p; } \
562 void RemoveAt(size_t uiIndex, size_t nRemove = 1); \
564 void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC##base)fCmp); } \
568 void DoCopy(const name& src); \
571 // ============================================================================
572 // The public macros for declaration and definition of the dynamic arrays
573 // ============================================================================
575 // Please note that for each macro WX_FOO_ARRAY we also have
576 // WX_FOO_EXPORTED_ARRAY and WX_FOO_USER_EXPORTED_ARRAY which are exactly the
577 // same except that they use an additional __declspec(dllexport) or equivalent
578 // under Windows if needed.
580 // The first (just EXPORTED) macros do it if wxWindows was compiled as a DLL
581 // and so must be used used inside the library. The second kind (USER_EXPORTED)
582 // allow the user code to do it when it wants. This is needed if you have a dll
583 // that wants to export a wxArray daubed with your own import/export goo.
585 // Finally, you can define the macro below as something special to modify the
586 // arrays defined by a simple WX_FOO_ARRAY as well. By default is is empty.
587 #define wxARRAY_DEFAULT_EXPORT
589 // ----------------------------------------------------------------------------
590 // WX_DECLARE_BASEARRAY(T, name) declare an array class named "name" containing
591 // the elements of type T
592 // ----------------------------------------------------------------------------
594 #define WX_DECLARE_BASEARRAY(T, name) \
595 WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, wxARRAY_DEFAULT_EXPORT)
597 #define WX_DECLARE_EXPORTED_BASEARRAY(T, name) \
598 WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, WXDLLEXPORT)
600 #define WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, expmode) \
601 typedef T _wxArray##name; \
602 _WX_DECLARE_BASEARRAY(_wxArray##name, name, class expmode)
604 // ----------------------------------------------------------------------------
605 // WX_DEFINE_TYPEARRAY(T, name, base) define an array class named "name" deriving
606 // from class "base" containing the elements of type T
608 // Note that the class defined has only inline function and doesn't take any
609 // space at all so there is no size penalty for defining multiple array classes
610 // ----------------------------------------------------------------------------
612 #define WX_DEFINE_TYPEARRAY(T, name, base) \
613 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, class wxARRAY_DEFAULT_EXPORT)
615 #define WX_DEFINE_EXPORTED_TYPEARRAY(T, name, base) \
616 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, class WXDLLEXPORT)
618 #define WX_DEFINE_USER_EXPORTED_TYPEARRAY(T, name, base, expdecl) \
619 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, class expdecl)
621 #define WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, classdecl) \
622 typedef T _wxArray##name; \
623 _WX_DEFINE_TYPEARRAY(_wxArray##name, name, base, classdecl)
625 // ----------------------------------------------------------------------------
626 // WX_DEFINE_SORTED_TYPEARRAY: this is the same as the previous macro, but it
627 // defines a sorted array.
630 // 1) it must be given a COMPARE function in ctor which takes 2 items of type
631 // T* and should return -1, 0 or +1 if the first one is less/greater
632 // than/equal to the second one.
633 // 2) the Add() method inserts the item in such was that the array is always
634 // sorted (it uses the COMPARE function)
635 // 3) it has no Sort() method because it's always sorted
636 // 4) Index() method is much faster (the sorted arrays use binary search
637 // instead of linear one), but Add() is slower.
638 // 5) there is no Insert() method because you can't insert an item into the
639 // given position in a sorted array but there is IndexForInsert()/AddAt()
640 // pair which may be used to optimize a common operation of "insert only if
643 // Note that you have to specify the comparison function when creating the
644 // objects of this array type. If, as in 99% of cases, the comparison function
645 // is the same for all objects of a class, WX_DEFINE_SORTED_TYPEARRAY_CMP below
646 // is more convenient.
648 // Summary: use this class when the speed of Index() function is important, use
649 // the normal arrays otherwise.
650 // ----------------------------------------------------------------------------
652 #define wxARRAY_EMPTY_CMP
654 #define WX_DEFINE_SORTED_TYPEARRAY(T, name, base) \
655 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, \
656 wxARRAY_DEFAULT_EXPORT)
658 #define WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, base) \
659 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, WXDLLEXPORT)
661 #define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, expmode) \
662 typedef T _wxArray##name; \
663 _WX_DEFINE_SORTED_TYPEARRAY(_wxArray##name, name, base, \
664 wxARRAY_EMPTY_CMP, class expmode)
666 // ----------------------------------------------------------------------------
667 // WX_DEFINE_SORTED_TYPEARRAY_CMP: exactly the same as above but the comparison
668 // function is provided by this macro and the objects of this class have a
669 // default constructor which just uses it.
671 // The arguments are: the element type, the comparison function and the array
674 // NB: this is, of course, how WX_DEFINE_SORTED_TYPEARRAY() should have worked
675 // from the very beginning - unfortunately I didn't think about this earlier
676 // ----------------------------------------------------------------------------
678 #define WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, base) \
679 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base, \
680 wxARRAY_DEFAULT_EXPORT)
682 #define WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base) \
683 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base, \
686 #define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base, \
688 typedef T _wxArray##name; \
689 _WX_DEFINE_SORTED_TYPEARRAY(_wxArray##name, name, base, = cmpfunc, \
692 // ----------------------------------------------------------------------------
693 // WX_DECLARE_OBJARRAY(T, name): this macro generates a new array class
694 // named "name" which owns the objects of type T it contains, i.e. it will
695 // delete them when it is destroyed.
697 // An element is of type T*, but arguments of type T& are taken (see below!)
698 // and T& is returned.
700 // Don't use this for simple types such as "int" or "long"!
702 // Note on Add/Insert functions:
703 // 1) function(T*) gives the object to the array, i.e. it will delete the
704 // object when it's removed or in the array's dtor
705 // 2) function(T&) will create a copy of the object and work with it
708 // 1) Remove() will delete the object after removing it from the array
709 // 2) Detach() just removes the object from the array (returning pointer to it)
711 // NB1: Base type T should have an accessible copy ctor if Add(T&) is used
712 // NB2: Never ever cast a array to it's base type: as dtor is not virtual
713 // and so you risk having at least the memory leaks and probably worse
715 // Some functions of this class are not inline, so it takes some space to
716 // define new class from this template even if you don't use it - which is not
717 // the case for the simple (non-object) array classes
719 // To use an objarray class you must
720 // #include "dynarray.h"
721 // WX_DECLARE_OBJARRAY(element_type, list_class_name)
722 // #include "arrimpl.cpp"
723 // WX_DEFINE_OBJARRAY(list_class_name) // name must be the same as above!
725 // This is necessary because at the moment of DEFINE_OBJARRAY class parsing the
726 // element_type must be fully defined (i.e. forward declaration is not
727 // enough), while WX_DECLARE_OBJARRAY may be done anywhere. The separation of
728 // two allows to break cicrcular dependencies with classes which have member
729 // variables of objarray type.
730 // ----------------------------------------------------------------------------
732 #define WX_DECLARE_OBJARRAY(T, name) \
733 WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, wxARRAY_DEFAULT_EXPORT)
735 #define WX_DECLARE_EXPORTED_OBJARRAY(T, name) \
736 WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLEXPORT)
738 #define WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, expmode) \
739 typedef T _wxObjArray##name; \
740 _WX_DECLARE_OBJARRAY(_wxObjArray##name, name, wxArrayPtrVoid, class expmode)
742 // WX_DEFINE_OBJARRAY is going to be redefined when arrimpl.cpp is included,
743 // try to provoke a human-understandable error if it used incorrectly.
745 // there is no real need for 3 different macros in the DEFINE case but do it
746 // anyhow for consistency
747 #define WX_DEFINE_OBJARRAY(name) DidYouIncludeArrimplCpp
748 #define WX_DEFINE_EXPORTED_OBJARRAY(name) WX_DEFINE_OBJARRAY(name)
749 #define WX_DEFINE_USER_EXPORTED_OBJARRAY(name) WX_DEFINE_OBJARRAY(name)
751 // ----------------------------------------------------------------------------
752 // Some commonly used predefined base arrays
753 // ----------------------------------------------------------------------------
755 WX_DECLARE_USER_EXPORTED_BASEARRAY(const void *, wxBaseArrayPtrVoid
,
757 WX_DECLARE_USER_EXPORTED_BASEARRAY(short, wxBaseArrayShort
,
759 WX_DECLARE_USER_EXPORTED_BASEARRAY(int, wxBaseArrayInt
,
761 WX_DECLARE_USER_EXPORTED_BASEARRAY(long, wxBaseArrayLong
,
763 WX_DECLARE_USER_EXPORTED_BASEARRAY(double, wxBaseArrayDouble
,
766 // ----------------------------------------------------------------------------
767 // Convenience macros to define arrays from base arrays
768 // ----------------------------------------------------------------------------
770 #define WX_DEFINE_ARRAY(T, name) \
771 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayPtrVoid)
772 #define WX_DEFINE_EXPORTED_ARRAY(T, name) \
773 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)
774 #define WX_DEFINE_USER_EXPORTED_ARRAY(T, name, expmode) \
775 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayPtrVoid, expmode)
777 #define WX_DEFINE_ARRAY_SHORT(T, name) \
778 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayShort)
779 #define WX_DEFINE_EXPORTED_ARRAY_SHORT(T, name) \
780 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayShort)
781 #define WX_DEFINE_USER_EXPORTED_ARRAY_SHORT(T, name, expmode) \
782 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayShort, expmode)
784 #define WX_DEFINE_ARRAY_INT(T, name) \
785 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayInt)
786 #define WX_DEFINE_EXPORTED_ARRAY_INT(T, name) \
787 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayInt)
788 #define WX_DEFINE_USER_EXPORTED_ARRAY_INT(T, name, expmode) \
789 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayInt, expmode)
791 #define WX_DEFINE_ARRAY_LONG(T, name) \
792 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayLong)
793 #define WX_DEFINE_EXPORTED_ARRAY_LONG(T, name) \
794 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayLong)
795 #define WX_DEFINE_USER_EXPORTED_ARRAY_LONG(T, name, expmode) \
796 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayLong, expmode)
798 #define WX_DEFINE_ARRAY_DOUBLE(T, name) \
799 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayDouble)
800 #define WX_DEFINE_EXPORTED_ARRAY_DOUBLE(T, name) \
801 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayDouble)
802 #define WX_DEFINE_USER_EXPORTED_ARRAY_DOUBLE(T, name, expmode) \
803 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayDouble, expmode)
805 // ----------------------------------------------------------------------------
806 // Convenience macros to define sorted arrays from base arrays
807 // ----------------------------------------------------------------------------
809 #define WX_DEFINE_SORTED_ARRAY(T, name) \
810 WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)
811 #define WX_DEFINE_SORTED_EXPORTED_ARRAY(T, name) \
812 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)
813 #define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY(T, name, expmode) \
814 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid, expmode)
816 #define WX_DEFINE_SORTED_ARRAY_SHORT(T, name) \
817 WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayShort)
818 #define WX_DEFINE_SORTED_EXPORTED_ARRAY_SHORT(T, name) \
819 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayShort)
820 #define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SHORT(T, name, expmode) \
821 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayShort, expmode)
823 #define WX_DEFINE_SORTED_ARRAY_INT(T, name) \
824 WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayInt)
825 #define WX_DEFINE_SORTED_EXPORTED_ARRAY_INT(T, name) \
826 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayInt)
827 #define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_INT(T, name, expmode) \
828 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayInt, expmode)
830 #define WX_DEFINE_SORTED_ARRAY_LONG(T, name) \
831 WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayLong)
832 #define WX_DEFINE_SORTED_EXPORTED_ARRAY_LONG(T, name) \
833 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayLong)
834 #define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_LONG(T, name, expmode) \
835 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayLong, expmode)
837 // ----------------------------------------------------------------------------
838 // Convenience macros to define sorted arrays from base arrays
839 // ----------------------------------------------------------------------------
841 #define WX_DEFINE_SORTED_ARRAY_CMP(T, cmpfunc, name) \
842 WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayPtrVoid)
843 #define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP(T, cmpfunc, name) \
844 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayPtrVoid)
845 #define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP(T, cmpfunc, \
847 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, \
848 wxBaseArrayPtrVoid, expmode)
850 #define WX_DEFINE_SORTED_ARRAY_CMP_SHORT(T, cmpfunc, name) \
851 WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayShort)
852 #define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_SHORT(T, cmpfunc, name) \
853 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayShort)
854 #define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_SHORT(T, cmpfunc, \
856 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, \
857 wxBaseArrayShort, expmode)
859 #define WX_DEFINE_SORTED_ARRAY_CMP_INT(T, cmpfunc, name) \
860 WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayInt)
861 #define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_INT(T, cmpfunc, name) \
862 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayInt)
863 #define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_INT(T, cmpfunc, \
865 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, \
866 wxBaseArrayInt, expmode)
868 #define WX_DEFINE_SORTED_ARRAY_CMP_LONG(T, cmpfunc, name) \
869 WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayLong)
870 #define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_LONG(T, cmpfunc, name) \
871 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayLong)
872 #define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_LONG(T, cmpfunc, \
874 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, \
875 wxBaseArrayLong, expmode)
877 // ----------------------------------------------------------------------------
878 // Some commonly used predefined arrays
879 // ----------------------------------------------------------------------------
881 WX_DEFINE_USER_EXPORTED_ARRAY_SHORT (short, wxArrayShort
, class WXDLLIMPEXP_BASE
);
882 WX_DEFINE_USER_EXPORTED_ARRAY_INT (int, wxArrayInt
, class WXDLLIMPEXP_BASE
);
883 WX_DEFINE_USER_EXPORTED_ARRAY_LONG (long, wxArrayLong
, class WXDLLIMPEXP_BASE
);
884 WX_DEFINE_USER_EXPORTED_ARRAY (void *, wxArrayPtrVoid
, class WXDLLIMPEXP_BASE
);
886 // -----------------------------------------------------------------------------
887 // convenience macros
888 // -----------------------------------------------------------------------------
890 // append all element of one array to another one
891 #define WX_APPEND_ARRAY(array, other) \
893 size_t count = (other).size(); \
894 for ( size_t n = 0; n < count; n++ ) \
896 (array).push_back((other)[n]); \
900 // delete all array elements
902 // NB: the class declaration of the array elements must be visible from the
903 // place where you use this macro, otherwise the proper destructor may not
904 // be called (a decent compiler should give a warning about it, but don't
906 #define WX_CLEAR_ARRAY(array) \
908 size_t count = (array).size(); \
909 for ( size_t n = 0; n < count; n++ ) \
917 #endif // _DYNARRAY_H