diff --git a/projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp b/projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp index e46ada36dc359e33ad3d7b991b02782ca86f7c26..1667ed9fec3e51edf11070c84b2b8e957da0e145 100644 --- a/projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp +++ b/projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp @@ -545,6 +545,10 @@ SOURCE=..\..\..\..\..\src\xercesc\util\FlagJanitor.hpp # End Source File # Begin Source File +SOURCE=..\..\..\..\..\src\xercesc\util\Hash2KeysSetOf.hpp +# End Source File +# Begin Source File + SOURCE=..\..\..\..\..\src\xercesc\util\Hashers.hpp # End Source File # Begin Source File diff --git a/projects/Win32/VC7.1/xerces-all/XercesLib/XercesLib.vcproj b/projects/Win32/VC7.1/xerces-all/XercesLib/XercesLib.vcproj index f72a49bf511b299fc74210037b3cd66849321023..a89c447ad07467eb40bddc507ed37fc13a98ba88 100644 --- a/projects/Win32/VC7.1/xerces-all/XercesLib/XercesLib.vcproj +++ b/projects/Win32/VC7.1/xerces-all/XercesLib/XercesLib.vcproj @@ -462,6 +462,10 @@ <File RelativePath="..\..\..\..\..\src\xercesc\util\FlagJanitor.hpp"> </File> + <File + RelativePath="..\..\..\..\..\src\xercesc\util\Hash2KeysSetOf.hpp" + > + </File> <File RelativePath="..\..\..\..\..\src\xercesc\util\Hashers.hpp"> </File> diff --git a/projects/Win32/VC8/xerces-all/XercesLib/XercesLib.vcproj b/projects/Win32/VC8/xerces-all/XercesLib/XercesLib.vcproj index e411a2206d2f1d746e2aa718b0e382f4a8a15475..bc6a8bb0d8a40b303e6c9c6092147857ee57bf59 100644 --- a/projects/Win32/VC8/xerces-all/XercesLib/XercesLib.vcproj +++ b/projects/Win32/VC8/xerces-all/XercesLib/XercesLib.vcproj @@ -1181,6 +1181,10 @@ RelativePath="..\..\..\..\..\src\xercesc\util\FlagJanitor.hpp" > </File> + <File + RelativePath="..\..\..\..\..\src\xercesc\util\Hash2KeysSetOf.hpp" + > + </File> <File RelativePath="..\..\..\..\..\src\xercesc\util\Hashers.hpp" > diff --git a/projects/Win32/VC9/xerces-all/XercesLib/XercesLib.vcproj b/projects/Win32/VC9/xerces-all/XercesLib/XercesLib.vcproj index 490a8d57e0206fb3b35e30daffb241a7c806eb3c..90a777ddfb156e3d9cb0c73c82ea69a9f902b7c7 100644 --- a/projects/Win32/VC9/xerces-all/XercesLib/XercesLib.vcproj +++ b/projects/Win32/VC9/xerces-all/XercesLib/XercesLib.vcproj @@ -1180,6 +1180,10 @@ RelativePath="..\..\..\..\..\src\xercesc\util\FlagJanitor.hpp" > </File> + <File + RelativePath="..\..\..\..\..\src\xercesc\util\Hash2KeysSetOf.hpp" + > + </File> <File RelativePath="..\..\..\..\..\src\xercesc\util\Hashers.hpp" > diff --git a/src/Makefile.am b/src/Makefile.am index e986f2044f9e237e58f6597af511736789183f3d..17eb8ba502c293e10dd18599f254326b1bfd1856 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -578,6 +578,8 @@ util_headers = \ xercesc/util/FlagJanitor.hpp \ xercesc/util/FlagJanitor.c \ xercesc/util/Hashers.hpp \ + xercesc/util/Hash2KeysSetOf.hpp \ + xercesc/util/Hash2KeysSetOf.c \ xercesc/util/HexBin.hpp \ xercesc/util/IllegalArgumentException.hpp \ xercesc/util/InvalidCastException.hpp \ diff --git a/src/xercesc/internal/DGXMLScanner.cpp b/src/xercesc/internal/DGXMLScanner.cpp index 516305623a21314822d598c3a697d48b50d8a487..213154c5586b83c70c74e3b43484fcef89495582 100644 --- a/src/xercesc/internal/DGXMLScanner.cpp +++ b/src/xercesc/internal/DGXMLScanner.cpp @@ -1365,10 +1365,7 @@ bool DGXMLScanner::scanStartTag(bool& gotData) { // reset namePtr so it refers to newly-allocated memory namePtr = (XMLCh *)curAtt->getQName(); - if (!fUndeclaredAttrRegistry->containsKey(namePtr)) { - fUndeclaredAttrRegistry->put((void *)namePtr, 0); - } - else + if (!fUndeclaredAttrRegistry->putIfNotPresent(namePtr, 0)) { emitError( XMLErrs::AttrAlreadyUsedInSTag @@ -2256,10 +2253,7 @@ void DGXMLScanner::commonInit() ( 131, false, fMemoryManager ); - fUndeclaredAttrRegistry = new (fMemoryManager) RefHashTableOf<unsigned int> - ( - 7, false, fMemoryManager - ); + fUndeclaredAttrRegistry = new (fMemoryManager) Hash2KeysSetOf<StringHasher>(7, fMemoryManager); if (fValidator) { diff --git a/src/xercesc/internal/DGXMLScanner.hpp b/src/xercesc/internal/DGXMLScanner.hpp index bdb9d83efd1c3137b93bfe02154951573e865208..dcab0e542bc83fb03f1072527454a05cd3daa2f0 100644 --- a/src/xercesc/internal/DGXMLScanner.hpp +++ b/src/xercesc/internal/DGXMLScanner.hpp @@ -25,6 +25,7 @@ #include <xercesc/internal/XMLScanner.hpp> #include <xercesc/util/ValueVectorOf.hpp> #include <xercesc/util/NameIdPool.hpp> +#include <xercesc/util/Hash2KeysSetOf.hpp> #include <xercesc/validators/common/Grammar.hpp> XERCES_CPP_NAMESPACE_BEGIN @@ -176,7 +177,7 @@ private : // mapping from XMLAttDef instances to the count of the last // start tag where they were utilized. // fUndeclaredAttrRegistry - // mapping of attr QNames to the count of the last start tag in which they occurred + // mapping of attr QNames to detect duplicates // // ----------------------------------------------------------------------- ValueVectorOf<XMLAttr*>* fAttrNSList; @@ -185,7 +186,7 @@ private : NameIdPool<DTDElementDecl>* fDTDElemNonDeclPool; unsigned int fElemCount; RefHashTableOf<unsigned int, PtrHasher>* fAttDefRegistry; - RefHashTableOf<unsigned int>* fUndeclaredAttrRegistry; + Hash2KeysSetOf<StringHasher>* fUndeclaredAttrRegistry; }; inline const XMLCh* DGXMLScanner::getName() const diff --git a/src/xercesc/internal/IGXMLScanner.cpp b/src/xercesc/internal/IGXMLScanner.cpp index 8b513759e5681afceb41d2fd6f553c689ad010a2..f5cb5dbf93493f03d08696f5c1d0d2569c4a1c3b 100644 --- a/src/xercesc/internal/IGXMLScanner.cpp +++ b/src/xercesc/internal/IGXMLScanner.cpp @@ -80,7 +80,6 @@ IGXMLScanner::IGXMLScanner( XMLValidator* const valToAdopt , fElemCount(0) , fAttDefRegistry(0) , fUndeclaredAttrRegistry(0) - , fUndeclaredAttrRegistryNS(0) , fPSVIAttrList(0) , fModel(0) , fPSVIElement(0) @@ -132,7 +131,6 @@ IGXMLScanner::IGXMLScanner( XMLDocumentHandler* const docHandler , fElemCount(0) , fAttDefRegistry(0) , fUndeclaredAttrRegistry(0) - , fUndeclaredAttrRegistryNS(0) , fPSVIAttrList(0) , fModel(0) , fPSVIElement(0) @@ -542,14 +540,7 @@ void IGXMLScanner::commonInit() ( 131, false, fMemoryManager ); - fUndeclaredAttrRegistry = new (fMemoryManager) RefHashTableOf<unsigned int> - ( - 7, false, fMemoryManager - ); - fUndeclaredAttrRegistryNS = new (fMemoryManager) RefHash2KeysTableOf<unsigned int> - ( - 7, false, fMemoryManager - ); + fUndeclaredAttrRegistry = new (fMemoryManager) Hash2KeysSetOf<StringHasher>(7, fMemoryManager); fPSVIAttrList = new (fMemoryManager) PSVIAttributeList(fMemoryManager); // use fDTDValidator as the default validator @@ -571,7 +562,6 @@ void IGXMLScanner::cleanUp() delete fSchemaElemNonDeclPool; delete fAttDefRegistry; delete fUndeclaredAttrRegistry; - delete fUndeclaredAttrRegistryNS; delete fPSVIAttrList; delete fPSVIElement; delete fErrorStack; @@ -1814,9 +1804,7 @@ bool IGXMLScanner::scanStartTag(bool& gotData) , elemDecl->getFullName() ); } - if(!fUndeclaredAttrRegistry->containsKey(namePtr)) - fUndeclaredAttrRegistry->put((void *)namePtr, 0); - else + if(!fUndeclaredAttrRegistry->putIfNotPresent(namePtr, 0)) { emitError ( @@ -2602,7 +2590,6 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) // clean up after ourselves: // clear the map used to detect duplicate attributes fUndeclaredAttrRegistry->removeAll(); - fUndeclaredAttrRegistryNS->removeAll(); } // activate identity constraints diff --git a/src/xercesc/internal/IGXMLScanner.hpp b/src/xercesc/internal/IGXMLScanner.hpp index 54589e28868fec85394d825135ca1793036e6886..eca71ff476d711caa5a1fd2b671becadb5358cae 100644 --- a/src/xercesc/internal/IGXMLScanner.hpp +++ b/src/xercesc/internal/IGXMLScanner.hpp @@ -26,6 +26,7 @@ #include <xercesc/util/KVStringPair.hpp> #include <xercesc/util/NameIdPool.hpp> #include <xercesc/util/RefHash3KeysIdPool.hpp> +#include <xercesc/util/Hash2KeysSetOf.hpp> #include <xercesc/validators/common/Grammar.hpp> #include <xercesc/validators/schema/SchemaElementDecl.hpp> @@ -271,10 +272,7 @@ private : // mapping from XMLAttDef instances to the count of the last // start tag where they were utilized. // fUndeclaredAttrRegistry - // mapping of attr QNames to the count of the last start tag in which they occurred - // fUndeclaredAttrRegistryNS - // mapping of namespaceId/localName pairs to the count of the last - // start tag in which they occurred. + // set of attr QNames to detect duplicates // fPSVIAttrList // PSVI attribute list implementation that needs to be // filled when a PSVIHandler is registered @@ -298,8 +296,7 @@ private : RefHash3KeysIdPool<SchemaElementDecl>* fSchemaElemNonDeclPool; unsigned int fElemCount; RefHashTableOf<unsigned int, PtrHasher>*fAttDefRegistry; - RefHashTableOf<unsigned int>* fUndeclaredAttrRegistry; - RefHash2KeysTableOf<unsigned int>* fUndeclaredAttrRegistryNS; + Hash2KeysSetOf<StringHasher>* fUndeclaredAttrRegistry; PSVIAttributeList * fPSVIAttrList; XSModel* fModel; PSVIElement* fPSVIElement; diff --git a/src/xercesc/internal/IGXMLScanner2.cpp b/src/xercesc/internal/IGXMLScanner2.cpp index 7c34a4ed45417ea255e8190d0f4472a90bb7af52..cf7406490965a472c1fa09b8a8faf18b124f17a2 100644 --- a/src/xercesc/internal/IGXMLScanner2.cpp +++ b/src/xercesc/internal/IGXMLScanner2.cpp @@ -197,7 +197,7 @@ IGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs if (isNSAttr && fGrammarType == Grammar::SchemaGrammarType) { - if(fUndeclaredAttrRegistryNS->containsKey(suffPtr, uriId)) + if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId)) { emitError ( @@ -262,8 +262,6 @@ IGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs } if (!otherXSI) { - fUndeclaredAttrRegistryNS->put((void *)suffPtr, uriId, 0); - normalizeAttRawValue ( namePtr @@ -305,20 +303,20 @@ IGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs if(getPSVIHandler()) { - psviAttr = fPSVIAttrList->getPSVIAttributeToFill(suffPtr, fURIStringPool->getValueForId(uriId)); - XSSimpleTypeDefinition *validatingType = (attrValidator) + psviAttr = fPSVIAttrList->getPSVIAttributeToFill(suffPtr, fURIStringPool->getValueForId(uriId)); + XSSimpleTypeDefinition *validatingType = (attrValidator) ? (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator) : 0; // no attribute declarations for these... - psviAttr->reset( - fRootElemName - , PSVIItem::VALIDITY_NOTKNOWN - , PSVIItem::VALIDATION_NONE - , validatingType - , 0 - , 0 + psviAttr->reset( + fRootElemName + , PSVIItem::VALIDITY_NOTKNOWN + , PSVIItem::VALIDATION_NONE + , validatingType + , 0 + , 0 , false - , 0 + , 0 , attrValidator ); } @@ -453,9 +451,7 @@ IGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs { if(fGrammarType == Grammar::DTDGrammarType) { - if(!fUndeclaredAttrRegistry->containsKey(namePtr)) - fUndeclaredAttrRegistry->put((void *)namePtr, 0); - else + if(!fUndeclaredAttrRegistry->putIfNotPresent(namePtr, 0)) { emitError ( @@ -467,9 +463,7 @@ IGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs } else // schema grammar { - if(!fUndeclaredAttrRegistryNS->containsKey(suffPtr, uriId)) - fUndeclaredAttrRegistryNS->put((void *)suffPtr, uriId, 0); - else + if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId)) { emitError ( @@ -641,69 +635,69 @@ IGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs // now fill in the PSVIAttributes entry for this attribute: if(getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType) - { - psviAttr = fPSVIAttrList->getPSVIAttributeToFill(suffPtr, fURIStringPool->getValueForId(uriId)); - SchemaAttDef *actualAttDef = 0; - if(attDef) - actualAttDef = (SchemaAttDef *)attDef; - else if (attDefForWildCard) - actualAttDef = (SchemaAttDef *)attDefForWildCard; + { + psviAttr = fPSVIAttrList->getPSVIAttributeToFill(suffPtr, fURIStringPool->getValueForId(uriId)); + SchemaAttDef *actualAttDef = 0; + if(attDef) + actualAttDef = (SchemaAttDef *)attDef; + else if (attDefForWildCard) + actualAttDef = (SchemaAttDef *)attDefForWildCard; if(actualAttDef) { - XSAttributeDeclaration *attrDecl = (XSAttributeDeclaration *)fModel->getXSObject(actualAttDef); + XSAttributeDeclaration *attrDecl = (XSAttributeDeclaration *)fModel->getXSObject(actualAttDef); DatatypeValidator * attrDataType = actualAttDef->getDatatypeValidator(); - XSSimpleTypeDefinition *validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrDataType); - if(attrValid != PSVIItem::VALIDITY_VALID) - { - psviAttr->reset + XSSimpleTypeDefinition *validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrDataType); + if(attrValid != PSVIItem::VALIDITY_VALID) + { + psviAttr->reset ( - fRootElemName - , attrValid - , attrAssessed - , validatingType - , 0 - , actualAttDef->getValue() - , false - , attrDecl + fRootElemName + , attrValid + , attrAssessed + , validatingType + , 0 + , actualAttDef->getValue() + , false + , attrDecl , 0 - ); - } - else - { - XSSimpleTypeDefinition *memberType = 0; - if(validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION) - memberType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator); - psviAttr->reset + ); + } + else + { + XSSimpleTypeDefinition *memberType = 0; + if(validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION) + memberType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator); + psviAttr->reset ( - fRootElemName - , attrValid - , attrAssessed - , validatingType - , memberType - , actualAttDef->getValue() - , false - , attrDecl + fRootElemName + , attrValid + , attrAssessed + , validatingType + , memberType + , actualAttDef->getValue() + , false + , attrDecl , (memberType)?attrValidator:attrDataType - ); - } + ); + } } else { - psviAttr->reset + psviAttr->reset ( - fRootElemName - , attrValid - , attrAssessed + fRootElemName + , attrValid + , attrAssessed + , 0 , 0 - , 0 - , 0 - , false - , 0 , 0 - ); + , false + , 0 + , 0 + ); } - } - } + } + } // Add this attribute to the attribute list that we use to pass them // to the handler. We reuse its existing elements but expand it as @@ -1390,7 +1384,6 @@ void IGXMLScanner::scanReset(const InputSource& src) resetUIntPool(); } fUndeclaredAttrRegistry->removeAll(); - fUndeclaredAttrRegistryNS->removeAll(); fDTDElemNonDeclPool->removeAll(); } diff --git a/src/xercesc/internal/SGXMLScanner.cpp b/src/xercesc/internal/SGXMLScanner.cpp index c67fe60ea023e4dd2e41a0b00c1e307d7474faa5..33e2d554ec8d4c84e1fde8d1f2d2303630e91b67 100644 --- a/src/xercesc/internal/SGXMLScanner.cpp +++ b/src/xercesc/internal/SGXMLScanner.cpp @@ -84,7 +84,7 @@ SGXMLScanner::SGXMLScanner( XMLValidator* const valToAdopt , fElemNonDeclPool(0) , fElemCount(0) , fAttDefRegistry(0) - , fUndeclaredAttrRegistryNS(0) + , fUndeclaredAttrRegistry(0) , fPSVIAttrList(0) , fModel(0) , fPSVIElement(0) @@ -133,7 +133,7 @@ SGXMLScanner::SGXMLScanner( XMLDocumentHandler* const docHandler , fElemNonDeclPool(0) , fElemCount(0) , fAttDefRegistry(0) - , fUndeclaredAttrRegistryNS(0) + , fUndeclaredAttrRegistry(0) , fPSVIAttrList(0) , fModel(0) , fPSVIElement(0) @@ -1588,7 +1588,7 @@ bool SGXMLScanner::scanStartTag(bool& gotData) { // clean up after ourselves: // clear the map used to detect duplicate attributes - fUndeclaredAttrRegistryNS->removeAll(); + fUndeclaredAttrRegistry->removeAll(); } // activate identity constraints @@ -2029,10 +2029,7 @@ void SGXMLScanner::commonInit() ( 131, false, fMemoryManager ); - fUndeclaredAttrRegistryNS = new (fMemoryManager) RefHash2KeysTableOf<unsigned int> - ( - 7, false, fMemoryManager - ); + fUndeclaredAttrRegistry = new (fMemoryManager) Hash2KeysSetOf<StringHasher>(7, fMemoryManager); fPSVIAttrList = new (fMemoryManager) PSVIAttributeList(fMemoryManager); if (fValidator) @@ -2058,7 +2055,7 @@ void SGXMLScanner::cleanUp() delete fICHandler; delete fElemNonDeclPool; delete fAttDefRegistry; - delete fUndeclaredAttrRegistryNS; + delete fUndeclaredAttrRegistry; delete fPSVIAttrList; if (fPSVIElement) delete fPSVIElement; @@ -2234,7 +2231,7 @@ SGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs if (isNSAttr) { - if(fUndeclaredAttrRegistryNS->containsKey(suffPtr, uriId)) + if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId)) { emitError ( @@ -2299,8 +2296,6 @@ SGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs } if (!otherXSI) { - fUndeclaredAttrRegistryNS->put((void *)suffPtr, uriId, 0); - normalizeAttRawValue ( namePtr @@ -2472,9 +2467,7 @@ SGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs } else { - if(!fUndeclaredAttrRegistryNS->containsKey(suffPtr, uriId)) - fUndeclaredAttrRegistryNS->put((void *)suffPtr, uriId, 0); - else + if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId)) { emitError ( @@ -3304,7 +3297,7 @@ void SGXMLScanner::scanReset(const InputSource& src) // though their buckets will still be tied up resetUIntPool(); } - fUndeclaredAttrRegistryNS->removeAll(); + fUndeclaredAttrRegistry->removeAll(); } diff --git a/src/xercesc/internal/SGXMLScanner.hpp b/src/xercesc/internal/SGXMLScanner.hpp index 6a032ef967e3ebdf602cfcab3b0863ad62a7371e..0ecdb3540c44fbbe42935042c4d8c06d5f456dfe 100644 --- a/src/xercesc/internal/SGXMLScanner.hpp +++ b/src/xercesc/internal/SGXMLScanner.hpp @@ -26,6 +26,7 @@ #include <xercesc/util/KVStringPair.hpp> #include <xercesc/util/ValueHashTableOf.hpp> #include <xercesc/util/RefHash3KeysIdPool.hpp> +#include <xercesc/util/Hash2KeysSetOf.hpp> #include <xercesc/validators/common/Grammar.hpp> #include <xercesc/validators/schema/SchemaElementDecl.hpp> @@ -179,9 +180,8 @@ protected: // fAttDefRegistry // mapping from XMLAttDef instances to the count of the last // start tag where they were utilized. - // fUndeclaredAttrRegistryNS - // mapping of namespaceId/localName pairs to the count of the last - // start tag in which they occurred. + // fUndeclaredAttrRegistry + // set of namespaceId/localName pairs to detect duplicates // fPSVIAttrList // PSVI attribute list implementation that needs to be // filled when a PSVIHandler is registered @@ -203,7 +203,7 @@ protected: RefHash3KeysIdPool<SchemaElementDecl>* fElemNonDeclPool; unsigned int fElemCount; RefHashTableOf<unsigned int, PtrHasher>*fAttDefRegistry; - RefHash2KeysTableOf<unsigned int>* fUndeclaredAttrRegistryNS; + Hash2KeysSetOf<StringHasher>* fUndeclaredAttrRegistry; PSVIAttributeList * fPSVIAttrList; XSModel* fModel; PSVIElement* fPSVIElement; diff --git a/src/xercesc/internal/XSAXMLScanner.cpp b/src/xercesc/internal/XSAXMLScanner.cpp index c1094a6c5024179b3cfa50fe7f7899b1a08c1dd5..95fc54dd431972b3e666d7b95ad593166d0ad5ff 100644 --- a/src/xercesc/internal/XSAXMLScanner.cpp +++ b/src/xercesc/internal/XSAXMLScanner.cpp @@ -433,7 +433,7 @@ bool XSAXMLScanner::scanStartTag(bool& gotData) { // clean up after ourselves: // clear the map used to detect duplicate attributes - fUndeclaredAttrRegistryNS->removeAll(); + fUndeclaredAttrRegistry->removeAll(); } // Since the element may have default values, call start tag now regardless if it is empty or not @@ -603,7 +603,7 @@ void XSAXMLScanner::scanReset(const InputSource& src) // though their buckets will still be tied up resetUIntPool(); } - fUndeclaredAttrRegistryNS->removeAll(); + fUndeclaredAttrRegistry->removeAll(); } diff --git a/src/xercesc/util/Hash2KeysSetOf.c b/src/xercesc/util/Hash2KeysSetOf.c new file mode 100644 index 0000000000000000000000000000000000000000..c929100a1e86154de750b225b04a66f92fd3899a --- /dev/null +++ b/src/xercesc/util/Hash2KeysSetOf.c @@ -0,0 +1,591 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * $Id$ + */ + + +// --------------------------------------------------------------------------- +// Include +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include <xercesc/util/Hash2KeysSetOf.hpp> +#endif + +#include <xercesc/util/Janitor.hpp> +#include <xercesc/util/NullPointerException.hpp> +#include <assert.h> +#include <new> + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Constructors and Destructor +// --------------------------------------------------------------------------- + +template <class THasher> +Hash2KeysSetOf<THasher>::Hash2KeysSetOf( + const XMLSize_t modulus, + MemoryManager* const manager) + + : fMemoryManager(manager) + , fBucketList(0) + , fHashModulus(modulus) + , fCount(0) + , fAvailable(0) +{ + initialize(modulus); +} + +template <class THasher> +Hash2KeysSetOf<THasher>::Hash2KeysSetOf( + const XMLSize_t modulus, + const THasher& hasher, + MemoryManager* const manager) + + : fMemoryManager(manager) + , fBucketList(0) + , fHashModulus(modulus) + , fCount(0) + , fHasher (hasher) + , fAvailable(0) +{ + initialize(modulus); +} + +template <class THasher> +void Hash2KeysSetOf<THasher>::initialize(const XMLSize_t modulus) +{ + if (modulus == 0) + ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager); + + // Allocate the bucket list and zero them + fBucketList = (Hash2KeysSetBucketElem**) fMemoryManager->allocate + ( + fHashModulus * sizeof(Hash2KeysSetBucketElem*) + ); //new Hash2KeysSetBucketElem*[fHashModulus]; + memset(fBucketList, 0, sizeof(fBucketList[0]) * fHashModulus); +} + +template <class THasher> +Hash2KeysSetOf<THasher>::~Hash2KeysSetOf() +{ + Hash2KeysSetBucketElem* nextElem; + if(!isEmpty()) + { + // Clean up the buckets first + for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++) + { + // Get the bucket list head for this entry + Hash2KeysSetBucketElem* curElem = fBucketList[buckInd]; + while (curElem) + { + // Save the next element before we hose this one + nextElem = curElem->fNext; + fMemoryManager->deallocate(curElem); + curElem = nextElem; + } + + // Clean out this entry + fBucketList[buckInd] = 0; + } + } + // Then delete the list of available blocks + Hash2KeysSetBucketElem* curElem = fAvailable; + while (curElem) + { + // Save the next element before we hose this one + nextElem = curElem->fNext; + fMemoryManager->deallocate(curElem); + curElem = nextElem; + } + fAvailable = 0; + + // Then delete the bucket list & hasher + fMemoryManager->deallocate(fBucketList); //delete [] fBucketList; + fBucketList = 0; +} + + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Element management +// --------------------------------------------------------------------------- +template <class THasher> +bool Hash2KeysSetOf<THasher>::isEmpty() const +{ + return (fCount==0); +} + +template <class THasher> +bool Hash2KeysSetOf<THasher>::containsKey(const void* const key1, const int key2) const +{ + XMLSize_t hashVal; + const Hash2KeysSetBucketElem* findIt = findBucketElem(key1, key2, hashVal); + return (findIt != 0); +} + +template <class THasher> +void Hash2KeysSetOf<THasher>::removeKey(const void* const key1, const int key2) +{ + // Hash the key + XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // + // Search the given bucket for this key. Keep up with the previous + // element so we can patch around it. + // + Hash2KeysSetBucketElem* curElem = fBucketList[hashVal]; + Hash2KeysSetBucketElem* lastElem = 0; + + while (curElem) + { + if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) + { + if (!lastElem) + { + // It was the first in the bucket + fBucketList[hashVal] = curElem->fNext; + } + else + { + // Patch around the current element + lastElem->fNext = curElem->fNext; + } + + // Move the current element to the list of available blocks + curElem->fNext=fAvailable; + fAvailable=curElem; + + fCount--; + return; + } + + // Move both pointers upwards + lastElem = curElem; + curElem = curElem->fNext; + } + + // We never found that key + ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager); +} + +template <class THasher> +void Hash2KeysSetOf<THasher>:: +removeKey(const void* const key1) +{ + // Hash the key + XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // + // Search the given bucket for this key. Keep up with the previous + // element so we can patch around it. + // + Hash2KeysSetBucketElem* curElem = fBucketList[hashVal]; + Hash2KeysSetBucketElem* lastElem = 0; + + while (curElem) + { + if(fHasher.equals(key1, curElem->fKey1)) + { + if (!lastElem) + { + // It was the first in the bucket + fBucketList[hashVal] = curElem->fNext; + } + else + { + // Patch around the current element + lastElem->fNext = curElem->fNext; + } + + Hash2KeysSetBucketElem* toBeDeleted=curElem; + curElem = curElem->fNext; + + // Move the current element to the list of available blocks + toBeDeleted->fNext=fAvailable; + fAvailable=toBeDeleted; + + fCount--; + } + else + { + // Move both pointers upwards + lastElem = curElem; + curElem = curElem->fNext; + } + } +} + +template <class THasher> +void Hash2KeysSetOf<THasher>::removeAll() +{ + if(isEmpty()) + return; + + for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++) + { + if(fBucketList[buckInd]!=0) + { + // Advance to the end of the chain, and connect it to the list of + // available blocks + Hash2KeysSetBucketElem* curElem = fBucketList[buckInd]; + while (curElem->fNext) + curElem = curElem->fNext; + curElem->fNext=fAvailable; + fAvailable=fBucketList[buckInd]; + fBucketList[buckInd] = 0; + } + } + fCount=0; +} + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Getters +// --------------------------------------------------------------------------- +template <class THasher> +MemoryManager* Hash2KeysSetOf<THasher>::getMemoryManager() const +{ + return fMemoryManager; +} + +template <class THasher> +XMLSize_t Hash2KeysSetOf<THasher>::getHashModulus() const +{ + return fHashModulus; +} + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Putters +// --------------------------------------------------------------------------- +template <class THasher> +void Hash2KeysSetOf<THasher>::put(const void* key1, int key2) +{ + // Apply 4 load factor to find threshold. + XMLSize_t threshold = fHashModulus * 4; + + // If we've grown too big, expand the table and rehash. + if (fCount >= threshold) + rehash(); + + // First see if the key exists already + XMLSize_t hashVal; + Hash2KeysSetBucketElem* newBucket = findBucketElem(key1, key2, hashVal); + + // + // If so,then update its value. If not, then we need to add it to + // the right bucket + // + if (newBucket) + { + newBucket->fKey1 = key1; + newBucket->fKey2 = key2; + } + else + { + if(fAvailable==0) + newBucket = (Hash2KeysSetBucketElem*)fMemoryManager->allocate(sizeof(Hash2KeysSetBucketElem)); + else + { + newBucket = fAvailable; + fAvailable = fAvailable->fNext; + } + newBucket->fKey1 = key1; + newBucket->fKey2 = key2; + newBucket->fNext = fBucketList[hashVal]; + fBucketList[hashVal] = newBucket; + fCount++; + } +} + +template <class THasher> +bool Hash2KeysSetOf<THasher>::putIfNotPresent(const void* key1, int key2) +{ + // First see if the key exists already + XMLSize_t hashVal; + Hash2KeysSetBucketElem* newBucket = findBucketElem(key1, key2, hashVal); + + // + // If so,then update its value. If not, then we need to add it to + // the right bucket + // + if (newBucket) + return false; + + // Apply 4 load factor to find threshold. + XMLSize_t threshold = fHashModulus * 4; + + // If we've grown too big, expand the table and rehash. + if (fCount >= threshold) + rehash(); + + if(fAvailable==0) + newBucket = (Hash2KeysSetBucketElem*)fMemoryManager->allocate(sizeof(Hash2KeysSetBucketElem)); + else + { + newBucket = fAvailable; + fAvailable = fAvailable->fNext; + } + newBucket->fKey1 = key1; + newBucket->fKey2 = key2; + newBucket->fNext = fBucketList[hashVal]; + fBucketList[hashVal] = newBucket; + fCount++; + return true; +} + + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Private methods +// --------------------------------------------------------------------------- +template <class THasher> +inline Hash2KeysSetBucketElem* Hash2KeysSetOf<THasher>:: +findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) +{ + // Hash the key + hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // Search that bucket for the key + Hash2KeysSetBucketElem* curElem = fBucketList[hashVal]; + while (curElem) + { + if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) + return curElem; + + curElem = curElem->fNext; + } + return 0; +} + +template <class THasher> +inline const Hash2KeysSetBucketElem* Hash2KeysSetOf<THasher>:: +findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) const +{ + // Hash the key + hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // Search that bucket for the key + const Hash2KeysSetBucketElem* curElem = fBucketList[hashVal]; + while (curElem) + { + if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) + return curElem; + + curElem = curElem->fNext; + } + return 0; +} + + +template <class THasher> +void Hash2KeysSetOf<THasher>:: +rehash() +{ + const XMLSize_t newMod = (fHashModulus * 8)+1; + + Hash2KeysSetBucketElem** newBucketList = + (Hash2KeysSetBucketElem**) fMemoryManager->allocate + ( + newMod * sizeof(Hash2KeysSetBucketElem*) + );//new Hash2KeysSetBucketElem*[fHashModulus]; + + // Make sure the new bucket list is destroyed if an + // exception is thrown. + ArrayJanitor<Hash2KeysSetBucketElem*> guard(newBucketList, fMemoryManager); + + memset(newBucketList, 0, newMod * sizeof(newBucketList[0])); + + // Rehash all existing entries. + for (XMLSize_t index = 0; index < fHashModulus; index++) + { + // Get the bucket list head for this entry + Hash2KeysSetBucketElem* curElem = fBucketList[index]; + while (curElem) + { + // Save the next element before we detach this one + Hash2KeysSetBucketElem* nextElem = curElem->fNext; + + const XMLSize_t hashVal = fHasher.getHashVal(curElem->fKey1, newMod); + assert(hashVal < newMod); + + Hash2KeysSetBucketElem* newHeadElem = newBucketList[hashVal]; + + // Insert at the start of this bucket's list. + curElem->fNext = newHeadElem; + newBucketList[hashVal] = curElem; + + curElem = nextElem; + } + } + + Hash2KeysSetBucketElem** const oldBucketList = fBucketList; + + // Everything is OK at this point, so update the + // member variables. + fBucketList = guard.release(); + fHashModulus = newMod; + + // Delete the old bucket list. + fMemoryManager->deallocate(oldBucketList);//delete[] oldBucketList; + +} + + + +// --------------------------------------------------------------------------- +// Hash2KeysSetOfEnumerator: Constructors and Destructor +// --------------------------------------------------------------------------- +template <class THasher> +Hash2KeysSetOfEnumerator<THasher>:: +Hash2KeysSetOfEnumerator(Hash2KeysSetOf<THasher>* const toEnum + , const bool adopt + , MemoryManager* const manager) + : fAdopted(adopt), fCurElem(0), fCurHash((XMLSize_t)-1), fToEnum(toEnum) + , fMemoryManager(manager) + , fLockPrimaryKey(0) +{ + if (!toEnum) + ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, fMemoryManager); + + // + // Find the next available bucket element in the hash table. If it + // comes back zero, that just means the table is empty. + // + // Note that the -1 in the current hash tells it to start + // from the beginning. + // + findNext(); +} + +template <class THasher> +Hash2KeysSetOfEnumerator<THasher>::~Hash2KeysSetOfEnumerator() +{ + if (fAdopted) + delete fToEnum; +} + + +// --------------------------------------------------------------------------- +// Hash2KeysSetOfEnumerator: Enum interface +// --------------------------------------------------------------------------- +template <class THasher> +bool Hash2KeysSetOfEnumerator<THasher>::hasMoreElements() const +{ + // + // If our current has is at the max and there are no more elements + // in the current bucket, then no more elements. + // + if (!fCurElem && (fCurHash == fToEnum->fHashModulus)) + return false; + return true; +} + +template <class THasher> +void Hash2KeysSetOfEnumerator<THasher>::nextElementKey(const void*& retKey1, int& retKey2) +{ + // Make sure we have an element to return + if (!hasMoreElements()) + ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager); + + // + // Save the current element, then move up to the next one for the + // next time around. + // + Hash2KeysSetBucketElem* saveElem = fCurElem; + findNext(); + + retKey1 = saveElem->fKey1; + retKey2 = saveElem->fKey2; + + return; +} + +template <class THasher> +void Hash2KeysSetOfEnumerator<THasher>::Reset() +{ + if(fLockPrimaryKey) + fCurHash=fToEnum->fHasher.getHashVal(fLockPrimaryKey, fToEnum->fHashModulus); + else + fCurHash = (XMLSize_t)-1; + + fCurElem = 0; + findNext(); +} + + +template <class THasher> +void Hash2KeysSetOfEnumerator<THasher>::setPrimaryKey(const void* key) +{ + fLockPrimaryKey=key; + Reset(); +} + +// --------------------------------------------------------------------------- +// Hash2KeysSetOfEnumerator: Private helper methods +// --------------------------------------------------------------------------- +template <class THasher> +void Hash2KeysSetOfEnumerator<THasher>::findNext() +{ + // Code to execute if we have to return only values with the primary key + if(fLockPrimaryKey) + { + if(!fCurElem) + fCurElem = fToEnum->fBucketList[fCurHash]; + else + fCurElem = fCurElem->fNext; + while (fCurElem && (!fToEnum->fHasher.equals(fLockPrimaryKey, fCurElem->fKey1))) + fCurElem = fCurElem->fNext; + // if we didn't found it, make so hasMoreElements() returns false + if(!fCurElem) + fCurHash = fToEnum->fHashModulus; + return; + } + // + // If there is a current element, move to its next element. If this + // hits the end of the bucket, the next block will handle the rest. + // + if (fCurElem) + fCurElem = fCurElem->fNext; + + // + // If the current element is null, then we have to move up to the + // next hash value. If that is the hash modulus, then we cannot + // go further. + // + if (!fCurElem) + { + fCurHash++; + if (fCurHash == fToEnum->fHashModulus) + return; + + // Else find the next non-empty bucket + while (fToEnum->fBucketList[fCurHash]==0) + { + // Bump to the next hash value. If we max out return + fCurHash++; + if (fCurHash == fToEnum->fHashModulus) + return; + } + fCurElem = fToEnum->fBucketList[fCurHash]; + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/src/xercesc/util/Hash2KeysSetOf.hpp b/src/xercesc/util/Hash2KeysSetOf.hpp new file mode 100644 index 0000000000000000000000000000000000000000..29aa102e95469eeaddc5f4141fc63de03c6daef8 --- /dev/null +++ b/src/xercesc/util/Hash2KeysSetOf.hpp @@ -0,0 +1,223 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * $Id$ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_HASH2KEYSSETOF_HPP) +#define XERCESC_INCLUDE_GUARD_HASH2KEYSSETOF_HPP + + +#include <xercesc/util/Hashers.hpp> +#include <xercesc/util/IllegalArgumentException.hpp> +#include <xercesc/util/NoSuchElementException.hpp> +#include <xercesc/util/RuntimeException.hpp> +#include <xercesc/util/PlatformUtils.hpp> + +XERCES_CPP_NAMESPACE_BEGIN + +// This hash table is similar to Hash2KeysSetOf with an additional integer as key2 + +// Forward declare the enumerator so it can be our friend. +// +template <class THasher> +class Hash2KeysSetOfEnumerator; + +// +// This should really be a nested class, but some of the compilers we +// have to support cannot deal with that! +// +struct Hash2KeysSetBucketElem +{ + Hash2KeysSetBucketElem* fNext; + const void* fKey1; + int fKey2; +}; + + +template <class THasher> +class Hash2KeysSetOf : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + Hash2KeysSetOf( + const XMLSize_t modulus, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + Hash2KeysSetOf( + const XMLSize_t modulus, + const THasher& hasher, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + ~Hash2KeysSetOf(); + + + // ----------------------------------------------------------------------- + // Element management + // ----------------------------------------------------------------------- + bool isEmpty() const; + bool containsKey(const void* const key1, const int key2) const; + void removeKey(const void* const key1, const int key2); + void removeKey(const void* const key1); + void removeAll(); + + // ----------------------------------------------------------------------- + // Getters + // ----------------------------------------------------------------------- + MemoryManager* getMemoryManager() const; + XMLSize_t getHashModulus() const; + + // ----------------------------------------------------------------------- + // Putters + // ----------------------------------------------------------------------- + void put(const void* key1, int key2); + bool putIfNotPresent(const void* key1, int key2); + +private : + // ----------------------------------------------------------------------- + // Declare our friends + // ----------------------------------------------------------------------- + friend class Hash2KeysSetOfEnumerator<THasher>; + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Hash2KeysSetOf(const Hash2KeysSetOf<THasher>&); + Hash2KeysSetOf<THasher>& operator=(const Hash2KeysSetOf<THasher>&); + + // ----------------------------------------------------------------------- + // Private methods + // ----------------------------------------------------------------------- + Hash2KeysSetBucketElem* findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal); + const Hash2KeysSetBucketElem* findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) const; + void initialize(const XMLSize_t modulus); + void rehash(); + + + // ----------------------------------------------------------------------- + // Data members + // + // fBucketList + // This is the array that contains the heads of all of the list + // buckets, one for each possible hash value. + // + // fHashModulus + // The modulus used for this hash table, to hash the keys. This is + // also the number of elements in the bucket list. + // + // fCount + // The number of elements currently in the map + // + // fHash + // The hasher for the key1 data type. + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + Hash2KeysSetBucketElem** fBucketList; + XMLSize_t fHashModulus; + XMLSize_t fCount; + THasher fHasher; + Hash2KeysSetBucketElem* fAvailable; +}; + + + +// +// An enumerator for a value array. It derives from the basic enumerator +// class, so that value vectors can be generically enumerated. +// +template <class THasher> +class Hash2KeysSetOfEnumerator : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + Hash2KeysSetOfEnumerator(Hash2KeysSetOf<THasher>* const toEnum + , const bool adopt = false + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + virtual ~Hash2KeysSetOfEnumerator(); + + + // ----------------------------------------------------------------------- + // Enum interface + // ----------------------------------------------------------------------- + bool hasMoreElements() const; + void Reset(); + + // ----------------------------------------------------------------------- + // New interface + // ----------------------------------------------------------------------- + void nextElementKey(const void*&, int&); + void setPrimaryKey(const void* key); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Hash2KeysSetOfEnumerator(const Hash2KeysSetOfEnumerator<THasher>&); + Hash2KeysSetOfEnumerator<THasher>& operator=(const Hash2KeysSetOfEnumerator<THasher>&); + + // ----------------------------------------------------------------------- + // Private methods + // ----------------------------------------------------------------------- + void findNext(); + + + // ----------------------------------------------------------------------- + // Data Members + // + // fAdopted + // Indicates whether we have adopted the passed vector. If so then + // we delete the vector when we are destroyed. + // + // fCurElem + // This is the current bucket bucket element that we are on. + // + // fCurHash + // The is the current hash buck that we are working on. Once we hit + // the end of the bucket that fCurElem is in, then we have to start + // working this one up to the next non-empty bucket. + // + // fToEnum + // The value array being enumerated. + // + // fLockPrimaryKey + // Indicates that we are requested to iterate over the secondary keys + // associated with the given primary key + // + // ----------------------------------------------------------------------- + bool fAdopted; + Hash2KeysSetBucketElem* fCurElem; + XMLSize_t fCurHash; + Hash2KeysSetOf<THasher>* fToEnum; + MemoryManager* const fMemoryManager; + const void* fLockPrimaryKey; +}; + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include <xercesc/util/Hash2KeysSetOf.c> +#endif + +#endif