source: icXML/icXML-devel/src/icxmlc/stringpool.h @ 2720

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

Initial check-in of icXML 0.8 source files

File size: 4.2 KB
Line 
1/*
2 *  Copyright © 2012 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icXML is a trademark of International Characters.
5 */
6
7/*
8 * @author Nigel Medforth, nigelm -at- interational-characters.com
9 * @version $Id: stringpool.h 207 2012-12-02 20:38:22Z robc $
10 *
11 */
12
13//  StringPool.h - Coterminal String Pools.
14
15#ifndef STRINGPOOL_H
16#define STRINGPOOL_H
17
18#include <stdlib.h>
19#include <string.h>
20#include <xercesc/framework/MemoryManager.hpp>
21#include <xercesc/util/XMLString.hpp>
22#include <icxmlc/Array.hpp>
23
24XERCES_CPP_NAMESPACE_BEGIN
25
26template <typename Char, int BasePoolSize, bool NullTerminated = 1>
27class StringPool
28{
29public:
30                StringPool
31                (
32                        MemoryManager* const manager
33                );
34
35                ~StringPool();
36
37                const Char * insert
38                (
39                        const Char * data
40                        , const size_t size
41                );
42
43                Char * allocate(size_t size);
44
45                void flushAll();
46
47                inline size_t available() const { return fSpaceAvail; }
48
49private:
50
51                void extend(const size_t minimumSize);
52
53private:
54                enum { MEMORY_NODE_PADDING = sizeof(BitBlock) / sizeof(Char) };
55
56                /* The initial buffer is allocated as part of the MemoryPool object.
57                   For stack allocated MemoryPools that do not exceed the initial
58                   BasePoolSize, this completely eliminates the overhead and memory
59                   fragmentation associated with calls to new and delete. */
60                struct MemoryNode
61                {
62                        MemoryNode                      * fNextPool;
63                        size_t                            fSize;
64                        Char                                                      fMemory[BasePoolSize + MEMORY_NODE_PADDING];
65                };
66
67                MemoryNode                            fStackMemory;
68                MemoryNode                          * fCurrentPool;
69                size_t                                fTotalSize;
70                Char                                                            * fInsertionPtr;
71                size_t                                fSpaceAvail;
72
73                MemoryManager                       * fMemoryManager;
74
75};
76
77template <typename Char, int BasePoolSize, bool NullTerminated>
78StringPool<Char, BasePoolSize, NullTerminated>::
79StringPool(MemoryManager* const manager)
80{
81        fStackMemory.fNextPool = NULL;
82        fStackMemory.fSize = BasePoolSize;
83        fTotalSize = BasePoolSize;
84        fInsertionPtr = fStackMemory.fMemory;
85        fSpaceAvail = BasePoolSize;
86        fCurrentPool = &fStackMemory;
87        fMemoryManager = manager;
88}
89
90template <typename Char, int BasePoolSize, bool NullTerminated>
91StringPool<Char, BasePoolSize, NullTerminated>::
92~StringPool()
93{
94        flushAll();
95}
96
97template <typename Char, int BasePoolSize, bool NullTerminated>
98void
99StringPool<Char, BasePoolSize, NullTerminated>::
100flushAll()
101{
102        while (fCurrentPool != &fStackMemory)
103        {
104                MemoryNode * node = fCurrentPool;
105                fCurrentPool = node->fNextPool;
106                fMemoryManager->deallocate(node);
107        }
108
109        fStackMemory.fNextPool = NULL;
110        fStackMemory.fSize = BasePoolSize;
111        fTotalSize = BasePoolSize;
112        fInsertionPtr = fStackMemory.fMemory;
113        fSpaceAvail = BasePoolSize;
114}
115
116template <typename Char, int BasePoolSize, bool NullTerminated>
117IDISA_ALWAYS_INLINE
118const Char *
119StringPool<Char, BasePoolSize, NullTerminated>::
120insert(const Char * string, const size_t length)
121{
122    Char * retVal = allocate(length + (NullTerminated ? 1 : 0));
123    Array<Char>::move(string, retVal, length);
124    if (NullTerminated)
125    {
126        retVal[length] = 0;
127    }
128    return retVal;
129}
130
131template <typename Char, int BasePoolSize, bool NullTerminated>
132IDISA_ALWAYS_INLINE
133Char *
134StringPool<Char, BasePoolSize, NullTerminated>::
135allocate(size_t length)
136{
137    if (unlikely(length >= fSpaceAvail))
138    {
139        // look back through the allocated pools to see if there is room in any of
140        // them? or would that just slow the hardware memory prediction down?
141
142        extend(length);
143    }
144
145    Char * retVal = fInsertionPtr;
146    fInsertionPtr += length;
147    fSpaceAvail -= length;
148
149    return retVal;
150}
151
152template <typename Char, int BasePoolSize, bool NullTerminated>
153void
154StringPool<Char, BasePoolSize, NullTerminated>::
155extend(const size_t minimumSize)
156{
157    const size_t additionalCapacity = max(minimumSize * 2, fTotalSize);
158
159        MemoryNode * node =
160           (MemoryNode *)fMemoryManager->allocate
161           (
162                        additionalCapacity * sizeof(Char) + MEMORY_NODE_PADDING
163           );
164        node->fNextPool = fCurrentPool;
165        node->fSize = additionalCapacity;
166        fTotalSize += additionalCapacity;
167        fCurrentPool = node;
168        fInsertionPtr = node->fMemory;
169        fSpaceAvail = additionalCapacity;
170}
171
172XERCES_CPP_NAMESPACE_END
173
174#endif
Note: See TracBrowser for help on using the repository browser.