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)                      \
25class WXDLLIMPEXP_BASE classname                                            \
26{                                                                           \
27public:                                                                     \
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                                                                            \
110private:                                                                    \
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)              \
117class WXDLLIMPEXP_BASE classname : public baseclass                         \
118{                                                                           \
119public:                                                                     \
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
127DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
128#if wxABI_VERSION >= 20804
129DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
130#endif
131
132#if wxUSE_WCHAR_T
133
134DEFINE_BUFFER(wxWCharBuffer, wchar_t, wxStrdupW);
135#if wxABI_VERSION >= 20804
136DEFINE_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.
165class wxMemoryBufferData
166{
167public:
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
174private:
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    }
179    ~wxMemoryBufferData() { free(m_data); }
180
181
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
197    void IncRef() { m_ref += 1; }
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
222class wxMemoryBuffer
223{
224public:
225    // ctor and dtor
226    wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
227    {
228        m_bufdata = new wxMemoryBufferData(size);
229        m_bufdata->IncRef();
230    }
231
232    ~wxMemoryBuffer() { m_bufdata->DecRef(); }
233
234
235    // copy and assignment
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
252    void  *GetData() const    { return m_bufdata->m_data; }
253    size_t GetBufSize() const { return m_bufdata->m_size; }
254    size_t GetDataLen() const { return m_bufdata->m_len; }
255
256    void   SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
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
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
271    void  UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
272
273    // Like the above, but appends to the buffer
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
281    void  UngetAppendBuf(size_t sizeUsed)
282    {
283        SetDataLen(m_bufdata->m_len + sizeUsed);
284    }
285
286    // Other ways to append to the buffer
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
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
304private:
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