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

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

Penultimate check-in for icXML 0.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    inline void set(const XMLCh* const chars)
177    {
178        fIndex = 0;
179        if (chars != 0 && *chars != 0)
180            append(chars);
181    }
182
183    inline void set (const XMLCh ch)
184    {
185        fBuffer[0] = ch;
186        fIndex = 1;
187    }
188
189    inline 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    inline const XMLCh* getRawBuffer() const
201        {
202                fBuffer[fIndex] = 0;
203                return fBuffer;
204        }
205
206    inline XMLCh* getRawBuffer()
207        {
208                fBuffer[fIndex] = 0;
209                return fBuffer;
210        }
211
212        void reset()
213        {
214                fIndex = 0;
215        }
216
217        // -----------------------------------------------------------------------
218        //  Getters
219        // -----------------------------------------------------------------------
220        bool getInUse() const
221        {
222                return fUsed;
223        }
224
225        XMLSize_t getLen() const
226        {
227                return fIndex;
228        }
229
230        bool isEmpty() const
231        {
232                return (fIndex == 0);
233        }
234
235        // -----------------------------------------------------------------------
236        //  Setters
237        // -----------------------------------------------------------------------
238        void setInUse(const bool newValue)
239        {
240                fUsed = newValue;
241        }
242
243        void setLen(const XMLSize_t length)
244        {
245                fIndex = length;
246        }
247
248    // -----------------------------------------------------------------------
249    //  Private helpers
250    // -----------------------------------------------------------------------
251    void ensureCapacity(const XMLSize_t extraNeeded);
252
253private :
254        // -----------------------------------------------------------------------
255        //  Unimplemented constructors and operators
256        // -----------------------------------------------------------------------
257        XMLBuffer(const XMLBuffer&);
258        XMLBuffer& operator=(const XMLBuffer&);
259
260        // -----------------------------------------------------------------------
261        //  Declare our friends
262        // -----------------------------------------------------------------------
263        friend class XMLBufBid;
264
265        // -----------------------------------------------------------------------
266        //  Private data members
267        //
268        //  fBuffer
269        //      The pointer to the buffer data. Its grown as needed. Its always
270        //      one larger than fCapacity, to leave room for the null terminator.
271        //
272        //  fIndex
273        //      The current index into the buffer, as characters are appended
274        //      to it. If its zero, then the buffer is empty.
275        //
276        //  fCapacity
277        //      The current capacity of the buffer. Its actually always one
278        //      larger, to leave room for the null terminator.
279        //
280        //  fUsed
281        //      Indicates whether this buffer is in use or not.
282        //
283        //  fFullHandler, fFullSize
284        //      If fFullHandler is non-null, the buffer has a maximum size
285        //      indicated by fFullSize. If writing to the buffer would exceed the
286        //      buffer's maximum size, fFullHandler's bufferFull callback is
287        //      invoked, to empty the buffer.
288        // -----------------------------------------------------------------------
289        XMLSize_t                   fIndex;
290        XMLSize_t                   fCapacity;
291        XMLSize_t                   fFullSize;
292        bool                        fUsed;
293        MemoryManager* const        fMemoryManager;
294        XMLBufferFullHandler*       fFullHandler;
295        XMLCh*                      fBuffer;
296};
297
298/**
299 *  XMLBufferFullHandler is a callback interface for clients of
300 *  XMLBuffers that impose a size restriction (e.g. XMLScanner).
301 *  Note that this is intended solely as a mix-in for internal
302 *  use, and therefore does not derive from XMemory (to avoid
303 *  the ambiguous base class problem).
304 */
305class XMLPARSER_EXPORT XMLBufferFullHandler
306{
307public :
308
309        virtual ~XMLBufferFullHandler() {}
310
311        /**
312         * Callback method, intended to allow clients of an XMLBuffer which has
313         * become full to empty it appropriately.
314         * @return true if the handler was able to empty the buffer (either
315         * partially or completely), otherwise false to indicate an error.
316         */
317        virtual bool bufferFull(XMLBuffer&) = 0;
318
319};
320
321XERCES_CPP_NAMESPACE_END
322
323#endif
Note: See TracBrowser for help on using the repository browser.