Move #inclusion of wx/msw/winundef.h for MinGW to afterstd.h.
[wxWidgets.git] / include / wx / dynarray.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dynarray.h
3 // Purpose: auto-resizable (i.e. dynamic) array support
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 12.09.97
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _DYNARRAY_H
13 #define _DYNARRAY_H
14
15 #if defined(__GNUG__) && !defined(__APPLE__) && \
16 !(defined(__MINGW32__) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
17 #pragma interface "dynarray.h"
18 #endif
19
20 #include "wx/defs.h"
21
22 #if wxUSE_STL
23 #include "wx/beforestd.h"
24 #include <vector>
25 #include <algorithm>
26 #include "wx/afterstd.h"
27 #endif
28
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 */
50
51 // ----------------------------------------------------------------------------
52 // constants
53 // ----------------------------------------------------------------------------
54
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
59 */
60 #define WX_ARRAY_DEFAULT_INITIAL_SIZE (16)
61
62 // ----------------------------------------------------------------------------
63 // types
64 // ----------------------------------------------------------------------------
65
66 /*
67 Callback compare function for quick sort.
68
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.
71 */
72 extern "C"
73 {
74 typedef int (wxCMPFUNC_CONV *CMPFUNC)(const void* pItem1, const void* pItem2);
75 }
76
77 // ----------------------------------------------------------------------------
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)
85 // ----------------------------------------------------------------------------
86
87 #if wxUSE_STL
88
89 #define _WX_DECLARE_BASEARRAY(T, name, classexp) \
90 classexp name : public std::vector<T> \
91 { \
92 public: \
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 \
105 protected: \
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); } \
114 size_t Add(T lItem, CMPFUNC fnCompare); \
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 } \
126 private: \
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
140 #define _WX_DECLARE_BASEARRAY(T, name, classexp) \
141 classexp name \
142 { \
143 public: \
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 \
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; } \
158 \
159 typedef T base_type; \
160 \
161 protected: \
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; \
169 void Add(T lItem, size_t nInsert = 1); \
170 size_t Add(T lItem, CMPFUNC fnCompare); \
171 void Insert(T lItem, size_t uiIndex, size_t nInsert = 1); \
172 void Remove(T lItem); \
173 void RemoveAt(size_t uiIndex, size_t nRemove = 1); \
174 \
175 void Sort(CMPFUNC fnCompare); \
176 \
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; } \
218 private: \
219 void Grow(size_t nIncrement = 0); \
220 bool Realloc(size_t nSize); \
221 \
222 size_t m_nSize, \
223 m_nCount; \
224 \
225 T *m_pItems; \
226 }
227
228 #endif // !wxUSE_STL
229
230 // ============================================================================
231 // The private helper macros containing the core of the array classes
232 // ============================================================================
233
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()
243 // macro and T typedef: we can't use wxT() inside WX_DEFINE_ARRAY!
244
245 #define _WX_ERROR_REMOVE wxT("removing inexisting element in wxArray::Remove")
246
247 // ----------------------------------------------------------------------------
248 // _WX_DEFINE_TYPEARRAY: array for simple types
249 // ----------------------------------------------------------------------------
250
251 #if wxUSE_STL
252
253 #define _WX_DEFINE_TYPEARRAY(T, name, base, classexp) \
254 typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2); \
255 classexp name : public base \
256 { \
257 public: \
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
286 #define _WX_DEFINE_TYPEARRAY(T, name, base, classexp) \
287 wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type), \
288 TypeTooBigToBeStoredIn##base, \
289 name); \
290 typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2); \
291 classexp name : public base \
292 { \
293 public: \
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 \
303 { return (T&)(base::operator[](uiIndex)); } \
304 T& Item(size_t uiIndex) const \
305 { return (T&)(base::operator[](uiIndex)); } \
306 T& Last() const \
307 { return (T&)(base::operator[](Count() - 1)); } \
308 \
309 int Index(T Item, bool bFromEnd = FALSE) const \
310 { return base::Index((base_type)Item, bFromEnd); } \
311 \
312 void Add(T Item, size_t nInsert = 1) \
313 { base::Add((base_type)Item, nInsert); } \
314 void Insert(T Item, size_t uiIndex, size_t nInsert = 1) \
315 { base::Insert((base_type)Item, uiIndex, nInsert) ; } \
316 \
317 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
318 { base::RemoveAt(uiIndex, nRemove); } \
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); } \
326 \
327 /* STL-like interface */ \
328 private: \
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; \
333 public: \
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 { \
346 typedef T value_type; \
347 typedef value_type& reference; \
348 typedef value_type* pointer; \
349 typedef reverse_iterator itor; \
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 \
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 { \
378 typedef T value_type; \
379 typedef const value_type& reference; \
380 typedef const value_type* pointer; \
381 typedef const_reverse_iterator itor; \
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 \
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(); } \
446 }
447
448
449 #endif // !wxUSE_STL
450
451 // ----------------------------------------------------------------------------
452 // _WX_DEFINE_SORTED_TYPEARRAY: sorted array for simple data types
453 // cannot handle types with size greater than pointer because of sorting
454 // ----------------------------------------------------------------------------
455
456 #define _WX_DEFINE_SORTED_TYPEARRAY_2(T, name, base, defcomp, classexp, comptype)\
457 wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type), \
458 TypeTooBigToBeStoredInSorted##base, \
459 name); \
460 classexp name : public base \
461 { \
462 public: \
463 name(comptype fn defcomp) { m_fnCompare = fn; } \
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 \
472 { return (T&)(base::operator[](uiIndex)); } \
473 T& Item(size_t uiIndex) const \
474 { return (T&)(base::operator[](uiIndex)); } \
475 T& Last() const \
476 { return (T&)(base::operator[](size() - 1)); } \
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) \
485 { base::insert(begin() + index, item); } \
486 \
487 size_t Add(T Item) \
488 { return base::Add(Item, (CMPFUNC)m_fnCompare); } \
489 \
490 void RemoveAt(size_t uiIndex, size_t nRemove = 1) \
491 { base::erase(begin() + uiIndex, begin() + uiIndex + nRemove); } \
492 void Remove(T Item) \
493 { int iIndex = Index(Item); \
494 wxCHECK2_MSG( iIndex != wxNOT_FOUND, return, \
495 _WX_ERROR_REMOVE ); \
496 base::erase(begin() + iIndex); } \
497 \
498 private: \
499 comptype m_fnCompare; \
500 }
501
502
503 // ----------------------------------------------------------------------------
504 // _WX_DECLARE_OBJARRAY: an array for pointers to type T with owning semantics
505 // ----------------------------------------------------------------------------
506
507 #define _WX_DECLARE_OBJARRAY(T, name, base, classexp) \
508 typedef int (CMPFUNC_CONV *CMPFUNC##T)(T **pItem1, T **pItem2); \
509 classexp name : protected base \
510 { \
511 typedef int (CMPFUNC_CONV *CMPFUNC##base)(void **pItem1, void **pItem2); \
512 typedef base base_array; \
513 public: \
514 name() { } \
515 name(const name& src); \
516 name& operator=(const name& src); \
517 \
518 ~name(); \
519 \
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 \
527 T& operator[](size_t uiIndex) const \
528 { return *(T*)base::operator[](uiIndex); } \
529 T& Item(size_t uiIndex) const \
530 { return *(T*)base::operator[](uiIndex); } \
531 T& Last() const \
532 { return *(T*)(base::operator[](size() - 1)); } \
533 \
534 int Index(const T& Item, bool bFromEnd = FALSE) const; \
535 \
536 void Add(const T& Item, size_t nInsert = 1); \
537 void Add(const T* pItem) \
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); } \
543 \
544 void Insert(const T& Item, size_t uiIndex, size_t nInsert = 1); \
545 void Insert(const T* pItem, size_t uiIndex) \
546 { base::insert(begin() + uiIndex, (T*)pItem); } \
547 \
548 void Empty() { DoEmpty(); base::clear(); } \
549 void Clear() { DoEmpty(); base::clear(); } \
550 \
551 T* Detach(size_t uiIndex) \
552 { T* p = (T*)base::operator[](uiIndex); \
553 base::erase(begin() + uiIndex); return p; } \
554 void RemoveAt(size_t uiIndex, size_t nRemove = 1); \
555 \
556 void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC##base)fCmp); } \
557 \
558 private: \
559 void DoEmpty(); \
560 void DoCopy(const name& src); \
561 }
562
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 // ----------------------------------------------------------------------------
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
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
602 // ----------------------------------------------------------------------------
603
604 #define WX_DEFINE_TYPEARRAY(T, name, base) \
605 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, class wxARRAY_DEFAULT_EXPORT)
606
607 #define WX_DEFINE_EXPORTED_TYPEARRAY(T, name, base) \
608 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, class WXDLLEXPORT)
609
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) \
614 typedef T _wxArray##name; \
615 _WX_DEFINE_TYPEARRAY(_wxArray##name, name, base, classdecl)
616
617 // ----------------------------------------------------------------------------
618 // WX_DEFINE_SORTED_TYPEARRAY: this is the same as the previous macro, but it
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
637 // is the same for all objects of a class, WX_DEFINE_SORTED_TYPEARRAY_CMP below
638 // is more convenient.
639 //
640 // Summary: use this class when the speed of Index() function is important, use
641 // the normal arrays otherwise.
642 // ----------------------------------------------------------------------------
643
644 #define wxARRAY_EMPTY_CMP
645
646 #define WX_DEFINE_SORTED_TYPEARRAY(T, name, base) \
647 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, \
648 wxARRAY_DEFAULT_EXPORT)
649
650 #define WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, base) \
651 WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, WXDLLEXPORT)
652
653 #define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, expmode) \
654 typedef T _wxArray##name; \
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)
658
659 // ----------------------------------------------------------------------------
660 // WX_DEFINE_SORTED_TYPEARRAY_CMP: exactly the same as above but the comparison
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 //
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
669 // ----------------------------------------------------------------------------
670
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)
674
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)
678
679 #define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base, \
680 expmode) \
681 typedef T _wxArray##name; \
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)
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"!
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 //
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; \
734 _WX_DECLARE_OBJARRAY(_wxObjArray##name, name, wxArrayPtrVoid, class expmode)
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)
743 #define WX_DEFINE_USER_EXPORTED_OBJARRAY(name) WX_DEFINE_OBJARRAY(name)
744
745 // ----------------------------------------------------------------------------
746 // Some commonly used predefined base arrays
747 // ----------------------------------------------------------------------------
748
749 WX_DECLARE_USER_EXPORTED_BASEARRAY(const void *, wxBaseArrayPtrVoid,
750 WXDLLIMPEXP_BASE);
751 WX_DECLARE_USER_EXPORTED_BASEARRAY(short, wxBaseArrayShort,
752 WXDLLIMPEXP_BASE);
753 WX_DECLARE_USER_EXPORTED_BASEARRAY(int, wxBaseArrayInt,
754 WXDLLIMPEXP_BASE);
755 WX_DECLARE_USER_EXPORTED_BASEARRAY(long, wxBaseArrayLong,
756 WXDLLIMPEXP_BASE);
757 WX_DECLARE_USER_EXPORTED_BASEARRAY(double, wxBaseArrayDouble,
758 WXDLLIMPEXP_BASE);
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) \
769 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayPtrVoid, expmode)
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) \
776 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayShort, expmode)
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) \
783 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayInt, expmode)
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) \
790 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayLong, expmode)
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) \
797 WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayDouble, expmode)
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
871 // ----------------------------------------------------------------------------
872 // Some commonly used predefined arrays
873 // ----------------------------------------------------------------------------
874
875 WX_DEFINE_USER_EXPORTED_ARRAY_SHORT (short, wxArrayShort, class WXDLLIMPEXP_BASE);
876 WX_DEFINE_USER_EXPORTED_ARRAY_INT (int, wxArrayInt, class WXDLLIMPEXP_BASE);
877 WX_DEFINE_USER_EXPORTED_ARRAY_LONG (long, wxArrayLong, class WXDLLIMPEXP_BASE);
878 WX_DEFINE_USER_EXPORTED_ARRAY (void *, wxArrayPtrVoid, class WXDLLIMPEXP_BASE);
879
880 // -----------------------------------------------------------------------------
881 // convenience macros
882 // -----------------------------------------------------------------------------
883
884 // append all element of one array to another one
885 #define WX_APPEND_ARRAY(array, other) \
886 { \
887 size_t count = (other).size(); \
888 for ( size_t n = 0; n < count; n++ ) \
889 { \
890 (array).push_back((other)[n]); \
891 } \
892 }
893
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 { \
902 size_t count = (array).size(); \
903 for ( size_t n = 0; n < count; n++ ) \
904 { \
905 delete (array)[n]; \
906 } \
907 \
908 (array).clear(); \
909 }
910
911 #endif // _DYNARRAY_H
912