]> git.saurik.com Git - wxWidgets.git/blame - include/wx/buffer.h
g++ compilation fix after latest changes
[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>
6b583d40 30class 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
6b583d40 40 m_data = GetNullData();
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 66 {
6b583d40 67 if ( m_data == GetNullData() )
5c1de526 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
6b583d40 124 if ( m_data == GetNullData() )
5c1de526
VS
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
6b583d40
VZ
170 static Data *GetNullData()
171 {
172 static Data s_nullData(NULL);
173
174 return &s_nullData;
175 }
5c1de526
VS
176
177 void IncRef()
178 {
6b583d40 179 if ( m_data == GetNullData() ) // exception, not ref-counted
5c1de526
VS
180 return;
181 m_data->m_ref++;
486a5941
VS
182 }
183
5c1de526 184 void DecRef()
486a5941 185 {
6b583d40 186 if ( m_data == GetNullData() ) // exception, not ref-counted
5c1de526
VS
187 return;
188 if ( --m_data->m_ref == 0 )
189 delete m_data;
6b583d40 190 m_data = GetNullData();
486a5941
VS
191 }
192
d18c8d3d 193private:
5c1de526 194 Data *m_data;
d18c8d3d
VS
195};
196
7c77f334
VZ
197WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
198
6b583d40 199class wxCharBuffer : public wxCharTypeBuffer<char>
d18c8d3d
VS
200{
201public:
ccd4deab
VZ
202 typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
203
681e4412
VS
204 wxCharBuffer(const wxCharTypeBufferBase& buf)
205 : wxCharTypeBufferBase(buf) {}
206
ccd4deab
VZ
207 wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
208 wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
209
ccd4deab 210 wxCharBuffer(const wxCStrData& cstr);
d18c8d3d
VS
211};
212
213#if wxUSE_WCHAR_T
7c77f334
VZ
214WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
215
6b583d40 216class wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
d18c8d3d
VS
217{
218public:
ccd4deab
VZ
219 typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
220
681e4412
VS
221 wxWCharBuffer(const wxCharTypeBufferBase& buf)
222 : wxCharTypeBufferBase(buf) {}
223
ccd4deab
VZ
224 wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
225 wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
226
ccd4deab 227 wxWCharBuffer(const wxCStrData& cstr);
d18c8d3d
VS
228};
229#endif // wxUSE_WCHAR_T
2b5f62a0 230
ef0f1387
VS
231// wxCharTypeBuffer<T> implicitly convertible to T*
232template <typename T>
665e6a87 233class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
ef0f1387
VS
234{
235public:
236 typedef typename wxCharTypeBuffer<T>::CharType CharType;
237
238 wxWritableCharTypeBuffer(const wxCharTypeBuffer<T>& src)
239 : wxCharTypeBuffer<T>(src) {}
240 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
241 // always return a buffer
242 wxWritableCharTypeBuffer(const CharType *str = NULL)
243 : wxCharTypeBuffer<T>(str) {}
244
245 operator CharType*() { return this->data(); }
246};
247
248typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
249typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
250
251
f93d01be 252#if wxUSE_UNICODE
ccd4deab 253 #define wxWxCharBuffer wxWCharBuffer
2f4f6de7 254
e90c1d2a
VZ
255 #define wxMB2WXbuf wxWCharBuffer
256 #define wxWX2MBbuf wxCharBuffer
81727065
VS
257 #if wxUSE_UNICODE_WCHAR
258 #define wxWC2WXbuf wxChar*
259 #define wxWX2WCbuf wxChar*
260 #elif wxUSE_UNICODE_UTF8
261 #define wxWC2WXbuf wxWCharBuffer
262 #define wxWX2WCbuf wxWCharBuffer
263 #endif
e90c1d2a 264#else // ANSI
ccd4deab 265 #define wxWxCharBuffer wxCharBuffer
2f4f6de7 266
e90c1d2a
VZ
267 #define wxMB2WXbuf wxChar*
268 #define wxWX2MBbuf wxChar*
269 #define wxWC2WXbuf wxCharBuffer
270 #define wxWX2WCbuf wxWCharBuffer
271#endif // Unicode/ANSI
f93d01be 272
30386aeb
VZ
273// type of the value returned by wxString::utf8_str()
274#if wxUSE_UNICODE_UTF8
30386aeb 275 #define wxUTF8Buf char *
53c75dc2
VZ
276#else
277 #define wxUTF8Buf wxCharBuffer
30386aeb
VZ
278#endif
279
b9fdb397
RD
280// ----------------------------------------------------------------------------
281// A class for holding growable data buffers (not necessarily strings)
282// ----------------------------------------------------------------------------
283
2b5f62a0
VZ
284// This class manages the actual data buffer pointer and is ref-counted.
285class wxMemoryBufferData
b9fdb397
RD
286{
287public:
2b5f62a0 288 // the initial size and also the size added by ResizeIfNeeded()
ae0ca755 289 enum { DefBufSize = 1024 };
2b5f62a0
VZ
290
291 friend class wxMemoryBuffer;
292
293 // everyting is private as it can only be used by wxMemoryBuffer
294private:
ae0ca755 295 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
2b5f62a0 296 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
b9fdb397 297 {
b9fdb397 298 }
2b5f62a0 299 ~wxMemoryBufferData() { free(m_data); }
b9fdb397 300
b9fdb397 301
2b5f62a0 302 void ResizeIfNeeded(size_t newSize)
b9fdb397 303 {
2b5f62a0
VZ
304 if (newSize > m_size)
305 {
306 void *dataOld = m_data;
ae0ca755 307 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
2b5f62a0
VZ
308 if ( !m_data )
309 {
310 free(dataOld);
311 }
312
ae0ca755 313 m_size = newSize + wxMemoryBufferData::DefBufSize;
2b5f62a0 314 }
b9fdb397
RD
315 }
316
2b5f62a0
VZ
317 void IncRef() { m_ref += 1; }
318 void DecRef()
b9fdb397 319 {
2b5f62a0
VZ
320 m_ref -= 1;
321 if (m_ref == 0) // are there no more references?
322 delete this;
b9fdb397 323 }
b9fdb397 324
2b5f62a0
VZ
325
326 // the buffer containing the data
327 void *m_data;
328
329 // the size of the buffer
330 size_t m_size;
331
332 // the amount of data currently in the buffer
333 size_t m_len;
334
335 // the reference count
336 size_t m_ref;
22f3361e
VZ
337
338 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
2b5f62a0
VZ
339};
340
341
6b583d40 342class wxMemoryBuffer
2b5f62a0
VZ
343{
344public:
345 // ctor and dtor
ae0ca755 346 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
b9fdb397 347 {
2b5f62a0
VZ
348 m_bufdata = new wxMemoryBufferData(size);
349 m_bufdata->IncRef();
b9fdb397 350 }
b9fdb397 351
2b5f62a0
VZ
352 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
353
354
355 // copy and assignment
356 wxMemoryBuffer(const wxMemoryBuffer& src)
357 : m_bufdata(src.m_bufdata)
358 {
359 m_bufdata->IncRef();
b9fdb397 360 }
2b5f62a0
VZ
361
362 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
b9fdb397 363 {
162e998c
PC
364 if (&src != this)
365 {
366 m_bufdata->DecRef();
367 m_bufdata = src.m_bufdata;
368 m_bufdata->IncRef();
369 }
2b5f62a0 370 return *this;
b9fdb397
RD
371 }
372
b9fdb397 373
2b5f62a0
VZ
374 // Accessors
375 void *GetData() const { return m_bufdata->m_data; }
376 size_t GetBufSize() const { return m_bufdata->m_size; }
377 size_t GetDataLen() const { return m_bufdata->m_len; }
ef1cae87 378
2b5f62a0
VZ
379 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
380 void SetDataLen(size_t len)
ef1cae87 381 {
2b5f62a0
VZ
382 wxASSERT(len <= m_bufdata->m_size);
383 m_bufdata->m_len = len;
ef1cae87
RD
384 }
385
2b5f62a0
VZ
386 // Ensure the buffer is big enough and return a pointer to it
387 void *GetWriteBuf(size_t sizeNeeded)
ef1cae87 388 {
2b5f62a0
VZ
389 m_bufdata->ResizeIfNeeded(sizeNeeded);
390 return m_bufdata->m_data;
391 }
c12ef8a2 392
2b5f62a0
VZ
393 // Update the length after the write
394 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
ef1cae87 395
2b5f62a0
VZ
396 // Like the above, but appends to the buffer
397 void *GetAppendBuf(size_t sizeNeeded)
398 {
399 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
400 return (char*)m_bufdata->m_data + m_bufdata->m_len;
401 }
ef1cae87 402
2b5f62a0
VZ
403 // Update the length after the append
404 void UngetAppendBuf(size_t sizeUsed)
405 {
406 SetDataLen(m_bufdata->m_len + sizeUsed);
407 }
ef1cae87 408
2b5f62a0
VZ
409 // Other ways to append to the buffer
410 void AppendByte(char data)
b9fdb397 411 {
2b5f62a0
VZ
412 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
413
414 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
415 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
416 m_bufdata->m_len += 1;
417 }
418
68bc51a9 419 void AppendData(const void *data, size_t len)
2b5f62a0
VZ
420 {
421 memcpy(GetAppendBuf(len), data, len);
422 UngetAppendBuf(len);
b9fdb397
RD
423 }
424
2b5f62a0
VZ
425 operator const char *() const { return (const char*)GetData(); }
426
b9fdb397 427private:
2b5f62a0 428 wxMemoryBufferData* m_bufdata;
b9fdb397
RD
429};
430
14971e5b
VZ
431// ----------------------------------------------------------------------------
432// template class for any kind of data
433// ----------------------------------------------------------------------------
434
435// TODO
436
437#endif // _WX_BUFFER_H