]> git.saurik.com Git - wxWidgets.git/blame - include/wx/buffer.h
SourceForge patch #654210 to fix naming/numbering shared libs under OS X
[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>
9// Licence: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// these classes are for private use only for now, they're not documented
13
14#ifndef _WX_BUFFER_H
15#define _WX_BUFFER_H
16
853d7d3d 17#include "wx/wxchar.h"
e90c1d2a 18
14971e5b
VZ
19// ----------------------------------------------------------------------------
20// Special classes for (wide) character strings: they use malloc/free instead
21// of new/delete
22// ----------------------------------------------------------------------------
23
2b5f62a0
VZ
24#define DEFINE_BUFFER(classname, chartype, strdupfunc) \
25class classname \
26{ \
27public: \
28 classname(const chartype *str) \
29 : m_str(str ? strdupfunc(str) : NULL) \
30 { \
31 } \
32 \
33 classname(size_t len) \
34 : m_str((chartype *)malloc((len + 1)*sizeof(chartype))) \
35 { \
36 m_str[len] = (chartype)0; \
37 } \
38 \
39 /* no need to check for NULL, free() does it */ \
40 ~classname() { free(m_str); } \
41 \
42 /* \
43 WARNING: \
44 \
45 the copy ctor and assignment operators change the passed in object \
46 even although it is declared as "const", so: \
47 \
48 a) it shouldn't be really const \
49 b) you shouldn't use it afterwards (or know that it was reset) \
50 \
51 This is very ugly but is unfortunately needed to make the normal use\
52 of classname buffer objects possible and is very similar to what \
53 std::auto_ptr<> does (as if it were an excuse...) \
54 */ \
55 \
56 /* \
57 because of the remark above, release() is declared const even if it \
58 isn't really const \
59 */ \
60 chartype *release() const \
61 { \
62 chartype *p = m_str; \
63 ((classname *)this)->m_str = NULL; \
64 return p; \
65 } \
66 \
67 classname(const classname& src) \
68 : m_str(src.release()) \
69 { \
70 } \
71 \
72 classname& operator=(const chartype *str) \
73 { \
74 free(m_str); \
75 m_str = str ? strdupfunc(str) : NULL; \
76 return *this; \
77 } \
78 \
79 classname& operator=(const classname& src) \
80 { \
81 free(m_str); \
82 m_str = src.release(); \
83 \
84 return *this; \
85 } \
86 \
87 chartype *data() { return m_str; } \
88 const chartype *data() const { return m_str; } \
89 operator const chartype *() const { return m_str; } \
90 chartype operator[](size_t n) const { return m_str[n]; } \
91 \
92private: \
93 chartype *m_str; \
94}
95
07243717 96DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
14971e5b 97
7a3e402c 98#if wxUSE_WCHAR_T
c12ef8a2 99
07243717 100DEFINE_BUFFER(wxWCharBuffer, wchar_t, wxStrdupW);
c12ef8a2
VZ
101
102#endif // wxUSE_WCHAR_T
14971e5b 103
2b5f62a0
VZ
104#undef DEFINE_BUFFER
105
f93d01be 106#if wxUSE_UNICODE
e90c1d2a
VZ
107 #define wxMB2WXbuf wxWCharBuffer
108 #define wxWX2MBbuf wxCharBuffer
109 #define wxWC2WXbuf wxChar*
110 #define wxWX2WCbuf wxChar*
111#else // ANSI
112 #define wxMB2WXbuf wxChar*
113 #define wxWX2MBbuf wxChar*
114 #define wxWC2WXbuf wxCharBuffer
115 #define wxWX2WCbuf wxWCharBuffer
116#endif // Unicode/ANSI
f93d01be 117
b9fdb397
RD
118// ----------------------------------------------------------------------------
119// A class for holding growable data buffers (not necessarily strings)
120// ----------------------------------------------------------------------------
121
2b5f62a0
VZ
122// This class manages the actual data buffer pointer and is ref-counted.
123class wxMemoryBufferData
b9fdb397
RD
124{
125public:
2b5f62a0 126 // the initial size and also the size added by ResizeIfNeeded()
b9fdb397 127 enum { BLOCK_SIZE = 1024 };
2b5f62a0
VZ
128
129 friend class wxMemoryBuffer;
130
131 // everyting is private as it can only be used by wxMemoryBuffer
132private:
133 wxMemoryBufferData(size_t size = wxMemoryBufferData::BLOCK_SIZE)
134 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
b9fdb397 135 {
b9fdb397 136 }
2b5f62a0 137 ~wxMemoryBufferData() { free(m_data); }
b9fdb397 138
b9fdb397 139
2b5f62a0 140 void ResizeIfNeeded(size_t newSize)
b9fdb397 141 {
2b5f62a0
VZ
142 if (newSize > m_size)
143 {
144 void *dataOld = m_data;
145 m_data = realloc(m_data, newSize + wxMemoryBufferData::BLOCK_SIZE);
146 if ( !m_data )
147 {
148 free(dataOld);
149 }
150
151 m_size = newSize + wxMemoryBufferData::BLOCK_SIZE;
152 }
b9fdb397
RD
153 }
154
2b5f62a0
VZ
155 void IncRef() { m_ref += 1; }
156 void DecRef()
b9fdb397 157 {
2b5f62a0
VZ
158 m_ref -= 1;
159 if (m_ref == 0) // are there no more references?
160 delete this;
b9fdb397 161 }
b9fdb397 162
2b5f62a0
VZ
163
164 // the buffer containing the data
165 void *m_data;
166
167 // the size of the buffer
168 size_t m_size;
169
170 // the amount of data currently in the buffer
171 size_t m_len;
172
173 // the reference count
174 size_t m_ref;
175};
176
177
178class wxMemoryBuffer
179{
180public:
181 // ctor and dtor
182 wxMemoryBuffer(size_t size = wxMemoryBufferData::BLOCK_SIZE)
b9fdb397 183 {
2b5f62a0
VZ
184 m_bufdata = new wxMemoryBufferData(size);
185 m_bufdata->IncRef();
b9fdb397 186 }
b9fdb397 187
2b5f62a0
VZ
188 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
189
190
191 // copy and assignment
192 wxMemoryBuffer(const wxMemoryBuffer& src)
193 : m_bufdata(src.m_bufdata)
194 {
195 m_bufdata->IncRef();
b9fdb397 196 }
2b5f62a0
VZ
197
198 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
b9fdb397 199 {
2b5f62a0
VZ
200 m_bufdata->DecRef();
201 m_bufdata = src.m_bufdata;
202 m_bufdata->IncRef();
203 return *this;
b9fdb397
RD
204 }
205
b9fdb397 206
2b5f62a0
VZ
207 // Accessors
208 void *GetData() const { return m_bufdata->m_data; }
209 size_t GetBufSize() const { return m_bufdata->m_size; }
210 size_t GetDataLen() const { return m_bufdata->m_len; }
ef1cae87 211
2b5f62a0
VZ
212 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
213 void SetDataLen(size_t len)
ef1cae87 214 {
2b5f62a0
VZ
215 wxASSERT(len <= m_bufdata->m_size);
216 m_bufdata->m_len = len;
ef1cae87
RD
217 }
218
2b5f62a0
VZ
219 // Ensure the buffer is big enough and return a pointer to it
220 void *GetWriteBuf(size_t sizeNeeded)
ef1cae87 221 {
2b5f62a0
VZ
222 m_bufdata->ResizeIfNeeded(sizeNeeded);
223 return m_bufdata->m_data;
224 }
c12ef8a2 225
2b5f62a0
VZ
226 // Update the length after the write
227 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
ef1cae87 228
2b5f62a0
VZ
229 // Like the above, but appends to the buffer
230 void *GetAppendBuf(size_t sizeNeeded)
231 {
232 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
233 return (char*)m_bufdata->m_data + m_bufdata->m_len;
234 }
ef1cae87 235
2b5f62a0
VZ
236 // Update the length after the append
237 void UngetAppendBuf(size_t sizeUsed)
238 {
239 SetDataLen(m_bufdata->m_len + sizeUsed);
240 }
ef1cae87 241
2b5f62a0
VZ
242 // Other ways to append to the buffer
243 void AppendByte(char data)
b9fdb397 244 {
2b5f62a0
VZ
245 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
246
247 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
248 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
249 m_bufdata->m_len += 1;
250 }
251
252 void AppendData(void* data, size_t len)
253 {
254 memcpy(GetAppendBuf(len), data, len);
255 UngetAppendBuf(len);
b9fdb397
RD
256 }
257
2b5f62a0
VZ
258 operator const char *() const { return (const char*)GetData(); }
259
b9fdb397 260private:
2b5f62a0 261 wxMemoryBufferData* m_bufdata;
b9fdb397
RD
262};
263
14971e5b
VZ
264// ----------------------------------------------------------------------------
265// template class for any kind of data
266// ----------------------------------------------------------------------------
267
268// TODO
269
270#endif // _WX_BUFFER_H