1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/buffer.h
3 // Purpose:     auto buffer classes: buffers which automatically free memory
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     12.04.99
7 // RCS-ID:      $Id: buffer.h 61872 2009-09-09 22:37:05Z VZ $
8 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence:     wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef _WX_BUFFER_H
13 #define _WX_BUFFER_H
14 
15 #include "wx/wxchar.h"
16 
17 #include <stdlib.h>             // malloc() and free()
18 
19 // ----------------------------------------------------------------------------
20 // Special classes for (wide) character strings: they use malloc/free instead
21 // of new/delete
22 // ----------------------------------------------------------------------------
23 
24 #define DEFINE_BUFFER(classname, chartype, strdupfunc)                      \
25 class WXDLLIMPEXP_BASE classname                                            \
26 {                                                                           \
27 public:                                                                     \
28     classname(const chartype *str = NULL)                                   \
29         : m_str(str ? strdupfunc(str) : NULL)                               \
30     {                                                                       \
31     }                                                                       \
32                                                                             \
33     classname(size_t len)                                                   \
34         : m_str((chartype *)malloc((len + 1)*sizeof(chartype)))             \
35     {                                                                       \
36         m_str[len] = (chartype)0;                                           \
37     }                                                                       \
38                                                                             \
39     /* no need to check for NULL, free() does it */                         \
40     ~classname() { free(m_str); }                                           \
41                                                                             \
42     /*                                                                      \
43         WARNING:                                                            \
44                                                                             \
45         the copy ctor and assignment operators change the passed in object  \
46         even although it is declared as "const", so:                        \
47                                                                             \
48         a) it shouldn't be really const                                     \
49         b) you shouldn't use it afterwards (or know that it was reset)      \
50                                                                             \
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...)                   \
54     */                                                                      \
55                                                                             \
56     /*                                                                      \
57        because of the remark above, release() is declared const even if it  \
58        isn't really const                                                   \
59      */                                                                     \
60     chartype *release() const                                               \
61     {                                                                       \
62         chartype *p = m_str;                                                \
63         ((classname *)this)->m_str = NULL;                                  \
64         return p;                                                           \
65     }                                                                       \
66                                                                             \
67     void reset()                                                            \
68     {                                                                       \
69         free(m_str);                                                        \
70         m_str = NULL;                                                       \
71     }                                                                       \
72                                                                             \
73     classname(const classname& src)                                         \
74         : m_str(src.release())                                              \
75     {                                                                       \
76     }                                                                       \
77                                                                             \
78     classname& operator=(const chartype *str)                               \
79     {                                                                       \
80         free(m_str);                                                        \
81         m_str = str ? strdupfunc(str) : NULL;                               \
82         return *this;                                                       \
83     }                                                                       \
84                                                                             \
85     classname& operator=(const classname& src)                              \
86     {                                                                       \
87         free(m_str);                                                        \
88         m_str = src.release();                                              \
89                                                                             \
90         return *this;                                                       \
91     }                                                                       \
92                                                                             \
93     bool extend(size_t len)                                                 \
94     {                                                                       \
95         chartype *                                                          \
96             str = (chartype *)realloc(m_str, (len + 1)*sizeof(chartype));   \
97         if ( !str )                                                         \
98             return false;                                                   \
99                                                                             \
100         m_str = str;                                                        \
101                                                                             \
102         return true;                                                        \
103     }                                                                       \
104                                                                             \
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]; }                \
109                                                                             \
110 private:                                                                    \
111     chartype *m_str;                                                        \
112 }
113 
114 #if wxABI_VERSION >= 20804
115 // needed for wxString::char_str() and wchar_str()
116 #define DEFINE_WRITABLE_BUFFER(classname, baseclass, chartype)              \
117 class WXDLLIMPEXP_BASE classname : public baseclass                         \
118 {                                                                           \
119 public:                                                                     \
120     classname(const baseclass& src) : baseclass(src) {}                     \
121     classname(const chartype *str = NULL) : baseclass(str) {}               \
122                                                                             \
123     operator chartype*() { return this->data(); }                           \
124 }
125 #endif // wxABI_VERSION >= 20804
126 
127 DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
128 #if wxABI_VERSION >= 20804
129 DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
130 #endif
131 
132 #if wxUSE_WCHAR_T
133 
134 DEFINE_BUFFER(wxWCharBuffer, wchar_t, wxStrdupW);
135 #if wxABI_VERSION >= 20804
136 DEFINE_WRITABLE_BUFFER(wxWritableWCharBuffer, wxWCharBuffer, wchar_t);
137 #endif
138 
139 #endif // wxUSE_WCHAR_T
140 
141 #undef DEFINE_BUFFER
142 #undef DEFINE_WRITABLE_BUFFER
143 
144 #if wxUSE_UNICODE
145     typedef wxWCharBuffer wxWxCharBuffer;
146 
147     #define wxMB2WXbuf wxWCharBuffer
148     #define wxWX2MBbuf wxCharBuffer
149     #define wxWC2WXbuf wxChar*
150     #define wxWX2WCbuf wxChar*
151 #else // ANSI
152     typedef wxCharBuffer wxWxCharBuffer;
153 
154     #define wxMB2WXbuf wxChar*
155     #define wxWX2MBbuf wxChar*
156     #define wxWC2WXbuf wxCharBuffer
157     #define wxWX2WCbuf wxWCharBuffer
158 #endif // Unicode/ANSI
159 
160 // ----------------------------------------------------------------------------
161 // A class for holding growable data buffers (not necessarily strings)
162 // ----------------------------------------------------------------------------
163 
164 // This class manages the actual data buffer pointer and is ref-counted.
165 class wxMemoryBufferData
166 {
167 public:
168     // the initial size and also the size added by ResizeIfNeeded()
169     enum { DefBufSize = 1024 };
170 
171     friend class wxMemoryBuffer;
172 
173     // everyting is private as it can only be used by wxMemoryBuffer
174 private:
175     wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
176         : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
177     {
178     }
~wxMemoryBufferData()179     ~wxMemoryBufferData() { free(m_data); }
180 
181 
ResizeIfNeeded(size_t newSize)182     void ResizeIfNeeded(size_t newSize)
183     {
184         if (newSize > m_size)
185         {
186             void *dataOld = m_data;
187             m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
188             if ( !m_data )
189             {
190                 free(dataOld);
191             }
192 
193             m_size = newSize + wxMemoryBufferData::DefBufSize;
194         }
195     }
196 
IncRef()197     void IncRef() { m_ref += 1; }
DecRef()198     void DecRef()
199     {
200         m_ref -= 1;
201         if (m_ref == 0)  // are there no more references?
202             delete this;
203     }
204 
205 
206     // the buffer containing the data
207     void  *m_data;
208 
209     // the size of the buffer
210     size_t m_size;
211 
212     // the amount of data currently in the buffer
213     size_t m_len;
214 
215     // the reference count
216     size_t m_ref;
217 
218     DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
219 };
220 
221 
222 class wxMemoryBuffer
223 {
224 public:
225     // ctor and dtor
226     wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
227     {
228         m_bufdata = new wxMemoryBufferData(size);
229         m_bufdata->IncRef();
230     }
231 
~wxMemoryBuffer()232     ~wxMemoryBuffer() { m_bufdata->DecRef(); }
233 
234 
235     // copy and assignment
wxMemoryBuffer(const wxMemoryBuffer & src)236     wxMemoryBuffer(const wxMemoryBuffer& src)
237         : m_bufdata(src.m_bufdata)
238     {
239         m_bufdata->IncRef();
240     }
241 
242     wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
243     {
244         m_bufdata->DecRef();
245         m_bufdata = src.m_bufdata;
246         m_bufdata->IncRef();
247         return *this;
248     }
249 
250 
251     // Accessors
GetData()252     void  *GetData() const    { return m_bufdata->m_data; }
GetBufSize()253     size_t GetBufSize() const { return m_bufdata->m_size; }
GetDataLen()254     size_t GetDataLen() const { return m_bufdata->m_len; }
255 
SetBufSize(size_t size)256     void   SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
SetDataLen(size_t len)257     void   SetDataLen(size_t len)
258     {
259         wxASSERT(len <= m_bufdata->m_size);
260         m_bufdata->m_len = len;
261     }
262 
263     // Ensure the buffer is big enough and return a pointer to it
GetWriteBuf(size_t sizeNeeded)264     void *GetWriteBuf(size_t sizeNeeded)
265     {
266         m_bufdata->ResizeIfNeeded(sizeNeeded);
267         return m_bufdata->m_data;
268     }
269 
270     // Update the length after the write
UngetWriteBuf(size_t sizeUsed)271     void  UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
272 
273     // Like the above, but appends to the buffer
GetAppendBuf(size_t sizeNeeded)274     void *GetAppendBuf(size_t sizeNeeded)
275     {
276         m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
277         return (char*)m_bufdata->m_data + m_bufdata->m_len;
278     }
279 
280     // Update the length after the append
UngetAppendBuf(size_t sizeUsed)281     void  UngetAppendBuf(size_t sizeUsed)
282     {
283         SetDataLen(m_bufdata->m_len + sizeUsed);
284     }
285 
286     // Other ways to append to the buffer
AppendByte(char data)287     void  AppendByte(char data)
288     {
289         wxCHECK_RET( m_bufdata->m_data, wxT("invalid wxMemoryBuffer") );
290 
291         m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
292         *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
293         m_bufdata->m_len += 1;
294     }
295 
AppendData(const void * data,size_t len)296     void  AppendData(const void *data, size_t len)
297     {
298         memcpy(GetAppendBuf(len), data, len);
299         UngetAppendBuf(len);
300     }
301 
302     operator const char *() const { return (const char*)GetData(); }
303 
304 private:
305     wxMemoryBufferData*  m_bufdata;
306 };
307 
308 // ----------------------------------------------------------------------------
309 // template class for any kind of data
310 // ----------------------------------------------------------------------------
311 
312 // TODO
313 
314 #endif // _WX_BUFFER_H
315