]> git.saurik.com Git - wxWidgets.git/blob - include/wx/buffer.h
made wxCharTypeBuffer<T>::release() const again, for compatibility
[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 #ifndef __WXPALMOS5__
19 #include <stdlib.h> // malloc() and free()
20 #endif // ! __WXPALMOS5__
21
22 class WXDLLIMPEXP_FWD_BASE wxCStrData;
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 WXDLLIMPEXP_BASE wxCharTypeBuffer
31 {
32 public:
33 typedef T CharType;
34
35 wxCharTypeBuffer(const CharType *str = NULL)
36 {
37 if ( str )
38 m_data = new Data(wxStrdup(str));
39 else
40 m_data = &NullData;
41 }
42
43 wxCharTypeBuffer(size_t len)
44 {
45 m_data = new Data((CharType *)malloc((len + 1)*sizeof(CharType)));
46 m_data->m_str[len] = (CharType)0;
47 }
48
49 static const wxCharTypeBuffer CreateNonOwned(const CharType *str)
50 {
51 wxCharTypeBuffer buf;
52 if ( str )
53 buf.m_data = new Data(wx_const_cast(CharType*, str), Data::NonOwned);
54 return buf;
55 }
56
57 ~wxCharTypeBuffer()
58 {
59 DecRef();
60 }
61
62 // NB: this method is only const for backward compatibility. It used to
63 // be needed for auto_ptr-like semantics of the copy ctor, but now
64 // that ref-counting is used, it's not really needed.
65 CharType *release() const
66 {
67 if ( m_data == &NullData )
68 return NULL;
69
70 wxASSERT_MSG( m_data->m_owned, _T("can't release non-owned buffer") );
71 wxASSERT_MSG( m_data->m_ref == 1, _T("can't release shared buffer") );
72
73 CharType *p = m_data->m_str;
74
75 wxCharTypeBuffer *self = wx_const_cast(wxCharTypeBuffer*, this);
76 self->m_data->m_str = NULL;
77 self->DecRef();
78
79 return p;
80 }
81
82 void reset()
83 {
84 DecRef();
85 }
86
87 wxCharTypeBuffer(const wxCharTypeBuffer& src)
88 {
89 m_data = src.m_data;
90 IncRef();
91 }
92
93 wxCharTypeBuffer& operator=(const CharType *str)
94 {
95 DecRef();
96
97 if ( str )
98 m_data = new Data(wxStrdup(str));
99 return *this;
100 }
101
102 wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src)
103 {
104 if ( &src == this )
105 return *this;
106
107 DecRef();
108 m_data = src.m_data;
109 IncRef();
110
111 return *this;
112 }
113
114 bool extend(size_t len)
115 {
116 wxASSERT_MSG( m_data->m_owned, _T("cannot extend non-owned buffer") );
117 wxASSERT_MSG( m_data->m_ref == 1, _T("can't extend shared buffer") );
118
119 CharType *str =
120 (CharType *)realloc(data(), (len + 1) * sizeof(CharType));
121 if ( !str )
122 return false;
123
124 if ( m_data == &NullData )
125 {
126 m_data = new Data(str);
127 }
128 else
129 {
130 m_data->m_str = str;
131 m_data->m_owned = true;
132 }
133
134 return true;
135 }
136
137 CharType *data() { return m_data->m_str; }
138 const CharType *data() const { return m_data->m_str; }
139 operator const CharType *() const { return data(); }
140 CharType operator[](size_t n) const { return data()[n]; }
141
142 private:
143 // reference-counted data
144 struct Data
145 {
146 enum Kind
147 {
148 Owned,
149 NonOwned
150 };
151
152 Data(CharType *str, Kind kind = Owned)
153 : m_str(str), m_ref(1), m_owned(kind == Owned) {}
154
155 ~Data()
156 {
157 if ( m_owned )
158 free(m_str);
159 }
160
161 CharType *m_str;
162
163 // "short" to have sizeof(Data)=8 on 32bit archs
164 unsigned short m_ref;
165
166 bool m_owned;
167 };
168
169 // placeholder for NULL string, to simplify this code
170 // NB: this is defined in string.cpp, not (non-existent) buffer.cpp
171 static WXDLLIMPEXP_DATA_BASE(Data) NullData;
172
173 void IncRef()
174 {
175 if ( m_data == &NullData ) // exception, not ref-counted
176 return;
177 m_data->m_ref++;
178 }
179
180 void DecRef()
181 {
182 if ( m_data == &NullData ) // exception, not ref-counted
183 return;
184 if ( --m_data->m_ref == 0 )
185 delete m_data;
186 m_data = &NullData;
187 }
188
189 private:
190 Data *m_data;
191 };
192
193 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
194
195 class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char>
196 {
197 public:
198 typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
199
200 wxCharBuffer(const wxCharTypeBufferBase& buf)
201 : wxCharTypeBufferBase(buf) {}
202
203 wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
204 wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
205
206 wxCharBuffer(const wxCStrData& cstr);
207 };
208
209 #if wxUSE_WCHAR_T
210 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
211
212 class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
213 {
214 public:
215 typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
216
217 wxWCharBuffer(const wxCharTypeBufferBase& buf)
218 : wxCharTypeBufferBase(buf) {}
219
220 wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
221 wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
222
223 wxWCharBuffer(const wxCStrData& cstr);
224 };
225 #endif // wxUSE_WCHAR_T
226
227 // wxCharTypeBuffer<T> implicitly convertible to T*
228 template <typename T>
229 class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
230 {
231 public:
232 typedef typename wxCharTypeBuffer<T>::CharType CharType;
233
234 wxWritableCharTypeBuffer(const wxCharTypeBuffer<T>& src)
235 : wxCharTypeBuffer<T>(src) {}
236 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
237 // always return a buffer
238 wxWritableCharTypeBuffer(const CharType *str = NULL)
239 : wxCharTypeBuffer<T>(str) {}
240
241 operator CharType*() { return this->data(); }
242 };
243
244 typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
245 typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
246
247
248 #if wxUSE_UNICODE
249 #define wxWxCharBuffer wxWCharBuffer
250
251 #define wxMB2WXbuf wxWCharBuffer
252 #define wxWX2MBbuf wxCharBuffer
253 #if wxUSE_UNICODE_WCHAR
254 #define wxWC2WXbuf wxChar*
255 #define wxWX2WCbuf wxChar*
256 #elif wxUSE_UNICODE_UTF8
257 #define wxWC2WXbuf wxWCharBuffer
258 #define wxWX2WCbuf wxWCharBuffer
259 #endif
260 #else // ANSI
261 #define wxWxCharBuffer wxCharBuffer
262
263 #define wxMB2WXbuf wxChar*
264 #define wxWX2MBbuf wxChar*
265 #define wxWC2WXbuf wxCharBuffer
266 #define wxWX2WCbuf wxWCharBuffer
267 #endif // Unicode/ANSI
268
269 // type of the value returned by wxString::utf8_str()
270 #if wxUSE_UNICODE_UTF8
271 #define wxUTF8Buf char *
272 #else
273 #define wxUTF8Buf wxCharBuffer
274 #endif
275
276 // ----------------------------------------------------------------------------
277 // A class for holding growable data buffers (not necessarily strings)
278 // ----------------------------------------------------------------------------
279
280 // This class manages the actual data buffer pointer and is ref-counted.
281 class wxMemoryBufferData
282 {
283 public:
284 // the initial size and also the size added by ResizeIfNeeded()
285 enum { DefBufSize = 1024 };
286
287 friend class wxMemoryBuffer;
288
289 // everyting is private as it can only be used by wxMemoryBuffer
290 private:
291 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
292 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
293 {
294 }
295 ~wxMemoryBufferData() { free(m_data); }
296
297
298 void ResizeIfNeeded(size_t newSize)
299 {
300 if (newSize > m_size)
301 {
302 void *dataOld = m_data;
303 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
304 if ( !m_data )
305 {
306 free(dataOld);
307 }
308
309 m_size = newSize + wxMemoryBufferData::DefBufSize;
310 }
311 }
312
313 void IncRef() { m_ref += 1; }
314 void DecRef()
315 {
316 m_ref -= 1;
317 if (m_ref == 0) // are there no more references?
318 delete this;
319 }
320
321
322 // the buffer containing the data
323 void *m_data;
324
325 // the size of the buffer
326 size_t m_size;
327
328 // the amount of data currently in the buffer
329 size_t m_len;
330
331 // the reference count
332 size_t m_ref;
333
334 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
335 };
336
337
338 class WXDLLIMPEXP_BASE wxMemoryBuffer
339 {
340 public:
341 // ctor and dtor
342 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
343 {
344 m_bufdata = new wxMemoryBufferData(size);
345 m_bufdata->IncRef();
346 }
347
348 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
349
350
351 // copy and assignment
352 wxMemoryBuffer(const wxMemoryBuffer& src)
353 : m_bufdata(src.m_bufdata)
354 {
355 m_bufdata->IncRef();
356 }
357
358 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
359 {
360 if (&src != this)
361 {
362 m_bufdata->DecRef();
363 m_bufdata = src.m_bufdata;
364 m_bufdata->IncRef();
365 }
366 return *this;
367 }
368
369
370 // Accessors
371 void *GetData() const { return m_bufdata->m_data; }
372 size_t GetBufSize() const { return m_bufdata->m_size; }
373 size_t GetDataLen() const { return m_bufdata->m_len; }
374
375 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
376 void SetDataLen(size_t len)
377 {
378 wxASSERT(len <= m_bufdata->m_size);
379 m_bufdata->m_len = len;
380 }
381
382 // Ensure the buffer is big enough and return a pointer to it
383 void *GetWriteBuf(size_t sizeNeeded)
384 {
385 m_bufdata->ResizeIfNeeded(sizeNeeded);
386 return m_bufdata->m_data;
387 }
388
389 // Update the length after the write
390 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
391
392 // Like the above, but appends to the buffer
393 void *GetAppendBuf(size_t sizeNeeded)
394 {
395 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
396 return (char*)m_bufdata->m_data + m_bufdata->m_len;
397 }
398
399 // Update the length after the append
400 void UngetAppendBuf(size_t sizeUsed)
401 {
402 SetDataLen(m_bufdata->m_len + sizeUsed);
403 }
404
405 // Other ways to append to the buffer
406 void AppendByte(char data)
407 {
408 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
409
410 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
411 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
412 m_bufdata->m_len += 1;
413 }
414
415 void AppendData(const void *data, size_t len)
416 {
417 memcpy(GetAppendBuf(len), data, len);
418 UngetAppendBuf(len);
419 }
420
421 operator const char *() const { return (const char*)GetData(); }
422
423 private:
424 wxMemoryBufferData* m_bufdata;
425 };
426
427 // ----------------------------------------------------------------------------
428 // template class for any kind of data
429 // ----------------------------------------------------------------------------
430
431 // TODO
432
433 #endif // _WX_BUFFER_H