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 // ----------------------------------------------------------------------------
20 // Special classes for (wide) character strings: they use malloc/free instead
22 // ----------------------------------------------------------------------------
24 #define DEFINE_BUFFER(classname, chartype, strdupfunc) \
25 class WXDLLIMPEXP_BASE classname \
28 classname(const chartype *str = NULL) \
29 : m_str(str ? strdupfunc(str) : NULL) \
33 classname(size_t len) \
34 : m_str((chartype *)malloc((len + 1)*sizeof(chartype))) \
36 m_str[len] = (chartype)0; \
39 /* no need to check for NULL, free() does it */ \
40 ~classname() { free(m_str); } \
45 the copy ctor and assignment operators change the passed in object \
46 even although it is declared as "const", so: \
48 a) it shouldn't be really const \
49 b) you shouldn't use it afterwards (or know that it was reset) \
51 This is very ugly but is unfortunately needed to make the normal use\
52 of classname buffer objects possible and is very similar to what \
53 std::auto_ptr<> does (as if it were an excuse...) \
57 because of the remark above, release() is declared const even if it \
60 chartype *release() const \
62 chartype *p = m_str; \
63 ((classname *)this)->m_str = NULL; \
73 classname(const classname& src) \
74 : m_str(src.release()) \
78 classname& operator=(const chartype *str) \
81 m_str = str ? strdupfunc(str) : NULL; \
85 classname& operator=(const classname& src) \
88 m_str = src.release(); \
93 bool extend(size_t len) \
96 str = (chartype *)realloc(m_str, (len + 1)*sizeof(chartype)); \
105 chartype *data() { return m_str; } \
106 const chartype *data() const { return m_str; } \
107 operator const chartype *() const { return m_str; } \
108 chartype operator[](size_t n) const { return m_str[n]; } \
114 DEFINE_BUFFER(wxCharBuffer
, char, wxStrdupA
);
118 DEFINE_BUFFER(wxWCharBuffer
, wchar_t, wxStrdupW
);
120 #endif // wxUSE_WCHAR_T
125 typedef wxWCharBuffer wxWxCharBuffer
;
127 #define wxMB2WXbuf wxWCharBuffer
128 #define wxWX2MBbuf wxCharBuffer
129 #define wxWC2WXbuf wxChar*
130 #define wxWX2WCbuf wxChar*
132 typedef wxCharBuffer wxWxCharBuffer
;
134 #define wxMB2WXbuf wxChar*
135 #define wxWX2MBbuf wxChar*
136 #define wxWC2WXbuf wxCharBuffer
137 #define wxWX2WCbuf wxWCharBuffer
138 #endif // Unicode/ANSI
140 // ----------------------------------------------------------------------------
141 // A class for holding growable data buffers (not necessarily strings)
142 // ----------------------------------------------------------------------------
144 // This class manages the actual data buffer pointer and is ref-counted.
145 class wxMemoryBufferData
148 // the initial size and also the size added by ResizeIfNeeded()
149 enum { DefBufSize
= 1024 };
151 friend class wxMemoryBuffer
;
153 // everyting is private as it can only be used by wxMemoryBuffer
155 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
156 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
159 ~wxMemoryBufferData() { free(m_data
); }
162 void ResizeIfNeeded(size_t newSize
)
164 if (newSize
> m_size
)
166 void *dataOld
= m_data
;
167 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
173 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
177 void IncRef() { m_ref
+= 1; }
181 if (m_ref
== 0) // are there no more references?
186 // the buffer containing the data
189 // the size of the buffer
192 // the amount of data currently in the buffer
195 // the reference count
198 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
206 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
208 m_bufdata
= new wxMemoryBufferData(size
);
212 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
215 // copy and assignment
216 wxMemoryBuffer(const wxMemoryBuffer
& src
)
217 : m_bufdata(src
.m_bufdata
)
222 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
225 m_bufdata
= src
.m_bufdata
;
232 void *GetData() const { return m_bufdata
->m_data
; }
233 size_t GetBufSize() const { return m_bufdata
->m_size
; }
234 size_t GetDataLen() const { return m_bufdata
->m_len
; }
236 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
237 void SetDataLen(size_t len
)
239 wxASSERT(len
<= m_bufdata
->m_size
);
240 m_bufdata
->m_len
= len
;
243 // Ensure the buffer is big enough and return a pointer to it
244 void *GetWriteBuf(size_t sizeNeeded
)
246 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
247 return m_bufdata
->m_data
;
250 // Update the length after the write
251 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
253 // Like the above, but appends to the buffer
254 void *GetAppendBuf(size_t sizeNeeded
)
256 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
257 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
260 // Update the length after the append
261 void UngetAppendBuf(size_t sizeUsed
)
263 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
266 // Other ways to append to the buffer
267 void AppendByte(char data
)
269 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
271 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
272 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
273 m_bufdata
->m_len
+= 1;
276 void AppendData(const void *data
, size_t len
)
278 memcpy(GetAppendBuf(len
), data
, len
);
282 operator const char *() const { return (const char*)GetData(); }
285 wxMemoryBufferData
* m_bufdata
;
288 // ----------------------------------------------------------------------------
289 // template class for any kind of data
290 // ----------------------------------------------------------------------------
294 #endif // _WX_BUFFER_H