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