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 WXDLLIMPEXP_BASE wxCharTypeBuffer
35 wxCharTypeBuffer(const CharType
*str
= NULL
)
36 : m_str(str ?
wxStrDup(str
) : NULL
)
40 wxCharTypeBuffer(const wxCStrData
& cstr
)
45 wxCharTypeBuffer(size_t len
)
46 : m_str((CharType
*)malloc((len
+ 1)*sizeof(CharType
)))
48 m_str
[len
] = (CharType
)0;
51 /* no need to check for NULL, free() does it */
52 ~wxCharTypeBuffer() { free(m_str
); }
57 the copy ctor and assignment operators change the passed in object
58 even although it is declared as "const", so:
60 a) it shouldn't be really const
61 b) you shouldn't use it afterwards (or know that it was reset)
63 This is very ugly but is unfortunately needed to make the normal use\
64 of wxCharTypeBuffer buffer objects possible and is very similar to what
65 std::auto_ptr<> does (as if it were an excuse...)
69 because of the remark above, release() is declared const even if it
72 CharType
*release() const
75 ((wxCharTypeBuffer
*)this)->m_str
= NULL
;
85 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
86 : m_str(src
.release())
90 wxCharTypeBuffer
& operator=(const CharType
*str
)
93 m_str
= str ?
wxStrDup(str
) : NULL
;
97 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
100 m_str
= src
.release();
105 bool extend(size_t len
)
108 str
= (CharType
*)realloc(m_str
, (len
+ 1)*sizeof(CharType
));
117 CharType
*data() { return m_str
; }
118 const CharType
*data() const { return m_str
; }
119 operator const CharType
*() const { return m_str
; }
120 CharType
operator[](size_t n
) const { return m_str
[n
]; }
123 void FromCStrData(const wxCStrData
& cstr
);
129 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
132 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBuffer
<char>(str
) {}
133 wxCharBuffer(const wxCStrData
& cstr
) : wxCharTypeBuffer
<char>(cstr
) {}
134 wxCharBuffer(size_t len
) : wxCharTypeBuffer
<char>(len
) {}
138 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
141 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBuffer
<wchar_t>(str
) {}
142 wxWCharBuffer(const wxCStrData
& cstr
) : wxCharTypeBuffer
<wchar_t>(cstr
) {}
143 wxWCharBuffer(size_t len
) : wxCharTypeBuffer
<wchar_t>(len
) {}
145 #endif // wxUSE_WCHAR_T
148 typedef wxWCharBuffer wxWxCharBuffer
;
150 #define wxMB2WXbuf wxWCharBuffer
151 #define wxWX2MBbuf wxCharBuffer
152 #define wxWC2WXbuf wxChar*
153 #define wxWX2WCbuf wxChar*
155 typedef wxCharBuffer wxWxCharBuffer
;
157 #define wxMB2WXbuf wxChar*
158 #define wxWX2MBbuf wxChar*
159 #define wxWC2WXbuf wxCharBuffer
160 #define wxWX2WCbuf wxWCharBuffer
161 #endif // Unicode/ANSI
163 // ----------------------------------------------------------------------------
164 // A class for holding growable data buffers (not necessarily strings)
165 // ----------------------------------------------------------------------------
167 // This class manages the actual data buffer pointer and is ref-counted.
168 class wxMemoryBufferData
171 // the initial size and also the size added by ResizeIfNeeded()
172 enum { DefBufSize
= 1024 };
174 friend class wxMemoryBuffer
;
176 // everyting is private as it can only be used by wxMemoryBuffer
178 wxMemoryBufferData(size_t size
= wxMemoryBufferData
::DefBufSize
)
179 : m_data(size ?
malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
182 ~wxMemoryBufferData() { free(m_data
); }
185 void ResizeIfNeeded(size_t newSize
)
187 if (newSize
> m_size
)
189 void *dataOld
= m_data
;
190 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData
::DefBufSize
);
196 m_size
= newSize
+ wxMemoryBufferData
::DefBufSize
;
200 void IncRef() { m_ref
+= 1; }
204 if (m_ref
== 0) // are there no more references?
209 // the buffer containing the data
212 // the size of the buffer
215 // the amount of data currently in the buffer
218 // the reference count
221 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
229 wxMemoryBuffer(size_t size
= wxMemoryBufferData
::DefBufSize
)
231 m_bufdata
= new wxMemoryBufferData(size
);
235 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
238 // copy and assignment
239 wxMemoryBuffer(const wxMemoryBuffer
& src
)
240 : m_bufdata(src
.m_bufdata
)
245 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
248 m_bufdata
= src
.m_bufdata
;
255 void *GetData() const { return m_bufdata
->m_data
; }
256 size_t GetBufSize() const { return m_bufdata
->m_size
; }
257 size_t GetDataLen() const { return m_bufdata
->m_len
; }
259 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
260 void SetDataLen(size_t len
)
262 wxASSERT(len
<= m_bufdata
->m_size
);
263 m_bufdata
->m_len
= len
;
266 // Ensure the buffer is big enough and return a pointer to it
267 void *GetWriteBuf(size_t sizeNeeded
)
269 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
270 return m_bufdata
->m_data
;
273 // Update the length after the write
274 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
276 // Like the above, but appends to the buffer
277 void *GetAppendBuf(size_t sizeNeeded
)
279 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
280 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
283 // Update the length after the append
284 void UngetAppendBuf(size_t sizeUsed
)
286 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
289 // Other ways to append to the buffer
290 void AppendByte(char data
)
292 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
294 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
295 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
296 m_bufdata
->m_len
+= 1;
299 void AppendData(const void *data
, size_t len
)
301 memcpy(GetAppendBuf(len
), data
, len
);
305 operator const char *() const { return (const char*)GetData(); }
308 wxMemoryBufferData
* m_bufdata
;
311 // ----------------------------------------------------------------------------
312 // template class for any kind of data
313 // ----------------------------------------------------------------------------
317 #endif // _WX_BUFFER_H