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