GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: ElemStack.cpp 830538 2009-10-28 13:41:11Z amassari $ 00020 */ 00021 00022 // --------------------------------------------------------------------------- 00023 // Includes 00024 // --------------------------------------------------------------------------- 00025 #include <string.h> 00026 #include <xercesc/util/EmptyStackException.hpp> 00027 #include <xercesc/util/NoSuchElementException.hpp> 00028 #include <xercesc/framework/XMLElementDecl.hpp> 00029 #include <xercesc/internal/ElemStack.hpp> 00030 #include <xercesc/validators/common/Grammar.hpp> 00031 00032 XERCES_CPP_NAMESPACE_BEGIN 00033 00034 // --------------------------------------------------------------------------- 00035 // ElemStack: Constructors and Destructor 00036 // --------------------------------------------------------------------------- 00037 ElemStack::ElemStack(MemoryManager* const manager) : 00038 00039 fEmptyNamespaceId(0) 00040 , fGlobalPoolId(0) 00041 , fPrefixPool(109, manager) 00042 , fGlobalNamespaces(0) 00043 , fStack(0) 00044 , fStackCapacity(32) 00045 , fStackTop(0) 00046 , fUnknownNamespaceId(0) 00047 , fXMLNamespaceId(0) 00048 , fXMLPoolId(0) 00049 , fXMLNSNamespaceId(0) 00050 , fXMLNSPoolId(0) 00051 , fNamespaceMap(0) 00052 , fMemoryManager(manager) 00053 { 00054 // Do an initial allocation of the stack and zero it out 00055 fStack = (StackElem**) fMemoryManager->allocate 00056 ( 00057 fStackCapacity * sizeof(StackElem*) 00058 );//new StackElem*[fStackCapacity]; 00059 memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); 00060 00061 fNamespaceMap = new (fMemoryManager) ValueVectorOf<PrefMapElem*>(16, fMemoryManager); 00062 } 00063 00064 ElemStack::~ElemStack() 00065 { 00066 if(fGlobalNamespaces) 00067 { 00068 fMemoryManager->deallocate(fGlobalNamespaces->fMap); 00069 delete fGlobalNamespaces; 00070 } 00071 00072 // 00073 // Start working from the bottom of the stack and clear it out as we 00074 // go up. Once we hit an uninitialized one, we can break out. 00075 // 00076 for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++) 00077 { 00078 // If this entry has been set, then lets clean it up 00079 if (!fStack[stackInd]) 00080 break; 00081 00082 fMemoryManager->deallocate(fStack[stackInd]->fChildren);//delete [] fStack[stackInd]->fChildren; 00083 fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap; 00084 fMemoryManager->deallocate(fStack[stackInd]->fSchemaElemName); 00085 delete fStack[stackInd]; 00086 } 00087 00088 // Delete the stack array itself now 00089 fMemoryManager->deallocate(fStack);//delete [] fStack; 00090 delete fNamespaceMap; 00091 } 00092 00093 00094 // --------------------------------------------------------------------------- 00095 // ElemStack: Stack access 00096 // --------------------------------------------------------------------------- 00097 XMLSize_t ElemStack::addLevel() 00098 { 00099 // See if we need to expand the stack 00100 if (fStackTop == fStackCapacity) 00101 expandStack(); 00102 00103 // If this element has not been initialized yet, then initialize it 00104 if (!fStack[fStackTop]) 00105 { 00106 fStack[fStackTop] = new (fMemoryManager) StackElem; 00107 fStack[fStackTop]->fChildCapacity = 0; 00108 fStack[fStackTop]->fChildren = 0; 00109 fStack[fStackTop]->fMapCapacity = 0; 00110 fStack[fStackTop]->fMap = 0; 00111 fStack[fStackTop]->fSchemaElemName = 0; 00112 fStack[fStackTop]->fSchemaElemNameMaxLen = 0; 00113 } 00114 00115 // Set up the new top row 00116 fStack[fStackTop]->fThisElement = 0; 00117 fStack[fStackTop]->fReaderNum = 0xFFFFFFFF; 00118 fStack[fStackTop]->fChildCount = 0; 00119 fStack[fStackTop]->fMapCount = 0; 00120 fStack[fStackTop]->fValidationFlag = false; 00121 fStack[fStackTop]->fCommentOrPISeen = false; 00122 fStack[fStackTop]->fReferenceEscaped = false; 00123 fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; 00124 fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; 00125 fStack[fStackTop]->fCurrentGrammar = 0; 00126 00127 // Bump the top of stack 00128 fStackTop++; 00129 00130 return fStackTop-1; 00131 } 00132 00133 00134 XMLSize_t ElemStack::addLevel(XMLElementDecl* const toSet, const XMLSize_t readerNum) 00135 { 00136 // See if we need to expand the stack 00137 if (fStackTop == fStackCapacity) 00138 expandStack(); 00139 00140 // If this element has not been initialized yet, then initialize it 00141 if (!fStack[fStackTop]) 00142 { 00143 fStack[fStackTop] = new (fMemoryManager) StackElem; 00144 fStack[fStackTop]->fChildCapacity = 0; 00145 fStack[fStackTop]->fChildren = 0; 00146 fStack[fStackTop]->fMapCapacity = 0; 00147 fStack[fStackTop]->fMap = 0; 00148 fStack[fStackTop]->fSchemaElemName = 0; 00149 fStack[fStackTop]->fSchemaElemNameMaxLen = 0; 00150 } 00151 00152 // Set up the new top row 00153 fStack[fStackTop]->fThisElement = toSet; 00154 fStack[fStackTop]->fReaderNum = readerNum; 00155 fStack[fStackTop]->fChildCount = 0; 00156 fStack[fStackTop]->fMapCount = 0; 00157 fStack[fStackTop]->fValidationFlag = false; 00158 fStack[fStackTop]->fCommentOrPISeen = false; 00159 fStack[fStackTop]->fReferenceEscaped = false; 00160 fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; 00161 fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; 00162 fStack[fStackTop]->fCurrentGrammar = 0; 00163 00164 // Bump the top of stack 00165 fStackTop++; 00166 00167 return fStackTop-1; 00168 } 00169 00170 00171 00172 const ElemStack::StackElem* ElemStack::popTop() 00173 { 00174 // Watch for an underflow error 00175 if (!fStackTop) 00176 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); 00177 00178 fStackTop--; 00179 return fStack[fStackTop]; 00180 } 00181 00182 00183 void 00184 ElemStack::setElement(XMLElementDecl* const toSet, const XMLSize_t readerNum) 00185 { 00186 if (!fStackTop) 00187 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); 00188 00189 fStack[fStackTop - 1]->fThisElement = toSet; 00190 fStack[fStackTop - 1]->fReaderNum = readerNum; 00191 } 00192 00193 00194 // --------------------------------------------------------------------------- 00195 // ElemStack: Stack top access 00196 // --------------------------------------------------------------------------- 00197 XMLSize_t ElemStack::addChild(QName* const child, const bool toParent) 00198 { 00199 if (!fStackTop) 00200 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); 00201 00202 // 00203 // If they want to add to the parent, then we have to have at least two 00204 // elements on the stack. 00205 // 00206 if (toParent && (fStackTop < 2)) 00207 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::ElemStack_NoParentPushed, fMemoryManager); 00208 00209 // Get a convenience pointer to the stack top row 00210 StackElem* curRow = toParent 00211 ? fStack[fStackTop - 2] : fStack[fStackTop - 1]; 00212 00213 // See if we need to expand this row's child array 00214 if (curRow->fChildCount == curRow->fChildCapacity) 00215 { 00216 // Increase the capacity by a quarter and allocate a new row 00217 const XMLSize_t newCapacity = curRow->fChildCapacity ? 00218 (XMLSize_t)(curRow->fChildCapacity * 1.25) : 00219 32; 00220 QName** newRow = (QName**) fMemoryManager->allocate 00221 ( 00222 newCapacity * sizeof(QName*) 00223 );//new QName*[newCapacity]; 00224 00225 // 00226 // Copy over the old contents. We don't have to initialize the new 00227 // part because The current child count is used to know how much of 00228 // it is valid. 00229 // 00230 // Only both doing this if there is any current content, since 00231 // this code also does the initial faulting in of the array when 00232 // both the current capacity and child count are zero. 00233 // 00234 for (XMLSize_t index = 0; index < curRow->fChildCount; index++) 00235 newRow[index] = curRow->fChildren[index]; 00236 00237 // Clean up the old children and store the new info 00238 fMemoryManager->deallocate(curRow->fChildren);//delete [] curRow->fChildren; 00239 curRow->fChildren = newRow; 00240 curRow->fChildCapacity = newCapacity; 00241 } 00242 00243 // Add this id to the end of the row's child id array and bump the count 00244 curRow->fChildren[curRow->fChildCount++] = child; 00245 00246 // Return the level of the index we just filled (before the bump) 00247 return curRow->fChildCount - 1; 00248 } 00249 00250 const ElemStack::StackElem* ElemStack::topElement() const 00251 { 00252 if (!fStackTop) 00253 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); 00254 00255 return fStack[fStackTop - 1]; 00256 } 00257 00258 00259 // --------------------------------------------------------------------------- 00260 // ElemStack: Prefix map methods 00261 // --------------------------------------------------------------------------- 00262 void ElemStack::addGlobalPrefix(const XMLCh* const prefixToAdd 00263 , const unsigned int uriId) 00264 { 00265 if (!fGlobalNamespaces) 00266 { 00267 fGlobalNamespaces = new (fMemoryManager) StackElem; 00268 fGlobalNamespaces->fChildCapacity = 0; 00269 fGlobalNamespaces->fChildren = 0; 00270 fGlobalNamespaces->fMapCapacity = 0; 00271 fGlobalNamespaces->fMap = 0; 00272 fGlobalNamespaces->fMapCount = 0; 00273 fGlobalNamespaces->fSchemaElemName = 0; 00274 fGlobalNamespaces->fSchemaElemNameMaxLen = 0; 00275 fGlobalNamespaces->fThisElement = 0; 00276 fGlobalNamespaces->fReaderNum = 0xFFFFFFFF; 00277 fGlobalNamespaces->fChildCount = 0; 00278 fGlobalNamespaces->fValidationFlag = false; 00279 fGlobalNamespaces->fCommentOrPISeen = false; 00280 fGlobalNamespaces->fReferenceEscaped = false; 00281 fGlobalNamespaces->fCurrentURI = fUnknownNamespaceId; 00282 fGlobalNamespaces->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; 00283 fGlobalNamespaces->fCurrentGrammar = 0; 00284 } 00285 00286 // Map the prefix to its unique id 00287 const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); 00288 00289 // 00290 // Add a new element to the prefix map for this element. If its full, 00291 // then expand it out. 00292 // 00293 if (fGlobalNamespaces->fMapCount == fGlobalNamespaces->fMapCapacity) 00294 expandMap(fGlobalNamespaces); 00295 00296 // 00297 // And now add a new element for this prefix. Watch for the special case 00298 // of xmlns=="", and force it to ""=[globalid] 00299 // 00300 fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fPrefId = prefId; 00301 if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) 00302 fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = fEmptyNamespaceId; 00303 else 00304 fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = uriId; 00305 00306 // Bump the map count now 00307 fGlobalNamespaces->fMapCount++; 00308 } 00309 00310 void ElemStack::addPrefix( const XMLCh* const prefixToAdd 00311 , const unsigned int uriId) 00312 { 00313 if (!fStackTop) 00314 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); 00315 00316 // Get a convenience pointer to the stack top row 00317 StackElem* curRow = fStack[fStackTop - 1]; 00318 00319 // Map the prefix to its unique id 00320 const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); 00321 00322 // 00323 // Add a new element to the prefix map for this element. If its full, 00324 // then expand it out. 00325 // 00326 if (curRow->fMapCount == curRow->fMapCapacity) 00327 expandMap(curRow); 00328 00329 // 00330 // And now add a new element for this prefix. Watch for the special case 00331 // of xmlns=="", and force it to ""=[globalid] 00332 // 00333 curRow->fMap[curRow->fMapCount].fPrefId = prefId; 00334 if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) 00335 curRow->fMap[curRow->fMapCount].fURIId = fEmptyNamespaceId; 00336 else 00337 curRow->fMap[curRow->fMapCount].fURIId = uriId; 00338 00339 // Bump the map count now 00340 curRow->fMapCount++; 00341 } 00342 00343 00344 unsigned int ElemStack::mapPrefixToURI( const XMLCh* const prefixToMap 00345 , bool& unknown) const 00346 { 00347 // Assume we find it 00348 unknown = false; 00349 00350 // 00351 // Map the prefix to its unique id, from the prefix string pool. If its 00352 // not a valid prefix, then its a failure. 00353 // 00354 unsigned int prefixId = (!prefixToMap || !*prefixToMap)?fGlobalPoolId : fPrefixPool.getId(prefixToMap); 00355 if (prefixId == 0) 00356 { 00357 unknown = true; 00358 return fUnknownNamespaceId; 00359 } 00360 // 00361 // Check for the special prefixes 'xml' and 'xmlns' since they cannot 00362 // be overridden. 00363 // 00364 else if (prefixId == fXMLPoolId) 00365 return fXMLNamespaceId; 00366 else if (prefixId == fXMLNSPoolId) 00367 return fXMLNSNamespaceId; 00368 00369 // 00370 // Start at the stack top and work backwards until we come to some 00371 // element that mapped this prefix. 00372 // 00373 for (XMLSize_t index = fStackTop; index > 0; index--) 00374 { 00375 // Get a convenience pointer to the current element 00376 StackElem* curRow = fStack[index-1]; 00377 00378 // Search the map at this level for the passed prefix 00379 for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) 00380 { 00381 if (curRow->fMap[mapIndex].fPrefId == prefixId) 00382 return curRow->fMap[mapIndex].fURIId; 00383 } 00384 } 00385 // If the prefix wasn't found, try in the global namespaces 00386 if(fGlobalNamespaces) 00387 { 00388 for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++) 00389 { 00390 if (fGlobalNamespaces->fMap[mapIndex].fPrefId == prefixId) 00391 return fGlobalNamespaces->fMap[mapIndex].fURIId; 00392 } 00393 } 00394 00395 // 00396 // If the prefix is an empty string, then we will return the special 00397 // global namespace id. This can be overridden, but no one has or we 00398 // would have not gotten here. 00399 // 00400 if (!*prefixToMap) 00401 return fEmptyNamespaceId; 00402 00403 // Oh well, don't have a clue so return the unknown id 00404 unknown = true; 00405 return fUnknownNamespaceId; 00406 } 00407 00408 00409 ValueVectorOf<PrefMapElem*>* ElemStack::getNamespaceMap() const 00410 { 00411 fNamespaceMap->removeAllElements(); 00412 00413 // Start at the stack top and work backwards until we come to some 00414 // element that mapped this prefix. 00415 for (XMLSize_t index = fStackTop; index > 0; index--) 00416 { 00417 // Get a convenience pointer to the current element 00418 StackElem* curRow = fStack[index-1]; 00419 00420 // If no prefixes mapped at this level, then go the next one 00421 if (!curRow->fMapCount) 00422 continue; 00423 00424 // Search the map at this level for the passed prefix 00425 for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) 00426 fNamespaceMap->addElement(&(curRow->fMap[mapIndex])); 00427 } 00428 // Add the global namespaces 00429 if(fGlobalNamespaces) 00430 { 00431 for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++) 00432 fNamespaceMap->addElement(&(fGlobalNamespaces->fMap[mapIndex])); 00433 } 00434 00435 return fNamespaceMap; 00436 } 00437 00438 // --------------------------------------------------------------------------- 00439 // ElemStack: Miscellaneous methods 00440 // --------------------------------------------------------------------------- 00441 void ElemStack::reset( const unsigned int emptyId 00442 , const unsigned int unknownId 00443 , const unsigned int xmlId 00444 , const unsigned int xmlNSId) 00445 { 00446 if(fGlobalNamespaces) 00447 { 00448 fMemoryManager->deallocate(fGlobalNamespaces->fMap); 00449 delete fGlobalNamespaces; 00450 fGlobalNamespaces = 0; 00451 } 00452 00453 // Reset the stack top to clear the stack 00454 fStackTop = 0; 00455 00456 // if first time, put in the standard prefixes 00457 if (fXMLPoolId == 0) { 00458 00459 fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString); 00460 fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString); 00461 fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString); 00462 } 00463 00464 // And store the new special URI ids 00465 fEmptyNamespaceId = emptyId; 00466 fUnknownNamespaceId = unknownId; 00467 fXMLNamespaceId = xmlId; 00468 fXMLNSNamespaceId = xmlNSId; 00469 } 00470 00471 00472 // --------------------------------------------------------------------------- 00473 // ElemStack: Private helpers 00474 // --------------------------------------------------------------------------- 00475 void ElemStack::expandMap(StackElem* const toExpand) 00476 { 00477 // For convenience get the old map size 00478 const XMLSize_t oldCap = toExpand->fMapCapacity; 00479 00480 // 00481 // Expand the capacity by 25%, or initialize it to 16 if its currently 00482 // empty. Then allocate a new temp buffer. 00483 // 00484 const XMLSize_t newCapacity = oldCap ? 00485 (XMLSize_t )(oldCap * 1.25) : 16; 00486 PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate 00487 ( 00488 newCapacity * sizeof(PrefMapElem) 00489 );//new PrefMapElem[newCapacity]; 00490 00491 // 00492 // Copy over the old stuff. We DON'T have to zero out the new stuff 00493 // since this is a by value map and the current map index controls what 00494 // is relevant. 00495 // 00496 memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem)); 00497 00498 // Delete the old map and store the new stuff 00499 fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap; 00500 toExpand->fMap = newMap; 00501 toExpand->fMapCapacity = newCapacity; 00502 } 00503 00504 void ElemStack::expandStack() 00505 { 00506 // Expand the capacity by 25% and allocate a new buffer 00507 const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25); 00508 StackElem** newStack = (StackElem**) fMemoryManager->allocate 00509 ( 00510 newCapacity * sizeof(StackElem*) 00511 );//new StackElem*[newCapacity]; 00512 00513 // Copy over the old stuff 00514 memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); 00515 00516 // 00517 // And zero out the new stuff. Though we use a stack top, we reuse old 00518 // stack contents so we need to know if elements have been initially 00519 // allocated or not as we push new stuff onto the stack. 00520 // 00521 memset 00522 ( 00523 &newStack[fStackCapacity] 00524 , 0 00525 , (newCapacity - fStackCapacity) * sizeof(StackElem*) 00526 ); 00527 00528 // Delete the old array and update our members 00529 fMemoryManager->deallocate(fStack);//delete [] fStack; 00530 fStack = newStack; 00531 fStackCapacity = newCapacity; 00532 } 00533 00534 00535 00536 // --------------------------------------------------------------------------- 00537 // WFElemStack: Constructors and Destructor 00538 // --------------------------------------------------------------------------- 00539 WFElemStack::WFElemStack(MemoryManager* const manager) : 00540 00541 fEmptyNamespaceId(0) 00542 , fGlobalPoolId(0) 00543 , fStackCapacity(32) 00544 , fStackTop(0) 00545 , fUnknownNamespaceId(0) 00546 , fXMLNamespaceId(0) 00547 , fXMLPoolId(0) 00548 , fXMLNSNamespaceId(0) 00549 , fXMLNSPoolId(0) 00550 , fMapCapacity(0) 00551 , fMap(0) 00552 , fStack(0) 00553 , fPrefixPool(109, manager) 00554 , fMemoryManager(manager) 00555 { 00556 // Do an initial allocation of the stack and zero it out 00557 fStack = (StackElem**) fMemoryManager->allocate 00558 ( 00559 fStackCapacity * sizeof(StackElem*) 00560 );//new StackElem*[fStackCapacity]; 00561 memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); 00562 } 00563 00564 WFElemStack::~WFElemStack() 00565 { 00566 // 00567 // Start working from the bottom of the stack and clear it out as we 00568 // go up. Once we hit an uninitialized one, we can break out. 00569 // 00570 for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++) 00571 { 00572 // If this entry has been set, then lets clean it up 00573 if (!fStack[stackInd]) 00574 break; 00575 00576 fMemoryManager->deallocate(fStack[stackInd]->fThisElement);//delete [] fStack[stackInd]->fThisElement; 00577 delete fStack[stackInd]; 00578 } 00579 00580 if (fMap) 00581 fMemoryManager->deallocate(fMap);//delete [] fMap; 00582 00583 // Delete the stack array itself now 00584 fMemoryManager->deallocate(fStack);//delete [] fStack; 00585 } 00586 00587 00588 // --------------------------------------------------------------------------- 00589 // WFElemStack: Stack access 00590 // --------------------------------------------------------------------------- 00591 XMLSize_t WFElemStack::addLevel() 00592 { 00593 // See if we need to expand the stack 00594 if (fStackTop == fStackCapacity) 00595 expandStack(); 00596 00597 00598 // If this element has not been initialized yet, then initialize it 00599 if (!fStack[fStackTop]) 00600 { 00601 fStack[fStackTop] = new (fMemoryManager) StackElem; 00602 fStack[fStackTop]->fThisElement = 0; 00603 fStack[fStackTop]->fElemMaxLength = 0; 00604 } 00605 00606 // Set up the new top row 00607 fStack[fStackTop]->fReaderNum = 0xFFFFFFFF; 00608 fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; 00609 fStack[fStackTop]->fTopPrefix = -1; 00610 00611 if (fStackTop != 0) 00612 fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix; 00613 00614 // Bump the top of stack 00615 fStackTop++; 00616 00617 return fStackTop-1; 00618 } 00619 00620 00621 XMLSize_t 00622 WFElemStack::addLevel(const XMLCh* const toSet, 00623 const unsigned int toSetLen, 00624 const unsigned int readerNum) 00625 { 00626 // See if we need to expand the stack 00627 if (fStackTop == fStackCapacity) 00628 expandStack(); 00629 00630 // If this element has not been initialized yet, then initialize it 00631 if (!fStack[fStackTop]) 00632 { 00633 fStack[fStackTop] = new (fMemoryManager) StackElem; 00634 fStack[fStackTop]->fThisElement = 0; 00635 fStack[fStackTop]->fElemMaxLength = 0; 00636 } 00637 00638 // Set up the new top row 00639 fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; 00640 fStack[fStackTop]->fTopPrefix = -1; 00641 00642 // And store the new stuff 00643 if (toSetLen > fStack[fStackTop]->fElemMaxLength) { 00644 00645 fMemoryManager->deallocate(fStack[fStackTop]->fThisElement);//delete [] fStack[fStackTop]->fThisElement; 00646 fStack[fStackTop]->fElemMaxLength = toSetLen; 00647 fStack[fStackTop]->fThisElement = (XMLCh*) fMemoryManager->allocate 00648 ( 00649 (toSetLen + 1) * sizeof(XMLCh) 00650 );//new XMLCh[toSetLen + 1]; 00651 } 00652 00653 XMLString::moveChars(fStack[fStackTop]->fThisElement, toSet, toSetLen + 1); 00654 fStack[fStackTop]->fReaderNum = readerNum; 00655 00656 if (fStackTop != 0) 00657 fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix; 00658 00659 // Bump the top of stack 00660 fStackTop++; 00661 00662 return fStackTop-1; 00663 } 00664 00665 00666 00667 const WFElemStack::StackElem* WFElemStack::popTop() 00668 { 00669 // Watch for an underflow error 00670 if (!fStackTop) 00671 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); 00672 00673 fStackTop--; 00674 return fStack[fStackTop]; 00675 } 00676 00677 00678 void 00679 WFElemStack::setElement(const XMLCh* const toSet, 00680 const unsigned int toSetLen, 00681 const unsigned int readerNum) 00682 { 00683 if (!fStackTop) 00684 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); 00685 00686 if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) { 00687 00688 fMemoryManager->deallocate(fStack[fStackTop - 1]->fThisElement);//delete [] fStack[fStackTop - 1]->fThisElement; 00689 fStack[fStackTop - 1]->fElemMaxLength = toSetLen; 00690 fStack[fStackTop - 1]->fThisElement = (XMLCh*) fMemoryManager->allocate 00691 ( 00692 (toSetLen + 1) * sizeof(XMLCh) 00693 );//new XMLCh[toSetLen + 1]; 00694 } 00695 00696 XMLString::moveChars(fStack[fStackTop - 1]->fThisElement, toSet, toSetLen + 1); 00697 fStack[fStackTop - 1]->fReaderNum = readerNum; 00698 } 00699 00700 00701 // --------------------------------------------------------------------------- 00702 // WFElemStack: Stack top access 00703 // --------------------------------------------------------------------------- 00704 const WFElemStack::StackElem* WFElemStack::topElement() const 00705 { 00706 if (!fStackTop) 00707 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); 00708 00709 return fStack[fStackTop - 1]; 00710 } 00711 00712 00713 // --------------------------------------------------------------------------- 00714 // WFElemStack: Prefix map methods 00715 // --------------------------------------------------------------------------- 00716 void WFElemStack::addPrefix( const XMLCh* const prefixToAdd 00717 , const unsigned int uriId) 00718 { 00719 if (!fStackTop) 00720 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); 00721 00722 // Get a convenience pointer to the stack top row 00723 StackElem* curRow = fStack[fStackTop - 1]; 00724 00725 // Map the prefix to its unique id 00726 const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); 00727 00728 // 00729 // Add a new element to the prefix map for this element. If its full, 00730 // then expand it out. 00731 // 00732 if ((unsigned int)curRow->fTopPrefix + 1 == fMapCapacity) 00733 expandMap(); 00734 00735 // 00736 // And now add a new element for this prefix. Watch for the special case 00737 // of xmlns=="", and force it to ""=[globalid] 00738 // 00739 fMap[curRow->fTopPrefix + 1].fPrefId = prefId; 00740 if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) 00741 fMap[curRow->fTopPrefix + 1].fURIId = fEmptyNamespaceId; 00742 else 00743 fMap[curRow->fTopPrefix + 1].fURIId = uriId; 00744 00745 // Bump the map count now 00746 curRow->fTopPrefix++; 00747 } 00748 00749 00750 unsigned int WFElemStack::mapPrefixToURI( const XMLCh* const prefixToMap 00751 , bool& unknown) const 00752 { 00753 // Assume we find it 00754 unknown = false; 00755 00756 // 00757 // Map the prefix to its unique id, from the prefix string pool. If its 00758 // not a valid prefix, then its a failure. 00759 // 00760 unsigned int prefixId = fPrefixPool.getId(prefixToMap); 00761 if (!prefixId) 00762 { 00763 unknown = true; 00764 return fUnknownNamespaceId; 00765 } 00766 00767 // 00768 // Check for the special prefixes 'xml' and 'xmlns' since they cannot 00769 // be overridden. 00770 // 00771 if (prefixId == fXMLPoolId) 00772 return fXMLNamespaceId; 00773 else if (prefixId == fXMLNSPoolId) 00774 return fXMLNSNamespaceId; 00775 00776 // 00777 // Start at the stack top and work backwards until we come to some 00778 // element that mapped this prefix. 00779 // 00780 // Get a convenience pointer to the stack top row 00781 StackElem* curRow = fStack[fStackTop - 1]; 00782 for (int mapIndex = curRow->fTopPrefix; mapIndex >=0; mapIndex--) 00783 { 00784 if (fMap[mapIndex].fPrefId == prefixId) 00785 return fMap[mapIndex].fURIId; 00786 } 00787 00788 // 00789 // If the prefix is an empty string, then we will return the special 00790 // global namespace id. This can be overridden, but no one has or we 00791 // would have not gotten here. 00792 // 00793 if (!*prefixToMap) 00794 return fEmptyNamespaceId; 00795 00796 // Oh well, don't have a clue so return the unknown id 00797 unknown = true; 00798 return fUnknownNamespaceId; 00799 } 00800 00801 00802 // --------------------------------------------------------------------------- 00803 // WFElemStack: Miscellaneous methods 00804 // --------------------------------------------------------------------------- 00805 void WFElemStack::reset( const unsigned int emptyId 00806 , const unsigned int unknownId 00807 , const unsigned int xmlId 00808 , const unsigned int xmlNSId) 00809 { 00810 // Reset the stack top to clear the stack 00811 fStackTop = 0; 00812 00813 // if first time, put in the standard prefixes 00814 if (fXMLPoolId == 0) { 00815 00816 fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString); 00817 fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString); 00818 fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString); 00819 } 00820 00821 // And store the new special URI ids 00822 fEmptyNamespaceId = emptyId; 00823 fUnknownNamespaceId = unknownId; 00824 fXMLNamespaceId = xmlId; 00825 fXMLNSNamespaceId = xmlNSId; 00826 } 00827 00828 00829 // --------------------------------------------------------------------------- 00830 // WFElemStack: Private helpers 00831 // --------------------------------------------------------------------------- 00832 void WFElemStack::expandMap() 00833 { 00834 // 00835 // Expand the capacity by 25%, or initialize it to 16 if its currently 00836 // empty. Then allocate a new temp buffer. 00837 // 00838 const XMLSize_t newCapacity = fMapCapacity ? 00839 (XMLSize_t)(fMapCapacity * 1.25) : 16; 00840 PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate 00841 ( 00842 newCapacity * sizeof(PrefMapElem) 00843 );//new PrefMapElem[newCapacity]; 00844 00845 // 00846 // Copy over the old stuff. We DON'T have to zero out the new stuff 00847 // since this is a by value map and the current map index controls what 00848 // is relevant. 00849 // 00850 if (fMapCapacity) { 00851 00852 memcpy(newMap, fMap, fMapCapacity * sizeof(PrefMapElem)); 00853 fMemoryManager->deallocate(fMap);//delete [] fMap; 00854 } 00855 00856 fMap = newMap; 00857 fMapCapacity = newCapacity; 00858 } 00859 00860 void WFElemStack::expandStack() 00861 { 00862 // Expand the capacity by 25% and allocate a new buffer 00863 const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25); 00864 StackElem** newStack = (StackElem**) fMemoryManager->allocate 00865 ( 00866 newCapacity * sizeof(StackElem*) 00867 );//new StackElem*[newCapacity]; 00868 00869 // Copy over the old stuff 00870 memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); 00871 00872 // 00873 // And zero out the new stuff. Though we use a stack top, we reuse old 00874 // stack contents so we need to know if elements have been initially 00875 // allocated or not as we push new stuff onto the stack. 00876 // 00877 memset 00878 ( 00879 &newStack[fStackCapacity] 00880 , 0 00881 , (newCapacity - fStackCapacity) * sizeof(StackElem*) 00882 ); 00883 00884 // Delete the old array and update our members 00885 fMemoryManager->deallocate(fStack);//delete [] fStack; 00886 fStack = newStack; 00887 fStackCapacity = newCapacity; 00888 } 00889 00890 00891 XERCES_CPP_NAMESPACE_END