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 class WXDLLIMPEXP_BASE wxCStrData
;
22 inline char *wxStrDup(const char *s
) { return wxStrdupA(s
); }
24 inline wchar_t *wxStrDup(const wchar_t *ws
) { return wxStrdupW(ws
); }
27 // ----------------------------------------------------------------------------
28 // Special classes for (wide) character strings: they use malloc/free instead
30 // ----------------------------------------------------------------------------
33 class wxCharTypeBuffer
38 wxCharTypeBuffer(const CharType
*str
= NULL
)
39 : m_str(str
? wxStrDup(str
) : NULL
),
44 wxCharTypeBuffer(size_t len
)
45 : m_str((CharType
*)malloc((len
+ 1)*sizeof(CharType
))),
48 m_str
[len
] = (CharType
)0;
51 static const wxCharTypeBuffer
CreateNonOwned(const CharType
*str
)
54 buf
.m_str
= wx_const_cast(CharType
*, str
);
59 /* no need to check for NULL, free() does it */
69 the copy ctor and assignment operators change the passed in object
70 even although it is declared as "const", so:
72 a) it shouldn't be really const
73 b) you shouldn't use it afterwards (or know that it was reset)
75 This is very ugly but is unfortunately needed to make the normal use
76 of wxCharTypeBuffer buffer objects possible and is very similar to what
77 std::auto_ptr<> does (as if it were an excuse...)
81 because of the remark above, release() is declared const even if it
84 CharType
*release() const
86 wxASSERT_MSG( m_owned
, _T("can't release non-owned buffer") );
97 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
102 wxCharTypeBuffer
& operator=(const CharType
*str
)
106 m_str
= str
? wxStrDup(str
) : NULL
;
111 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 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
161 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
163 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
164 : wxCharTypeBufferBase(buf
) {}
166 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
167 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
169 wxCharBuffer(const wxCStrData
& cstr
);
173 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
176 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
178 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
179 : wxCharTypeBufferBase(buf
) {}
181 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
182 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
184 wxWCharBuffer(const wxCStrData
& cstr
);
186 #endif // wxUSE_WCHAR_T
188 // wxCharTypeBuffer<T> implicitly convertible to T*
189 template <typename T
>
190 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
193 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
195 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
196 : wxCharTypeBuffer
<T
>(src
) {}
197 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
198 // always return a buffer
199 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
200 : wxCharTypeBuffer
<T
>(str
) {}
202 operator CharType
*() { return this->data(); }
205 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
206 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
210 #define wxWxCharBuffer wxWCharBuffer
212 #define wxMB2WXbuf wxWCharBuffer
213 #define wxWX2MBbuf wxCharBuffer
214 #if wxUSE_UNICODE_WCHAR
215 #define wxWC2WXbuf wxChar*
216 #define wxWX2WCbuf wxChar*
217 #elif wxUSE_UNICODE_UTF8
218 #define wxWC2WXbuf wxWCharBuffer
219 #define wxWX2WCbuf wxWCharBuffer
222 #define wxWxCharBuffer wxCharBuffer
224 #define wxMB2WXbuf wxChar*
225 #define wxWX2MBbuf wxChar*
226 #define wxWC2WXbuf wxCharBuffer
227 #define wxWX2WCbuf wxWCharBuffer
228 #endif // Unicode/ANSI
230 // ----------------------------------------------------------------------------
231 // A class for holding growable data buffers (not necessarily strings)
232 // ----------------------------------------------------------------------------
234 // This class manages the actual data buffer pointer and is ref-counted.
235 class wxMemoryBufferData
238 // the initial size and also the size added by ResizeIfNeeded()
239 enum { DefBufSize
= 1024 };
241 friend class wxMemoryBuffer
;
243 // everyting is private as it can only be used by wxMemoryBuffer
245 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
246 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
249 ~wxMemoryBufferData() { free(m_data
); }
252 void ResizeIfNeeded(size_t newSize
)
254 if (newSize
> m_size
)
256 void *dataOld
= m_data
;
257 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
263 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
267 void IncRef() { m_ref
+= 1; }
271 if (m_ref
== 0) // are there no more references?
276 // the buffer containing the data
279 // the size of the buffer
282 // the amount of data currently in the buffer
285 // the reference count
288 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
296 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
298 m_bufdata
= new wxMemoryBufferData(size
);
302 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
305 // copy and assignment
306 wxMemoryBuffer(const wxMemoryBuffer
& src
)
307 : m_bufdata(src
.m_bufdata
)
312 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
315 m_bufdata
= src
.m_bufdata
;
322 void *GetData() const { return m_bufdata
->m_data
; }
323 size_t GetBufSize() const { return m_bufdata
->m_size
; }
324 size_t GetDataLen() const { return m_bufdata
->m_len
; }
326 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
327 void SetDataLen(size_t len
)
329 wxASSERT(len
<= m_bufdata
->m_size
);
330 m_bufdata
->m_len
= len
;
333 // Ensure the buffer is big enough and return a pointer to it
334 void *GetWriteBuf(size_t sizeNeeded
)
336 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
337 return m_bufdata
->m_data
;
340 // Update the length after the write
341 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
343 // Like the above, but appends to the buffer
344 void *GetAppendBuf(size_t sizeNeeded
)
346 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
347 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
350 // Update the length after the append
351 void UngetAppendBuf(size_t sizeUsed
)
353 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
356 // Other ways to append to the buffer
357 void AppendByte(char data
)
359 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
361 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
362 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
363 m_bufdata
->m_len
+= 1;
366 void AppendData(const void *data
, size_t len
)
368 memcpy(GetAppendBuf(len
), data
, len
);
372 operator const char *() const { return (const char*)GetData(); }
375 wxMemoryBufferData
* m_bufdata
;
378 // ----------------------------------------------------------------------------
379 // template class for any kind of data
380 // ----------------------------------------------------------------------------
384 #endif // _WX_BUFFER_H