]> git.saurik.com Git - wxWidgets.git/blame - include/wx/buffer.h
Fix crash again
[wxWidgets.git] / include / wx / buffer.h
CommitLineData
14971e5b 1///////////////////////////////////////////////////////////////////////////////
c12ef8a2 2// Name: wx/buffer.h
14971e5b
VZ
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>
65571936 9// Licence: wxWindows licence
14971e5b
VZ
10///////////////////////////////////////////////////////////////////////////////
11
14971e5b
VZ
12#ifndef _WX_BUFFER_H
13#define _WX_BUFFER_H
14
e713a90b 15#include "wx/chartype.h"
52de37c7 16#include "wx/wxcrtbase.h"
e90c1d2a 17
9b4da627 18#ifndef __WXPALMOS5__
e2473d4c 19#include <stdlib.h> // malloc() and free()
9b4da627 20#endif // ! __WXPALMOS5__
e2473d4c 21
b5dbe15d 22class WXDLLIMPEXP_FWD_BASE wxCStrData;
8db4a5d2 23
14971e5b
VZ
24// ----------------------------------------------------------------------------
25// Special classes for (wide) character strings: they use malloc/free instead
26// of new/delete
27// ----------------------------------------------------------------------------
28
d18c8d3d 29template <typename T>
4ec4d861 30class WXDLLIMPEXP_BASE wxCharTypeBuffer
d18c8d3d
VS
31{
32public:
33 typedef T CharType;
34
35 wxCharTypeBuffer(const CharType *str = NULL)
d18c8d3d 36 {
5c1de526
VS
37 if ( str )
38 m_data = new Data(wxStrdup(str));
39 else
40 m_data = &NullData;
d18c8d3d
VS
41 }
42
d18c8d3d 43 wxCharTypeBuffer(size_t len)
d18c8d3d 44 {
5c1de526
VS
45 m_data = new Data((CharType *)malloc((len + 1)*sizeof(CharType)));
46 m_data->m_str[len] = (CharType)0;
d18c8d3d
VS
47 }
48
681e4412 49 static const wxCharTypeBuffer CreateNonOwned(const CharType *str)
486a5941
VS
50 {
51 wxCharTypeBuffer buf;
5c1de526
VS
52 if ( str )
53 buf.m_data = new Data(wx_const_cast(CharType*, str), Data::NonOwned);
486a5941
VS
54 return buf;
55 }
56
486a5941
VS
57 ~wxCharTypeBuffer()
58 {
5c1de526 59 DecRef();
486a5941 60 }
d18c8d3d 61
03af437f
VS
62 // NB: this method is only const for backward compatibility. It used to
63 // be needed for auto_ptr-like semantics of the copy ctor, but now
64 // that ref-counting is used, it's not really needed.
65 CharType *release() const
5c1de526
VS
66 {
67 if ( m_data == &NullData )
68 return NULL;
d18c8d3d 69
5c1de526
VS
70 wxASSERT_MSG( m_data->m_owned, _T("can't release non-owned buffer") );
71 wxASSERT_MSG( m_data->m_ref == 1, _T("can't release shared buffer") );
14971e5b 72
5c1de526 73 CharType *p = m_data->m_str;
03af437f
VS
74
75 wxCharTypeBuffer *self = wx_const_cast(wxCharTypeBuffer*, this);
76 self->m_data->m_str = NULL;
77 self->DecRef();
78
5c1de526 79 return p;
d18c8d3d 80 }
c12ef8a2 81
d18c8d3d
VS
82 void reset()
83 {
5c1de526 84 DecRef();
d18c8d3d 85 }
c12ef8a2 86
d18c8d3d 87 wxCharTypeBuffer(const wxCharTypeBuffer& src)
d18c8d3d 88 {
5c1de526
VS
89 m_data = src.m_data;
90 IncRef();
d18c8d3d 91 }
14971e5b 92
d18c8d3d
VS
93 wxCharTypeBuffer& operator=(const CharType *str)
94 {
5c1de526
VS
95 DecRef();
96
97 if ( str )
98 m_data = new Data(wxStrdup(str));
d18c8d3d
VS
99 return *this;
100 }
101
102 wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src)
103 {
5c1de526
VS
104 if ( &src == this )
105 return *this;
106
107 DecRef();
108 m_data = src.m_data;
109 IncRef();
110
d18c8d3d
VS
111 return *this;
112 }
113
114 bool extend(size_t len)
115 {
5c1de526
VS
116 wxASSERT_MSG( m_data->m_owned, _T("cannot extend non-owned buffer") );
117 wxASSERT_MSG( m_data->m_ref == 1, _T("can't extend shared buffer") );
486a5941 118
5c1de526
VS
119 CharType *str =
120 (CharType *)realloc(data(), (len + 1) * sizeof(CharType));
d18c8d3d
VS
121 if ( !str )
122 return false;
123
5c1de526
VS
124 if ( m_data == &NullData )
125 {
126 m_data = new Data(str);
127 }
128 else
129 {
130 m_data->m_str = str;
131 m_data->m_owned = true;
132 }
d18c8d3d
VS
133
134 return true;
135 }
136
5c1de526
VS
137 CharType *data() { return m_data->m_str; }
138 const CharType *data() const { return m_data->m_str; }
139 operator const CharType *() const { return data(); }
140 CharType operator[](size_t n) const { return data()[n]; }
486a5941
VS
141
142private:
5c1de526
VS
143 // reference-counted data
144 struct Data
486a5941 145 {
5c1de526
VS
146 enum Kind
147 {
148 Owned,
149 NonOwned
150 };
151
152 Data(CharType *str, Kind kind = Owned)
153 : m_str(str), m_ref(1), m_owned(kind == Owned) {}
154
155 ~Data()
156 {
157 if ( m_owned )
158 free(m_str);
159 }
160
161 CharType *m_str;
162
163 // "short" to have sizeof(Data)=8 on 32bit archs
164 unsigned short m_ref;
165
166 bool m_owned;
167 };
168
169 // placeholder for NULL string, to simplify this code
170 // NB: this is defined in string.cpp, not (non-existent) buffer.cpp
fda71b39
VS
171#ifdef __MINGW32__
172 // MinGW requires explicit WXDLLIMPEXP_DATA_BASE to avoid compilation
173 // errors
174 static WXDLLIMPEXP_DATA_BASE(Data) NullData;
175#else
176 // but Visual C++ doesn't like it
aa74cc21 177 static Data NullData;
fda71b39 178#endif
5c1de526
VS
179
180 void IncRef()
181 {
182 if ( m_data == &NullData ) // exception, not ref-counted
183 return;
184 m_data->m_ref++;
486a5941
VS
185 }
186
5c1de526 187 void DecRef()
486a5941 188 {
5c1de526
VS
189 if ( m_data == &NullData ) // exception, not ref-counted
190 return;
191 if ( --m_data->m_ref == 0 )
192 delete m_data;
193 m_data = &NullData;
486a5941
VS
194 }
195
d18c8d3d 196private:
5c1de526 197 Data *m_data;
d18c8d3d
VS
198};
199
7c77f334
VZ
200WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
201
4ec4d861 202class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char>
d18c8d3d
VS
203{
204public:
ccd4deab
VZ
205 typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
206
681e4412
VS
207 wxCharBuffer(const wxCharTypeBufferBase& buf)
208 : wxCharTypeBufferBase(buf) {}
209
ccd4deab
VZ
210 wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
211 wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
212
ccd4deab 213 wxCharBuffer(const wxCStrData& cstr);
d18c8d3d
VS
214};
215
216#if wxUSE_WCHAR_T
7c77f334
VZ
217WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
218
4ec4d861 219class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
d18c8d3d
VS
220{
221public:
ccd4deab
VZ
222 typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
223
681e4412
VS
224 wxWCharBuffer(const wxCharTypeBufferBase& buf)
225 : wxCharTypeBufferBase(buf) {}
226
ccd4deab
VZ
227 wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
228 wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
229
ccd4deab 230 wxWCharBuffer(const wxCStrData& cstr);
d18c8d3d
VS
231};
232#endif // wxUSE_WCHAR_T
2b5f62a0 233
ef0f1387
VS
234// wxCharTypeBuffer<T> implicitly convertible to T*
235template <typename T>
665e6a87 236class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
ef0f1387
VS
237{
238public:
239 typedef typename wxCharTypeBuffer<T>::CharType CharType;
240
241 wxWritableCharTypeBuffer(const wxCharTypeBuffer<T>& src)
242 : wxCharTypeBuffer<T>(src) {}
243 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
244 // always return a buffer
245 wxWritableCharTypeBuffer(const CharType *str = NULL)
246 : wxCharTypeBuffer<T>(str) {}
247
248 operator CharType*() { return this->data(); }
249};
250
251typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
252typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
253
254
f93d01be 255#if wxUSE_UNICODE
ccd4deab 256 #define wxWxCharBuffer wxWCharBuffer
2f4f6de7 257
e90c1d2a
VZ
258 #define wxMB2WXbuf wxWCharBuffer
259 #define wxWX2MBbuf wxCharBuffer
81727065
VS
260 #if wxUSE_UNICODE_WCHAR
261 #define wxWC2WXbuf wxChar*
262 #define wxWX2WCbuf wxChar*
263 #elif wxUSE_UNICODE_UTF8
264 #define wxWC2WXbuf wxWCharBuffer
265 #define wxWX2WCbuf wxWCharBuffer
266 #endif
e90c1d2a 267#else // ANSI
ccd4deab 268 #define wxWxCharBuffer wxCharBuffer
2f4f6de7 269
e90c1d2a
VZ
270 #define wxMB2WXbuf wxChar*
271 #define wxWX2MBbuf wxChar*
272 #define wxWC2WXbuf wxCharBuffer
273 #define wxWX2WCbuf wxWCharBuffer
274#endif // Unicode/ANSI
f93d01be 275
30386aeb
VZ
276// type of the value returned by wxString::utf8_str()
277#if wxUSE_UNICODE_UTF8
30386aeb 278 #define wxUTF8Buf char *
53c75dc2
VZ
279#else
280 #define wxUTF8Buf wxCharBuffer
30386aeb
VZ
281#endif
282
b9fdb397
RD
283// ----------------------------------------------------------------------------
284// A class for holding growable data buffers (not necessarily strings)
285// ----------------------------------------------------------------------------
286
2b5f62a0
VZ
287// This class manages the actual data buffer pointer and is ref-counted.
288class wxMemoryBufferData
b9fdb397
RD
289{
290public:
2b5f62a0 291 // the initial size and also the size added by ResizeIfNeeded()
ae0ca755 292 enum { DefBufSize = 1024 };
2b5f62a0
VZ
293
294 friend class wxMemoryBuffer;
295
296 // everyting is private as it can only be used by wxMemoryBuffer
297private:
ae0ca755 298 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
2b5f62a0 299 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
b9fdb397 300 {
b9fdb397 301 }
2b5f62a0 302 ~wxMemoryBufferData() { free(m_data); }
b9fdb397 303
b9fdb397 304
2b5f62a0 305 void ResizeIfNeeded(size_t newSize)
b9fdb397 306 {
2b5f62a0
VZ
307 if (newSize > m_size)
308 {
309 void *dataOld = m_data;
ae0ca755 310 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
2b5f62a0
VZ
311 if ( !m_data )
312 {
313 free(dataOld);
314 }
315
ae0ca755 316 m_size = newSize + wxMemoryBufferData::DefBufSize;
2b5f62a0 317 }
b9fdb397
RD
318 }
319
2b5f62a0
VZ
320 void IncRef() { m_ref += 1; }
321 void DecRef()
b9fdb397 322 {
2b5f62a0
VZ
323 m_ref -= 1;
324 if (m_ref == 0) // are there no more references?
325 delete this;
b9fdb397 326 }
b9fdb397 327
2b5f62a0
VZ
328
329 // the buffer containing the data
330 void *m_data;
331
332 // the size of the buffer
333 size_t m_size;
334
335 // the amount of data currently in the buffer
336 size_t m_len;
337
338 // the reference count
339 size_t m_ref;
22f3361e
VZ
340
341 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
2b5f62a0
VZ
342};
343
344
4ec4d861 345class WXDLLIMPEXP_BASE wxMemoryBuffer
2b5f62a0
VZ
346{
347public:
348 // ctor and dtor
ae0ca755 349 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
b9fdb397 350 {
2b5f62a0
VZ
351 m_bufdata = new wxMemoryBufferData(size);
352 m_bufdata->IncRef();
b9fdb397 353 }
b9fdb397 354
2b5f62a0
VZ
355 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
356
357
358 // copy and assignment
359 wxMemoryBuffer(const wxMemoryBuffer& src)
360 : m_bufdata(src.m_bufdata)
361 {
362 m_bufdata->IncRef();
b9fdb397 363 }
2b5f62a0
VZ
364
365 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
b9fdb397 366 {
162e998c
PC
367 if (&src != this)
368 {
369 m_bufdata->DecRef();
370 m_bufdata = src.m_bufdata;
371 m_bufdata->IncRef();
372 }
2b5f62a0 373 return *this;
b9fdb397
RD
374 }
375
b9fdb397 376
2b5f62a0
VZ
377 // Accessors
378 void *GetData() const { return m_bufdata->m_data; }
379 size_t GetBufSize() const { return m_bufdata->m_size; }
380 size_t GetDataLen() const { return m_bufdata->m_len; }
ef1cae87 381
2b5f62a0
VZ
382 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
383 void SetDataLen(size_t len)
ef1cae87 384 {
2b5f62a0
VZ
385 wxASSERT(len <= m_bufdata->m_size);
386 m_bufdata->m_len = len;
ef1cae87
RD
387 }
388
2b5f62a0
VZ
389 // Ensure the buffer is big enough and return a pointer to it
390 void *GetWriteBuf(size_t sizeNeeded)
ef1cae87 391 {
2b5f62a0
VZ
392 m_bufdata->ResizeIfNeeded(sizeNeeded);
393 return m_bufdata->m_data;
394 }
c12ef8a2 395
2b5f62a0
VZ
396 // Update the length after the write
397 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
ef1cae87 398
2b5f62a0
VZ
399 // Like the above, but appends to the buffer
400 void *GetAppendBuf(size_t sizeNeeded)
401 {
402 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
403 return (char*)m_bufdata->m_data + m_bufdata->m_len;
404 }
ef1cae87 405
2b5f62a0
VZ
406 // Update the length after the append
407 void UngetAppendBuf(size_t sizeUsed)
408 {
409 SetDataLen(m_bufdata->m_len + sizeUsed);
410 }
ef1cae87 411
2b5f62a0
VZ
412 // Other ways to append to the buffer
413 void AppendByte(char data)
b9fdb397 414 {
2b5f62a0
VZ
415 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
416
417 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
418 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
419 m_bufdata->m_len += 1;
420 }
421
68bc51a9 422 void AppendData(const void *data, size_t len)
2b5f62a0
VZ
423 {
424 memcpy(GetAppendBuf(len), data, len);
425 UngetAppendBuf(len);
b9fdb397
RD
426 }
427
2b5f62a0
VZ
428 operator const char *() const { return (const char*)GetData(); }
429
b9fdb397 430private:
2b5f62a0 431 wxMemoryBufferData* m_bufdata;
b9fdb397
RD
432};
433
14971e5b
VZ
434// ----------------------------------------------------------------------------
435// template class for any kind of data
436// ----------------------------------------------------------------------------
437
438// TODO
439
440#endif // _WX_BUFFER_H