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"
18 #include <stdlib.h> // malloc() and free()
20 class WXDLLIMPEXP_FWD_BASE wxCStrData
;
22 // ----------------------------------------------------------------------------
23 // Special classes for (wide) character strings: they use malloc/free instead
25 // ----------------------------------------------------------------------------
28 class WXDLLIMPEXP_BASE wxCharTypeBuffer
33 wxCharTypeBuffer(const CharType
*str
= NULL
)
34 : m_str(str
? wxStrdup(str
) : NULL
),
39 wxCharTypeBuffer(size_t len
)
40 : m_str((CharType
*)malloc((len
+ 1)*sizeof(CharType
))),
43 m_str
[len
] = (CharType
)0;
46 static const wxCharTypeBuffer
CreateNonOwned(const CharType
*str
)
49 buf
.m_str
= wx_const_cast(CharType
*, str
);
54 /* no need to check for NULL, free() does it */
64 the copy ctor and assignment operators change the passed in object
65 even although it is declared as "const", so:
67 a) it shouldn't be really const
68 b) you shouldn't use it afterwards (or know that it was reset)
70 This is very ugly but is unfortunately needed to make the normal use
71 of wxCharTypeBuffer buffer objects possible and is very similar to what
72 std::auto_ptr<> does (as if it were an excuse...)
76 because of the remark above, release() is declared const even if it
79 CharType
*release() const
81 wxASSERT_MSG( m_owned
, _T("can't release non-owned buffer") );
92 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
97 wxCharTypeBuffer
& operator=(const CharType
*str
)
101 m_str
= str
? wxStrdup(str
) : NULL
;
106 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
114 bool extend(size_t len
)
116 wxASSERT_MSG( m_owned
, _T("cannot extend non-owned buffer") );
119 str
= (CharType
*)realloc(m_str
, (len
+ 1)*sizeof(CharType
));
128 CharType
*data() { return m_str
; }
129 const CharType
*data() const { return m_str
; }
130 operator const CharType
*() const { return m_str
; }
131 CharType
operator[](size_t n
) const { return m_str
[n
]; }
135 CharType
*DoRelease() const
138 ((wxCharTypeBuffer
*)this)->m_str
= NULL
;
142 void CopyFrom(const wxCharTypeBuffer
& src
)
144 m_owned
= src
.m_owned
;
145 m_str
= src
.DoRelease();
153 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<char> )
155 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
158 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
160 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
161 : wxCharTypeBufferBase(buf
) {}
163 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
164 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
166 wxCharBuffer(const wxCStrData
& cstr
);
170 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<wchar_t> )
172 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
175 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
177 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
178 : wxCharTypeBufferBase(buf
) {}
180 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
181 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
183 wxWCharBuffer(const wxCStrData
& cstr
);
185 #endif // wxUSE_WCHAR_T
187 // wxCharTypeBuffer<T> implicitly convertible to T*
188 template <typename T
>
189 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
192 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
194 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
195 : wxCharTypeBuffer
<T
>(src
) {}
196 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
197 // always return a buffer
198 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
199 : wxCharTypeBuffer
<T
>(str
) {}
201 operator CharType
*() { return this->data(); }
204 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
205 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
209 #define wxWxCharBuffer wxWCharBuffer
211 #define wxMB2WXbuf wxWCharBuffer
212 #define wxWX2MBbuf wxCharBuffer
213 #if wxUSE_UNICODE_WCHAR
214 #define wxWC2WXbuf wxChar*
215 #define wxWX2WCbuf wxChar*
216 #elif wxUSE_UNICODE_UTF8
217 #define wxWC2WXbuf wxWCharBuffer
218 #define wxWX2WCbuf wxWCharBuffer
221 #define wxWxCharBuffer wxCharBuffer
223 #define wxMB2WXbuf wxChar*
224 #define wxWX2MBbuf wxChar*
225 #define wxWC2WXbuf wxCharBuffer
226 #define wxWX2WCbuf wxWCharBuffer
227 #endif // Unicode/ANSI
229 // ----------------------------------------------------------------------------
230 // A class for holding growable data buffers (not necessarily strings)
231 // ----------------------------------------------------------------------------
233 // This class manages the actual data buffer pointer and is ref-counted.
234 class wxMemoryBufferData
237 // the initial size and also the size added by ResizeIfNeeded()
238 enum { DefBufSize
= 1024 };
240 friend class wxMemoryBuffer
;
242 // everyting is private as it can only be used by wxMemoryBuffer
244 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
245 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
248 ~wxMemoryBufferData() { free(m_data
); }
251 void ResizeIfNeeded(size_t newSize
)
253 if (newSize
> m_size
)
255 void *dataOld
= m_data
;
256 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
262 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
266 void IncRef() { m_ref
+= 1; }
270 if (m_ref
== 0) // are there no more references?
275 // the buffer containing the data
278 // the size of the buffer
281 // the amount of data currently in the buffer
284 // the reference count
287 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
291 class WXDLLIMPEXP_BASE wxMemoryBuffer
295 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
297 m_bufdata
= new wxMemoryBufferData(size
);
301 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
304 // copy and assignment
305 wxMemoryBuffer(const wxMemoryBuffer
& src
)
306 : m_bufdata(src
.m_bufdata
)
311 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
314 m_bufdata
= src
.m_bufdata
;
321 void *GetData() const { return m_bufdata
->m_data
; }
322 size_t GetBufSize() const { return m_bufdata
->m_size
; }
323 size_t GetDataLen() const { return m_bufdata
->m_len
; }
325 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
326 void SetDataLen(size_t len
)
328 wxASSERT(len
<= m_bufdata
->m_size
);
329 m_bufdata
->m_len
= len
;
332 // Ensure the buffer is big enough and return a pointer to it
333 void *GetWriteBuf(size_t sizeNeeded
)
335 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
336 return m_bufdata
->m_data
;
339 // Update the length after the write
340 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
342 // Like the above, but appends to the buffer
343 void *GetAppendBuf(size_t sizeNeeded
)
345 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
346 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
349 // Update the length after the append
350 void UngetAppendBuf(size_t sizeUsed
)
352 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
355 // Other ways to append to the buffer
356 void AppendByte(char data
)
358 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
360 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
361 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
362 m_bufdata
->m_len
+= 1;
365 void AppendData(const void *data
, size_t len
)
367 memcpy(GetAppendBuf(len
), data
, len
);
371 operator const char *() const { return (const char*)GetData(); }
374 wxMemoryBufferData
* m_bufdata
;
377 // ----------------------------------------------------------------------------
378 // template class for any kind of data
379 // ----------------------------------------------------------------------------
383 #endif // _WX_BUFFER_H