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