/src/xerces-c/src/xercesc/internal/ElemStack.cpp
Line | Count | Source (jump to first uncovered 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: ElemStack.cpp 830538 2009-10-28 13:41:11Z amassari $ |
20 | | */ |
21 | | |
22 | | // --------------------------------------------------------------------------- |
23 | | // Includes |
24 | | // --------------------------------------------------------------------------- |
25 | | #include <string.h> |
26 | | #include <xercesc/util/EmptyStackException.hpp> |
27 | | #include <xercesc/util/NoSuchElementException.hpp> |
28 | | #include <xercesc/framework/XMLElementDecl.hpp> |
29 | | #include <xercesc/internal/ElemStack.hpp> |
30 | | #include <xercesc/validators/common/Grammar.hpp> |
31 | | |
32 | | XERCES_CPP_NAMESPACE_BEGIN |
33 | | |
34 | | // --------------------------------------------------------------------------- |
35 | | // ElemStack: Constructors and Destructor |
36 | | // --------------------------------------------------------------------------- |
37 | | ElemStack::ElemStack(MemoryManager* const manager) : |
38 | | |
39 | | fEmptyNamespaceId(0) |
40 | | , fGlobalPoolId(0) |
41 | | , fPrefixPool(109, manager) |
42 | | , fGlobalNamespaces(0) |
43 | | , fStack(0) |
44 | | , fStackCapacity(32) |
45 | | , fStackTop(0) |
46 | | , fUnknownNamespaceId(0) |
47 | | , fXMLNamespaceId(0) |
48 | | , fXMLPoolId(0) |
49 | | , fXMLNSNamespaceId(0) |
50 | | , fXMLNSPoolId(0) |
51 | | , fNamespaceMap(0) |
52 | | , fMemoryManager(manager) |
53 | 11.0k | { |
54 | | // Do an initial allocation of the stack and zero it out |
55 | 11.0k | fStack = (StackElem**) fMemoryManager->allocate |
56 | 11.0k | ( |
57 | 11.0k | fStackCapacity * sizeof(StackElem*) |
58 | 11.0k | );//new StackElem*[fStackCapacity]; |
59 | 11.0k | memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); |
60 | | |
61 | 11.0k | fNamespaceMap = new (fMemoryManager) ValueVectorOf<PrefMapElem*>(16, fMemoryManager); |
62 | 11.0k | } |
63 | | |
64 | | ElemStack::~ElemStack() |
65 | 11.0k | { |
66 | 11.0k | if(fGlobalNamespaces) |
67 | 0 | { |
68 | 0 | fMemoryManager->deallocate(fGlobalNamespaces->fMap); |
69 | 0 | delete fGlobalNamespaces; |
70 | 0 | } |
71 | | |
72 | | // |
73 | | // Start working from the bottom of the stack and clear it out as we |
74 | | // go up. Once we hit an uninitialized one, we can break out. |
75 | | // |
76 | 17.1M | for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++) |
77 | 17.1M | { |
78 | | // If this entry has been set, then lets clean it up |
79 | 17.1M | if (!fStack[stackInd]) |
80 | 11.0k | break; |
81 | | |
82 | 17.1M | fMemoryManager->deallocate(fStack[stackInd]->fChildren);//delete [] fStack[stackInd]->fChildren; |
83 | 17.1M | fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap; |
84 | 17.1M | fMemoryManager->deallocate(fStack[stackInd]->fSchemaElemName); |
85 | 17.1M | delete fStack[stackInd]; |
86 | 17.1M | } |
87 | | |
88 | | // Delete the stack array itself now |
89 | 11.0k | fMemoryManager->deallocate(fStack);//delete [] fStack; |
90 | 11.0k | delete fNamespaceMap; |
91 | 11.0k | } |
92 | | |
93 | | |
94 | | // --------------------------------------------------------------------------- |
95 | | // ElemStack: Stack access |
96 | | // --------------------------------------------------------------------------- |
97 | | XMLSize_t ElemStack::addLevel() |
98 | 0 | { |
99 | | // See if we need to expand the stack |
100 | 0 | if (fStackTop == fStackCapacity) |
101 | 0 | expandStack(); |
102 | | |
103 | | // If this element has not been initialized yet, then initialize it |
104 | 0 | if (!fStack[fStackTop]) |
105 | 0 | { |
106 | 0 | fStack[fStackTop] = new (fMemoryManager) StackElem; |
107 | 0 | fStack[fStackTop]->fChildCapacity = 0; |
108 | 0 | fStack[fStackTop]->fChildren = 0; |
109 | 0 | fStack[fStackTop]->fMapCapacity = 0; |
110 | 0 | fStack[fStackTop]->fMap = 0; |
111 | 0 | fStack[fStackTop]->fSchemaElemName = 0; |
112 | 0 | fStack[fStackTop]->fSchemaElemNameMaxLen = 0; |
113 | 0 | } |
114 | | |
115 | | // Set up the new top row |
116 | 0 | fStack[fStackTop]->fThisElement = 0; |
117 | 0 | fStack[fStackTop]->fReaderNum = 0xFFFFFFFF; |
118 | 0 | fStack[fStackTop]->fChildCount = 0; |
119 | 0 | fStack[fStackTop]->fMapCount = 0; |
120 | 0 | fStack[fStackTop]->fValidationFlag = false; |
121 | 0 | fStack[fStackTop]->fCommentOrPISeen = false; |
122 | 0 | fStack[fStackTop]->fReferenceEscaped = false; |
123 | 0 | fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; |
124 | 0 | fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; |
125 | 0 | fStack[fStackTop]->fCurrentGrammar = 0; |
126 | | |
127 | | // Bump the top of stack |
128 | 0 | fStackTop++; |
129 | |
|
130 | 0 | return fStackTop-1; |
131 | 0 | } |
132 | | |
133 | | |
134 | | XMLSize_t ElemStack::addLevel(XMLElementDecl* const toSet, const XMLSize_t readerNum) |
135 | 19.7M | { |
136 | | // See if we need to expand the stack |
137 | 19.7M | if (fStackTop == fStackCapacity) |
138 | 3.50k | expandStack(); |
139 | | |
140 | | // If this element has not been initialized yet, then initialize it |
141 | 19.7M | if (!fStack[fStackTop]) |
142 | 17.1M | { |
143 | 17.1M | fStack[fStackTop] = new (fMemoryManager) StackElem; |
144 | 17.1M | fStack[fStackTop]->fChildCapacity = 0; |
145 | 17.1M | fStack[fStackTop]->fChildren = 0; |
146 | 17.1M | fStack[fStackTop]->fMapCapacity = 0; |
147 | 17.1M | fStack[fStackTop]->fMap = 0; |
148 | 17.1M | fStack[fStackTop]->fSchemaElemName = 0; |
149 | 17.1M | fStack[fStackTop]->fSchemaElemNameMaxLen = 0; |
150 | 17.1M | } |
151 | | |
152 | | // Set up the new top row |
153 | 19.7M | fStack[fStackTop]->fThisElement = toSet; |
154 | 19.7M | fStack[fStackTop]->fReaderNum = readerNum; |
155 | 19.7M | fStack[fStackTop]->fChildCount = 0; |
156 | 19.7M | fStack[fStackTop]->fMapCount = 0; |
157 | 19.7M | fStack[fStackTop]->fValidationFlag = false; |
158 | 19.7M | fStack[fStackTop]->fCommentOrPISeen = false; |
159 | 19.7M | fStack[fStackTop]->fReferenceEscaped = false; |
160 | 19.7M | fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; |
161 | 19.7M | fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; |
162 | 19.7M | fStack[fStackTop]->fCurrentGrammar = 0; |
163 | | |
164 | | // Bump the top of stack |
165 | 19.7M | fStackTop++; |
166 | | |
167 | 19.7M | return fStackTop-1; |
168 | 19.7M | } |
169 | | |
170 | | |
171 | | |
172 | | const ElemStack::StackElem* ElemStack::popTop() |
173 | 2.61M | { |
174 | | // Watch for an underflow error |
175 | 2.61M | if (!fStackTop) |
176 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); |
177 | | |
178 | 2.61M | fStackTop--; |
179 | 2.61M | return fStack[fStackTop]; |
180 | 2.61M | } |
181 | | |
182 | | |
183 | | void |
184 | | ElemStack::setElement(XMLElementDecl* const toSet, const XMLSize_t readerNum) |
185 | 0 | { |
186 | 0 | if (!fStackTop) |
187 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
188 | | |
189 | 0 | fStack[fStackTop - 1]->fThisElement = toSet; |
190 | 0 | fStack[fStackTop - 1]->fReaderNum = readerNum; |
191 | 0 | } |
192 | | |
193 | | |
194 | | // --------------------------------------------------------------------------- |
195 | | // ElemStack: Stack top access |
196 | | // --------------------------------------------------------------------------- |
197 | | XMLSize_t ElemStack::addChild(QName* const child, const bool toParent) |
198 | 19.7M | { |
199 | 19.7M | if (!fStackTop) |
200 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
201 | | |
202 | | // |
203 | | // If they want to add to the parent, then we have to have at least two |
204 | | // elements on the stack. |
205 | | // |
206 | 19.7M | if (toParent && (fStackTop < 2)) |
207 | 0 | ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::ElemStack_NoParentPushed, fMemoryManager); |
208 | | |
209 | | // Get a convenience pointer to the stack top row |
210 | 19.7M | StackElem* curRow = toParent |
211 | 19.7M | ? fStack[fStackTop - 2] : fStack[fStackTop - 1]; |
212 | | |
213 | | // See if we need to expand this row's child array |
214 | 19.7M | if (curRow->fChildCount == curRow->fChildCapacity) |
215 | 17.1M | { |
216 | | // Increase the capacity by a quarter and allocate a new row |
217 | 17.1M | const XMLSize_t newCapacity = curRow->fChildCapacity ? |
218 | 11.7k | (XMLSize_t)(curRow->fChildCapacity * 1.25) : |
219 | 17.1M | 32; |
220 | 17.1M | QName** newRow = (QName**) fMemoryManager->allocate |
221 | 17.1M | ( |
222 | 17.1M | newCapacity * sizeof(QName*) |
223 | 17.1M | );//new QName*[newCapacity]; |
224 | | |
225 | | // |
226 | | // Copy over the old contents. We don't have to initialize the new |
227 | | // part because The current child count is used to know how much of |
228 | | // it is valid. |
229 | | // |
230 | | // Only both doing this if there is any current content, since |
231 | | // this code also does the initial faulting in of the array when |
232 | | // both the current capacity and child count are zero. |
233 | | // |
234 | 17.8M | for (XMLSize_t index = 0; index < curRow->fChildCount; index++) |
235 | 710k | newRow[index] = curRow->fChildren[index]; |
236 | | |
237 | | // Clean up the old children and store the new info |
238 | 17.1M | fMemoryManager->deallocate(curRow->fChildren);//delete [] curRow->fChildren; |
239 | 17.1M | curRow->fChildren = newRow; |
240 | 17.1M | curRow->fChildCapacity = newCapacity; |
241 | 17.1M | } |
242 | | |
243 | | // Add this id to the end of the row's child id array and bump the count |
244 | 19.7M | curRow->fChildren[curRow->fChildCount++] = child; |
245 | | |
246 | | // Return the level of the index we just filled (before the bump) |
247 | 19.7M | return curRow->fChildCount - 1; |
248 | 19.7M | } |
249 | | |
250 | | const ElemStack::StackElem* ElemStack::topElement() const |
251 | 6.85M | { |
252 | 6.85M | if (!fStackTop) |
253 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
254 | | |
255 | 6.85M | return fStack[fStackTop - 1]; |
256 | 6.85M | } |
257 | | |
258 | | |
259 | | // --------------------------------------------------------------------------- |
260 | | // ElemStack: Prefix map methods |
261 | | // --------------------------------------------------------------------------- |
262 | | void ElemStack::addGlobalPrefix(const XMLCh* const prefixToAdd |
263 | | , const unsigned int uriId) |
264 | 0 | { |
265 | 0 | if (!fGlobalNamespaces) |
266 | 0 | { |
267 | 0 | fGlobalNamespaces = new (fMemoryManager) StackElem; |
268 | 0 | fGlobalNamespaces->fChildCapacity = 0; |
269 | 0 | fGlobalNamespaces->fChildren = 0; |
270 | 0 | fGlobalNamespaces->fMapCapacity = 0; |
271 | 0 | fGlobalNamespaces->fMap = 0; |
272 | 0 | fGlobalNamespaces->fMapCount = 0; |
273 | 0 | fGlobalNamespaces->fSchemaElemName = 0; |
274 | 0 | fGlobalNamespaces->fSchemaElemNameMaxLen = 0; |
275 | 0 | fGlobalNamespaces->fThisElement = 0; |
276 | 0 | fGlobalNamespaces->fReaderNum = 0xFFFFFFFF; |
277 | 0 | fGlobalNamespaces->fChildCount = 0; |
278 | 0 | fGlobalNamespaces->fValidationFlag = false; |
279 | 0 | fGlobalNamespaces->fCommentOrPISeen = false; |
280 | 0 | fGlobalNamespaces->fReferenceEscaped = false; |
281 | 0 | fGlobalNamespaces->fCurrentURI = fUnknownNamespaceId; |
282 | 0 | fGlobalNamespaces->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; |
283 | 0 | fGlobalNamespaces->fCurrentGrammar = 0; |
284 | 0 | } |
285 | | |
286 | | // Map the prefix to its unique id |
287 | 0 | const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); |
288 | | |
289 | | // |
290 | | // Add a new element to the prefix map for this element. If its full, |
291 | | // then expand it out. |
292 | | // |
293 | 0 | if (fGlobalNamespaces->fMapCount == fGlobalNamespaces->fMapCapacity) |
294 | 0 | expandMap(fGlobalNamespaces); |
295 | | |
296 | | // |
297 | | // And now add a new element for this prefix. Watch for the special case |
298 | | // of xmlns=="", and force it to ""=[globalid] |
299 | | // |
300 | 0 | fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fPrefId = prefId; |
301 | 0 | if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) |
302 | 0 | fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = fEmptyNamespaceId; |
303 | 0 | else |
304 | 0 | fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = uriId; |
305 | | |
306 | | // Bump the map count now |
307 | 0 | fGlobalNamespaces->fMapCount++; |
308 | 0 | } |
309 | | |
310 | | void ElemStack::addPrefix( const XMLCh* const prefixToAdd |
311 | | , const unsigned int uriId) |
312 | 0 | { |
313 | 0 | if (!fStackTop) |
314 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
315 | | |
316 | | // Get a convenience pointer to the stack top row |
317 | 0 | StackElem* curRow = fStack[fStackTop - 1]; |
318 | | |
319 | | // Map the prefix to its unique id |
320 | 0 | const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); |
321 | | |
322 | | // |
323 | | // Add a new element to the prefix map for this element. If its full, |
324 | | // then expand it out. |
325 | | // |
326 | 0 | if (curRow->fMapCount == curRow->fMapCapacity) |
327 | 0 | expandMap(curRow); |
328 | | |
329 | | // |
330 | | // And now add a new element for this prefix. Watch for the special case |
331 | | // of xmlns=="", and force it to ""=[globalid] |
332 | | // |
333 | 0 | curRow->fMap[curRow->fMapCount].fPrefId = prefId; |
334 | 0 | if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) |
335 | 0 | curRow->fMap[curRow->fMapCount].fURIId = fEmptyNamespaceId; |
336 | 0 | else |
337 | 0 | curRow->fMap[curRow->fMapCount].fURIId = uriId; |
338 | | |
339 | | // Bump the map count now |
340 | 0 | curRow->fMapCount++; |
341 | 0 | } |
342 | | |
343 | | |
344 | | unsigned int ElemStack::mapPrefixToURI( const XMLCh* const prefixToMap |
345 | | , bool& unknown) const |
346 | 0 | { |
347 | | // Assume we find it |
348 | 0 | unknown = false; |
349 | | |
350 | | // |
351 | | // Map the prefix to its unique id, from the prefix string pool. If its |
352 | | // not a valid prefix, then its a failure. |
353 | | // |
354 | 0 | unsigned int prefixId = (!prefixToMap || !*prefixToMap)?fGlobalPoolId : fPrefixPool.getId(prefixToMap); |
355 | 0 | if (prefixId == 0) |
356 | 0 | { |
357 | 0 | unknown = true; |
358 | 0 | return fUnknownNamespaceId; |
359 | 0 | } |
360 | | // |
361 | | // Check for the special prefixes 'xml' and 'xmlns' since they cannot |
362 | | // be overridden. |
363 | | // |
364 | 0 | else if (prefixId == fXMLPoolId) |
365 | 0 | return fXMLNamespaceId; |
366 | 0 | else if (prefixId == fXMLNSPoolId) |
367 | 0 | return fXMLNSNamespaceId; |
368 | | |
369 | | // |
370 | | // Start at the stack top and work backwards until we come to some |
371 | | // element that mapped this prefix. |
372 | | // |
373 | 0 | for (XMLSize_t index = fStackTop; index > 0; index--) |
374 | 0 | { |
375 | | // Get a convenience pointer to the current element |
376 | 0 | StackElem* curRow = fStack[index-1]; |
377 | | |
378 | | // Search the map at this level for the passed prefix |
379 | 0 | for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) |
380 | 0 | { |
381 | 0 | if (curRow->fMap[mapIndex].fPrefId == prefixId) |
382 | 0 | return curRow->fMap[mapIndex].fURIId; |
383 | 0 | } |
384 | 0 | } |
385 | | // If the prefix wasn't found, try in the global namespaces |
386 | 0 | if(fGlobalNamespaces) |
387 | 0 | { |
388 | 0 | for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++) |
389 | 0 | { |
390 | 0 | if (fGlobalNamespaces->fMap[mapIndex].fPrefId == prefixId) |
391 | 0 | return fGlobalNamespaces->fMap[mapIndex].fURIId; |
392 | 0 | } |
393 | 0 | } |
394 | | |
395 | | // |
396 | | // If the prefix is an empty string, then we will return the special |
397 | | // global namespace id. This can be overridden, but no one has or we |
398 | | // would have not gotten here. |
399 | | // |
400 | 0 | if (!*prefixToMap) |
401 | 0 | return fEmptyNamespaceId; |
402 | | |
403 | | // Oh well, don't have a clue so return the unknown id |
404 | 0 | unknown = true; |
405 | 0 | return fUnknownNamespaceId; |
406 | 0 | } |
407 | | |
408 | | |
409 | | ValueVectorOf<PrefMapElem*>* ElemStack::getNamespaceMap() const |
410 | 0 | { |
411 | 0 | fNamespaceMap->removeAllElements(); |
412 | | |
413 | | // Start at the stack top and work backwards until we come to some |
414 | | // element that mapped this prefix. |
415 | 0 | for (XMLSize_t index = fStackTop; index > 0; index--) |
416 | 0 | { |
417 | | // Get a convenience pointer to the current element |
418 | 0 | StackElem* curRow = fStack[index-1]; |
419 | | |
420 | | // If no prefixes mapped at this level, then go the next one |
421 | 0 | if (!curRow->fMapCount) |
422 | 0 | continue; |
423 | | |
424 | | // Search the map at this level for the passed prefix |
425 | 0 | for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) |
426 | 0 | fNamespaceMap->addElement(&(curRow->fMap[mapIndex])); |
427 | 0 | } |
428 | | // Add the global namespaces |
429 | 0 | if(fGlobalNamespaces) |
430 | 0 | { |
431 | 0 | for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++) |
432 | 0 | fNamespaceMap->addElement(&(fGlobalNamespaces->fMap[mapIndex])); |
433 | 0 | } |
434 | |
|
435 | 0 | return fNamespaceMap; |
436 | 0 | } |
437 | | |
438 | | // --------------------------------------------------------------------------- |
439 | | // ElemStack: Miscellaneous methods |
440 | | // --------------------------------------------------------------------------- |
441 | | void ElemStack::reset( const unsigned int emptyId |
442 | | , const unsigned int unknownId |
443 | | , const unsigned int xmlId |
444 | | , const unsigned int xmlNSId) |
445 | 11.0k | { |
446 | 11.0k | if(fGlobalNamespaces) |
447 | 0 | { |
448 | 0 | fMemoryManager->deallocate(fGlobalNamespaces->fMap); |
449 | 0 | delete fGlobalNamespaces; |
450 | 0 | fGlobalNamespaces = 0; |
451 | 0 | } |
452 | | |
453 | | // Reset the stack top to clear the stack |
454 | 11.0k | fStackTop = 0; |
455 | | |
456 | | // if first time, put in the standard prefixes |
457 | 11.0k | if (fXMLPoolId == 0) { |
458 | | |
459 | 11.0k | fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString); |
460 | 11.0k | fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString); |
461 | 11.0k | fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString); |
462 | 11.0k | } |
463 | | |
464 | | // And store the new special URI ids |
465 | 11.0k | fEmptyNamespaceId = emptyId; |
466 | 11.0k | fUnknownNamespaceId = unknownId; |
467 | 11.0k | fXMLNamespaceId = xmlId; |
468 | 11.0k | fXMLNSNamespaceId = xmlNSId; |
469 | 11.0k | } |
470 | | |
471 | | |
472 | | // --------------------------------------------------------------------------- |
473 | | // ElemStack: Private helpers |
474 | | // --------------------------------------------------------------------------- |
475 | | void ElemStack::expandMap(StackElem* const toExpand) |
476 | 0 | { |
477 | | // For convenience get the old map size |
478 | 0 | const XMLSize_t oldCap = toExpand->fMapCapacity; |
479 | | |
480 | | // |
481 | | // Expand the capacity by 25%, or initialize it to 16 if its currently |
482 | | // empty. Then allocate a new temp buffer. |
483 | | // |
484 | 0 | const XMLSize_t newCapacity = oldCap ? |
485 | 0 | (XMLSize_t )(oldCap * 1.25) : 16; |
486 | 0 | PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate |
487 | 0 | ( |
488 | 0 | newCapacity * sizeof(PrefMapElem) |
489 | 0 | );//new PrefMapElem[newCapacity]; |
490 | | |
491 | | // |
492 | | // Copy over the old stuff. We DON'T have to zero out the new stuff |
493 | | // since this is a by value map and the current map index controls what |
494 | | // is relevant. |
495 | | // |
496 | 0 | memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem)); |
497 | | |
498 | | // Delete the old map and store the new stuff |
499 | 0 | fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap; |
500 | 0 | toExpand->fMap = newMap; |
501 | 0 | toExpand->fMapCapacity = newCapacity; |
502 | 0 | } |
503 | | |
504 | | void ElemStack::expandStack() |
505 | 3.50k | { |
506 | | // Expand the capacity by 25% and allocate a new buffer |
507 | 3.50k | const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25); |
508 | 3.50k | StackElem** newStack = (StackElem**) fMemoryManager->allocate |
509 | 3.50k | ( |
510 | 3.50k | newCapacity * sizeof(StackElem*) |
511 | 3.50k | );//new StackElem*[newCapacity]; |
512 | | |
513 | | // Copy over the old stuff |
514 | 3.50k | memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); |
515 | | |
516 | | // |
517 | | // And zero out the new stuff. Though we use a stack top, we reuse old |
518 | | // stack contents so we need to know if elements have been initially |
519 | | // allocated or not as we push new stuff onto the stack. |
520 | | // |
521 | 3.50k | memset |
522 | 3.50k | ( |
523 | 3.50k | &newStack[fStackCapacity] |
524 | 3.50k | , 0 |
525 | 3.50k | , (newCapacity - fStackCapacity) * sizeof(StackElem*) |
526 | 3.50k | ); |
527 | | |
528 | | // Delete the old array and update our members |
529 | 3.50k | fMemoryManager->deallocate(fStack);//delete [] fStack; |
530 | 3.50k | fStack = newStack; |
531 | 3.50k | fStackCapacity = newCapacity; |
532 | 3.50k | } |
533 | | |
534 | | |
535 | | |
536 | | // --------------------------------------------------------------------------- |
537 | | // WFElemStack: Constructors and Destructor |
538 | | // --------------------------------------------------------------------------- |
539 | | WFElemStack::WFElemStack(MemoryManager* const manager) : |
540 | | |
541 | | fEmptyNamespaceId(0) |
542 | | , fGlobalPoolId(0) |
543 | | , fStackCapacity(32) |
544 | | , fStackTop(0) |
545 | | , fUnknownNamespaceId(0) |
546 | | , fXMLNamespaceId(0) |
547 | | , fXMLPoolId(0) |
548 | | , fXMLNSNamespaceId(0) |
549 | | , fXMLNSPoolId(0) |
550 | | , fMapCapacity(0) |
551 | | , fMap(0) |
552 | | , fStack(0) |
553 | | , fPrefixPool(109, manager) |
554 | | , fMemoryManager(manager) |
555 | 0 | { |
556 | | // Do an initial allocation of the stack and zero it out |
557 | 0 | fStack = (StackElem**) fMemoryManager->allocate |
558 | 0 | ( |
559 | 0 | fStackCapacity * sizeof(StackElem*) |
560 | 0 | );//new StackElem*[fStackCapacity]; |
561 | 0 | memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); |
562 | 0 | } |
563 | | |
564 | | WFElemStack::~WFElemStack() |
565 | 0 | { |
566 | | // |
567 | | // Start working from the bottom of the stack and clear it out as we |
568 | | // go up. Once we hit an uninitialized one, we can break out. |
569 | | // |
570 | 0 | for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++) |
571 | 0 | { |
572 | | // If this entry has been set, then lets clean it up |
573 | 0 | if (!fStack[stackInd]) |
574 | 0 | break; |
575 | | |
576 | 0 | fMemoryManager->deallocate(fStack[stackInd]->fThisElement);//delete [] fStack[stackInd]->fThisElement; |
577 | 0 | delete fStack[stackInd]; |
578 | 0 | } |
579 | |
|
580 | 0 | if (fMap) |
581 | 0 | fMemoryManager->deallocate(fMap);//delete [] fMap; |
582 | | |
583 | | // Delete the stack array itself now |
584 | 0 | fMemoryManager->deallocate(fStack);//delete [] fStack; |
585 | 0 | } |
586 | | |
587 | | |
588 | | // --------------------------------------------------------------------------- |
589 | | // WFElemStack: Stack access |
590 | | // --------------------------------------------------------------------------- |
591 | | XMLSize_t WFElemStack::addLevel() |
592 | 0 | { |
593 | | // See if we need to expand the stack |
594 | 0 | if (fStackTop == fStackCapacity) |
595 | 0 | expandStack(); |
596 | | |
597 | | |
598 | | // If this element has not been initialized yet, then initialize it |
599 | 0 | if (!fStack[fStackTop]) |
600 | 0 | { |
601 | 0 | fStack[fStackTop] = new (fMemoryManager) StackElem; |
602 | 0 | fStack[fStackTop]->fThisElement = 0; |
603 | 0 | fStack[fStackTop]->fElemMaxLength = 0; |
604 | 0 | } |
605 | | |
606 | | // Set up the new top row |
607 | 0 | fStack[fStackTop]->fReaderNum = 0xFFFFFFFF; |
608 | 0 | fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; |
609 | 0 | fStack[fStackTop]->fTopPrefix = -1; |
610 | |
|
611 | 0 | if (fStackTop != 0) |
612 | 0 | fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix; |
613 | | |
614 | | // Bump the top of stack |
615 | 0 | fStackTop++; |
616 | |
|
617 | 0 | return fStackTop-1; |
618 | 0 | } |
619 | | |
620 | | |
621 | | XMLSize_t |
622 | | WFElemStack::addLevel(const XMLCh* const toSet, |
623 | | const unsigned int toSetLen, |
624 | | const unsigned int readerNum) |
625 | 0 | { |
626 | | // See if we need to expand the stack |
627 | 0 | if (fStackTop == fStackCapacity) |
628 | 0 | expandStack(); |
629 | | |
630 | | // If this element has not been initialized yet, then initialize it |
631 | 0 | if (!fStack[fStackTop]) |
632 | 0 | { |
633 | 0 | fStack[fStackTop] = new (fMemoryManager) StackElem; |
634 | 0 | fStack[fStackTop]->fThisElement = 0; |
635 | 0 | fStack[fStackTop]->fElemMaxLength = 0; |
636 | 0 | } |
637 | | |
638 | | // Set up the new top row |
639 | 0 | fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; |
640 | 0 | fStack[fStackTop]->fTopPrefix = -1; |
641 | | |
642 | | // And store the new stuff |
643 | 0 | if (toSetLen > fStack[fStackTop]->fElemMaxLength) { |
644 | |
|
645 | 0 | fMemoryManager->deallocate(fStack[fStackTop]->fThisElement);//delete [] fStack[fStackTop]->fThisElement; |
646 | 0 | fStack[fStackTop]->fElemMaxLength = toSetLen; |
647 | 0 | fStack[fStackTop]->fThisElement = (XMLCh*) fMemoryManager->allocate |
648 | 0 | ( |
649 | 0 | (toSetLen + 1) * sizeof(XMLCh) |
650 | 0 | );//new XMLCh[toSetLen + 1]; |
651 | 0 | } |
652 | |
|
653 | 0 | XMLString::moveChars(fStack[fStackTop]->fThisElement, toSet, toSetLen + 1); |
654 | 0 | fStack[fStackTop]->fReaderNum = readerNum; |
655 | |
|
656 | 0 | if (fStackTop != 0) |
657 | 0 | fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix; |
658 | | |
659 | | // Bump the top of stack |
660 | 0 | fStackTop++; |
661 | |
|
662 | 0 | return fStackTop-1; |
663 | 0 | } |
664 | | |
665 | | |
666 | | |
667 | | const WFElemStack::StackElem* WFElemStack::popTop() |
668 | 0 | { |
669 | | // Watch for an underflow error |
670 | 0 | if (!fStackTop) |
671 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); |
672 | | |
673 | 0 | fStackTop--; |
674 | 0 | return fStack[fStackTop]; |
675 | 0 | } |
676 | | |
677 | | |
678 | | void |
679 | | WFElemStack::setElement(const XMLCh* const toSet, |
680 | | const unsigned int toSetLen, |
681 | | const unsigned int readerNum) |
682 | 0 | { |
683 | 0 | if (!fStackTop) |
684 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
685 | | |
686 | 0 | if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) { |
687 | |
|
688 | 0 | fMemoryManager->deallocate(fStack[fStackTop - 1]->fThisElement);//delete [] fStack[fStackTop - 1]->fThisElement; |
689 | 0 | fStack[fStackTop - 1]->fElemMaxLength = toSetLen; |
690 | 0 | fStack[fStackTop - 1]->fThisElement = (XMLCh*) fMemoryManager->allocate |
691 | 0 | ( |
692 | 0 | (toSetLen + 1) * sizeof(XMLCh) |
693 | 0 | );//new XMLCh[toSetLen + 1]; |
694 | 0 | } |
695 | |
|
696 | 0 | XMLString::moveChars(fStack[fStackTop - 1]->fThisElement, toSet, toSetLen + 1); |
697 | 0 | fStack[fStackTop - 1]->fReaderNum = readerNum; |
698 | 0 | } |
699 | | |
700 | | |
701 | | // --------------------------------------------------------------------------- |
702 | | // WFElemStack: Stack top access |
703 | | // --------------------------------------------------------------------------- |
704 | | const WFElemStack::StackElem* WFElemStack::topElement() const |
705 | 0 | { |
706 | 0 | if (!fStackTop) |
707 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
708 | | |
709 | 0 | return fStack[fStackTop - 1]; |
710 | 0 | } |
711 | | |
712 | | |
713 | | // --------------------------------------------------------------------------- |
714 | | // WFElemStack: Prefix map methods |
715 | | // --------------------------------------------------------------------------- |
716 | | void WFElemStack::addPrefix( const XMLCh* const prefixToAdd |
717 | | , const unsigned int uriId) |
718 | 0 | { |
719 | 0 | if (!fStackTop) |
720 | 0 | ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
721 | | |
722 | | // Get a convenience pointer to the stack top row |
723 | 0 | StackElem* curRow = fStack[fStackTop - 1]; |
724 | | |
725 | | // Map the prefix to its unique id |
726 | 0 | const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); |
727 | | |
728 | | // |
729 | | // Add a new element to the prefix map for this element. If its full, |
730 | | // then expand it out. |
731 | | // |
732 | 0 | if ((unsigned int)curRow->fTopPrefix + 1 == fMapCapacity) |
733 | 0 | expandMap(); |
734 | | |
735 | | // |
736 | | // And now add a new element for this prefix. Watch for the special case |
737 | | // of xmlns=="", and force it to ""=[globalid] |
738 | | // |
739 | 0 | fMap[curRow->fTopPrefix + 1].fPrefId = prefId; |
740 | 0 | if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) |
741 | 0 | fMap[curRow->fTopPrefix + 1].fURIId = fEmptyNamespaceId; |
742 | 0 | else |
743 | 0 | fMap[curRow->fTopPrefix + 1].fURIId = uriId; |
744 | | |
745 | | // Bump the map count now |
746 | 0 | curRow->fTopPrefix++; |
747 | 0 | } |
748 | | |
749 | | |
750 | | unsigned int WFElemStack::mapPrefixToURI( const XMLCh* const prefixToMap |
751 | | , bool& unknown) const |
752 | 0 | { |
753 | | // Assume we find it |
754 | 0 | unknown = false; |
755 | | |
756 | | // |
757 | | // Map the prefix to its unique id, from the prefix string pool. If its |
758 | | // not a valid prefix, then its a failure. |
759 | | // |
760 | 0 | unsigned int prefixId = fPrefixPool.getId(prefixToMap); |
761 | 0 | if (!prefixId) |
762 | 0 | { |
763 | 0 | unknown = true; |
764 | 0 | return fUnknownNamespaceId; |
765 | 0 | } |
766 | | |
767 | | // |
768 | | // Check for the special prefixes 'xml' and 'xmlns' since they cannot |
769 | | // be overridden. |
770 | | // |
771 | 0 | if (prefixId == fXMLPoolId) |
772 | 0 | return fXMLNamespaceId; |
773 | 0 | else if (prefixId == fXMLNSPoolId) |
774 | 0 | return fXMLNSNamespaceId; |
775 | | |
776 | | // |
777 | | // Start at the stack top and work backwards until we come to some |
778 | | // element that mapped this prefix. |
779 | | // |
780 | | // Get a convenience pointer to the stack top row |
781 | 0 | StackElem* curRow = fStack[fStackTop - 1]; |
782 | 0 | for (int mapIndex = curRow->fTopPrefix; mapIndex >=0; mapIndex--) |
783 | 0 | { |
784 | 0 | if (fMap[mapIndex].fPrefId == prefixId) |
785 | 0 | return fMap[mapIndex].fURIId; |
786 | 0 | } |
787 | | |
788 | | // |
789 | | // If the prefix is an empty string, then we will return the special |
790 | | // global namespace id. This can be overridden, but no one has or we |
791 | | // would have not gotten here. |
792 | | // |
793 | 0 | if (!*prefixToMap) |
794 | 0 | return fEmptyNamespaceId; |
795 | | |
796 | | // Oh well, don't have a clue so return the unknown id |
797 | 0 | unknown = true; |
798 | 0 | return fUnknownNamespaceId; |
799 | 0 | } |
800 | | |
801 | | |
802 | | // --------------------------------------------------------------------------- |
803 | | // WFElemStack: Miscellaneous methods |
804 | | // --------------------------------------------------------------------------- |
805 | | void WFElemStack::reset( const unsigned int emptyId |
806 | | , const unsigned int unknownId |
807 | | , const unsigned int xmlId |
808 | | , const unsigned int xmlNSId) |
809 | 0 | { |
810 | | // Reset the stack top to clear the stack |
811 | 0 | fStackTop = 0; |
812 | | |
813 | | // if first time, put in the standard prefixes |
814 | 0 | if (fXMLPoolId == 0) { |
815 | |
|
816 | 0 | fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString); |
817 | 0 | fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString); |
818 | 0 | fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString); |
819 | 0 | } |
820 | | |
821 | | // And store the new special URI ids |
822 | 0 | fEmptyNamespaceId = emptyId; |
823 | 0 | fUnknownNamespaceId = unknownId; |
824 | 0 | fXMLNamespaceId = xmlId; |
825 | 0 | fXMLNSNamespaceId = xmlNSId; |
826 | 0 | } |
827 | | |
828 | | |
829 | | // --------------------------------------------------------------------------- |
830 | | // WFElemStack: Private helpers |
831 | | // --------------------------------------------------------------------------- |
832 | | void WFElemStack::expandMap() |
833 | 0 | { |
834 | | // |
835 | | // Expand the capacity by 25%, or initialize it to 16 if its currently |
836 | | // empty. Then allocate a new temp buffer. |
837 | | // |
838 | 0 | const XMLSize_t newCapacity = fMapCapacity ? |
839 | 0 | (XMLSize_t)(fMapCapacity * 1.25) : 16; |
840 | 0 | PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate |
841 | 0 | ( |
842 | 0 | newCapacity * sizeof(PrefMapElem) |
843 | 0 | );//new PrefMapElem[newCapacity]; |
844 | | |
845 | | // |
846 | | // Copy over the old stuff. We DON'T have to zero out the new stuff |
847 | | // since this is a by value map and the current map index controls what |
848 | | // is relevant. |
849 | | // |
850 | 0 | if (fMapCapacity) { |
851 | |
|
852 | 0 | memcpy(newMap, fMap, fMapCapacity * sizeof(PrefMapElem)); |
853 | 0 | fMemoryManager->deallocate(fMap);//delete [] fMap; |
854 | 0 | } |
855 | |
|
856 | 0 | fMap = newMap; |
857 | 0 | fMapCapacity = newCapacity; |
858 | 0 | } |
859 | | |
860 | | void WFElemStack::expandStack() |
861 | 0 | { |
862 | | // Expand the capacity by 25% and allocate a new buffer |
863 | 0 | const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25); |
864 | 0 | StackElem** newStack = (StackElem**) fMemoryManager->allocate |
865 | 0 | ( |
866 | 0 | newCapacity * sizeof(StackElem*) |
867 | 0 | );//new StackElem*[newCapacity]; |
868 | | |
869 | | // Copy over the old stuff |
870 | 0 | memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); |
871 | | |
872 | | // |
873 | | // And zero out the new stuff. Though we use a stack top, we reuse old |
874 | | // stack contents so we need to know if elements have been initially |
875 | | // allocated or not as we push new stuff onto the stack. |
876 | | // |
877 | 0 | memset |
878 | 0 | ( |
879 | 0 | &newStack[fStackCapacity] |
880 | 0 | , 0 |
881 | 0 | , (newCapacity - fStackCapacity) * sizeof(StackElem*) |
882 | 0 | ); |
883 | | |
884 | | // Delete the old array and update our members |
885 | 0 | fMemoryManager->deallocate(fStack);//delete [] fStack; |
886 | 0 | fStack = newStack; |
887 | 0 | fStackCapacity = newCapacity; |
888 | 0 | } |
889 | | |
890 | | |
891 | | XERCES_CPP_NAMESPACE_END |