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