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 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 class wxCharBuffer
: public wxCharTypeBuffer
<char>
156 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
158 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
159 : wxCharTypeBufferBase(buf
) {}
161 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
162 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
164 wxCharBuffer(const wxCStrData
& cstr
);
168 class wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
171 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
173 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
174 : wxCharTypeBufferBase(buf
) {}
176 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
177 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
179 wxWCharBuffer(const wxCStrData
& cstr
);
181 #endif // wxUSE_WCHAR_T
183 // wxCharTypeBuffer<T> implicitly convertible to T*
184 template <typename T
>
185 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
188 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
190 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
191 : wxCharTypeBuffer
<T
>(src
) {}
192 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
193 // always return a buffer
194 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
195 : wxCharTypeBuffer
<T
>(str
) {}
197 operator CharType
*() { return this->data(); }
200 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
201 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
205 #define wxWxCharBuffer wxWCharBuffer
207 #define wxMB2WXbuf wxWCharBuffer
208 #define wxWX2MBbuf wxCharBuffer
209 #if wxUSE_UNICODE_WCHAR
210 #define wxWC2WXbuf wxChar*
211 #define wxWX2WCbuf wxChar*
212 #elif wxUSE_UNICODE_UTF8
213 #define wxWC2WXbuf wxWCharBuffer
214 #define wxWX2WCbuf wxWCharBuffer
217 #define wxWxCharBuffer wxCharBuffer
219 #define wxMB2WXbuf wxChar*
220 #define wxWX2MBbuf wxChar*
221 #define wxWC2WXbuf wxCharBuffer
222 #define wxWX2WCbuf wxWCharBuffer
223 #endif // Unicode/ANSI
225 // ----------------------------------------------------------------------------
226 // A class for holding growable data buffers (not necessarily strings)
227 // ----------------------------------------------------------------------------
229 // This class manages the actual data buffer pointer and is ref-counted.
230 class wxMemoryBufferData
233 // the initial size and also the size added by ResizeIfNeeded()
234 enum { DefBufSize
= 1024 };
236 friend class wxMemoryBuffer
;
238 // everyting is private as it can only be used by wxMemoryBuffer
240 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
241 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
244 ~wxMemoryBufferData() { free(m_data
); }
247 void ResizeIfNeeded(size_t newSize
)
249 if (newSize
> m_size
)
251 void *dataOld
= m_data
;
252 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
258 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
262 void IncRef() { m_ref
+= 1; }
266 if (m_ref
== 0) // are there no more references?
271 // the buffer containing the data
274 // the size of the buffer
277 // the amount of data currently in the buffer
280 // the reference count
283 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
291 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
293 m_bufdata
= new wxMemoryBufferData(size
);
297 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
300 // copy and assignment
301 wxMemoryBuffer(const wxMemoryBuffer
& src
)
302 : m_bufdata(src
.m_bufdata
)
307 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
310 m_bufdata
= src
.m_bufdata
;
317 void *GetData() const { return m_bufdata
->m_data
; }
318 size_t GetBufSize() const { return m_bufdata
->m_size
; }
319 size_t GetDataLen() const { return m_bufdata
->m_len
; }
321 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
322 void SetDataLen(size_t len
)
324 wxASSERT(len
<= m_bufdata
->m_size
);
325 m_bufdata
->m_len
= len
;
328 // Ensure the buffer is big enough and return a pointer to it
329 void *GetWriteBuf(size_t sizeNeeded
)
331 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
332 return m_bufdata
->m_data
;
335 // Update the length after the write
336 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
338 // Like the above, but appends to the buffer
339 void *GetAppendBuf(size_t sizeNeeded
)
341 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
342 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
345 // Update the length after the append
346 void UngetAppendBuf(size_t sizeUsed
)
348 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
351 // Other ways to append to the buffer
352 void AppendByte(char data
)
354 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
356 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
357 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
358 m_bufdata
->m_len
+= 1;
361 void AppendData(const void *data
, size_t len
)
363 memcpy(GetAppendBuf(len
), data
, len
);
367 operator const char *() const { return (const char*)GetData(); }
370 wxMemoryBufferData
* m_bufdata
;
373 // ----------------------------------------------------------------------------
374 // template class for any kind of data
375 // ----------------------------------------------------------------------------
379 #endif // _WX_BUFFER_H