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 wxCharTypeBuffer
35 wxCharTypeBuffer(const CharType
*str
= NULL
)
38 m_data
= new Data(wxStrdup(str
));
40 m_data
= GetNullData();
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
== GetNullData() )
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
== GetNullData() )
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 static Data
*GetNullData()
172 static Data
s_nullData(NULL
);
179 if ( m_data
== GetNullData() ) // exception, not ref-counted
186 if ( m_data
== GetNullData() ) // exception, not ref-counted
188 if ( --m_data
->m_ref
== 0 )
190 m_data
= GetNullData();
197 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<char> )
199 class wxCharBuffer
: public wxCharTypeBuffer
<char>
202 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
204 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
205 : wxCharTypeBufferBase(buf
) {}
207 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
208 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
210 wxCharBuffer(const wxCStrData
& cstr
);
214 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<wchar_t> )
216 class wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
219 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
221 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
222 : wxCharTypeBufferBase(buf
) {}
224 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
225 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
227 wxWCharBuffer(const wxCStrData
& cstr
);
229 #endif // wxUSE_WCHAR_T
231 // wxCharTypeBuffer<T> implicitly convertible to T*
232 template <typename T
>
233 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
236 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
238 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
239 : wxCharTypeBuffer
<T
>(src
) {}
240 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
241 // always return a buffer
242 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
243 : wxCharTypeBuffer
<T
>(str
) {}
245 operator CharType
*() { return this->data(); }
248 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
249 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
253 #define wxWxCharBuffer wxWCharBuffer
255 #define wxMB2WXbuf wxWCharBuffer
256 #define wxWX2MBbuf wxCharBuffer
257 #if wxUSE_UNICODE_WCHAR
258 #define wxWC2WXbuf wxChar*
259 #define wxWX2WCbuf wxChar*
260 #elif wxUSE_UNICODE_UTF8
261 #define wxWC2WXbuf wxWCharBuffer
262 #define wxWX2WCbuf wxWCharBuffer
265 #define wxWxCharBuffer wxCharBuffer
267 #define wxMB2WXbuf wxChar*
268 #define wxWX2MBbuf wxChar*
269 #define wxWC2WXbuf wxCharBuffer
270 #define wxWX2WCbuf wxWCharBuffer
271 #endif // Unicode/ANSI
273 // type of the value returned by wxString::utf8_str()
274 #if wxUSE_UNICODE_UTF8
275 #define wxUTF8Buf char *
277 #define wxUTF8Buf wxCharBuffer
280 // ----------------------------------------------------------------------------
281 // A class for holding growable data buffers (not necessarily strings)
282 // ----------------------------------------------------------------------------
284 // This class manages the actual data buffer pointer and is ref-counted.
285 class wxMemoryBufferData
288 // the initial size and also the size added by ResizeIfNeeded()
289 enum { DefBufSize
= 1024 };
291 friend class wxMemoryBuffer
;
293 // everyting is private as it can only be used by wxMemoryBuffer
295 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
296 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
299 ~wxMemoryBufferData() { free(m_data
); }
302 void ResizeIfNeeded(size_t newSize
)
304 if (newSize
> m_size
)
306 void *dataOld
= m_data
;
307 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
313 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
317 void IncRef() { m_ref
+= 1; }
321 if (m_ref
== 0) // are there no more references?
326 // the buffer containing the data
329 // the size of the buffer
332 // the amount of data currently in the buffer
335 // the reference count
338 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
346 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
348 m_bufdata
= new wxMemoryBufferData(size
);
352 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
355 // copy and assignment
356 wxMemoryBuffer(const wxMemoryBuffer
& src
)
357 : m_bufdata(src
.m_bufdata
)
362 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
367 m_bufdata
= src
.m_bufdata
;
375 void *GetData() const { return m_bufdata
->m_data
; }
376 size_t GetBufSize() const { return m_bufdata
->m_size
; }
377 size_t GetDataLen() const { return m_bufdata
->m_len
; }
379 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
380 void SetDataLen(size_t len
)
382 wxASSERT(len
<= m_bufdata
->m_size
);
383 m_bufdata
->m_len
= len
;
386 // Ensure the buffer is big enough and return a pointer to it
387 void *GetWriteBuf(size_t sizeNeeded
)
389 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
390 return m_bufdata
->m_data
;
393 // Update the length after the write
394 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
396 // Like the above, but appends to the buffer
397 void *GetAppendBuf(size_t sizeNeeded
)
399 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
400 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
403 // Update the length after the append
404 void UngetAppendBuf(size_t sizeUsed
)
406 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
409 // Other ways to append to the buffer
410 void AppendByte(char data
)
412 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
414 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
415 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
416 m_bufdata
->m_len
+= 1;
419 void AppendData(const void *data
, size_t len
)
421 memcpy(GetAppendBuf(len
), data
, len
);
425 operator const char *() const { return (const char*)GetData(); }
428 wxMemoryBufferData
* m_bufdata
;
431 // ----------------------------------------------------------------------------
432 // template class for any kind of data
433 // ----------------------------------------------------------------------------
437 #endif // _WX_BUFFER_H