1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: auto buffer classes: buffers which automatically free memory
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
15 #include "wx/chartype.h"
16 #include "wx/wxcrtbase.h"
19 #include <stdlib.h> // malloc() and free()
20 #endif // ! __WXPALMOS5__
22 class WXDLLIMPEXP_FWD_BASE wxCStrData
;
24 // ----------------------------------------------------------------------------
25 // Special classes for (wide) character strings: they use malloc/free instead
27 // ----------------------------------------------------------------------------
30 class WXDLLIMPEXP_BASE wxCharTypeBuffer
35 wxCharTypeBuffer(const CharType
*str
= NULL
)
38 m_data
= new Data(wxStrdup(str
));
43 wxCharTypeBuffer(size_t len
)
45 m_data
= new Data((CharType
*)malloc((len
+ 1)*sizeof(CharType
)));
46 m_data
->m_str
[len
] = (CharType
)0;
49 static const wxCharTypeBuffer
CreateNonOwned(const CharType
*str
)
53 buf
.m_data
= new Data(wx_const_cast(CharType
*, str
), Data::NonOwned
);
64 if ( m_data
== &NullData
)
67 wxASSERT_MSG( m_data
->m_owned
, _T("can't release non-owned buffer") );
68 wxASSERT_MSG( m_data
->m_ref
== 1, _T("can't release shared buffer") );
70 CharType
*p
= m_data
->m_str
;
81 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
87 wxCharTypeBuffer
& operator=(const CharType
*str
)
92 m_data
= new Data(wxStrdup(str
));
96 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
108 bool extend(size_t len
)
110 wxASSERT_MSG( m_data
->m_owned
, _T("cannot extend non-owned buffer") );
111 wxASSERT_MSG( m_data
->m_ref
== 1, _T("can't extend shared buffer") );
114 (CharType
*)realloc(data(), (len
+ 1) * sizeof(CharType
));
118 if ( m_data
== &NullData
)
120 m_data
= new Data(str
);
125 m_data
->m_owned
= true;
131 CharType
*data() { return m_data
->m_str
; }
132 const CharType
*data() const { return m_data
->m_str
; }
133 operator const CharType
*() const { return data(); }
134 CharType
operator[](size_t n
) const { return data()[n
]; }
137 // reference-counted data
146 Data(CharType
*str
, Kind kind
= Owned
)
147 : m_str(str
), m_ref(1), m_owned(kind
== Owned
) {}
157 // "short" to have sizeof(Data)=8 on 32bit archs
158 unsigned short m_ref
;
163 // placeholder for NULL string, to simplify this code
164 // NB: this is defined in string.cpp, not (non-existent) buffer.cpp
165 static WXDLLIMPEXP_DATA_BASE(Data
) NullData
;
169 if ( m_data
== &NullData
) // exception, not ref-counted
176 if ( m_data
== &NullData
) // exception, not ref-counted
178 if ( --m_data
->m_ref
== 0 )
187 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<char> )
189 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
192 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
194 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
195 : wxCharTypeBufferBase(buf
) {}
197 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
198 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
200 wxCharBuffer(const wxCStrData
& cstr
);
204 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<wchar_t> )
206 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
209 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
211 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
212 : wxCharTypeBufferBase(buf
) {}
214 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
215 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
217 wxWCharBuffer(const wxCStrData
& cstr
);
219 #endif // wxUSE_WCHAR_T
221 // wxCharTypeBuffer<T> implicitly convertible to T*
222 template <typename T
>
223 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
226 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
228 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
229 : wxCharTypeBuffer
<T
>(src
) {}
230 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
231 // always return a buffer
232 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
233 : wxCharTypeBuffer
<T
>(str
) {}
235 operator CharType
*() { return this->data(); }
238 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
239 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
243 #define wxWxCharBuffer wxWCharBuffer
245 #define wxMB2WXbuf wxWCharBuffer
246 #define wxWX2MBbuf wxCharBuffer
247 #if wxUSE_UNICODE_WCHAR
248 #define wxWC2WXbuf wxChar*
249 #define wxWX2WCbuf wxChar*
250 #elif wxUSE_UNICODE_UTF8
251 #define wxWC2WXbuf wxWCharBuffer
252 #define wxWX2WCbuf wxWCharBuffer
255 #define wxWxCharBuffer wxCharBuffer
257 #define wxMB2WXbuf wxChar*
258 #define wxWX2MBbuf wxChar*
259 #define wxWC2WXbuf wxCharBuffer
260 #define wxWX2WCbuf wxWCharBuffer
261 #endif // Unicode/ANSI
263 // type of the value returned by wxString::utf8_str()
264 #if wxUSE_UNICODE_UTF8
265 #define wxUTF8Buf char *
267 #define wxUTF8Buf wxCharBuffer
270 // ----------------------------------------------------------------------------
271 // A class for holding growable data buffers (not necessarily strings)
272 // ----------------------------------------------------------------------------
274 // This class manages the actual data buffer pointer and is ref-counted.
275 class wxMemoryBufferData
278 // the initial size and also the size added by ResizeIfNeeded()
279 enum { DefBufSize
= 1024 };
281 friend class wxMemoryBuffer
;
283 // everyting is private as it can only be used by wxMemoryBuffer
285 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
286 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
289 ~wxMemoryBufferData() { free(m_data
); }
292 void ResizeIfNeeded(size_t newSize
)
294 if (newSize
> m_size
)
296 void *dataOld
= m_data
;
297 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
303 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
307 void IncRef() { m_ref
+= 1; }
311 if (m_ref
== 0) // are there no more references?
316 // the buffer containing the data
319 // the size of the buffer
322 // the amount of data currently in the buffer
325 // the reference count
328 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
332 class WXDLLIMPEXP_BASE wxMemoryBuffer
336 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
338 m_bufdata
= new wxMemoryBufferData(size
);
342 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
345 // copy and assignment
346 wxMemoryBuffer(const wxMemoryBuffer
& src
)
347 : m_bufdata(src
.m_bufdata
)
352 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
357 m_bufdata
= src
.m_bufdata
;
365 void *GetData() const { return m_bufdata
->m_data
; }
366 size_t GetBufSize() const { return m_bufdata
->m_size
; }
367 size_t GetDataLen() const { return m_bufdata
->m_len
; }
369 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
370 void SetDataLen(size_t len
)
372 wxASSERT(len
<= m_bufdata
->m_size
);
373 m_bufdata
->m_len
= len
;
376 // Ensure the buffer is big enough and return a pointer to it
377 void *GetWriteBuf(size_t sizeNeeded
)
379 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
380 return m_bufdata
->m_data
;
383 // Update the length after the write
384 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
386 // Like the above, but appends to the buffer
387 void *GetAppendBuf(size_t sizeNeeded
)
389 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
390 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
393 // Update the length after the append
394 void UngetAppendBuf(size_t sizeUsed
)
396 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
399 // Other ways to append to the buffer
400 void AppendByte(char data
)
402 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
404 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
405 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
406 m_bufdata
->m_len
+= 1;
409 void AppendData(const void *data
, size_t len
)
411 memcpy(GetAppendBuf(len
), data
, len
);
415 operator const char *() const { return (const char*)GetData(); }
418 wxMemoryBufferData
* m_bufdata
;
421 // ----------------------------------------------------------------------------
422 // template class for any kind of data
423 // ----------------------------------------------------------------------------
427 #endif // _WX_BUFFER_H