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
);
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
67 if ( m_data
== &NullData
)
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") );
73 CharType
*p
= m_data
->m_str
;
75 wxCharTypeBuffer
*self
= wx_const_cast(wxCharTypeBuffer
*, this);
76 self
->m_data
->m_str
= NULL
;
87 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
93 wxCharTypeBuffer
& operator=(const CharType
*str
)
98 m_data
= new Data(wxStrdup(str
));
102 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
114 bool extend(size_t len
)
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") );
120 (CharType
*)realloc(data(), (len
+ 1) * sizeof(CharType
));
124 if ( m_data
== &NullData
)
126 m_data
= new Data(str
);
131 m_data
->m_owned
= true;
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
]; }
143 // reference-counted data
152 Data(CharType
*str
, Kind kind
= Owned
)
153 : m_str(str
), m_ref(1), m_owned(kind
== Owned
) {}
163 // "short" to have sizeof(Data)=8 on 32bit archs
164 unsigned short m_ref
;
169 // placeholder for NULL string, to simplify this code
170 // NB: this is defined in string.cpp, not (non-existent) buffer.cpp
171 static Data NullData
;
175 if ( m_data
== &NullData
) // exception, not ref-counted
182 if ( m_data
== &NullData
) // exception, not ref-counted
184 if ( --m_data
->m_ref
== 0 )
193 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<char> )
195 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
198 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
200 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
201 : wxCharTypeBufferBase(buf
) {}
203 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
204 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
206 wxCharBuffer(const wxCStrData
& cstr
);
210 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<wchar_t> )
212 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
215 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
217 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
218 : wxCharTypeBufferBase(buf
) {}
220 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
221 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
223 wxWCharBuffer(const wxCStrData
& cstr
);
225 #endif // wxUSE_WCHAR_T
227 // wxCharTypeBuffer<T> implicitly convertible to T*
228 template <typename T
>
229 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
232 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
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
) {}
241 operator CharType
*() { return this->data(); }
244 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
245 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
249 #define wxWxCharBuffer wxWCharBuffer
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
261 #define wxWxCharBuffer wxCharBuffer
263 #define wxMB2WXbuf wxChar*
264 #define wxWX2MBbuf wxChar*
265 #define wxWC2WXbuf wxCharBuffer
266 #define wxWX2WCbuf wxWCharBuffer
267 #endif // Unicode/ANSI
269 // type of the value returned by wxString::utf8_str()
270 #if wxUSE_UNICODE_UTF8
271 #define wxUTF8Buf char *
273 #define wxUTF8Buf wxCharBuffer
276 // ----------------------------------------------------------------------------
277 // A class for holding growable data buffers (not necessarily strings)
278 // ----------------------------------------------------------------------------
280 // This class manages the actual data buffer pointer and is ref-counted.
281 class wxMemoryBufferData
284 // the initial size and also the size added by ResizeIfNeeded()
285 enum { DefBufSize
= 1024 };
287 friend class wxMemoryBuffer
;
289 // everyting is private as it can only be used by wxMemoryBuffer
291 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
292 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
295 ~wxMemoryBufferData() { free(m_data
); }
298 void ResizeIfNeeded(size_t newSize
)
300 if (newSize
> m_size
)
302 void *dataOld
= m_data
;
303 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
309 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
313 void IncRef() { m_ref
+= 1; }
317 if (m_ref
== 0) // are there no more references?
322 // the buffer containing the data
325 // the size of the buffer
328 // the amount of data currently in the buffer
331 // the reference count
334 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
338 class WXDLLIMPEXP_BASE wxMemoryBuffer
342 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
344 m_bufdata
= new wxMemoryBufferData(size
);
348 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
351 // copy and assignment
352 wxMemoryBuffer(const wxMemoryBuffer
& src
)
353 : m_bufdata(src
.m_bufdata
)
358 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
363 m_bufdata
= src
.m_bufdata
;
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
; }
375 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
376 void SetDataLen(size_t len
)
378 wxASSERT(len
<= m_bufdata
->m_size
);
379 m_bufdata
->m_len
= len
;
382 // Ensure the buffer is big enough and return a pointer to it
383 void *GetWriteBuf(size_t sizeNeeded
)
385 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
386 return m_bufdata
->m_data
;
389 // Update the length after the write
390 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
392 // Like the above, but appends to the buffer
393 void *GetAppendBuf(size_t sizeNeeded
)
395 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
396 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
399 // Update the length after the append
400 void UngetAppendBuf(size_t sizeUsed
)
402 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
405 // Other ways to append to the buffer
406 void AppendByte(char data
)
408 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
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;
415 void AppendData(const void *data
, size_t len
)
417 memcpy(GetAppendBuf(len
), data
, len
);
421 operator const char *() const { return (const char*)GetData(); }
424 wxMemoryBufferData
* m_bufdata
;
427 // ----------------------------------------------------------------------------
428 // template class for any kind of data
429 // ----------------------------------------------------------------------------
433 #endif // _WX_BUFFER_H