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
)
36 : m_str(str
? wxStrdup(str
) : NULL
),
41 wxCharTypeBuffer(size_t len
)
42 : m_str((CharType
*)malloc((len
+ 1)*sizeof(CharType
))),
45 m_str
[len
] = (CharType
)0;
48 static const wxCharTypeBuffer
CreateNonOwned(const CharType
*str
)
51 buf
.m_str
= wx_const_cast(CharType
*, str
);
56 /* no need to check for NULL, free() does it */
66 the copy ctor and assignment operators change the passed in object
67 even although it is declared as "const", so:
69 a) it shouldn't be really const
70 b) you shouldn't use it afterwards (or know that it was reset)
72 This is very ugly but is unfortunately needed to make the normal use
73 of wxCharTypeBuffer buffer objects possible and is very similar to what
74 std::auto_ptr<> does (as if it were an excuse...)
78 because of the remark above, release() is declared const even if it
81 CharType
*release() const
83 wxASSERT_MSG( m_owned
, _T("can't release non-owned buffer") );
94 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
99 wxCharTypeBuffer
& operator=(const CharType
*str
)
103 m_str
= str
? wxStrdup(str
) : NULL
;
108 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
119 bool extend(size_t len
)
121 wxASSERT_MSG( m_owned
, _T("cannot extend non-owned buffer") );
124 str
= (CharType
*)realloc(m_str
, (len
+ 1)*sizeof(CharType
));
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
]; }
140 CharType
*DoRelease() const
143 ((wxCharTypeBuffer
*)this)->m_str
= NULL
;
147 void CopyFrom(const wxCharTypeBuffer
& src
)
149 m_owned
= src
.m_owned
;
150 m_str
= src
.DoRelease();
158 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<char> )
160 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
163 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
165 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
166 : wxCharTypeBufferBase(buf
) {}
168 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
169 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
171 wxCharBuffer(const wxCStrData
& cstr
);
175 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<wchar_t> )
177 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
180 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
182 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
183 : wxCharTypeBufferBase(buf
) {}
185 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
186 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
188 wxWCharBuffer(const wxCStrData
& cstr
);
190 #endif // wxUSE_WCHAR_T
192 // wxCharTypeBuffer<T> implicitly convertible to T*
193 template <typename T
>
194 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
197 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
199 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
200 : wxCharTypeBuffer
<T
>(src
) {}
201 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
202 // always return a buffer
203 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
204 : wxCharTypeBuffer
<T
>(str
) {}
206 operator CharType
*() { return this->data(); }
209 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
210 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
214 #define wxWxCharBuffer wxWCharBuffer
216 #define wxMB2WXbuf wxWCharBuffer
217 #define wxWX2MBbuf wxCharBuffer
218 #if wxUSE_UNICODE_WCHAR
219 #define wxWC2WXbuf wxChar*
220 #define wxWX2WCbuf wxChar*
221 #elif wxUSE_UNICODE_UTF8
222 #define wxWC2WXbuf wxWCharBuffer
223 #define wxWX2WCbuf wxWCharBuffer
226 #define wxWxCharBuffer wxCharBuffer
228 #define wxMB2WXbuf wxChar*
229 #define wxWX2MBbuf wxChar*
230 #define wxWC2WXbuf wxCharBuffer
231 #define wxWX2WCbuf wxWCharBuffer
232 #endif // Unicode/ANSI
234 // type of the value returned by wxString::utf8_str()
235 #if wxUSE_UNICODE_UTF8
236 #define wxUTF8Buf char *
238 #define wxUTF8Buf wxCharBuffer
241 // ----------------------------------------------------------------------------
242 // A class for holding growable data buffers (not necessarily strings)
243 // ----------------------------------------------------------------------------
245 // This class manages the actual data buffer pointer and is ref-counted.
246 class wxMemoryBufferData
249 // the initial size and also the size added by ResizeIfNeeded()
250 enum { DefBufSize
= 1024 };
252 friend class wxMemoryBuffer
;
254 // everyting is private as it can only be used by wxMemoryBuffer
256 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
257 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
260 ~wxMemoryBufferData() { free(m_data
); }
263 void ResizeIfNeeded(size_t newSize
)
265 if (newSize
> m_size
)
267 void *dataOld
= m_data
;
268 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
274 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
278 void IncRef() { m_ref
+= 1; }
282 if (m_ref
== 0) // are there no more references?
287 // the buffer containing the data
290 // the size of the buffer
293 // the amount of data currently in the buffer
296 // the reference count
299 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
303 class WXDLLIMPEXP_BASE wxMemoryBuffer
307 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
309 m_bufdata
= new wxMemoryBufferData(size
);
313 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
316 // copy and assignment
317 wxMemoryBuffer(const wxMemoryBuffer
& src
)
318 : m_bufdata(src
.m_bufdata
)
323 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
328 m_bufdata
= src
.m_bufdata
;
336 void *GetData() const { return m_bufdata
->m_data
; }
337 size_t GetBufSize() const { return m_bufdata
->m_size
; }
338 size_t GetDataLen() const { return m_bufdata
->m_len
; }
340 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
341 void SetDataLen(size_t len
)
343 wxASSERT(len
<= m_bufdata
->m_size
);
344 m_bufdata
->m_len
= len
;
347 // Ensure the buffer is big enough and return a pointer to it
348 void *GetWriteBuf(size_t sizeNeeded
)
350 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
351 return m_bufdata
->m_data
;
354 // Update the length after the write
355 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
357 // Like the above, but appends to the buffer
358 void *GetAppendBuf(size_t sizeNeeded
)
360 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
361 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
364 // Update the length after the append
365 void UngetAppendBuf(size_t sizeUsed
)
367 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
370 // Other ways to append to the buffer
371 void AppendByte(char data
)
373 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
375 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
376 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
377 m_bufdata
->m_len
+= 1;
380 void AppendData(const void *data
, size_t len
)
382 memcpy(GetAppendBuf(len
), data
, len
);
386 operator const char *() const { return (const char*)GetData(); }
389 wxMemoryBufferData
* m_bufdata
;
392 // ----------------------------------------------------------------------------
393 // template class for any kind of data
394 // ----------------------------------------------------------------------------
398 #endif // _WX_BUFFER_H