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: NamespaceScope.cpp 729944 2008-12-29 17:03:32Z amassari $ 00020 */ 00021 00022 // --------------------------------------------------------------------------- 00023 // Includes 00024 // --------------------------------------------------------------------------- 00025 #include <string.h> 00026 #include <xercesc/util/EmptyStackException.hpp> 00027 #include <xercesc/validators/schema/NamespaceScope.hpp> 00028 00029 XERCES_CPP_NAMESPACE_BEGIN 00030 00031 // --------------------------------------------------------------------------- 00032 // NamespaceScope: Constructors and Destructor 00033 // --------------------------------------------------------------------------- 00034 NamespaceScope::NamespaceScope(MemoryManager* const manager /*= XMLPlatformUtils::fgMemoryManager*/) : 00035 fEmptyNamespaceId(0) 00036 , fStackCapacity(8) 00037 , fStackTop(0) 00038 , fPrefixPool(109, manager) 00039 , fStack(0) 00040 , fMemoryManager(manager) 00041 { 00042 // Do an initial allocation of the stack and zero it out 00043 fStack = (StackElem**) fMemoryManager->allocate 00044 ( 00045 fStackCapacity * sizeof(StackElem*) 00046 );//new StackElem*[fStackCapacity]; 00047 memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); 00048 } 00049 00050 NamespaceScope::NamespaceScope(const NamespaceScope* const initialize, MemoryManager* const manager /*= XMLPlatformUtils::fgMemoryManager*/) : 00051 fEmptyNamespaceId(0) 00052 , fStackCapacity(8) 00053 , fStackTop(0) 00054 , fPrefixPool(109, manager) 00055 , fStack(0) 00056 , fMemoryManager(manager) 00057 { 00058 // Do an initial allocation of the stack and zero it out 00059 fStack = (StackElem**) fMemoryManager->allocate 00060 ( 00061 fStackCapacity * sizeof(StackElem*) 00062 );//new StackElem*[fStackCapacity]; 00063 memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); 00064 00065 if(initialize) 00066 { 00067 reset(initialize->fEmptyNamespaceId); 00068 00069 // copy the existing bindings 00070 for (unsigned int index = initialize->fStackTop; index > 0; index--) 00071 { 00072 // Get a convenience pointer to the current element 00073 StackElem* curRow = initialize->fStack[index-1]; 00074 00075 // If no prefixes mapped at this level, then go the next one 00076 if (!curRow->fMapCount) 00077 continue; 00078 00079 for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) 00080 { 00081 // go from the id to the prefix 00082 const XMLCh* prefix = initialize->fPrefixPool.getValueForId(curRow->fMap[mapIndex].fPrefId); 00083 00084 // if the prefix is not already known, add it 00085 if(getNamespaceForPrefix(prefix)==fEmptyNamespaceId) 00086 addPrefix(prefix, curRow->fMap[mapIndex].fURIId); 00087 } 00088 } 00089 } 00090 } 00091 00092 NamespaceScope::~NamespaceScope() 00093 { 00094 // 00095 // Start working from the bottom of the stack and clear it out as we 00096 // go up. Once we hit an uninitialized one, we can break out. 00097 // 00098 for (unsigned int stackInd = 0; stackInd < fStackCapacity; stackInd++) 00099 { 00100 // If this entry has been set, then lets clean it up 00101 if (!fStack[stackInd]) 00102 break; 00103 00104 // Delete the row for this entry, then delete the row structure 00105 fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap; 00106 delete fStack[stackInd]; 00107 } 00108 00109 // Delete the stack array itself now 00110 fMemoryManager->deallocate(fStack);//delete [] fStack; 00111 } 00112 00113 00114 // --------------------------------------------------------------------------- 00115 // NamespaceScope: Stack access 00116 // --------------------------------------------------------------------------- 00117 unsigned int NamespaceScope::increaseDepth() 00118 { 00119 // See if we need to expand the stack 00120 if (fStackTop == fStackCapacity) 00121 expandStack(); 00122 00123 // If this element has not been initialized yet, then initialize it 00124 if (!fStack[fStackTop]) 00125 { 00126 fStack[fStackTop] = new (fMemoryManager) StackElem; 00127 fStack[fStackTop]->fMapCapacity = 0; 00128 fStack[fStackTop]->fMap = 0; 00129 } 00130 00131 // Set up the new top row 00132 fStack[fStackTop]->fMapCount = 0; 00133 00134 // Bump the top of stack 00135 fStackTop++; 00136 00137 return fStackTop-1; 00138 } 00139 00140 unsigned int NamespaceScope::decreaseDepth() 00141 { 00142 if (!fStackTop) 00143 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); 00144 00145 fStackTop--; 00146 00147 return fStackTop; 00148 } 00149 00150 00151 // --------------------------------------------------------------------------- 00152 // NamespaceScope: Prefix map methods 00153 // --------------------------------------------------------------------------- 00154 void NamespaceScope::addPrefix(const XMLCh* const prefixToAdd, 00155 const unsigned int uriId) { 00156 00157 if (!fStackTop) 00158 ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); 00159 00160 // Get a convenience pointer to the stack top row 00161 StackElem* curRow = fStack[fStackTop - 1]; 00162 00163 // Map the prefix to its unique id 00164 const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); 00165 00166 // Search the map at this level for the passed prefix 00167 for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) 00168 { 00169 if (curRow->fMap[mapIndex].fPrefId == prefId) 00170 { 00171 curRow->fMap[mapIndex].fURIId = uriId; 00172 return; 00173 } 00174 } 00175 00176 // 00177 // Add a new element to the prefix map for this element. If its full, 00178 // then expand it out. 00179 // 00180 if (curRow->fMapCount == curRow->fMapCapacity) 00181 expandMap(curRow); 00182 00183 // 00184 // And now add a new element for this prefix. 00185 // 00186 curRow->fMap[curRow->fMapCount].fPrefId = prefId; 00187 curRow->fMap[curRow->fMapCount].fURIId = uriId; 00188 00189 // Bump the map count now 00190 curRow->fMapCount++; 00191 } 00192 00193 unsigned int 00194 NamespaceScope::getNamespaceForPrefix(const XMLCh* const prefixToMap) const { 00195 00196 // 00197 // Map the prefix to its unique id, from the prefix string pool. If its 00198 // not a valid prefix, then its a failure. 00199 // 00200 unsigned int prefixId = fPrefixPool.getId(prefixToMap); 00201 00202 if (!prefixId){ 00203 return fEmptyNamespaceId; 00204 } 00205 00206 // 00207 // Start at the stack top and work backwards until we come to some 00208 // element that mapped this prefix. 00209 // 00210 for (unsigned int index = fStackTop; index > 0; index--) 00211 { 00212 // Get a convenience pointer to the current element 00213 StackElem* curRow = fStack[index-1]; 00214 00215 // If no prefixes mapped at this level, then go the next one 00216 if (!curRow->fMapCount) 00217 continue; 00218 00219 // Search the map at this level for the passed prefix 00220 for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) 00221 { 00222 if (curRow->fMap[mapIndex].fPrefId == prefixId) 00223 return curRow->fMap[mapIndex].fURIId; 00224 } 00225 } 00226 00227 return fEmptyNamespaceId; 00228 } 00229 00230 00231 // --------------------------------------------------------------------------- 00232 // NamespaceScope: Miscellaneous methods 00233 // --------------------------------------------------------------------------- 00234 void NamespaceScope::reset(const unsigned int emptyId) 00235 { 00236 // Flush the prefix pool and put back in the standard prefixes 00237 fPrefixPool.flushAll(); 00238 00239 // Reset the stack top to clear the stack 00240 fStackTop = 0; 00241 00242 // And store the new special URI ids 00243 fEmptyNamespaceId = emptyId; 00244 00245 // add the first storage 00246 increaseDepth(); 00247 } 00248 00249 00250 // --------------------------------------------------------------------------- 00251 // Namespace: Private helpers 00252 // --------------------------------------------------------------------------- 00253 void NamespaceScope::expandMap(StackElem* const toExpand) 00254 { 00255 // For convenience get the old map size 00256 const unsigned int oldCap = toExpand->fMapCapacity; 00257 00258 // 00259 // Expand the capacity by 25%, or initialize it to 16 if its currently 00260 // empty. Then allocate a new temp buffer. 00261 // 00262 const unsigned int newCapacity = oldCap ? 00263 (unsigned int)(oldCap * 1.25) : 16; 00264 PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate 00265 ( 00266 newCapacity * sizeof(PrefMapElem) 00267 );//new PrefMapElem[newCapacity]; 00268 00269 // 00270 // Copy over the old stuff. We DON'T have to zero out the new stuff 00271 // since this is a by value map and the current map index controls what 00272 // is relevant. 00273 // 00274 memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem)); 00275 00276 // Delete the old map and store the new stuff 00277 fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap; 00278 toExpand->fMap = newMap; 00279 toExpand->fMapCapacity = newCapacity; 00280 } 00281 00282 void NamespaceScope::expandStack() 00283 { 00284 // Expand the capacity by 25% and allocate a new buffer 00285 const unsigned int newCapacity = (unsigned int)(fStackCapacity * 1.25); 00286 StackElem** newStack = (StackElem**) fMemoryManager->allocate 00287 ( 00288 newCapacity * sizeof(StackElem*) 00289 );//new StackElem*[newCapacity]; 00290 00291 // Copy over the old stuff 00292 memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); 00293 00294 // 00295 // And zero out the new stuff. Though we use a stack top, we reuse old 00296 // stack contents so we need to know if elements have been initially 00297 // allocated or not as we push new stuff onto the stack. 00298 // 00299 memset 00300 ( 00301 &newStack[fStackCapacity] 00302 , 0 00303 , (newCapacity - fStackCapacity) * sizeof(StackElem*) 00304 ); 00305 00306 // Delete the old array and update our members 00307 fMemoryManager->deallocate(fStack);//delete [] fStack; 00308 fStack = newStack; 00309 fStackCapacity = newCapacity; 00310 } 00311 00312 XERCES_CPP_NAMESPACE_END 00313