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

Last change on this file since 3563 was 3563, checked in by cameron, 5 years ago

Update icxmlc files

File size: 5.0 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 371 2013-09-05 21:51:18Z nigelm $
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 <icxercesc/util/XMLString.hpp>
22#include <icxmlc/Array.hpp>
23
24// #define USE_MEMORY_MANAGER_ALLOCATION
25
26XERCES_CPP_NAMESPACE_BEGIN
27
28template <typename Char, int BasePoolSize, bool NullTerminated = 1>
29class StringPool
30{
31public:
32                StringPool(MemoryManager* const manager);
33
34                ~StringPool();
35
36                const Char * insert
37                (
38                        const Char * data
39                        , const size_t size
40                );
41
42                Char * allocate(size_t size);
43
44                void flushAll();
45
46                inline size_t available() const { return fSpaceAvail; }
47
48private:
49
50                void extend(const size_t minimumSize);
51
52private:
53
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 == 0 ? 0 : BasePoolSize + MEMORY_NODE_PADDING];
65                };
66
67                MemoryNode                            fStackMemory;
68                MemoryNode                          * fCurrentPool;
69                size_t                                fTotalSize;
70                Char                                                            * fInsertionPtr;
71                size_t                                fSpaceAvail;
72        size_t                                fMinAdditionalCapacity;
73        #ifdef USE_MEMORY_MANAGER_ALLOCATION
74                MemoryManager                       * fMemoryManager;
75        #endif
76};
77
78template <typename Char, int BasePoolSize, bool NullTerminated>
79StringPool<Char, BasePoolSize, NullTerminated>::
80StringPool(MemoryManager* const manager)
81: fTotalSize(BasePoolSize)
82, fSpaceAvail(BasePoolSize)
83, fCurrentPool(&fStackMemory)
84, fMinAdditionalCapacity(BasePoolSize == 0 ? 1024 : BasePoolSize)
85#ifdef USE_MEMORY_MANAGER_ALLOCATION
86, fMemoryManager(manager)
87#endif
88{
89        fStackMemory.fNextPool = NULL;
90        fStackMemory.fSize = BasePoolSize;
91        fInsertionPtr = fStackMemory.fMemory;
92}
93
94template <typename Char, int BasePoolSize, bool NullTerminated>
95StringPool<Char, BasePoolSize, NullTerminated>::
96~StringPool()
97{
98        flushAll();
99}
100
101template <typename Char, int BasePoolSize, bool NullTerminated>
102void
103StringPool<Char, BasePoolSize, NullTerminated>::
104flushAll()
105{
106    MemoryNode * node = fCurrentPool;
107
108    while (node != &fStackMemory)
109    {
110        MemoryNode * next = node->fNextPool;
111        #ifdef USE_MEMORY_MANAGER_ALLOCATION
112        fMemoryManager->deallocate(node);
113        #else
114        Array<Char>::deallocate((Char*)node);
115        #endif
116        node = next;
117    }
118
119    fStackMemory.fNextPool = NULL;
120    fStackMemory.fSize = BasePoolSize;
121    fTotalSize = BasePoolSize;
122    fInsertionPtr = fStackMemory.fMemory;
123    fSpaceAvail = BasePoolSize;
124    fCurrentPool = &fStackMemory;
125}
126
127template <typename Char, int BasePoolSize, bool NullTerminated>
128IDISA_ALWAYS_INLINE
129const Char *
130StringPool<Char, BasePoolSize, NullTerminated>::
131insert(const Char * string, const size_t length)
132{
133    Char * retVal = allocate(length + NullTerminated);
134    Array<Char>::move(string, retVal, length);
135    if (NullTerminated)
136    {
137        retVal[length] = 0;
138    }
139    return retVal;
140}
141
142template <typename Char, int BasePoolSize, bool NullTerminated>
143IDISA_ALWAYS_INLINE
144Char *
145StringPool<Char, BasePoolSize, NullTerminated>::
146allocate(size_t length)
147{
148    if (unlikely(length >= fSpaceAvail))
149    {
150        // look back through the allocated pools to see if there is room in any of
151        // them? or would that just slow the hardware memory prediction down?
152
153        extend(length);
154    }
155
156    Char * retVal = fInsertionPtr;
157    fInsertionPtr += length;
158    fSpaceAvail -= length;
159
160    return retVal;
161}
162
163template <typename Char, int BasePoolSize, bool NullTerminated>
164void
165StringPool<Char, BasePoolSize, NullTerminated>::
166extend(const size_t minimumSize)
167{
168    const size_t additionalCapacity = max(minimumSize * 2, fMinAdditionalCapacity);
169
170
171    DEBUG_MESSAGE("additionalCapacity=" << additionalCapacity)
172
173    MemoryNode * node = (MemoryNode *)
174    #ifdef USE_MEMORY_MANAGER_ALLOCATION
175        fMemoryManager->allocate((additionalCapacity + MEMORY_NODE_PADDING) * sizeof(Char));
176    #else
177        Array<Char>::allocate(additionalCapacity + MEMORY_NODE_PADDING);
178    #endif
179
180        node->fNextPool = fCurrentPool;
181        node->fSize = additionalCapacity;
182        fTotalSize += additionalCapacity;
183        fCurrentPool = node;
184        fInsertionPtr = node->fMemory;
185        fSpaceAvail = additionalCapacity;
186    fMinAdditionalCapacity = fTotalSize;
187}
188
189XERCES_CPP_NAMESPACE_END
190
191#endif
Note: See TracBrowser for help on using the repository browser.