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