GME  13
NamespaceScope.cpp
Go to the documentation of this file.
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