]> git.saurik.com Git - wxWidgets.git/blob - include/wx/dynarray.h
now MSW stuff is complete
[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 license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _DYNARRAY_H
13 #define _DYNARRAY_H
14
15 #ifdef __GNUG__
16 #pragma interface "dynarray.h"
17 #endif
18
19 #include "wx/defs.h"
20 #include "wx/utils.h"
21
22 typedef bool Bool;
23
24 /** @name Dynamic arrays and lists
25 @memo Arrays which grow on demand and do range checking (only in debug)
26 */
27 //@{
28
29 // ----------------------------------------------------------------------------
30 // constants
31 // ----------------------------------------------------------------------------
32
33 /**
34 the initial size by which an array/list grows when an element is added
35 default value avoids allocate one or two bytes when the array is created
36 which is rather inefficient
37 */
38 #define WX_ARRAY_DEFAULT_INITIAL_SIZE (16)
39
40 // ----------------------------------------------------------------------------
41 // types
42 // ----------------------------------------------------------------------------
43
44 /**
45 callback compare function for quick sort
46 must return -1, 0 or +1 if pItem1 <, = or > pItem2
47 */
48
49 #ifdef __VISUALC__
50 #define CMPFUNC_CONV _cdecl
51 #else // !Visual C++
52 #define CMPFUNC_CONV
53 #endif // compiler
54 typedef int (CMPFUNC_CONV *CMPFUNC)(const void* pItem1, const void* pItem2);
55
56 // ----------------------------------------------------------------------------
57 /**
58 base class managing data having size of type 'long' (not used directly)
59
60 NB: for efficiency this often used class has no virtual functions (hence no
61 VTBL), even dtor is <B>not</B> virtual. If used as expected it won't
62 create any problems because ARRAYs from DEFINE_ARRAY have no dtor at all,
63 so it's not too important if it's not called (this happens when you cast
64 "SomeArray *" as "BaseArray *" and then delete it)
65
66 @memo Base class for template array and list classes
67 */
68 // ----------------------------------------------------------------------------
69 class wxBaseArray
70 {
71 public:
72 /** @name ctors and dtor */
73 //@{
74 /// default ctor
75 wxBaseArray();
76 /// copy ctor
77 wxBaseArray(const wxBaseArray& array);
78 /// assignment operator
79 wxBaseArray& operator=(const wxBaseArray& src);
80 /// not virtual, see above
81 /// EXCEPT for Gnu compiler to reduce warnings...
82 #ifdef __GNUG__
83 virtual
84 #endif
85 ~wxBaseArray();
86 //@}
87
88 /** @name memory management */
89 //@{
90 /// empties the list, but doesn't release memory
91 void Empty() { m_uiCount = 0; }
92 /// empties the list and releases memory
93 void Clear();
94 /// preallocates memory for given number of items
95 void Alloc(uint uiSize);
96 //@}
97
98 /** @name simple accessors */
99 //@{
100 /// number of elements in the array
101 uint Count() const { return m_uiCount; }
102 /// is it empty?
103 Bool IsEmpty() const { return m_uiCount == 0; }
104 //@}
105
106 protected:
107 // these methods are protected because if they were public one could
108 // mistakenly call one of them instead of DEFINE_ARRAY's or LIST's
109 // type safe methods
110
111 /** @name items access */
112 //@{
113 /// get item at position uiIndex (range checking is done in debug version)
114 long& Item(uint uiIndex) const
115 { wxASSERT( uiIndex < m_uiCount ); return m_pItems[uiIndex]; }
116 /// same as Item()
117 long& operator[](uint uiIndex) const { return Item(uiIndex); }
118 //@}
119
120 /** @name item management */
121 //@{
122 /**
123 Search the element in the array, starting from the either side
124 @param bFromEnd if TRUE, start from the end
125 @return index of the first item matched or NOT_FOUND
126 @see NOT_FOUND
127 */
128 int Index (long lItem, Bool bFromEnd = FALSE) const;
129 /// add new element at the end
130 void Add (long lItem);
131 /// add new element at given position
132 void Insert(long lItem, uint uiIndex);
133 /// remove first item matching this value
134 void Remove(long lItem);
135 /// remove item by index
136 void Remove(uint uiIndex);
137 //@}
138
139 /// sort array elements using given compare function
140 void Sort(CMPFUNC fCmp);
141
142 private:
143 void Grow(); // makes array bigger if needed
144
145 uint m_uiSize, // current size of the array
146 m_uiCount; // current number of elements
147
148 long *m_pItems; // pointer to data
149 };
150
151 // ============================================================================
152 // template classes
153 // ============================================================================
154
155 // ----------------------------------------------------------------------------
156 // This macro generates a new array class. It is intended for storage of simple
157 // types of sizeof()<=sizeof(long) or pointers if sizeof(pointer)<=sizeof(long)
158 //
159 // NB: it has only inline functions => takes no space at all
160 // ----------------------------------------------------------------------------
161 #define _WX_DEFINE_ARRAY(T, name) \
162 typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2); \
163 class name : public wxBaseArray \
164 { \
165 public: \
166 name() \
167 { wxASSERT( sizeof(T) <= sizeof(long) ); } \
168 \
169 name& operator=(const name& src) \
170 { ((wxBaseArray *)this)->operator=((const wxBaseArray&)src); \
171 return *this; } \
172 \
173 T& operator[](uint uiIndex) const \
174 { return (T&)(wxBaseArray::Item(uiIndex)); } \
175 T& Item(uint uiIndex) const \
176 { return (T&)(wxBaseArray::Item(uiIndex)); } \
177 \
178 int Index(T Item, Bool bFromEnd = FALSE) const \
179 { return wxBaseArray::Index((long)Item, bFromEnd); } \
180 \
181 void Add(T Item) \
182 { wxBaseArray::Add((long)Item); } \
183 void Insert(T Item, uint uiIndex) \
184 { wxBaseArray::Insert((long)Item, uiIndex) ; } \
185 \
186 void Remove(uint uiIndex) { wxBaseArray::Remove(uiIndex); } \
187 void Remove(T Item) \
188 { int iIndex = Index(Item); \
189 wxCHECK( iIndex != NOT_FOUND ); \
190 wxBaseArray::Remove((uint)iIndex); } \
191 \
192 void Sort(CMPFUNC##T fCmp) { wxBaseArray::Sort((CMPFUNC)fCmp); } \
193 }
194
195 // ----------------------------------------------------------------------------
196 // see WX_DECLARE_LIST and WX_DEFINE_LIST
197 // ----------------------------------------------------------------------------
198 #define _WX_DECLARE_LIST(T, name) \
199 typedef int (CMPFUNC_CONV *CMPFUNC##T)(T** pItem1, T** pItem2); \
200 class name : public wxBaseArray \
201 { \
202 public: \
203 name() { } \
204 name(const name& src); \
205 name& operator=(const name& src); \
206 \
207 ~name(); \
208 \
209 T& operator[](uint uiIndex) const \
210 { return *(T*)wxBaseArray::Item(uiIndex); } \
211 T& Item(uint uiIndex) const \
212 { return *(T*)wxBaseArray::Item(uiIndex); } \
213 \
214 int Index(const T& Item, Bool bFromEnd = FALSE) const; \
215 \
216 void Add(const T& Item); \
217 void Add(const T* pItem) \
218 { wxBaseArray::Add((long)pItem); } \
219 \
220 void Insert(const T& Item, uint uiIndex); \
221 void Insert(const T* pItem, uint uiIndex) \
222 { wxBaseArray::Insert((long)pItem, uiIndex); } \
223 \
224 void Empty(); \
225 \
226 T* Detach(uint uiIndex) \
227 { T* p = (T*)wxBaseArray::Item(uiIndex); \
228 wxBaseArray::Remove(uiIndex); return p; } \
229 void Remove(uint uiIndex); \
230 \
231 void Sort(CMPFUNC##T fCmp) { wxBaseArray::Sort((CMPFUNC)fCmp); } \
232 \
233 private: \
234 void DoCopy(const name& src); \
235 }
236
237 // ----------------------------------------------------------------------------
238 /** @name Macros for definition of dynamic arrays and lists
239
240 These macros are ugly (especially if you look in the sources ;-), but they
241 allow us to define 'template' classes without actually using templates.
242 <BR>
243 <BR>
244 Range checking is performed in debug build for both arrays and lists. Type
245 checking is done at compile-time. Warning: arrays <I>never</I> shrink, they
246 only grow, so loading 10 millions in an array only to delete them 2 lines
247 below is <I>not</I> recommended. However, it does free memory when it's
248 destroyed, so if you destroy array also, it's ok.
249 */
250 // ----------------------------------------------------------------------------
251
252 //@{
253 /**
254 This macro generates a new array class. It is intended for storage of simple
255 types of sizeof()<=sizeof(long) or pointers if sizeof(pointer)<=sizeof(long)
256 <BR>
257 NB: it has only inline functions => takes no space at all
258 <BR>
259
260 @memo declare and define array class 'name' containing elements of type 'T'
261 */
262 #define WX_DEFINE_ARRAY(T, name) typedef T _A##name; \
263 _WX_DEFINE_ARRAY(_A##name, name)
264 /**
265 This macro generates a new list class which owns the objects it contains,
266 i.e. it will delete them when it is destroyed. An element is of type T*,
267 but arguments of type T& are taken (see below!) and T& is returned.
268 <BR>
269 Don't use this for simple types such as "int" or "long"!
270 You _may_ use it for "double" but it's awfully inefficient.
271 <BR>
272 <BR>
273 Note on Add/Insert functions:
274 <BR>
275 1) function(T*) gives the object to the list, i.e. it will delete the
276 object when it's removed or in the list's dtor
277 <BR>
278 2) function(T&) will create a copy of the object and work with it
279 <BR>
280 <BR>
281 Also:
282 <BR>
283 1) Remove() will delete the object after removing it from the list
284 <BR>
285 2) Detach() just removes the object from the list (returning pointer to it)
286 <BR>
287 <BR>
288 NB1: Base type T should have an accessible copy ctor if Add(T&) is used,
289 <BR>
290 NB2: Never ever cast a list to it's base type: as dtor is <B>not</B> virtual
291 it will provoke memory leaks
292 <BR>
293 <BR>
294 some functions of this class are not inline, so it takes some space to
295 define new class from this template.
296
297 @memo declare list class 'name' containing elements of type 'T'
298 */
299 #define WX_DECLARE_LIST(T, name) typedef T _L##name; \
300 _WX_DECLARE_LIST(_L##name, name)
301 /**
302 To use a list class you must
303 <ll>
304 <li>#include "dynarray.h"
305 <li>DECLARE_LIST(element_type, list_class_name)
306 <li>#include "listimpl.cpp"
307 <li>DEFINE_LIST(list_class_name) // same as above!
308 </ll>
309 <BR><BR>
310 This is necessary because at the moment of DEFINE_LIST class element_type
311 must be fully defined (i.e. forward declaration is not enough), while
312 DECLARE_LIST may be done anywhere. The separation of two allows to break
313 cicrcular dependencies with classes which have member variables of list
314 type.
315
316 @memo define (must include listimpl.cpp!) list class 'name'
317 */
318 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
319 //@}
320
321 // ----------------------------------------------------------------------------
322 /** @name Some commonly used predefined arrays */
323 // # overhead if not used?
324 // ----------------------------------------------------------------------------
325
326 //@{
327 /** @name ArrayInt */
328 WX_DEFINE_ARRAY(int, wxArrayInt);
329 /** @name ArrayLong */
330 WX_DEFINE_ARRAY(long, wxArrayLong);
331 /** @name ArrayPtrVoid */
332 WX_DEFINE_ARRAY(void *, wxArrayPtrVoid);
333 //@}
334
335 //@}
336
337 #endif // _DYNARRAY_H
338