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