]> git.saurik.com Git - wxWidgets.git/blame - include/wx/dynarray.h
don't break lines in the middle of word
[wxWidgets.git] / include / wx / dynarray.h
CommitLineData
c801d85f
KB
1///////////////////////////////////////////////////////////////////////////////
2// Name: dynarray.h
3// Purpose: auto-resizable (i.e. dynamic) array support
4// Author: Vadim Zeitlin
3bfa4402 5// Modified by:
c801d85f
KB
6// Created: 12.09.97
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
371a5b4e 9// Licence: wxWindows licence
c801d85f
KB
10///////////////////////////////////////////////////////////////////////////////
11
12#ifndef _DYNARRAY_H
13#define _DYNARRAY_H
14
df5168c4
MB
15#if defined(__GNUG__) && !defined(__APPLE__) && \
16 !(defined(__MINGW32__) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
c801d85f
KB
17#pragma interface "dynarray.h"
18#endif
19
20#include "wx/defs.h"
c801d85f 21
df5168c4
MB
22#if wxUSE_STL
23 #include "wx/beforestd.h"
24 #include <vector>
25 #include <algorithm>
26 #include "wx/afterstd.h"
df5168c4
MB
27#endif
28
1a931653
VZ
29/*
30 This header defines the dynamic arrays and object arrays (i.e. arrays which
31 own their elements). Dynamic means that the arrays grow automatically as
32 needed.
33
34 These macros are ugly (especially if you look in the sources ;-), but they
35 allow us to define "template" classes without actually using templates and so
36 this works with all compilers (and may be also much faster to compile even
37 with a compiler which does support templates). The arrays defined with these
38 macros are type-safe.
39
40 Range checking is performed in debug build for both arrays and objarrays but
41 not in release build - so using an invalid index will just lead to a crash
42 then.
43
44 Note about memory usage: arrays never shrink automatically (although you may
45 use Shrink() function explicitly), they only grow, so loading 10 millions in
46 an array only to delete them 2 lines below might be a bad idea if the array
47 object is not going to be destroyed soon. However, as it does free memory
48 when destroyed, it is ok if the array is a local variable.
49 */
c801d85f
KB
50
51// ----------------------------------------------------------------------------
52// constants
53// ----------------------------------------------------------------------------
54
1a931653
VZ
55/*
56 The initial size by which an array grows when an element is added default
57 value avoids allocate one or two bytes when the array is created which is
58 rather inefficient
c801d85f 59*/
1a931653 60#define WX_ARRAY_DEFAULT_INITIAL_SIZE (16)
c801d85f
KB
61
62// ----------------------------------------------------------------------------
63// types
64// ----------------------------------------------------------------------------
65
1a931653
VZ
66/*
67 Callback compare function for quick sort.
3b0b5f13 68
1a931653
VZ
69 It must return negative value, 0 or positive value if the first item is
70 less than, equal to or greater than the second one.
c801d85f 71 */
90350682
VZ
72extern "C"
73{
0661ec39 74typedef int (wxCMPFUNC_CONV *CMPFUNC)(const void* pItem1, const void* pItem2);
90350682 75}
c801d85f
KB
76
77// ----------------------------------------------------------------------------
1a931653
VZ
78// Base class managing data having size of type 'long' (not used directly)
79//
80// NB: for efficiency this often used class has no virtual functions (hence no
81// virtual table), even dtor is *not* virtual. If used as expected it
82// won't create any problems because ARRAYs from DEFINE_ARRAY have no dtor
83// at all, so it's not too important if it's not called (this happens when
84// you cast "SomeArray *" as "BaseArray *" and then delete it)
c801d85f 85// ----------------------------------------------------------------------------
1a931653 86
df5168c4
MB
87#if wxUSE_STL
88
89#define _WX_DECLARE_BASEARRAY(T, name, classexp) \
90classexp name : public std::vector<T> \
91{ \
92public: \
93 void Empty() { clear(); } \
94 void Clear() { clear(); } \
95 void Alloc(size_t uiSize) { reserve(uiSize); } \
96 void Shrink(); \
97 \
98 size_t GetCount() const { return size(); } \
99 void SetCount(size_t n, T v = T()) { resize(n, v); } \
100 bool IsEmpty() const { return empty(); } \
101 size_t Count() const { return size(); } \
102 \
103 typedef T base_type; \
104 \
105protected: \
106 T& Item(size_t uiIndex) const \
107 { wxASSERT( uiIndex < size() ); return (T&)operator[](uiIndex); } \
108 \
109 int Index(T e, bool bFromEnd = FALSE) const; \
110 int Index(T lItem, CMPFUNC fnCompare) const; \
111 size_t IndexForInsert(T lItem, CMPFUNC fnCompare) const; \
112 void Add(T lItem, size_t nInsert = 1) \
113 { insert(end(), nInsert, lItem); } \
6992d326 114 size_t Add(T lItem, CMPFUNC fnCompare); \
df5168c4
MB
115 void Insert(T lItem, size_t uiIndex, size_t nInsert = 1) \
116 { insert(begin() + uiIndex, nInsert, lItem); } \
117 void Remove(T lItem); \
118 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
119 { erase(begin() + uiIndex, begin() + uiIndex + nRemove); } \
120 \
121 void Sort(CMPFUNC fCmp) \
122 { \
123 Predicate p(fCmp); \
124 std::sort(begin(), end(), p); \
125 } \
126private: \
127 class Predicate \
128 { \
129 typedef CMPFUNC fnc; \
130 fnc m_f; \
131 public: \
132 Predicate(fnc f) : m_f(f) { } \
133 bool operator()(const T& i1, const T& i2) \
134 { return m_f((T*)&i1, (T*)&i2) < 0; /* const cast */ } \
135 }; \
136}
137
138#else // if !wxUSE_STL
139
5a1cad6e
GD
140#define _WX_DECLARE_BASEARRAY(T, name, classexp) \
141classexp name \
142{ \
143public: \
144 name(); \
145 name(const name& array); \
146 name& operator=(const name& src); \
147 ~name(); \
148 \
149 void Empty() { m_nCount = 0; } \
150 void Clear(); \
151 void Alloc(size_t uiSize); \
152 void Shrink(); \
153 \
2abb9d2f
VZ
154 size_t GetCount() const { return m_nCount; } \
155 void SetCount(size_t n, T defval = T(0)); \
156 bool IsEmpty() const { return m_nCount == 0; } \
157 size_t Count() const { return m_nCount; } \
5a1cad6e 158 \
75d7ef36 159 typedef T base_type; \
2abb9d2f 160 \
5a1cad6e
GD
161protected: \
162 T& Item(size_t uiIndex) const \
163 { wxASSERT( uiIndex < m_nCount ); return m_pItems[uiIndex]; } \
164 T& operator[](size_t uiIndex) const { return Item(uiIndex); } \
165 \
166 int Index(T lItem, bool bFromEnd = FALSE) const; \
167 int Index(T lItem, CMPFUNC fnCompare) const; \
168 size_t IndexForInsert(T lItem, CMPFUNC fnCompare) const; \
3b0b5f13 169 void Add(T lItem, size_t nInsert = 1); \
6992d326 170 size_t Add(T lItem, CMPFUNC fnCompare); \
3b0b5f13 171 void Insert(T lItem, size_t uiIndex, size_t nInsert = 1); \
5a1cad6e 172 void Remove(T lItem); \
3b0b5f13 173 void RemoveAt(size_t uiIndex, size_t nRemove = 1); \
5a1cad6e
GD
174 \
175 void Sort(CMPFUNC fnCompare); \
176 \
df5168c4
MB
177 /* *minimal* STL-ish interface, for derived classes */ \
178 typedef T value_type; \
179 typedef value_type* iterator; \
180 typedef const value_type* const_iterator; \
181 typedef value_type& reference; \
182 typedef const value_type& const_reference; \
183 typedef int difference_type; \
184 typedef size_t size_type; \
185 \
186 void assign(const_iterator first, const_iterator last); \
187 void assign(size_type n, const_reference v); \
188 size_type capacity() const { return m_nSize; } \
189 void clear() { Clear(); } \
190 bool empty() const { return IsEmpty(); } \
191 iterator erase(iterator first, iterator last) \
192 { \
193 size_type idx = first - begin(); \
194 RemoveAt(idx, last - first); \
195 return begin() + idx; \
196 } \
197 iterator erase(iterator it) { return erase(it, it + 1); } \
198 void insert(iterator it, size_type n, const value_type& v) \
199 { Insert(v, it - begin(), n); } \
200 iterator insert(iterator it, const value_type& v = value_type()) \
201 { \
202 size_type idx = it - begin(); \
203 Insert(v, idx); \
204 return begin() + idx; \
205 } \
206 void insert(iterator it, const_iterator first, const_iterator last);\
207 size_type max_size() const { return INT_MAX; } \
208 void pop_back() { RemoveAt(size() - 1); } \
209 void push_back(const value_type& v) { Add(v); } \
210 void reserve(size_type n) { if(n > m_nSize) Realloc(n); } \
211 void resize(size_type n, value_type v = value_type()); \
212 size_type size() const { return GetCount(); } \
213 \
214 iterator begin() { return m_pItems; } \
215 iterator end() { return m_pItems + m_nCount; } \
216 const_iterator begin() const { return m_pItems; } \
217 const_iterator end() const { return m_pItems + m_nCount; } \
5a1cad6e 218private: \
2abb9d2f
VZ
219 void Grow(size_t nIncrement = 0); \
220 bool Realloc(size_t nSize); \
5a1cad6e
GD
221 \
222 size_t m_nSize, \
223 m_nCount; \
224 \
225 T *m_pItems; \
e9bb94cf 226}
c801d85f 227
df5168c4
MB
228#endif // !wxUSE_STL
229
c801d85f 230// ============================================================================
1a931653 231// The private helper macros containing the core of the array classes
c801d85f
KB
232// ============================================================================
233
1a931653
VZ
234// Implementation notes:
235//
236// JACS: Salford C++ doesn't like 'var->operator=' syntax, as in:
237// { ((wxBaseArray *)this)->operator=((const wxBaseArray&)src);
238// so using a temporary variable instead.
239//
240// The classes need a (even trivial) ~name() to link under Mac X
241//
242// _WX_ERROR_REMOVE is needed to resolve the name conflict between the wxT()
5a1cad6e 243// macro and T typedef: we can't use wxT() inside WX_DEFINE_ARRAY!
1a931653
VZ
244
245#define _WX_ERROR_REMOVE wxT("removing inexisting element in wxArray::Remove")
e90c1d2a 246
c801d85f 247// ----------------------------------------------------------------------------
5a1cad6e 248// _WX_DEFINE_TYPEARRAY: array for simple types
c801d85f 249// ----------------------------------------------------------------------------
1a931653 250
df5168c4
MB
251#if wxUSE_STL
252
253#define _WX_DEFINE_TYPEARRAY(T, name, base, classexp) \
254typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2); \
255classexp name : public base \
256{ \
257public: \
258 T& operator[](size_t uiIndex) const \
259 { return (T&)(base::operator[](uiIndex)); } \
260 T& Item(size_t uiIndex) const \
261 { return (T&)/*const cast*/base::operator[](uiIndex); } \
262 T& Last() const \
263 { return Item(Count() - 1); } \
264 \
265 int Index(T e, bool bFromEnd = FALSE) const \
266 { return base::Index(e, bFromEnd); } \
267 \
268 void Add(T Item, size_t nInsert = 1) \
269 { insert(end(), nInsert, Item); } \
270 void Insert(T Item, size_t uiIndex, size_t nInsert = 1) \
271 { insert(begin() + uiIndex, nInsert, Item); } \
272 \
273 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
274 { base::RemoveAt(uiIndex, nRemove); } \
275 void Remove(T Item) \
276 { int iIndex = Index(Item); \
277 wxCHECK2_MSG( iIndex != wxNOT_FOUND, return, \
278 _WX_ERROR_REMOVE); \
279 RemoveAt((size_t)iIndex); } \
280 \
281 void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC)fCmp); } \
282}
283
284#else // if !wxUSE_STL
285
5a1cad6e
GD
286#define _WX_DEFINE_TYPEARRAY(T, name, base, classexp) \
287wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type), \
288 TypeTooBigToBeStoredIn##base, \
289 name); \
290typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2); \
291classexp name : public base \
292{ \
293public: \
294 name() { } \
295 ~name() { } \
296 \
297 name& operator=(const name& src) \
298 { base* temp = (base*) this; \
299 (*temp) = ((const base&)src); \
300 return *this; } \
301 \
302 T& operator[](size_t uiIndex) const \
df5168c4 303 { return (T&)(base::operator[](uiIndex)); } \
5a1cad6e 304 T& Item(size_t uiIndex) const \
df5168c4 305 { return (T&)(base::operator[](uiIndex)); } \
5a1cad6e 306 T& Last() const \
df5168c4 307 { return (T&)(base::operator[](Count() - 1)); } \
5a1cad6e
GD
308 \
309 int Index(T Item, bool bFromEnd = FALSE) const \
e38ed919 310 { return base::Index((base_type)Item, bFromEnd); } \
5a1cad6e 311 \
3b0b5f13 312 void Add(T Item, size_t nInsert = 1) \
e38ed919 313 { base::Add((base_type)Item, nInsert); } \
3b0b5f13 314 void Insert(T Item, size_t uiIndex, size_t nInsert = 1) \
e38ed919 315 { base::Insert((base_type)Item, uiIndex, nInsert) ; } \
5a1cad6e 316 \
3b0b5f13
VZ
317 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
318 { base::RemoveAt(uiIndex, nRemove); } \
5a1cad6e
GD
319 void Remove(T Item) \
320 { int iIndex = Index(Item); \
321 wxCHECK2_MSG( iIndex != wxNOT_FOUND, return, \
322 _WX_ERROR_REMOVE); \
323 base::RemoveAt((size_t)iIndex); } \
324 \
325 void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC)fCmp); } \
df5168c4
MB
326 \
327 /* STL-like interface */ \
328private: \
329 typedef base::iterator biterator; \
330 typedef base::const_iterator bconst_iterator; \
331 typedef base::value_type bvalue_type; \
332 typedef base::const_reference bconst_reference; \
333public: \
334 typedef T value_type; \
335 typedef value_type* pointer; \
336 typedef const value_type* const_pointer; \
337 typedef value_type* iterator; \
338 typedef const value_type* const_iterator; \
339 typedef value_type& reference; \
340 typedef const value_type& const_reference; \
341 typedef base::difference_type difference_type; \
342 typedef base::size_type size_type; \
343 \
344 class reverse_iterator \
345 { \
c514cd53
MB
346 typedef T value_type; \
347 typedef value_type& reference; \
348 typedef value_type* pointer; \
df5168c4 349 typedef reverse_iterator itor; \
31222b7c
VZ
350 friend inline itor operator+(int o, const itor& it) \
351 { return it.m_ptr - o; } \
352 friend inline itor operator+(const itor& it, int o) \
353 { return it.m_ptr - o; } \
354 friend inline itor operator-(const itor& it, int o) \
355 { return it.m_ptr + o; } \
356 friend inline difference_type operator-(const itor& i1, \
357 const itor& i2) \
358 { return i1.m_ptr - i2.m_ptr; } \
359 \
df5168c4
MB
360 public: \
361 pointer m_ptr; \
362 reverse_iterator() : m_ptr(NULL) { } \
363 reverse_iterator(pointer ptr) : m_ptr(ptr) { } \
364 reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { } \
365 reference operator*() const { return *m_ptr; } \
366 pointer operator->() const { return m_ptr; } \
367 itor operator++() { --m_ptr; return *this; } \
368 itor operator++(int) \
369 { reverse_iterator tmp = *this; --m_ptr; return tmp; } \
370 itor operator--() { ++m_ptr; return *this; } \
371 itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } \
372 bool operator ==(const itor& it) { return m_ptr == it.m_ptr; } \
373 bool operator !=(const itor& it) { return m_ptr != it.m_ptr; } \
374 }; \
375 \
376 class const_reverse_iterator \
377 { \
c514cd53
MB
378 typedef T value_type; \
379 typedef const value_type& reference; \
380 typedef const value_type* pointer; \
df5168c4 381 typedef const_reverse_iterator itor; \
31222b7c
VZ
382 friend inline itor operator+(int o, const itor& it) \
383 { return it.m_ptr - o; } \
384 friend inline itor operator+(const itor& it, int o) \
385 { return it.m_ptr - o; } \
386 friend inline itor operator-(const itor& it, int o) \
387 { return it.m_ptr + o; } \
388 friend inline difference_type operator-(const itor& i1, \
389 const itor& i2) \
390 { return i1.m_ptr - i2.m_ptr; } \
391 \
df5168c4
MB
392 public: \
393 pointer m_ptr; \
394 const_reverse_iterator() : m_ptr(NULL) { } \
395 const_reverse_iterator(pointer ptr) : m_ptr(ptr) { } \
396 const_reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { } \
397 const_reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { }\
398 reference operator*() const { return *m_ptr; } \
399 pointer operator->() const { return m_ptr; } \
400 itor operator++() { --m_ptr; return *this; } \
401 itor operator++(int) \
402 { itor tmp = *this; --m_ptr; return tmp; } \
403 itor operator--() { ++m_ptr; return *this; } \
404 itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } \
405 bool operator ==(const itor& it) { return m_ptr == it.m_ptr; } \
406 bool operator !=(const itor& it) { return m_ptr != it.m_ptr; } \
407 }; \
408 \
409 void assign(const_iterator first, const_iterator last) \
410 { base::assign((bconst_iterator)first, (bconst_iterator)last); } \
411 void assign(size_type n, const_reference v) \
412 { base::assign(n, (bconst_reference)v); } \
413 reference back() { return *(end() - 1); } \
414 const_reference back() const { return *(end() - 1); } \
415 iterator begin() { return (iterator)base::begin(); } \
416 const_iterator begin() const { return (const_iterator)base::begin(); }\
417 size_type capacity() const { return base::capacity(); } \
418 void clear() { base::clear(); } \
419 bool empty() const { return base::empty(); } \
420 iterator end() { return (iterator)base::end(); } \
421 const_iterator end() const { return (const_iterator)base::end(); } \
422 iterator erase(iterator first, iterator last) \
423 { return (iterator)base::erase((biterator)first, (biterator)last); }\
424 iterator erase(iterator it) \
425 { return (iterator)base::erase((biterator)it); } \
426 reference front() { return *begin(); } \
427 const_reference front() const { return *begin(); } \
428 void insert(iterator it, size_type n, const_reference v) \
429 { base::insert((biterator)it, n, (bconst_reference)v); } \
430 iterator insert(iterator it, const_reference v = value_type()) \
431 { return (iterator)base::insert((biterator)it, (bconst_reference)v); }\
432 void insert(iterator it, const_iterator first, const_iterator last) \
433 { base::insert((biterator)it, (bconst_iterator)first, \
434 (bconst_iterator)last); } \
435 size_type max_size() const { return base::max_size(); } \
436 void pop_back() { base::pop_back(); } \
437 void push_back(const_reference v) \
438 { base::push_back((bconst_reference)v); } \
439 reverse_iterator rbegin() { return reverse_iterator(end() - 1); } \
440 const_reverse_iterator rbegin() const; \
441 reverse_iterator rend() { return reverse_iterator(begin() - 1); } \
442 const_reverse_iterator rend() const; \
443 void reserve(size_type n) { base::reserve(n); }; \
444 void resize(size_type n, value_type v = value_type()); \
445 size_type size() const { return base::size(); } \
31222b7c
VZ
446}
447
df5168c4
MB
448
449#endif // !wxUSE_STL
c801d85f 450
3bfa4402 451// ----------------------------------------------------------------------------
5a1cad6e
GD
452// _WX_DEFINE_SORTED_TYPEARRAY: sorted array for simple data types
453// cannot handle types with size greater than pointer because of sorting
3bfa4402 454// ----------------------------------------------------------------------------
1a931653 455
df5168c4 456#define _WX_DEFINE_SORTED_TYPEARRAY_2(T, name, base, defcomp, classexp, comptype)\
335991af 457wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type), \
5a1cad6e
GD
458 TypeTooBigToBeStoredInSorted##base, \
459 name); \
5a1cad6e
GD
460classexp name : public base \
461{ \
462public: \
df5168c4 463 name(comptype fn defcomp) { m_fnCompare = fn; } \
5a1cad6e
GD
464 \
465 name& operator=(const name& src) \
466 { base* temp = (base*) this; \
467 (*temp) = ((const base&)src); \
468 m_fnCompare = src.m_fnCompare; \
469 return *this; } \
470 \
471 T& operator[](size_t uiIndex) const \
df5168c4 472 { return (T&)(base::operator[](uiIndex)); } \
5a1cad6e 473 T& Item(size_t uiIndex) const \
df5168c4 474 { return (T&)(base::operator[](uiIndex)); } \
5a1cad6e 475 T& Last() const \
df5168c4 476 { return (T&)(base::operator[](size() - 1)); } \
5a1cad6e
GD
477 \
478 int Index(T Item) const \
479 { return base::Index(Item, (CMPFUNC)m_fnCompare); } \
480 \
481 size_t IndexForInsert(T Item) const \
482 { return base::IndexForInsert(Item, (CMPFUNC)m_fnCompare); } \
483 \
484 void AddAt(T item, size_t index) \
df5168c4 485 { base::insert(begin() + index, item); } \
5a1cad6e 486 \
6992d326
MB
487 size_t Add(T Item) \
488 { return base::Add(Item, (CMPFUNC)m_fnCompare); } \
5a1cad6e 489 \
3b0b5f13 490 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
df5168c4 491 { base::erase(begin() + uiIndex, begin() + uiIndex + nRemove); } \
5a1cad6e
GD
492 void Remove(T Item) \
493 { int iIndex = Index(Item); \
494 wxCHECK2_MSG( iIndex != wxNOT_FOUND, return, \
495 _WX_ERROR_REMOVE ); \
df5168c4 496 base::erase(begin() + iIndex); } \
5a1cad6e
GD
497 \
498private: \
df5168c4 499 comptype m_fnCompare; \
3bfa4402
VZ
500}
501
df5168c4 502
c801d85f 503// ----------------------------------------------------------------------------
1a931653 504// _WX_DECLARE_OBJARRAY: an array for pointers to type T with owning semantics
c801d85f 505// ----------------------------------------------------------------------------
1a931653 506
5a1cad6e
GD
507#define _WX_DECLARE_OBJARRAY(T, name, base, classexp) \
508typedef int (CMPFUNC_CONV *CMPFUNC##T)(T **pItem1, T **pItem2); \
df5168c4 509classexp name : protected base \
5a1cad6e
GD
510{ \
511typedef int (CMPFUNC_CONV *CMPFUNC##base)(void **pItem1, void **pItem2); \
df5168c4 512typedef base base_array; \
5a1cad6e
GD
513public: \
514 name() { } \
515 name(const name& src); \
516 name& operator=(const name& src); \
517 \
518 ~name(); \
519 \
df5168c4
MB
520 void Alloc(size_t count) { reserve(count); } \
521 size_t GetCount() const { return base_array::size(); } \
522 size_t size() const { return base_array::size(); } \
523 bool IsEmpty() const { return base_array::empty(); } \
524 size_t Count() const { return base_array::size(); } \
525 void Shrink() { base::Shrink(); } \
526 \
5a1cad6e 527 T& operator[](size_t uiIndex) const \
df5168c4 528 { return *(T*)base::operator[](uiIndex); } \
5a1cad6e 529 T& Item(size_t uiIndex) const \
df5168c4 530 { return *(T*)base::operator[](uiIndex); } \
5a1cad6e 531 T& Last() const \
df5168c4 532 { return *(T*)(base::operator[](size() - 1)); } \
5a1cad6e
GD
533 \
534 int Index(const T& Item, bool bFromEnd = FALSE) const; \
535 \
3b0b5f13 536 void Add(const T& Item, size_t nInsert = 1); \
5a1cad6e 537 void Add(const T* pItem) \
df5168c4
MB
538 { base::push_back((T*)pItem); } \
539 void push_back(const T* pItem) \
540 { base::push_back((T*)pItem); } \
541 void push_back(const T& Item) \
542 { Add(Item); } \
5a1cad6e 543 \
3b0b5f13 544 void Insert(const T& Item, size_t uiIndex, size_t nInsert = 1); \
5a1cad6e 545 void Insert(const T* pItem, size_t uiIndex) \
df5168c4 546 { base::insert(begin() + uiIndex, (T*)pItem); } \
5a1cad6e 547 \
df5168c4
MB
548 void Empty() { DoEmpty(); base::clear(); } \
549 void Clear() { DoEmpty(); base::clear(); } \
5a1cad6e
GD
550 \
551 T* Detach(size_t uiIndex) \
df5168c4
MB
552 { T* p = (T*)base::operator[](uiIndex); \
553 base::erase(begin() + uiIndex); return p; } \
3b0b5f13 554 void RemoveAt(size_t uiIndex, size_t nRemove = 1); \
5a1cad6e
GD
555 \
556 void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC##base)fCmp); } \
557 \
558private: \
559 void DoEmpty(); \
560 void DoCopy(const name& src); \
c801d85f
KB
561}
562
1a931653
VZ
563// ============================================================================
564// The public macros for declaration and definition of the dynamic arrays
565// ============================================================================
566
567// Please note that for each macro WX_FOO_ARRAY we also have
568// WX_FOO_EXPORTED_ARRAY and WX_FOO_USER_EXPORTED_ARRAY which are exactly the
569// same except that they use an additional __declspec(dllexport) or equivalent
570// under Windows if needed.
571//
572// The first (just EXPORTED) macros do it if wxWindows was compiled as a DLL
573// and so must be used used inside the library. The second kind (USER_EXPORTED)
574// allow the user code to do it when it wants. This is needed if you have a dll
575// that wants to export a wxArray daubed with your own import/export goo.
576//
577// Finally, you can define the macro below as something special to modify the
578// arrays defined by a simple WX_FOO_ARRAY as well. By default is is empty.
579#define wxARRAY_DEFAULT_EXPORT
580
581// ----------------------------------------------------------------------------
5a1cad6e
GD
582// WX_DECLARE_BASEARRAY(T, name) declare an array class named "name" containing
583// the elements of type T
584// ----------------------------------------------------------------------------
585
586#define WX_DECLARE_BASEARRAY(T, name) \
587 WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, wxARRAY_DEFAULT_EXPORT)
588
589#define WX_DECLARE_EXPORTED_BASEARRAY(T, name) \
590 WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, WXDLLEXPORT)
591
592#define WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, expmode) \
593 typedef T _wxArray##name; \
594 _WX_DECLARE_BASEARRAY(_wxArray##name, name, class expmode)
595
596// ----------------------------------------------------------------------------
597// WX_DEFINE_TYPEARRAY(T, name, base) define an array class named "name" deriving
598// from class "base" containing the elements of type T
1a931653
VZ
599//
600// Note that the class defined has only inline function and doesn't take any
601// space at all so there is no size penalty for defining multiple array classes
c801d85f 602// ----------------------------------------------------------------------------
c801d85f 603
5a1cad6e 604#define WX_DEFINE_TYPEARRAY(T, name, base) \
68559fd5 605 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, class wxARRAY_DEFAULT_EXPORT)
1a931653 606
5a1cad6e 607#define WX_DEFINE_EXPORTED_TYPEARRAY(T, name, base) \
68559fd5 608 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, class WXDLLEXPORT)
1a931653 609
68559fd5
VZ
610#define WX_DEFINE_USER_EXPORTED_TYPEARRAY(T, name, base, expdecl) \
611 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, class expdecl)
612
613#define WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, classdecl) \
df5168c4 614 typedef T _wxArray##name; \
68559fd5 615 _WX_DEFINE_TYPEARRAY(_wxArray##name, name, base, classdecl)
1a931653
VZ
616
617// ----------------------------------------------------------------------------
5a1cad6e 618// WX_DEFINE_SORTED_TYPEARRAY: this is the same as the previous macro, but it
1a931653
VZ
619// defines a sorted array.
620//
621// Differences:
622// 1) it must be given a COMPARE function in ctor which takes 2 items of type
623// T* and should return -1, 0 or +1 if the first one is less/greater
624// than/equal to the second one.
625// 2) the Add() method inserts the item in such was that the array is always
626// sorted (it uses the COMPARE function)
627// 3) it has no Sort() method because it's always sorted
628// 4) Index() method is much faster (the sorted arrays use binary search
629// instead of linear one), but Add() is slower.
630// 5) there is no Insert() method because you can't insert an item into the
631// given position in a sorted array but there is IndexForInsert()/AddAt()
632// pair which may be used to optimize a common operation of "insert only if
633// not found"
634//
635// Note that you have to specify the comparison function when creating the
636// objects of this array type. If, as in 99% of cases, the comparison function
5a1cad6e
GD
637// is the same for all objects of a class, WX_DEFINE_SORTED_TYPEARRAY_CMP below
638// is more convenient.
1a931653
VZ
639//
640// Summary: use this class when the speed of Index() function is important, use
641// the normal arrays otherwise.
c801d85f
KB
642// ----------------------------------------------------------------------------
643
17e656b0
VZ
644#define wxARRAY_EMPTY_CMP
645
5a1cad6e
GD
646#define WX_DEFINE_SORTED_TYPEARRAY(T, name, base) \
647 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, \
648 wxARRAY_DEFAULT_EXPORT)
a497618a 649
5a1cad6e
GD
650#define WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, base) \
651 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, WXDLLEXPORT)
a497618a 652
5a1cad6e
GD
653#define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, expmode) \
654 typedef T _wxArray##name; \
3e49e577
MB
655 typedef int (CMPFUNC_CONV *SCMPFUNC##name)(T pItem1, T pItem2); \
656 _WX_DEFINE_SORTED_TYPEARRAY_2(_wxArray##name, name, base, \
657 wxARRAY_EMPTY_CMP, class expmode, SCMPFUNC##name)
1a931653
VZ
658
659// ----------------------------------------------------------------------------
5a1cad6e 660// WX_DEFINE_SORTED_TYPEARRAY_CMP: exactly the same as above but the comparison
1a931653
VZ
661// function is provided by this macro and the objects of this class have a
662// default constructor which just uses it.
663//
664// The arguments are: the element type, the comparison function and the array
665// name
666//
5a1cad6e
GD
667// NB: this is, of course, how WX_DEFINE_SORTED_TYPEARRAY() should have worked
668// from the very beginning - unfortunately I didn't think about this earlier
1a931653 669// ----------------------------------------------------------------------------
76314141 670
5a1cad6e
GD
671#define WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, base) \
672 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base, \
673 wxARRAY_DEFAULT_EXPORT)
76314141 674
5a1cad6e
GD
675#define WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base) \
676 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base, \
677 WXDLLEXPORT)
1a931653 678
5a1cad6e
GD
679#define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base, \
680 expmode) \
1a931653 681 typedef T _wxArray##name; \
3e49e577
MB
682 typedef int (CMPFUNC_CONV *SCMPFUNC##name)(T pItem1, T pItem2); \
683 _WX_DEFINE_SORTED_TYPEARRAY_2(_wxArray##name, name, base, = cmpfunc, \
684 class expmode, SCMPFUNC##name)
1a931653
VZ
685
686// ----------------------------------------------------------------------------
687// WX_DECLARE_OBJARRAY(T, name): this macro generates a new array class
688// named "name" which owns the objects of type T it contains, i.e. it will
689// delete them when it is destroyed.
690//
691// An element is of type T*, but arguments of type T& are taken (see below!)
692// and T& is returned.
693//
694// Don't use this for simple types such as "int" or "long"!
1a931653
VZ
695//
696// Note on Add/Insert functions:
697// 1) function(T*) gives the object to the array, i.e. it will delete the
698// object when it's removed or in the array's dtor
699// 2) function(T&) will create a copy of the object and work with it
700//
701// Also:
702// 1) Remove() will delete the object after removing it from the array
703// 2) Detach() just removes the object from the array (returning pointer to it)
704//
705// NB1: Base type T should have an accessible copy ctor if Add(T&) is used
706// NB2: Never ever cast a array to it's base type: as dtor is not virtual
707// and so you risk having at least the memory leaks and probably worse
708//
709// Some functions of this class are not inline, so it takes some space to
710// define new class from this template even if you don't use it - which is not
711// the case for the simple (non-object) array classes
712//
1a931653
VZ
713// To use an objarray class you must
714// #include "dynarray.h"
715// WX_DECLARE_OBJARRAY(element_type, list_class_name)
716// #include "arrimpl.cpp"
717// WX_DEFINE_OBJARRAY(list_class_name) // name must be the same as above!
718//
719// This is necessary because at the moment of DEFINE_OBJARRAY class parsing the
720// element_type must be fully defined (i.e. forward declaration is not
721// enough), while WX_DECLARE_OBJARRAY may be done anywhere. The separation of
722// two allows to break cicrcular dependencies with classes which have member
723// variables of objarray type.
724// ----------------------------------------------------------------------------
725
726#define WX_DECLARE_OBJARRAY(T, name) \
727 WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, wxARRAY_DEFAULT_EXPORT)
728
729#define WX_DECLARE_EXPORTED_OBJARRAY(T, name) \
730 WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLEXPORT)
731
732#define WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, expmode) \
733 typedef T _wxObjArray##name; \
5a1cad6e 734 _WX_DECLARE_OBJARRAY(_wxObjArray##name, name, wxArrayPtrVoid, class expmode)
1a931653
VZ
735
736// WX_DEFINE_OBJARRAY is going to be redefined when arrimpl.cpp is included,
737// try to provoke a human-understandable error if it used incorrectly.
738//
739// there is no real need for 3 different macros in the DEFINE case but do it
740// anyhow for consistency
741#define WX_DEFINE_OBJARRAY(name) DidYouIncludeArrimplCpp
742#define WX_DEFINE_EXPORTED_OBJARRAY(name) WX_DEFINE_OBJARRAY(name)
76314141 743#define WX_DEFINE_USER_EXPORTED_OBJARRAY(name) WX_DEFINE_OBJARRAY(name)
76314141 744
5a1cad6e
GD
745// ----------------------------------------------------------------------------
746// Some commonly used predefined base arrays
747// ----------------------------------------------------------------------------
748
eee614d3
VS
749WX_DECLARE_USER_EXPORTED_BASEARRAY(const void *, wxBaseArrayPtrVoid,
750 WXDLLIMPEXP_BASE);
751WX_DECLARE_USER_EXPORTED_BASEARRAY(short, wxBaseArrayShort,
752 WXDLLIMPEXP_BASE);
753WX_DECLARE_USER_EXPORTED_BASEARRAY(int, wxBaseArrayInt,
754 WXDLLIMPEXP_BASE);
755WX_DECLARE_USER_EXPORTED_BASEARRAY(long, wxBaseArrayLong,
756 WXDLLIMPEXP_BASE);
757WX_DECLARE_USER_EXPORTED_BASEARRAY(double, wxBaseArrayDouble,
758 WXDLLIMPEXP_BASE);
5a1cad6e
GD
759
760// ----------------------------------------------------------------------------
761// Convenience macros to define arrays from base arrays
762// ----------------------------------------------------------------------------
763
764#define WX_DEFINE_ARRAY(T, name) \
765 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayPtrVoid)
766#define WX_DEFINE_EXPORTED_ARRAY(T, name) \
767 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)
768#define WX_DEFINE_USER_EXPORTED_ARRAY(T, name, expmode) \
991023b4 769 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayPtrVoid, expmode)
5a1cad6e
GD
770
771#define WX_DEFINE_ARRAY_SHORT(T, name) \
772 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayShort)
773#define WX_DEFINE_EXPORTED_ARRAY_SHORT(T, name) \
774 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayShort)
775#define WX_DEFINE_USER_EXPORTED_ARRAY_SHORT(T, name, expmode) \
991023b4 776 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayShort, expmode)
5a1cad6e
GD
777
778#define WX_DEFINE_ARRAY_INT(T, name) \
779 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayInt)
780#define WX_DEFINE_EXPORTED_ARRAY_INT(T, name) \
781 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayInt)
782#define WX_DEFINE_USER_EXPORTED_ARRAY_INT(T, name, expmode) \
991023b4 783 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayInt, expmode)
5a1cad6e
GD
784
785#define WX_DEFINE_ARRAY_LONG(T, name) \
786 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayLong)
787#define WX_DEFINE_EXPORTED_ARRAY_LONG(T, name) \
788 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayLong)
789#define WX_DEFINE_USER_EXPORTED_ARRAY_LONG(T, name, expmode) \
991023b4 790 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayLong, expmode)
5a1cad6e
GD
791
792#define WX_DEFINE_ARRAY_DOUBLE(T, name) \
793 WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayDouble)
794#define WX_DEFINE_EXPORTED_ARRAY_DOUBLE(T, name) \
795 WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayDouble)
796#define WX_DEFINE_USER_EXPORTED_ARRAY_DOUBLE(T, name, expmode) \
991023b4 797 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayDouble, expmode)
5a1cad6e
GD
798
799// ----------------------------------------------------------------------------
800// Convenience macros to define sorted arrays from base arrays
801// ----------------------------------------------------------------------------
802
803#define WX_DEFINE_SORTED_ARRAY(T, name) \
804 WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)
805#define WX_DEFINE_SORTED_EXPORTED_ARRAY(T, name) \
806 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)
807#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY(T, name, expmode) \
808 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid, expmode)
809
810#define WX_DEFINE_SORTED_ARRAY_SHORT(T, name) \
811 WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayShort)
812#define WX_DEFINE_SORTED_EXPORTED_ARRAY_SHORT(T, name) \
813 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayShort)
814#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SHORT(T, name, expmode) \
815 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayShort, expmode)
816
817#define WX_DEFINE_SORTED_ARRAY_INT(T, name) \
818 WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayInt)
819#define WX_DEFINE_SORTED_EXPORTED_ARRAY_INT(T, name) \
820 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayInt)
821#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_INT(T, name, expmode) \
822 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayInt, expmode)
823
824#define WX_DEFINE_SORTED_ARRAY_LONG(T, name) \
825 WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayLong)
826#define WX_DEFINE_SORTED_EXPORTED_ARRAY_LONG(T, name) \
827 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayLong)
828#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_LONG(T, name, expmode) \
829 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayLong, expmode)
830
831// ----------------------------------------------------------------------------
832// Convenience macros to define sorted arrays from base arrays
833// ----------------------------------------------------------------------------
834
835#define WX_DEFINE_SORTED_ARRAY_CMP(T, cmpfunc, name) \
836 WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayPtrVoid)
837#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP(T, cmpfunc, name) \
838 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayPtrVoid)
839#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP(T, cmpfunc, \
840 name, expmode) \
841 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, \
842 wxBaseArrayPtrVoid, expmode)
843
844#define WX_DEFINE_SORTED_ARRAY_CMP_SHORT(T, cmpfunc, name) \
845 WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayShort)
846#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_SHORT(T, cmpfunc, name) \
847 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayShort)
848#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_SHORT(T, cmpfunc, \
849 name, expmode) \
850 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, \
851 wxBaseArrayShort, expmode)
852
853#define WX_DEFINE_SORTED_ARRAY_CMP_INT(T, cmpfunc, name) \
854 WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayInt)
855#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_INT(T, cmpfunc, name) \
856 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayInt)
857#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_INT(T, cmpfunc, \
858 name, expmode) \
859 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, \
860 wxBaseArrayInt, expmode)
861
862#define WX_DEFINE_SORTED_ARRAY_CMP_LONG(T, cmpfunc, name) \
863 WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayLong)
864#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_LONG(T, cmpfunc, name) \
865 WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayLong)
866#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_LONG(T, cmpfunc, \
867 name, expmode) \
868 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, \
869 wxBaseArrayLong, expmode)
870
c801d85f 871// ----------------------------------------------------------------------------
1a931653 872// Some commonly used predefined arrays
c801d85f
KB
873// ----------------------------------------------------------------------------
874
991023b4
VS
875WX_DEFINE_USER_EXPORTED_ARRAY_SHORT (short, wxArrayShort, class WXDLLIMPEXP_BASE);
876WX_DEFINE_USER_EXPORTED_ARRAY_INT (int, wxArrayInt, class WXDLLIMPEXP_BASE);
877WX_DEFINE_USER_EXPORTED_ARRAY_LONG (long, wxArrayLong, class WXDLLIMPEXP_BASE);
878WX_DEFINE_USER_EXPORTED_ARRAY (void *, wxArrayPtrVoid, class WXDLLIMPEXP_BASE);
c801d85f 879
2b9bd418 880// -----------------------------------------------------------------------------
0cbff120 881// convenience macros
2b9bd418
VZ
882// -----------------------------------------------------------------------------
883
4f6aed9c
VZ
884// append all element of one array to another one
885#define WX_APPEND_ARRAY(array, other) \
886 { \
df5168c4 887 size_t count = (other).size(); \
4f6aed9c
VZ
888 for ( size_t n = 0; n < count; n++ ) \
889 { \
df5168c4 890 (array).push_back((other)[n]); \
4f6aed9c
VZ
891 } \
892 }
893
2b9bd418
VZ
894// delete all array elements
895//
896// NB: the class declaration of the array elements must be visible from the
897// place where you use this macro, otherwise the proper destructor may not
898// be called (a decent compiler should give a warning about it, but don't
899// count on it)!
900#define WX_CLEAR_ARRAY(array) \
901 { \
df5168c4 902 size_t count = (array).size(); \
2b9bd418
VZ
903 for ( size_t n = 0; n < count; n++ ) \
904 { \
5d5b1c0c 905 delete (array)[n]; \
2b9bd418 906 } \
2c356747 907 \
df5168c4 908 (array).clear(); \
2b9bd418 909 }
a497618a 910
c801d85f
KB
911#endif // _DYNARRAY_H
912