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/wxchar.h"
17 #include <stdlib.h> // malloc() and free()
19 inline char *wxStrDup(const char *s
) { return wxStrdupA(s
); }
21 inline wchar_t *wxStrDup(const wchar_t *ws
) { return wxStrdupW(ws
); }
24 // ----------------------------------------------------------------------------
25 // Special classes for (wide) character strings: they use malloc/free instead
27 // ----------------------------------------------------------------------------
30 class 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
)
116 bool extend(size_t len
)
118 wxASSERT_MSG( m_owned
, _T("cannot extend non-owned buffer") );
121 str
= (CharType
*)realloc(m_str
, (len
+ 1)*sizeof(CharType
));
130 CharType
*data() { return m_str
; }
131 const CharType
*data() const { return m_str
; }
132 operator const CharType
*() const { return m_str
; }
133 CharType
operator[](size_t n
) const { return m_str
[n
]; }
137 CharType
*DoRelease() const
140 ((wxCharTypeBuffer
*)this)->m_str
= NULL
;
144 void CopyFrom(const wxCharTypeBuffer
& src
)
146 m_owned
= src
.m_owned
;
147 m_str
= src
.DoRelease();
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 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
173 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
175 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
176 : wxCharTypeBufferBase(buf
) {}
178 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
179 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
181 wxWCharBuffer(const wxCStrData
& cstr
);
183 #endif // wxUSE_WCHAR_T
185 // wxCharTypeBuffer<T> implicitly convertible to T*
186 template <typename T
>
187 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
190 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
192 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
193 : wxCharTypeBuffer
<T
>(src
) {}
194 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
195 // always return a buffer
196 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
197 : wxCharTypeBuffer
<T
>(str
) {}
199 operator CharType
*() { return this->data(); }
202 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
203 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
207 #define wxWxCharBuffer wxWCharBuffer
209 #define wxMB2WXbuf wxWCharBuffer
210 #define wxWX2MBbuf wxCharBuffer
211 #if wxUSE_UNICODE_WCHAR
212 #define wxWC2WXbuf wxChar*
213 #define wxWX2WCbuf wxChar*
214 #elif wxUSE_UNICODE_UTF8
215 #define wxWC2WXbuf wxWCharBuffer
216 #define wxWX2WCbuf wxWCharBuffer
219 #define wxWxCharBuffer wxCharBuffer
221 #define wxMB2WXbuf wxChar*
222 #define wxWX2MBbuf wxChar*
223 #define wxWC2WXbuf wxCharBuffer
224 #define wxWX2WCbuf wxWCharBuffer
225 #endif // Unicode/ANSI
227 // ----------------------------------------------------------------------------
228 // A class for holding growable data buffers (not necessarily strings)
229 // ----------------------------------------------------------------------------
231 // This class manages the actual data buffer pointer and is ref-counted.
232 class wxMemoryBufferData
235 // the initial size and also the size added by ResizeIfNeeded()
236 enum { DefBufSize
= 1024 };
238 friend class wxMemoryBuffer
;
240 // everyting is private as it can only be used by wxMemoryBuffer
242 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
243 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
246 ~wxMemoryBufferData() { free(m_data
); }
249 void ResizeIfNeeded(size_t newSize
)
251 if (newSize
> m_size
)
253 void *dataOld
= m_data
;
254 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
260 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
264 void IncRef() { m_ref
+= 1; }
268 if (m_ref
== 0) // are there no more references?
273 // the buffer containing the data
276 // the size of the buffer
279 // the amount of data currently in the buffer
282 // the reference count
285 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
293 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
295 m_bufdata
= new wxMemoryBufferData(size
);
299 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
302 // copy and assignment
303 wxMemoryBuffer(const wxMemoryBuffer
& src
)
304 : m_bufdata(src
.m_bufdata
)
309 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
312 m_bufdata
= src
.m_bufdata
;
319 void *GetData() const { return m_bufdata
->m_data
; }
320 size_t GetBufSize() const { return m_bufdata
->m_size
; }
321 size_t GetDataLen() const { return m_bufdata
->m_len
; }
323 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
324 void SetDataLen(size_t len
)
326 wxASSERT(len
<= m_bufdata
->m_size
);
327 m_bufdata
->m_len
= len
;
330 // Ensure the buffer is big enough and return a pointer to it
331 void *GetWriteBuf(size_t sizeNeeded
)
333 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
334 return m_bufdata
->m_data
;
337 // Update the length after the write
338 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
340 // Like the above, but appends to the buffer
341 void *GetAppendBuf(size_t sizeNeeded
)
343 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
344 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
347 // Update the length after the append
348 void UngetAppendBuf(size_t sizeUsed
)
350 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
353 // Other ways to append to the buffer
354 void AppendByte(char data
)
356 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
358 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
359 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
360 m_bufdata
->m_len
+= 1;
363 void AppendData(const void *data
, size_t len
)
365 memcpy(GetAppendBuf(len
), data
, len
);
369 operator const char *() const { return (const char*)GetData(); }
372 wxMemoryBufferData
* m_bufdata
;
375 // ----------------------------------------------------------------------------
376 // template class for any kind of data
377 // ----------------------------------------------------------------------------
381 #endif // _WX_BUFFER_H