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"
18 #include <stdlib.h> // malloc() and free()
20 inline char *wxStrDup(const char *s
) { return wxStrdupA(s
); }
22 inline wchar_t *wxStrDup(const wchar_t *ws
) { return wxStrdupW(ws
); }
25 // ----------------------------------------------------------------------------
26 // Special classes for (wide) character strings: they use malloc/free instead
28 // ----------------------------------------------------------------------------
31 class wxCharTypeBuffer
36 wxCharTypeBuffer(const CharType
*str
= NULL
)
37 : m_str(str ?
wxStrDup(str
) : NULL
),
42 wxCharTypeBuffer(size_t len
)
43 : m_str((CharType
*)malloc((len
+ 1)*sizeof(CharType
))),
46 m_str
[len
] = (CharType
)0;
49 static const wxCharTypeBuffer
CreateNonOwned(const CharType
*str
)
52 buf
.m_str
= wx_const_cast(CharType
*, str
);
57 /* no need to check for NULL, free() does it */
67 the copy ctor and assignment operators change the passed in object
68 even although it is declared as "const", so:
70 a) it shouldn't be really const
71 b) you shouldn't use it afterwards (or know that it was reset)
73 This is very ugly but is unfortunately needed to make the normal use
74 of wxCharTypeBuffer buffer objects possible and is very similar to what
75 std::auto_ptr<> does (as if it were an excuse...)
79 because of the remark above, release() is declared const even if it
82 CharType
*release() const
84 wxASSERT_MSG( m_owned
, _T("can't release non-owned buffer") );
95 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
100 wxCharTypeBuffer
& operator=(const CharType
*str
)
104 m_str
= str ?
wxStrDup(str
) : NULL
;
109 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
117 bool extend(size_t len
)
119 wxASSERT_MSG( m_owned
, _T("cannot extend non-owned buffer") );
122 str
= (CharType
*)realloc(m_str
, (len
+ 1)*sizeof(CharType
));
131 CharType
*data() { return m_str
; }
132 const CharType
*data() const { return m_str
; }
133 operator const CharType
*() const { return m_str
; }
134 CharType
operator[](size_t n
) const { return m_str
[n
]; }
138 CharType
*DoRelease() const
141 ((wxCharTypeBuffer
*)this)->m_str
= NULL
;
145 void CopyFrom(const wxCharTypeBuffer
& src
)
147 m_owned
= src
.m_owned
;
148 m_str
= src
.DoRelease();
156 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
159 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
161 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
162 : wxCharTypeBufferBase(buf
) {}
164 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
165 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
167 wxCharBuffer(const wxCStrData
& cstr
);
171 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
174 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
176 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
177 : wxCharTypeBufferBase(buf
) {}
179 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
180 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
182 wxWCharBuffer(const wxCStrData
& cstr
);
184 #endif // wxUSE_WCHAR_T
186 // wxCharTypeBuffer<T> implicitly convertible to T*
187 template <typename T
>
188 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
191 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
193 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
194 : wxCharTypeBuffer
<T
>(src
) {}
195 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
196 // always return a buffer
197 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
198 : wxCharTypeBuffer
<T
>(str
) {}
200 operator CharType
*() { return this->data(); }
203 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
204 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
208 #define wxWxCharBuffer wxWCharBuffer
210 #define wxMB2WXbuf wxWCharBuffer
211 #define wxWX2MBbuf wxCharBuffer
212 #if wxUSE_UNICODE_WCHAR
213 #define wxWC2WXbuf wxChar*
214 #define wxWX2WCbuf wxChar*
215 #elif wxUSE_UNICODE_UTF8
216 #define wxWC2WXbuf wxWCharBuffer
217 #define wxWX2WCbuf wxWCharBuffer
220 #define wxWxCharBuffer wxCharBuffer
222 #define wxMB2WXbuf wxChar*
223 #define wxWX2MBbuf wxChar*
224 #define wxWC2WXbuf wxCharBuffer
225 #define wxWX2WCbuf wxWCharBuffer
226 #endif // Unicode/ANSI
228 // ----------------------------------------------------------------------------
229 // A class for holding growable data buffers (not necessarily strings)
230 // ----------------------------------------------------------------------------
232 // This class manages the actual data buffer pointer and is ref-counted.
233 class wxMemoryBufferData
236 // the initial size and also the size added by ResizeIfNeeded()
237 enum { DefBufSize
= 1024 };
239 friend class wxMemoryBuffer
;
241 // everyting is private as it can only be used by wxMemoryBuffer
243 wxMemoryBufferData(size_t size
= wxMemoryBufferData
::DefBufSize
)
244 : m_data(size ?
malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
247 ~wxMemoryBufferData() { free(m_data
); }
250 void ResizeIfNeeded(size_t newSize
)
252 if (newSize
> m_size
)
254 void *dataOld
= m_data
;
255 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData
::DefBufSize
);
261 m_size
= newSize
+ wxMemoryBufferData
::DefBufSize
;
265 void IncRef() { m_ref
+= 1; }
269 if (m_ref
== 0) // are there no more references?
274 // the buffer containing the data
277 // the size of the buffer
280 // the amount of data currently in the buffer
283 // the reference count
286 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
294 wxMemoryBuffer(size_t size
= wxMemoryBufferData
::DefBufSize
)
296 m_bufdata
= new wxMemoryBufferData(size
);
300 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
303 // copy and assignment
304 wxMemoryBuffer(const wxMemoryBuffer
& src
)
305 : m_bufdata(src
.m_bufdata
)
310 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
313 m_bufdata
= src
.m_bufdata
;
320 void *GetData() const { return m_bufdata
->m_data
; }
321 size_t GetBufSize() const { return m_bufdata
->m_size
; }
322 size_t GetDataLen() const { return m_bufdata
->m_len
; }
324 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
325 void SetDataLen(size_t len
)
327 wxASSERT(len
<= m_bufdata
->m_size
);
328 m_bufdata
->m_len
= len
;
331 // Ensure the buffer is big enough and return a pointer to it
332 void *GetWriteBuf(size_t sizeNeeded
)
334 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
335 return m_bufdata
->m_data
;
338 // Update the length after the write
339 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
341 // Like the above, but appends to the buffer
342 void *GetAppendBuf(size_t sizeNeeded
)
344 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
345 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
348 // Update the length after the append
349 void UngetAppendBuf(size_t sizeUsed
)
351 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
354 // Other ways to append to the buffer
355 void AppendByte(char data
)
357 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
359 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
360 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
361 m_bufdata
->m_len
+= 1;
364 void AppendData(const void *data
, size_t len
)
366 memcpy(GetAppendBuf(len
), data
, len
);
370 operator const char *() const { return (const char*)GetData(); }
373 wxMemoryBufferData
* m_bufdata
;
376 // ----------------------------------------------------------------------------
377 // template class for any kind of data
378 // ----------------------------------------------------------------------------
382 #endif // _WX_BUFFER_H