source: icXML/icXML-devel/src/icxercesc/framework/XMLBuffer.hpp @ 3103

Last change on this file since 3103 was 3103, checked in by cameron, 6 years ago

Initial imports for icXML v0.9

File size: 8.8 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: XMLBuffer.hpp 932887 2010-04-11 13:04:59Z borisk $
20 */
21
22#if !defined(XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP)
23#define XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP
24
25#include <xercesc/util/XMemory.hpp>
26#include <icxercesc/util/PlatformUtils.hpp>
27#include <xercesc/framework/MemoryManager.hpp>
28#include <icxmlc/Array.hpp>
29#include <string.h>
30#include <assert.h>
31
32XERCES_CPP_NAMESPACE_BEGIN
33
34class XMLBufferFullHandler;
35
36/**
37 *  XMLBuffer is a lightweight, expandable Unicode text buffer. Since XML is
38 *  inherently theoretically unbounded in terms of the sizes of things, we
39 *  very often need to have expandable buffers. The primary concern here is
40 *  that appends of characters and other buffers or strings be very fast, so
41 *  it always maintains the current buffer size.
42 *
43 *  The buffer is not null terminated until some asks to see the raw buffer
44 *  contents. This also avoids overhead during append operations.
45 */
46class XMLPARSER_EXPORT XMLBuffer : public XMemory
47{
48        enum { ADDITIONAL_PADDING = (sizeof(BytePack) / sizeof(XMLCh)) };
49
50public :
51        // -----------------------------------------------------------------------
52        //  Constructors and Destructor
53        // -----------------------------------------------------------------------
54
55        /** @name Constructor */
56        //@{
57        XMLBuffer
58        (
59                const XMLSize_t                 capacity = 1023
60                , MemoryManager * const manager = XMLPlatformUtils::fgMemoryManager
61        )
62        : fIndex(0)
63        , fCapacity(capacity)
64        , fFullSize(0)
65        , fUsed(false)
66        , fMemoryManager(manager)
67        , fFullHandler(0)
68        , fBuffer(0)
69        {
70                fBuffer = (XMLCh*)manager->allocate((capacity + ADDITIONAL_PADDING) * sizeof(XMLCh));
71        }
72        //@}
73
74        /** @name Destructor */
75        //@{
76        ~XMLBuffer()
77        {
78                fMemoryManager->deallocate(fBuffer);
79                fBuffer = 0;
80        }
81        //@}
82
83
84    inline const XMLCh & operator[](const XMLSize_t index) const
85    {
86        return fBuffer[index];
87    }
88
89    inline XMLCh & operator[](const XMLSize_t index)
90    {
91        return fBuffer[index];
92    }
93
94        // -----------------------------------------------------------------------
95        //  Buffer Full Handler Management
96        // -----------------------------------------------------------------------
97        void setFullHandler(XMLBufferFullHandler* handler, const XMLSize_t fullSize)
98        {
99                if (handler && fullSize)
100                {
101                        fFullHandler = handler;
102                        fFullSize = fullSize;
103
104                        // Need to consider the case that the fullsize is less than the current capacity.
105                        // For example, say fullSize = 100 and fCapacity is 1023 (the default).
106                        // If the fIndex is less than the fullSize, then no problem.  We can just carry
107                        // on by resetting fCapacity to fullsize and proceed business as usual.
108                        // If the fIndex is already bigger than the fullSize then we call ensureCapacity
109                        // to see if it can handle emptying the current buffer (it will throw an
110                        // exception if it can't).
111                        if (fullSize < fCapacity)
112                        {
113                                fCapacity = fullSize;
114                                if (fIndex >= fullSize)
115                                {
116                                        ensureCapacity(0);
117                                }
118                        }
119                }
120                else
121                {
122                        // reset fFullHandler to zero because setFullHandler had bad input
123                        fFullHandler = 0;
124                }
125        }
126
127        // -----------------------------------------------------------------------
128        //  Buffer Management
129        // -----------------------------------------------------------------------
130    inline void append(const XMLCh toAppend)
131        {
132                // Put in char and bump the index
133        if (unlikely(fIndex == fCapacity))
134        {
135                        ensureCapacity(1);
136        }
137                fBuffer[fIndex++] = toAppend;
138        }
139
140    inline void append (const XMLCh* const chars, const XMLSize_t count)
141        {
142                if (count)
143                {
144            if (unlikely(fIndex + count >= fCapacity))
145                        {
146                                ensureCapacity(count);
147                        }
148                        Array<XMLCh>::copy(chars, &fBuffer[fIndex], count);
149                        fIndex += count;
150                }
151        }
152
153    inline void append (const XMLCh* const chars)
154        {
155                if (chars != 0 && *chars != 0)
156                {
157                        // get length of chars
158                        XMLSize_t count = 0;
159                        for (; chars[count]; count++ );
160
161            if (unlikely(fIndex + count >= fCapacity))
162                        {
163                                ensureCapacity(count);
164                        }
165                        Array<XMLCh>::copy(chars, &fBuffer[fIndex], count);
166                        fIndex += count;
167                }
168        }
169
170    inline void set (const XMLCh* const chars, const XMLSize_t count)
171        {
172                fIndex = 0;
173                append(chars, count);
174        }
175
176        void set (const XMLCh* const chars)
177        {
178                fIndex = 0;
179                if (chars != 0 && *chars != 0)
180                        append(chars);
181        }
182
183    void set (const XMLCh ch)
184    {
185        fBuffer[0] = ch;
186        fIndex = 1;
187    }
188
189    void fill(const XMLCh value, const XMLSize_t count)
190    {
191        if (unlikely(count >= fCapacity))
192        {
193            fIndex = 0;
194            ensureCapacity(count - fCapacity);
195        }
196        Array<XMLCh>::set(fBuffer, value, count);
197        fIndex = count;
198    }
199
200        const XMLCh* getRawBuffer() const
201        {
202                fBuffer[fIndex] = 0;
203                return fBuffer;
204        }
205
206        XMLCh* getRawBuffer()
207        {
208                fBuffer[fIndex] = 0;
209                return fBuffer;
210        }
211
212    XMLCh* getInternalBuffer()
213    {
214        return fBuffer;
215    }
216
217        void reset()
218        {
219                fIndex = 0;
220        }
221
222        // -----------------------------------------------------------------------
223        //  Getters
224        // -----------------------------------------------------------------------
225        bool getInUse() const
226        {
227                return fUsed;
228        }
229
230        XMLSize_t getLen() const
231        {
232                return fIndex;
233        }
234
235        bool isEmpty() const
236        {
237                return (fIndex == 0);
238        }
239
240        // -----------------------------------------------------------------------
241        //  Setters
242        // -----------------------------------------------------------------------
243        void setInUse(const bool newValue)
244        {
245                fUsed = newValue;
246        }
247
248        void setLen(const XMLSize_t length)
249        {
250                fIndex = length;
251        }
252
253    // -----------------------------------------------------------------------
254    //  Private helpers
255    // -----------------------------------------------------------------------
256    void ensureCapacity(const XMLSize_t extraNeeded);
257
258private :
259        // -----------------------------------------------------------------------
260        //  Unimplemented constructors and operators
261        // -----------------------------------------------------------------------
262        XMLBuffer(const XMLBuffer&);
263        XMLBuffer& operator=(const XMLBuffer&);
264
265        // -----------------------------------------------------------------------
266        //  Declare our friends
267        // -----------------------------------------------------------------------
268        friend class XMLBufBid;
269
270        // -----------------------------------------------------------------------
271        //  Private data members
272        //
273        //  fBuffer
274        //      The pointer to the buffer data. Its grown as needed. Its always
275        //      one larger than fCapacity, to leave room for the null terminator.
276        //
277        //  fIndex
278        //      The current index into the buffer, as characters are appended
279        //      to it. If its zero, then the buffer is empty.
280        //
281        //  fCapacity
282        //      The current capacity of the buffer. Its actually always one
283        //      larger, to leave room for the null terminator.
284        //
285        //  fUsed
286        //      Indicates whether this buffer is in use or not.
287        //
288        //  fFullHandler, fFullSize
289        //      If fFullHandler is non-null, the buffer has a maximum size
290        //      indicated by fFullSize. If writing to the buffer would exceed the
291        //      buffer's maximum size, fFullHandler's bufferFull callback is
292        //      invoked, to empty the buffer.
293        // -----------------------------------------------------------------------
294        XMLSize_t                   fIndex;
295        XMLSize_t                   fCapacity;
296        XMLSize_t                   fFullSize;
297        bool                        fUsed;
298        MemoryManager* const        fMemoryManager;
299        XMLBufferFullHandler*       fFullHandler;
300        XMLCh*                      fBuffer;
301};
302
303/**
304 *  XMLBufferFullHandler is a callback interface for clients of
305 *  XMLBuffers that impose a size restriction (e.g. XMLScanner).
306 *  Note that this is intended solely as a mix-in for internal
307 *  use, and therefore does not derive from XMemory (to avoid
308 *  the ambiguous base class problem).
309 */
310class XMLPARSER_EXPORT XMLBufferFullHandler
311{
312public :
313
314        virtual ~XMLBufferFullHandler() {}
315
316        /**
317         * Callback method, intended to allow clients of an XMLBuffer which has
318         * become full to empty it appropriately.
319         * @return true if the handler was able to empty the buffer (either
320         * partially or completely), otherwise false to indicate an error.
321         */
322        virtual bool bufferFull(XMLBuffer&) = 0;
323
324};
325
326XERCES_CPP_NAMESPACE_END
327
328#endif
Note: See TracBrowser for help on using the repository browser.