added wxBuffer::reset()
[wxWidgets.git] / include / wx / buffer.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/buffer.h
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 licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_BUFFER_H
13 #define _WX_BUFFER_H
14
15 #include "wx/wxchar.h"
16
17 #include <stdlib.h> // malloc() and free()
18
19 // ----------------------------------------------------------------------------
20 // Special classes for (wide) character strings: they use malloc/free instead
21 // of new/delete
22 // ----------------------------------------------------------------------------
23
24 #define DEFINE_BUFFER(classname, chartype, strdupfunc) \
25 class WXDLLIMPEXP_BASE classname \
26 { \
27 public: \
28 classname(const chartype *str = NULL) \
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 void reset() \
68 { \
69 free(m_str); \
70 m_str = NULL; \
71 } \
72 \
73 classname(const classname& src) \
74 : m_str(src.release()) \
75 { \
76 } \
77 \
78 classname& operator=(const chartype *str) \
79 { \
80 free(m_str); \
81 m_str = str ? strdupfunc(str) : NULL; \
82 return *this; \
83 } \
84 \
85 classname& operator=(const classname& src) \
86 { \
87 free(m_str); \
88 m_str = src.release(); \
89 \
90 return *this; \
91 } \
92 \
93 bool extend(size_t len) \
94 { \
95 chartype * \
96 str = (chartype *)realloc(m_str, (len + 1)*sizeof(chartype)); \
97 if ( !str ) \
98 return false; \
99 \
100 m_str = str; \
101 \
102 return true; \
103 } \
104 \
105 chartype *data() { return m_str; } \
106 const chartype *data() const { return m_str; } \
107 operator const chartype *() const { return m_str; } \
108 chartype operator[](size_t n) const { return m_str[n]; } \
109 \
110 private: \
111 chartype *m_str; \
112 }
113
114 DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
115
116 #if wxUSE_WCHAR_T
117
118 DEFINE_BUFFER(wxWCharBuffer, wchar_t, wxStrdupW);
119
120 #endif // wxUSE_WCHAR_T
121
122 #undef DEFINE_BUFFER
123
124 #if wxUSE_UNICODE
125 #define wxMB2WXbuf wxWCharBuffer
126 #define wxWX2MBbuf wxCharBuffer
127 #define wxWC2WXbuf wxChar*
128 #define wxWX2WCbuf wxChar*
129 #else // ANSI
130 #define wxMB2WXbuf wxChar*
131 #define wxWX2MBbuf wxChar*
132 #define wxWC2WXbuf wxCharBuffer
133 #define wxWX2WCbuf wxWCharBuffer
134 #endif // Unicode/ANSI
135
136 // ----------------------------------------------------------------------------
137 // A class for holding growable data buffers (not necessarily strings)
138 // ----------------------------------------------------------------------------
139
140 // This class manages the actual data buffer pointer and is ref-counted.
141 class wxMemoryBufferData
142 {
143 public:
144 // the initial size and also the size added by ResizeIfNeeded()
145 enum { DefBufSize = 1024 };
146
147 friend class wxMemoryBuffer;
148
149 // everyting is private as it can only be used by wxMemoryBuffer
150 private:
151 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
152 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
153 {
154 }
155 ~wxMemoryBufferData() { free(m_data); }
156
157
158 void ResizeIfNeeded(size_t newSize)
159 {
160 if (newSize > m_size)
161 {
162 void *dataOld = m_data;
163 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
164 if ( !m_data )
165 {
166 free(dataOld);
167 }
168
169 m_size = newSize + wxMemoryBufferData::DefBufSize;
170 }
171 }
172
173 void IncRef() { m_ref += 1; }
174 void DecRef()
175 {
176 m_ref -= 1;
177 if (m_ref == 0) // are there no more references?
178 delete this;
179 }
180
181
182 // the buffer containing the data
183 void *m_data;
184
185 // the size of the buffer
186 size_t m_size;
187
188 // the amount of data currently in the buffer
189 size_t m_len;
190
191 // the reference count
192 size_t m_ref;
193
194 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
195 };
196
197
198 class wxMemoryBuffer
199 {
200 public:
201 // ctor and dtor
202 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
203 {
204 m_bufdata = new wxMemoryBufferData(size);
205 m_bufdata->IncRef();
206 }
207
208 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
209
210
211 // copy and assignment
212 wxMemoryBuffer(const wxMemoryBuffer& src)
213 : m_bufdata(src.m_bufdata)
214 {
215 m_bufdata->IncRef();
216 }
217
218 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
219 {
220 m_bufdata->DecRef();
221 m_bufdata = src.m_bufdata;
222 m_bufdata->IncRef();
223 return *this;
224 }
225
226
227 // Accessors
228 void *GetData() const { return m_bufdata->m_data; }
229 size_t GetBufSize() const { return m_bufdata->m_size; }
230 size_t GetDataLen() const { return m_bufdata->m_len; }
231
232 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
233 void SetDataLen(size_t len)
234 {
235 wxASSERT(len <= m_bufdata->m_size);
236 m_bufdata->m_len = len;
237 }
238
239 // Ensure the buffer is big enough and return a pointer to it
240 void *GetWriteBuf(size_t sizeNeeded)
241 {
242 m_bufdata->ResizeIfNeeded(sizeNeeded);
243 return m_bufdata->m_data;
244 }
245
246 // Update the length after the write
247 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
248
249 // Like the above, but appends to the buffer
250 void *GetAppendBuf(size_t sizeNeeded)
251 {
252 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
253 return (char*)m_bufdata->m_data + m_bufdata->m_len;
254 }
255
256 // Update the length after the append
257 void UngetAppendBuf(size_t sizeUsed)
258 {
259 SetDataLen(m_bufdata->m_len + sizeUsed);
260 }
261
262 // Other ways to append to the buffer
263 void AppendByte(char data)
264 {
265 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
266
267 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
268 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
269 m_bufdata->m_len += 1;
270 }
271
272 void AppendData(const void *data, size_t len)
273 {
274 memcpy(GetAppendBuf(len), data, len);
275 UngetAppendBuf(len);
276 }
277
278 operator const char *() const { return (const char*)GetData(); }
279
280 private:
281 wxMemoryBufferData* m_bufdata;
282 };
283
284 // ----------------------------------------------------------------------------
285 // template class for any kind of data
286 // ----------------------------------------------------------------------------
287
288 // TODO
289
290 #endif // _WX_BUFFER_H