]> git.saurik.com Git - wxWidgets.git/blob - include/wx/buffer.h
copy the list in wxList::operator=(), for consistency with typed macro-based lists
[wxWidgets.git] / include / wx / buffer.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/buffer.h
3 // Purpose: auto buffer classes: buffers which automatically free memory
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 12.04.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_BUFFER_H
13 #define _WX_BUFFER_H
14
15 #include "wx/chartype.h"
16 #include "wx/wxcrtbase.h"
17
18 #include <stdlib.h> // malloc() and free()
19
20 class WXDLLIMPEXP_FWD_BASE wxCStrData;
21
22 // ----------------------------------------------------------------------------
23 // Special classes for (wide) character strings: they use malloc/free instead
24 // of new/delete
25 // ----------------------------------------------------------------------------
26
27 template <typename T>
28 class WXDLLIMPEXP_BASE wxCharTypeBuffer
29 {
30 public:
31 typedef T CharType;
32
33 wxCharTypeBuffer(const CharType *str = NULL)
34 : m_str(str ? wxStrdup(str) : NULL),
35 m_owned(true)
36 {
37 }
38
39 wxCharTypeBuffer(size_t len)
40 : m_str((CharType *)malloc((len + 1)*sizeof(CharType))),
41 m_owned(true)
42 {
43 m_str[len] = (CharType)0;
44 }
45
46 static const wxCharTypeBuffer CreateNonOwned(const CharType *str)
47 {
48 wxCharTypeBuffer buf;
49 buf.m_str = wx_const_cast(CharType*, str);
50 buf.m_owned = false;
51 return buf;
52 }
53
54 /* no need to check for NULL, free() does it */
55 ~wxCharTypeBuffer()
56 {
57 if ( m_owned)
58 free(m_str);
59 }
60
61 /*
62 WARNING:
63
64 the copy ctor and assignment operators change the passed in object
65 even although it is declared as "const", so:
66
67 a) it shouldn't be really const
68 b) you shouldn't use it afterwards (or know that it was reset)
69
70 This is very ugly but is unfortunately needed to make the normal use
71 of wxCharTypeBuffer buffer objects possible and is very similar to what
72 std::auto_ptr<> does (as if it were an excuse...)
73 */
74
75 /*
76 because of the remark above, release() is declared const even if it
77 isn't really const
78 */
79 CharType *release() const
80 {
81 wxASSERT_MSG( m_owned, _T("can't release non-owned buffer") );
82 return DoRelease();
83 }
84
85 void reset()
86 {
87 if ( m_owned )
88 free(m_str);
89 m_str = NULL;
90 }
91
92 wxCharTypeBuffer(const wxCharTypeBuffer& src)
93 {
94 CopyFrom(src);
95 }
96
97 wxCharTypeBuffer& operator=(const CharType *str)
98 {
99 if ( m_owned )
100 free(m_str);
101 m_str = str ? wxStrdup(str) : NULL;
102 m_owned = true;
103 return *this;
104 }
105
106 wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src)
107 {
108 if ( m_owned )
109 free(m_str);
110 CopyFrom(src);
111 return *this;
112 }
113
114 bool extend(size_t len)
115 {
116 wxASSERT_MSG( m_owned, _T("cannot extend non-owned buffer") );
117
118 CharType *
119 str = (CharType *)realloc(m_str, (len + 1)*sizeof(CharType));
120 if ( !str )
121 return false;
122
123 m_str = str;
124
125 return true;
126 }
127
128 CharType *data() { return m_str; }
129 const CharType *data() const { return m_str; }
130 operator const CharType *() const { return m_str; }
131 CharType operator[](size_t n) const { return m_str[n]; }
132
133
134 private:
135 CharType *DoRelease() const
136 {
137 CharType *p = m_str;
138 ((wxCharTypeBuffer *)this)->m_str = NULL;
139 return p;
140 }
141
142 void CopyFrom(const wxCharTypeBuffer& src)
143 {
144 m_owned = src.m_owned;
145 m_str = src.DoRelease();
146 }
147
148 private:
149 CharType *m_str;
150 bool m_owned;
151 };
152
153 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
154
155 class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char>
156 {
157 public:
158 typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
159
160 wxCharBuffer(const wxCharTypeBufferBase& buf)
161 : wxCharTypeBufferBase(buf) {}
162
163 wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
164 wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
165
166 wxCharBuffer(const wxCStrData& cstr);
167 };
168
169 #if wxUSE_WCHAR_T
170 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
171
172 class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
173 {
174 public:
175 typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
176
177 wxWCharBuffer(const wxCharTypeBufferBase& buf)
178 : wxCharTypeBufferBase(buf) {}
179
180 wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
181 wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
182
183 wxWCharBuffer(const wxCStrData& cstr);
184 };
185 #endif // wxUSE_WCHAR_T
186
187 // wxCharTypeBuffer<T> implicitly convertible to T*
188 template <typename T>
189 class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
190 {
191 public:
192 typedef typename wxCharTypeBuffer<T>::CharType CharType;
193
194 wxWritableCharTypeBuffer(const wxCharTypeBuffer<T>& src)
195 : wxCharTypeBuffer<T>(src) {}
196 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
197 // always return a buffer
198 wxWritableCharTypeBuffer(const CharType *str = NULL)
199 : wxCharTypeBuffer<T>(str) {}
200
201 operator CharType*() { return this->data(); }
202 };
203
204 typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
205 typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
206
207
208 #if wxUSE_UNICODE
209 #define wxWxCharBuffer wxWCharBuffer
210
211 #define wxMB2WXbuf wxWCharBuffer
212 #define wxWX2MBbuf wxCharBuffer
213 #if wxUSE_UNICODE_WCHAR
214 #define wxWC2WXbuf wxChar*
215 #define wxWX2WCbuf wxChar*
216 #elif wxUSE_UNICODE_UTF8
217 #define wxWC2WXbuf wxWCharBuffer
218 #define wxWX2WCbuf wxWCharBuffer
219 #endif
220 #else // ANSI
221 #define wxWxCharBuffer wxCharBuffer
222
223 #define wxMB2WXbuf wxChar*
224 #define wxWX2MBbuf wxChar*
225 #define wxWC2WXbuf wxCharBuffer
226 #define wxWX2WCbuf wxWCharBuffer
227 #endif // Unicode/ANSI
228
229 // ----------------------------------------------------------------------------
230 // A class for holding growable data buffers (not necessarily strings)
231 // ----------------------------------------------------------------------------
232
233 // This class manages the actual data buffer pointer and is ref-counted.
234 class wxMemoryBufferData
235 {
236 public:
237 // the initial size and also the size added by ResizeIfNeeded()
238 enum { DefBufSize = 1024 };
239
240 friend class wxMemoryBuffer;
241
242 // everyting is private as it can only be used by wxMemoryBuffer
243 private:
244 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
245 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
246 {
247 }
248 ~wxMemoryBufferData() { free(m_data); }
249
250
251 void ResizeIfNeeded(size_t newSize)
252 {
253 if (newSize > m_size)
254 {
255 void *dataOld = m_data;
256 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
257 if ( !m_data )
258 {
259 free(dataOld);
260 }
261
262 m_size = newSize + wxMemoryBufferData::DefBufSize;
263 }
264 }
265
266 void IncRef() { m_ref += 1; }
267 void DecRef()
268 {
269 m_ref -= 1;
270 if (m_ref == 0) // are there no more references?
271 delete this;
272 }
273
274
275 // the buffer containing the data
276 void *m_data;
277
278 // the size of the buffer
279 size_t m_size;
280
281 // the amount of data currently in the buffer
282 size_t m_len;
283
284 // the reference count
285 size_t m_ref;
286
287 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
288 };
289
290
291 class WXDLLIMPEXP_BASE wxMemoryBuffer
292 {
293 public:
294 // ctor and dtor
295 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
296 {
297 m_bufdata = new wxMemoryBufferData(size);
298 m_bufdata->IncRef();
299 }
300
301 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
302
303
304 // copy and assignment
305 wxMemoryBuffer(const wxMemoryBuffer& src)
306 : m_bufdata(src.m_bufdata)
307 {
308 m_bufdata->IncRef();
309 }
310
311 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
312 {
313 m_bufdata->DecRef();
314 m_bufdata = src.m_bufdata;
315 m_bufdata->IncRef();
316 return *this;
317 }
318
319
320 // Accessors
321 void *GetData() const { return m_bufdata->m_data; }
322 size_t GetBufSize() const { return m_bufdata->m_size; }
323 size_t GetDataLen() const { return m_bufdata->m_len; }
324
325 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
326 void SetDataLen(size_t len)
327 {
328 wxASSERT(len <= m_bufdata->m_size);
329 m_bufdata->m_len = len;
330 }
331
332 // Ensure the buffer is big enough and return a pointer to it
333 void *GetWriteBuf(size_t sizeNeeded)
334 {
335 m_bufdata->ResizeIfNeeded(sizeNeeded);
336 return m_bufdata->m_data;
337 }
338
339 // Update the length after the write
340 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
341
342 // Like the above, but appends to the buffer
343 void *GetAppendBuf(size_t sizeNeeded)
344 {
345 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
346 return (char*)m_bufdata->m_data + m_bufdata->m_len;
347 }
348
349 // Update the length after the append
350 void UngetAppendBuf(size_t sizeUsed)
351 {
352 SetDataLen(m_bufdata->m_len + sizeUsed);
353 }
354
355 // Other ways to append to the buffer
356 void AppendByte(char data)
357 {
358 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
359
360 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
361 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
362 m_bufdata->m_len += 1;
363 }
364
365 void AppendData(const void *data, size_t len)
366 {
367 memcpy(GetAppendBuf(len), data, len);
368 UngetAppendBuf(len);
369 }
370
371 operator const char *() const { return (const char*)GetData(); }
372
373 private:
374 wxMemoryBufferData* m_bufdata;
375 };
376
377 // ----------------------------------------------------------------------------
378 // template class for any kind of data
379 // ----------------------------------------------------------------------------
380
381 // TODO
382
383 #endif // _WX_BUFFER_H