reimplemented wx[W]CharBuffer using templates
[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 inline char *wxStrDup(const char *s) { return wxStrdupA(s); }
20 #if wxUSE_WCHAR_T
21 inline wchar_t *wxStrDup(const wchar_t *ws) { return wxStrdupW(ws); }
22 #endif
23
24 // ----------------------------------------------------------------------------
25 // Special classes for (wide) character strings: they use malloc/free instead
26 // of new/delete
27 // ----------------------------------------------------------------------------
28
29 template <typename T>
30 class WXDLLIMPEXP_BASE wxCharTypeBuffer
31 {
32 public:
33 typedef T CharType;
34
35 wxCharTypeBuffer(const CharType *str = NULL)
36 : m_str(str ? wxStrDup(str) : NULL)
37 {
38 }
39
40 wxCharTypeBuffer(const wxCStrData& cstr)
41 {
42 FromCStrData(cstr);
43 }
44
45 wxCharTypeBuffer(size_t len)
46 : m_str((CharType *)malloc((len + 1)*sizeof(CharType)))
47 {
48 m_str[len] = (CharType)0;
49 }
50
51 /* no need to check for NULL, free() does it */
52 ~wxCharTypeBuffer() { free(m_str); }
53
54 /*
55 WARNING:
56
57 the copy ctor and assignment operators change the passed in object
58 even although it is declared as "const", so:
59
60 a) it shouldn't be really const
61 b) you shouldn't use it afterwards (or know that it was reset)
62
63 This is very ugly but is unfortunately needed to make the normal use\
64 of wxCharTypeBuffer buffer objects possible and is very similar to what
65 std::auto_ptr<> does (as if it were an excuse...)
66 */
67
68 /*
69 because of the remark above, release() is declared const even if it
70 isn't really const
71 */
72 CharType *release() const
73 {
74 CharType *p = m_str;
75 ((wxCharTypeBuffer *)this)->m_str = NULL;
76 return p;
77 }
78
79 void reset()
80 {
81 free(m_str);
82 m_str = NULL;
83 }
84
85 wxCharTypeBuffer(const wxCharTypeBuffer& src)
86 : m_str(src.release())
87 {
88 }
89
90 wxCharTypeBuffer& operator=(const CharType *str)
91 {
92 free(m_str);
93 m_str = str ? wxStrDup(str) : NULL;
94 return *this;
95 }
96
97 wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src)
98 {
99 free(m_str);
100 m_str = src.release();
101
102 return *this;
103 }
104
105 bool extend(size_t len)
106 {
107 CharType *
108 str = (CharType *)realloc(m_str, (len + 1)*sizeof(CharType));
109 if ( !str )
110 return false;
111
112 m_str = str;
113
114 return true;
115 }
116
117 CharType *data() { return m_str; }
118 const CharType *data() const { return m_str; }
119 operator const CharType *() const { return m_str; }
120 CharType operator[](size_t n) const { return m_str[n]; }
121
122 private:
123 void FromCStrData(const wxCStrData& cstr);
124
125 private:
126 CharType *m_str;
127 };
128
129 class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char>
130 {
131 public:
132 wxCharBuffer(const CharType *str = NULL) : wxCharTypeBuffer<char>(str) {}
133 wxCharBuffer(const wxCStrData& cstr) : wxCharTypeBuffer<char>(cstr) {}
134 wxCharBuffer(size_t len) : wxCharTypeBuffer<char>(len) {}
135 };
136
137 #if wxUSE_WCHAR_T
138 class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
139 {
140 public:
141 wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBuffer<wchar_t>(str) {}
142 wxWCharBuffer(const wxCStrData& cstr) : wxCharTypeBuffer<wchar_t>(cstr) {}
143 wxWCharBuffer(size_t len) : wxCharTypeBuffer<wchar_t>(len) {}
144 };
145 #endif // wxUSE_WCHAR_T
146
147 #if wxUSE_UNICODE
148 typedef wxWCharBuffer wxWxCharBuffer;
149
150 #define wxMB2WXbuf wxWCharBuffer
151 #define wxWX2MBbuf wxCharBuffer
152 #define wxWC2WXbuf wxChar*
153 #define wxWX2WCbuf wxChar*
154 #else // ANSI
155 typedef wxCharBuffer wxWxCharBuffer;
156
157 #define wxMB2WXbuf wxChar*
158 #define wxWX2MBbuf wxChar*
159 #define wxWC2WXbuf wxCharBuffer
160 #define wxWX2WCbuf wxWCharBuffer
161 #endif // Unicode/ANSI
162
163 // ----------------------------------------------------------------------------
164 // A class for holding growable data buffers (not necessarily strings)
165 // ----------------------------------------------------------------------------
166
167 // This class manages the actual data buffer pointer and is ref-counted.
168 class wxMemoryBufferData
169 {
170 public:
171 // the initial size and also the size added by ResizeIfNeeded()
172 enum { DefBufSize = 1024 };
173
174 friend class wxMemoryBuffer;
175
176 // everyting is private as it can only be used by wxMemoryBuffer
177 private:
178 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
179 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
180 {
181 }
182 ~wxMemoryBufferData() { free(m_data); }
183
184
185 void ResizeIfNeeded(size_t newSize)
186 {
187 if (newSize > m_size)
188 {
189 void *dataOld = m_data;
190 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
191 if ( !m_data )
192 {
193 free(dataOld);
194 }
195
196 m_size = newSize + wxMemoryBufferData::DefBufSize;
197 }
198 }
199
200 void IncRef() { m_ref += 1; }
201 void DecRef()
202 {
203 m_ref -= 1;
204 if (m_ref == 0) // are there no more references?
205 delete this;
206 }
207
208
209 // the buffer containing the data
210 void *m_data;
211
212 // the size of the buffer
213 size_t m_size;
214
215 // the amount of data currently in the buffer
216 size_t m_len;
217
218 // the reference count
219 size_t m_ref;
220
221 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
222 };
223
224
225 class wxMemoryBuffer
226 {
227 public:
228 // ctor and dtor
229 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
230 {
231 m_bufdata = new wxMemoryBufferData(size);
232 m_bufdata->IncRef();
233 }
234
235 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
236
237
238 // copy and assignment
239 wxMemoryBuffer(const wxMemoryBuffer& src)
240 : m_bufdata(src.m_bufdata)
241 {
242 m_bufdata->IncRef();
243 }
244
245 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
246 {
247 m_bufdata->DecRef();
248 m_bufdata = src.m_bufdata;
249 m_bufdata->IncRef();
250 return *this;
251 }
252
253
254 // Accessors
255 void *GetData() const { return m_bufdata->m_data; }
256 size_t GetBufSize() const { return m_bufdata->m_size; }
257 size_t GetDataLen() const { return m_bufdata->m_len; }
258
259 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
260 void SetDataLen(size_t len)
261 {
262 wxASSERT(len <= m_bufdata->m_size);
263 m_bufdata->m_len = len;
264 }
265
266 // Ensure the buffer is big enough and return a pointer to it
267 void *GetWriteBuf(size_t sizeNeeded)
268 {
269 m_bufdata->ResizeIfNeeded(sizeNeeded);
270 return m_bufdata->m_data;
271 }
272
273 // Update the length after the write
274 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
275
276 // Like the above, but appends to the buffer
277 void *GetAppendBuf(size_t sizeNeeded)
278 {
279 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
280 return (char*)m_bufdata->m_data + m_bufdata->m_len;
281 }
282
283 // Update the length after the append
284 void UngetAppendBuf(size_t sizeUsed)
285 {
286 SetDataLen(m_bufdata->m_len + sizeUsed);
287 }
288
289 // Other ways to append to the buffer
290 void AppendByte(char data)
291 {
292 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
293
294 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
295 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
296 m_bufdata->m_len += 1;
297 }
298
299 void AppendData(const void *data, size_t len)
300 {
301 memcpy(GetAppendBuf(len), data, len);
302 UngetAppendBuf(len);
303 }
304
305 operator const char *() const { return (const char*)GetData(); }
306
307 private:
308 wxMemoryBufferData* m_bufdata;
309 };
310
311 // ----------------------------------------------------------------------------
312 // template class for any kind of data
313 // ----------------------------------------------------------------------------
314
315 // TODO
316
317 #endif // _WX_BUFFER_H