]> git.saurik.com Git - wxWidgets.git/blob - include/wx/buffer.h
More GC fixes.
[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 (&src != this)
109 {
110 if ( m_owned )
111 free(m_str);
112 CopyFrom(src);
113 }
114 return *this;
115 }
116
117 bool extend(size_t len)
118 {
119 wxASSERT_MSG( m_owned, _T("cannot extend non-owned buffer") );
120
121 CharType *
122 str = (CharType *)realloc(m_str, (len + 1)*sizeof(CharType));
123 if ( !str )
124 return false;
125
126 m_str = str;
127
128 return true;
129 }
130
131 CharType *data() { return m_str; }
132 const CharType *data() const { return m_str; }
133 operator const CharType *() const { return m_str; }
134 CharType operator[](size_t n) const { return m_str[n]; }
135
136
137 private:
138 CharType *DoRelease() const
139 {
140 CharType *p = m_str;
141 ((wxCharTypeBuffer *)this)->m_str = NULL;
142 return p;
143 }
144
145 void CopyFrom(const wxCharTypeBuffer& src)
146 {
147 m_owned = src.m_owned;
148 m_str = src.DoRelease();
149 }
150
151 private:
152 CharType *m_str;
153 bool m_owned;
154 };
155
156 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
157
158 class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char>
159 {
160 public:
161 typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
162
163 wxCharBuffer(const wxCharTypeBufferBase& buf)
164 : wxCharTypeBufferBase(buf) {}
165
166 wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
167 wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
168
169 wxCharBuffer(const wxCStrData& cstr);
170 };
171
172 #if wxUSE_WCHAR_T
173 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
174
175 class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
176 {
177 public:
178 typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
179
180 wxWCharBuffer(const wxCharTypeBufferBase& buf)
181 : wxCharTypeBufferBase(buf) {}
182
183 wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
184 wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
185
186 wxWCharBuffer(const wxCStrData& cstr);
187 };
188 #endif // wxUSE_WCHAR_T
189
190 // wxCharTypeBuffer<T> implicitly convertible to T*
191 template <typename T>
192 class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
193 {
194 public:
195 typedef typename wxCharTypeBuffer<T>::CharType CharType;
196
197 wxWritableCharTypeBuffer(const wxCharTypeBuffer<T>& src)
198 : wxCharTypeBuffer<T>(src) {}
199 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
200 // always return a buffer
201 wxWritableCharTypeBuffer(const CharType *str = NULL)
202 : wxCharTypeBuffer<T>(str) {}
203
204 operator CharType*() { return this->data(); }
205 };
206
207 typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
208 typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
209
210
211 #if wxUSE_UNICODE
212 #define wxWxCharBuffer wxWCharBuffer
213
214 #define wxMB2WXbuf wxWCharBuffer
215 #define wxWX2MBbuf wxCharBuffer
216 #if wxUSE_UNICODE_WCHAR
217 #define wxWC2WXbuf wxChar*
218 #define wxWX2WCbuf wxChar*
219 #elif wxUSE_UNICODE_UTF8
220 #define wxWC2WXbuf wxWCharBuffer
221 #define wxWX2WCbuf wxWCharBuffer
222 #endif
223 #else // ANSI
224 #define wxWxCharBuffer wxCharBuffer
225
226 #define wxMB2WXbuf wxChar*
227 #define wxWX2MBbuf wxChar*
228 #define wxWC2WXbuf wxCharBuffer
229 #define wxWX2WCbuf wxWCharBuffer
230 #endif // Unicode/ANSI
231
232 // type of the value returned by wxString::utf8_str()
233 #if wxUSE_UNICODE_UTF8
234 #define wxUTF8Buf char *
235 #else
236 #define wxUTF8Buf wxCharBuffer
237 #endif
238
239 // ----------------------------------------------------------------------------
240 // A class for holding growable data buffers (not necessarily strings)
241 // ----------------------------------------------------------------------------
242
243 // This class manages the actual data buffer pointer and is ref-counted.
244 class wxMemoryBufferData
245 {
246 public:
247 // the initial size and also the size added by ResizeIfNeeded()
248 enum { DefBufSize = 1024 };
249
250 friend class wxMemoryBuffer;
251
252 // everyting is private as it can only be used by wxMemoryBuffer
253 private:
254 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
255 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
256 {
257 }
258 ~wxMemoryBufferData() { free(m_data); }
259
260
261 void ResizeIfNeeded(size_t newSize)
262 {
263 if (newSize > m_size)
264 {
265 void *dataOld = m_data;
266 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
267 if ( !m_data )
268 {
269 free(dataOld);
270 }
271
272 m_size = newSize + wxMemoryBufferData::DefBufSize;
273 }
274 }
275
276 void IncRef() { m_ref += 1; }
277 void DecRef()
278 {
279 m_ref -= 1;
280 if (m_ref == 0) // are there no more references?
281 delete this;
282 }
283
284
285 // the buffer containing the data
286 void *m_data;
287
288 // the size of the buffer
289 size_t m_size;
290
291 // the amount of data currently in the buffer
292 size_t m_len;
293
294 // the reference count
295 size_t m_ref;
296
297 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
298 };
299
300
301 class WXDLLIMPEXP_BASE wxMemoryBuffer
302 {
303 public:
304 // ctor and dtor
305 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
306 {
307 m_bufdata = new wxMemoryBufferData(size);
308 m_bufdata->IncRef();
309 }
310
311 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
312
313
314 // copy and assignment
315 wxMemoryBuffer(const wxMemoryBuffer& src)
316 : m_bufdata(src.m_bufdata)
317 {
318 m_bufdata->IncRef();
319 }
320
321 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
322 {
323 if (&src != this)
324 {
325 m_bufdata->DecRef();
326 m_bufdata = src.m_bufdata;
327 m_bufdata->IncRef();
328 }
329 return *this;
330 }
331
332
333 // Accessors
334 void *GetData() const { return m_bufdata->m_data; }
335 size_t GetBufSize() const { return m_bufdata->m_size; }
336 size_t GetDataLen() const { return m_bufdata->m_len; }
337
338 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
339 void SetDataLen(size_t len)
340 {
341 wxASSERT(len <= m_bufdata->m_size);
342 m_bufdata->m_len = len;
343 }
344
345 // Ensure the buffer is big enough and return a pointer to it
346 void *GetWriteBuf(size_t sizeNeeded)
347 {
348 m_bufdata->ResizeIfNeeded(sizeNeeded);
349 return m_bufdata->m_data;
350 }
351
352 // Update the length after the write
353 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
354
355 // Like the above, but appends to the buffer
356 void *GetAppendBuf(size_t sizeNeeded)
357 {
358 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
359 return (char*)m_bufdata->m_data + m_bufdata->m_len;
360 }
361
362 // Update the length after the append
363 void UngetAppendBuf(size_t sizeUsed)
364 {
365 SetDataLen(m_bufdata->m_len + sizeUsed);
366 }
367
368 // Other ways to append to the buffer
369 void AppendByte(char data)
370 {
371 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
372
373 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
374 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
375 m_bufdata->m_len += 1;
376 }
377
378 void AppendData(const void *data, size_t len)
379 {
380 memcpy(GetAppendBuf(len), data, len);
381 UngetAppendBuf(len);
382 }
383
384 operator const char *() const { return (const char*)GetData(); }
385
386 private:
387 wxMemoryBufferData* m_bufdata;
388 };
389
390 // ----------------------------------------------------------------------------
391 // template class for any kind of data
392 // ----------------------------------------------------------------------------
393
394 // TODO
395
396 #endif // _WX_BUFFER_H