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