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