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