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