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