diff --git a/src/xercesc/internal/DGXMLScanner.cpp b/src/xercesc/internal/DGXMLScanner.cpp index fb3fabbc38895e2dc2bf0bca49d47cb5e086f510..6d3933a2832e4d91afc5d68e3b1f37f23bdff1cc 100644 --- a/src/xercesc/internal/DGXMLScanner.cpp +++ b/src/xercesc/internal/DGXMLScanner.cpp @@ -93,6 +93,7 @@ DGXMLScanner::DGXMLScanner(XMLValidator* const valToAdopt , fAttrNSList(0) , fDTDValidator(0) , fDTDGrammar(0) + , fDTDElemNonDeclPool(0) { try { @@ -128,6 +129,7 @@ DGXMLScanner::DGXMLScanner( XMLDocumentHandler* const docHandler , fAttrNSList(0) , fDTDValidator(0) , fDTDGrammar(0) + , fDTDElemNonDeclPool(0) { try { @@ -778,11 +780,20 @@ void DGXMLScanner::scanDocTypeDecl() , fEmptyNamespaceId , DTDElementDecl::Any , fGrammarPoolMemoryManager - ); - + ); rootDecl->setCreateReason(DTDElementDecl::AsRootElem); rootDecl->setExternalElemDeclaration(true); - ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl)); + if(!fUseCachedGrammar) + { + // this will break getRootElemId on DTDGrammar when + // cached grammars are in use, but + // why would one use this anyway??? + ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl)); + } else + { + // put this in the undeclared pool so it gets deleted... + rootDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)rootDecl)); + } // Skip any spaces after the name fReaderMgr.skipPastSpaces(); @@ -930,6 +941,10 @@ void DGXMLScanner::scanDocTypeDecl() fDTDGrammar = (DTDGrammar*) grammar; fGrammar = fDTDGrammar; fValidator->setGrammar(fGrammar); + // we *cannot* identify the root element on + // cached grammars; else we risk breaking multithreaded + // applications. - NG + /******* rootDecl = (DTDElementDecl*) fGrammar->getElemDecl(fEmptyNamespaceId, 0, bbRootName.getRawBuffer(), Grammar::TOP_LEVEL_SCOPE); if (rootDecl) @@ -946,6 +961,7 @@ void DGXMLScanner::scanDocTypeDecl() rootDecl->setExternalElemDeclaration(true); ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl)); } + *********/ return; } @@ -1032,18 +1048,34 @@ bool DGXMLScanner::scanStartTag(bool& gotData) // this can only be called if we are doing a DTD style validator and that // he will only look at the QName. // - // We tell him to fault in a decl if he does not find one. + // We *do not* tell him to fault in a decl if he does not find one - NG. bool wasAdded = false; - const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); - XMLElementDecl* elemDecl = fGrammar->findOrAddElemDecl + const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); + + XMLElementDecl* elemDecl = fGrammar->getElemDecl ( fEmptyNamespaceId , 0 - , 0 , qnameRawBuf , Grammar::TOP_LEVEL_SCOPE - , wasAdded ); + // look in the undeclared pool: + if(!elemDecl) + { + elemDecl = fDTDElemNonDeclPool->getByKey(qnameRawBuf); + } + if(!elemDecl) + { + wasAdded = true; + elemDecl = new (fMemoryManager) DTDElementDecl + ( + qnameRawBuf + , fEmptyNamespaceId + , DTDElementDecl::Any + , fMemoryManager + ); + elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl)); + } if (fValidate) { @@ -1802,12 +1834,14 @@ void DGXMLScanner::commonInit() // Create the Validator and init them fDTDValidator = new (fMemoryManager) DTDValidator(); initValidator(fDTDValidator); + fDTDElemNonDeclPool = new (fMemoryManager) NameIdPool<DTDElementDecl>(29, 128, fMemoryManager); } void DGXMLScanner::cleanUp() { delete fAttrNSList; delete fDTDValidator; + delete fDTDElemNonDeclPool; } diff --git a/src/xercesc/internal/DGXMLScanner.hpp b/src/xercesc/internal/DGXMLScanner.hpp index a13dd56e7b7981cf3fa60fcfc874eab124d938ca..c7b63df027d92e4551cc0fa1c8c5510baea3789f 100644 --- a/src/xercesc/internal/DGXMLScanner.hpp +++ b/src/xercesc/internal/DGXMLScanner.hpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.9 2003/09/22 19:51:41 neilg + * scanners should maintain their own pools of undeclared elements, rather than requiring grammars to do this. This makes grammar objects stateless with regard to validation. + * * Revision 1.8 2003/07/24 09:19:09 gareth * Patch for bug #20530 - Attributes which have the same expanded name are not considered duplicates. Patch by cargilld. * @@ -90,10 +93,12 @@ #include <xercesc/internal/XMLScanner.hpp> #include <xercesc/internal/ElemStack.hpp> #include <xercesc/util/ValueVectorOf.hpp> +#include <xercesc/util/NameIdPool.hpp> #include <xercesc/validators/common/Grammar.hpp> XERCES_CPP_NAMESPACE_BEGIN +class DTDElementDecl; class DTDGrammar; class DTDValidator; @@ -230,34 +235,20 @@ private : // fDTDValidator // The DTD validator instance. // - // fSchemaValidator - // The Schema validator instance. - // - // fSeeXsi - // This flag indicates a schema has been seen. - // // fElemState // fElemStateSize // Stores an element next state from DFA content model - used for // wildcard validation // - // fMatcherStack - // Stack of active XPath matchers for identity constraints. All - // active XPath matchers are notified of startElement, characters - // and endElement callbacks in order to perform their matches. - // - // fValueStoreCache - // Cache of value stores for identity constraint fields. - // - // fFieldActivator - // Activates fields within a certain scope when a selector matches - // its xpath. + // fDTDElemNonDeclPool + // registry of "faulted-in" DTD element decls // // ----------------------------------------------------------------------- ElemStack fElemStack; ValueVectorOf<XMLAttr*>* fAttrNSList; DTDValidator* fDTDValidator; DTDGrammar* fDTDGrammar; + NameIdPool<DTDElementDecl>* fDTDElemNonDeclPool; }; inline const XMLCh* DGXMLScanner::getName() const diff --git a/src/xercesc/internal/IGXMLScanner.cpp b/src/xercesc/internal/IGXMLScanner.cpp index ae88ddedccfb50671e5e5477d0539c6f417843e4..e18c88cdf5ae1be74e9439a7036e89db079e0279 100644 --- a/src/xercesc/internal/IGXMLScanner.cpp +++ b/src/xercesc/internal/IGXMLScanner.cpp @@ -106,6 +106,8 @@ IGXMLScanner::IGXMLScanner( XMLValidator* const valToAdopt , fMatcherStack(0) , fValueStoreCache(0) , fFieldActivator(0) + , fDTDElemNonDeclPool(0) + , fSchemaElemNonDeclPool(0) { try { @@ -143,6 +145,8 @@ IGXMLScanner::IGXMLScanner( XMLDocumentHandler* const docHandler , fMatcherStack(0) , fValueStoreCache(0) , fFieldActivator(0) + , fDTDElemNonDeclPool(0) + , fSchemaElemNonDeclPool(0) { try { @@ -521,6 +525,9 @@ void IGXMLScanner::commonInit() // Create schemaLocation pair info fLocationPairs = new (fMemoryManager) ValueVectorOf<XMLCh*>(8, fMemoryManager); + // create pools for undeclared elements + fDTDElemNonDeclPool = new (fMemoryManager) NameIdPool<DTDElementDecl>(29, 128, fMemoryManager); + fSchemaElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool<SchemaElementDecl>(29, true, 128, fMemoryManager); } void IGXMLScanner::cleanUp() @@ -533,6 +540,8 @@ void IGXMLScanner::cleanUp() delete fMatcherStack; delete fValueStoreCache; delete fLocationPairs; + delete fDTDElemNonDeclPool; + delete fSchemaElemNonDeclPool; } // --------------------------------------------------------------------------- @@ -1187,11 +1196,20 @@ void IGXMLScanner::scanDocTypeDecl() , fEmptyNamespaceId , DTDElementDecl::Any , fGrammarPoolMemoryManager - ); - + ); rootDecl->setCreateReason(DTDElementDecl::AsRootElem); rootDecl->setExternalElemDeclaration(true); - ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl)); + if(!fUseCachedGrammar) + { + // this will break getRootElemId on DTDGrammar when + // cached grammars are in use, but + // why would one use this anyway??? + ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl)); + } else + { + // attach this to the undeclared element pool so that it gets deleted + rootDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)rootDecl)); + } // Skip any spaces after the name fReaderMgr.skipPastSpaces(); @@ -1339,6 +1357,8 @@ void IGXMLScanner::scanDocTypeDecl() fDTDGrammar = (DTDGrammar*) grammar; fGrammar = fDTDGrammar; fValidator->setGrammar(fGrammar); + // should not be modifying cached grammars! + /******** rootDecl = (DTDElementDecl*) fGrammar->getElemDecl(fEmptyNamespaceId, 0, bbRootName.getRawBuffer(), Grammar::TOP_LEVEL_SCOPE); if (rootDecl) @@ -1355,6 +1375,7 @@ void IGXMLScanner::scanDocTypeDecl() rootDecl->setExternalElemDeclaration(true); ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl)); } + ********/ return; } @@ -1439,16 +1460,36 @@ bool IGXMLScanner::scanStartTag(bool& gotData) // he will only look at the QName. // // We tell him to fault in a decl if he does not find one. + // Actually, we *don't* tell him to fault in a decl if he does not find one- NG bool wasAdded = false; - XMLElementDecl* elemDecl = fGrammar->findOrAddElemDecl + const XMLCh *rawQName = fQNameBuf.getRawBuffer(); + XMLElementDecl* elemDecl = fGrammar->getElemDecl ( fEmptyNamespaceId , 0 - , 0 - , fQNameBuf.getRawBuffer() + , rawQName , Grammar::TOP_LEVEL_SCOPE - , wasAdded ); + // look for it in the undeclared pool: + if(!elemDecl) + { + elemDecl = fDTDElemNonDeclPool->getByKey(rawQName); + } + if(!elemDecl) + { + // we're assuming this must be a DTD element. DTD's can be + // used with or without namespaces, but schemas cannot be used without + // namespaces. + wasAdded = true; + elemDecl = new (fMemoryManager) DTDElementDecl + ( + rawQName + , fEmptyNamespaceId + , DTDElementDecl::Any + , fMemoryManager + ); + elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl)); + } // We do something different here according to whether we found the // element or not. @@ -2047,13 +2088,16 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) // this element. XMLElementDecl* elemDecl = 0; if (fGrammarType == Grammar::DTDGrammarType) { + const XMLCh *rawQName = fQNameBuf.getRawBuffer(); elemDecl = fGrammar->getElemDecl ( fEmptyNamespaceId , 0 - , fQNameBuf.getRawBuffer() + , rawQName , Grammar::TOP_LEVEL_SCOPE ); + // may have not been declared: + elemDecl = fDTDElemNonDeclPool->getByKey(rawQName); if (elemDecl) { if (elemDecl->hasAttDefs()) { XMLAttDefList& attDefList = elemDecl->getAttDefList(); @@ -2110,16 +2154,31 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) const XMLCh* original_uriStr = fGrammar->getTargetNamespace(); unsigned orgGrammarUri = fURIStringPool->getId(original_uriStr); + // REVISIT: since all this code only really + // makes sense for schemas, why can DTD validation theoretically pass + // through it? - NG if (uriId != fEmptyNamespaceId) { // Check in current grammar before switching if necessary + const XMLCh *rawQName = fQNameBuf.getRawBuffer(); elemDecl = fGrammar->getElemDecl ( uriId , nameRawBuf - , qnameRawBuf + , rawQName , currentScope ); + // may have not been declared; must look everywhere: + if (!elemDecl) + if(fGrammarType == Grammar::DTDGrammarType) + { + // should never occur in practice + elemDecl = fDTDElemNonDeclPool->getByKey(rawQName); + } + else if (fGrammarType == Grammar::SchemaGrammarType) + { + elemDecl = fSchemaElemNonDeclPool->getByKey(nameRawBuf, uriId, currentScope); + } if (!elemDecl && (orgGrammarUri != uriId)) { // not found, switch to the specified grammar @@ -2156,6 +2215,12 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) , Grammar::TOP_LEVEL_SCOPE ); + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fSchemaElemNonDeclPool->getByKey(nameRawBuf, uriId, Grammar::TOP_LEVEL_SCOPE); + } if(!elemDecl) { // still not found in specified uri // try emptyNamesapce see if element should be un-qualified. @@ -2185,12 +2250,29 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) // still not found, fault this in and issue error later // switch back to original grammar first switchGrammar(original_uriStr); - elemDecl = fGrammar->putElemDecl(uriId - , nameRawBuf - , fPrefixBuf.getRawBuffer() - , qnameRawBuf - , currentScope - , true); + if(fGrammarType == Grammar::DTDGrammarType) + { + elemDecl = new (fMemoryManager) DTDElementDecl + ( + qnameRawBuf + , uriId + , DTDElementDecl::Any + , fMemoryManager + ); + elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl)); + } else if (fGrammarType == Grammar::SchemaGrammarType) + { + elemDecl = new (fMemoryManager) SchemaElementDecl + ( + fPrefixBuf.getRawBuffer() + , nameRawBuf + , uriId + , SchemaElementDecl::Any + , Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + elemDecl->setId(fSchemaElemNonDeclPool->put((void*)elemDecl->getBaseName(), uriId, currentScope, (SchemaElementDecl*)elemDecl)); + } wasAdded = true; } } @@ -2200,7 +2282,7 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) //thus it is either a non-qualified element defined in current targetNS //or an element that is defined in the globalNS - //try unqualifed first + //try unqualified first elemDecl = fGrammar->getElemDecl ( uriId @@ -2209,6 +2291,19 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) , currentScope ); + // may have not been declared; must look everywhere: + if(!elemDecl) + if (fGrammarType == Grammar::DTDGrammarType) + { + // should never happen in practice? + elemDecl = fDTDElemNonDeclPool->getByKey(qnameRawBuf); + } + else if (fGrammarType == Grammar::SchemaGrammarType) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fSchemaElemNonDeclPool->getByKey(nameRawBuf, uriId, currentScope); + } if (!elemDecl && orgGrammarUri != fEmptyNamespaceId) { //not found, switch grammar and try globalNS bool errorCondition = !switchGrammar(XMLUni::fgZeroLenString) && fValidate; @@ -2242,16 +2337,20 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) , qnameRawBuf , Grammar::TOP_LEVEL_SCOPE ); + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fSchemaElemNonDeclPool->getByKey(nameRawBuf, uriId, Grammar::TOP_LEVEL_SCOPE); + } if (!elemDecl && orgGrammarUri != fEmptyNamespaceId) { // still Not found in specified uri // go to original Grammar again to see if element needs to be fully qualified. - const XMLCh* uriStr = getURIText(orgGrammarUri); bool errorCondition = !switchGrammar(original_uriStr) && fValidate; - if (errorCondition && !laxThisOne) - if (errorCondition && !laxThisOne) { + const XMLCh* uriStr = getURIText(orgGrammarUri); fValidator->emitError ( XMLValid::GrammarNotFound @@ -2269,7 +2368,6 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) , qnameRawBuf , currentScope ); - if (elemDecl && elemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) { fValidator->emitError ( @@ -2285,12 +2383,29 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) // still not found, fault this in and issue error later // switch back to original grammar first switchGrammar(original_uriStr); - elemDecl = fGrammar->putElemDecl(uriId - , nameRawBuf - , fPrefixBuf.getRawBuffer() - , qnameRawBuf - , currentScope - , true); + if(fGrammarType == Grammar::DTDGrammarType) + { + elemDecl = new (fMemoryManager) DTDElementDecl + ( + qnameRawBuf + , uriId + , DTDElementDecl::Any + , fMemoryManager + ); + elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl)); + } else if (fGrammarType == Grammar::SchemaGrammarType) + { + elemDecl = new (fMemoryManager) SchemaElementDecl + ( + fPrefixBuf.getRawBuffer() + , nameRawBuf + , uriId + , SchemaElementDecl::Any + , Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + elemDecl->setId(fSchemaElemNonDeclPool->put((void*)elemDecl->getBaseName(), uriId, currentScope, (SchemaElementDecl*)elemDecl)); + } wasAdded = true; } } @@ -2881,6 +2996,8 @@ Grammar* IGXMLScanner::loadDTDGrammar(const InputSource& src, // Clear out the id reference list fIDRefList->removeAll(); + // and clear out the darned undeclared DTD element pool... + fDTDElemNonDeclPool->removeAll(); if (toCache) { diff --git a/src/xercesc/internal/IGXMLScanner.hpp b/src/xercesc/internal/IGXMLScanner.hpp index 0c9f66e9572c80955d832cd092d8d463235dcef3..d7c8b453d7d6904c68788149c315e086a324d2f7 100644 --- a/src/xercesc/internal/IGXMLScanner.hpp +++ b/src/xercesc/internal/IGXMLScanner.hpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.10 2003/09/22 19:51:41 neilg + * scanners should maintain their own pools of undeclared elements, rather than requiring grammars to do this. This makes grammar objects stateless with regard to validation. + * * Revision 1.9 2003/08/14 02:56:41 knoaman * Code refactoring to improve performance of validation. * @@ -93,11 +96,14 @@ #include <xercesc/internal/XMLScanner.hpp> #include <xercesc/internal/ElemStack.hpp> #include <xercesc/util/KVStringPair.hpp> +#include <xercesc/util/NameIdPool.hpp> +#include <xercesc/util/RefHash3KeysIdPool.hpp> #include <xercesc/validators/common/Grammar.hpp> #include <xercesc/validators/schema/SchemaElementDecl.hpp> XERCES_CPP_NAMESPACE_BEGIN +class DTDElementDecl; class DTDGrammar; class DTDValidator; class SchemaValidator; @@ -316,6 +322,10 @@ private : // fFieldActivator // Activates fields within a certain scope when a selector matches // its xpath. + // fDTDElemNonDeclPool + // registry of "faulted-in" DTD element decls + // fSchemaElemNonDeclPool + // registry for elements without decls in the grammar // // ----------------------------------------------------------------------- bool fSeeXsi; @@ -332,6 +342,8 @@ private : ValueStoreCache* fValueStoreCache; FieldActivator* fFieldActivator; ValueVectorOf<XMLCh*>* fLocationPairs; + NameIdPool<DTDElementDecl>* fDTDElemNonDeclPool; + RefHash3KeysIdPool<SchemaElementDecl>* fSchemaElemNonDeclPool; }; inline const XMLCh* IGXMLScanner::getName() const diff --git a/src/xercesc/internal/SGXMLScanner.cpp b/src/xercesc/internal/SGXMLScanner.cpp index 5967c47cde2c0ef7fdd7571c081985275b9cb2ab..401c644cce0e1cb439279399c3edf65a4986ad24 100644 --- a/src/xercesc/internal/SGXMLScanner.cpp +++ b/src/xercesc/internal/SGXMLScanner.cpp @@ -106,6 +106,7 @@ SGXMLScanner::SGXMLScanner( XMLValidator* const valToAdopt , fMatcherStack(0) , fValueStoreCache(0) , fFieldActivator(0) + , fElemNonDeclPool(0) { try { @@ -148,6 +149,7 @@ SGXMLScanner::SGXMLScanner( XMLDocumentHandler* const docHandler , fMatcherStack(0) , fValueStoreCache(0) , fFieldActivator(0) + , fElemNonDeclPool(0) { try { @@ -1205,7 +1207,12 @@ bool SGXMLScanner::scanStartTag(bool& gotData) , qnameRawBuf , currentScope ); - + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, currentScope); + } if (!elemDecl && (orgGrammarUri != uriId)) { // not found, switch to the specified grammar const XMLCh* uriStr = getURIText(uriId); @@ -1240,7 +1247,12 @@ bool SGXMLScanner::scanStartTag(bool& gotData) , qnameRawBuf , Grammar::TOP_LEVEL_SCOPE ); - + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, Grammar::TOP_LEVEL_SCOPE); + } if(!elemDecl) { // still not found in specified uri // try emptyNamesapce see if element should be un-qualified. @@ -1250,8 +1262,7 @@ bool SGXMLScanner::scanStartTag(bool& gotData) , nameRawBuf , qnameRawBuf , currentScope - ); - + ); bool errorCondition = elemDecl && elemDecl->getCreateReason() != XMLElementDecl::JustFaultIn; if (errorCondition && fValidate) { fValidator->emitError @@ -1271,12 +1282,16 @@ bool SGXMLScanner::scanStartTag(bool& gotData) // still not found, fault this in and issue error later // switch back to original grammar first switchGrammar(original_uriStr); - elemDecl = fGrammar->putElemDecl(uriId - , nameRawBuf - , fPrefixBuf.getRawBuffer() - , qnameRawBuf - , currentScope - , true); + elemDecl = new (fMemoryManager) SchemaElementDecl + ( + fPrefixBuf.getRawBuffer() + , nameRawBuf + , uriId + , SchemaElementDecl::Any + , Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + elemDecl->setId(fElemNonDeclPool->put((void*)elemDecl->getBaseName(), uriId, currentScope, (SchemaElementDecl*)elemDecl)); wasAdded = true; } } @@ -1294,7 +1309,12 @@ bool SGXMLScanner::scanStartTag(bool& gotData) , qnameRawBuf , currentScope ); - + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, currentScope); + } if (!elemDecl && orgGrammarUri != fEmptyNamespaceId) { //not found, switch grammar and try globalNS bool errorCondition = !switchGrammar(XMLUni::fgZeroLenString) && fValidate; @@ -1329,7 +1349,12 @@ bool SGXMLScanner::scanStartTag(bool& gotData) , qnameRawBuf , Grammar::TOP_LEVEL_SCOPE ); - + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, Grammar::TOP_LEVEL_SCOPE); + } if (!elemDecl && orgGrammarUri != fEmptyNamespaceId) { // still Not found in specified uri // go to original Grammar again to see if element needs to be fully qualified. @@ -1354,7 +1379,6 @@ bool SGXMLScanner::scanStartTag(bool& gotData) , qnameRawBuf , currentScope ); - if (elemDecl && elemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) { fValidator->emitError ( @@ -1370,14 +1394,17 @@ bool SGXMLScanner::scanStartTag(bool& gotData) // still not found, fault this in and issue error later // switch back to original grammar first switchGrammar(original_uriStr); - elemDecl = fGrammar->putElemDecl(uriId - , nameRawBuf - , fPrefixBuf.getRawBuffer() - , qnameRawBuf - , currentScope - , true); + elemDecl = new (fMemoryManager) SchemaElementDecl + ( + fPrefixBuf.getRawBuffer() + , nameRawBuf + , uriId + , SchemaElementDecl::Any + , Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + elemDecl->setId(fElemNonDeclPool->put((void*)elemDecl->getBaseName(), uriId, currentScope, (SchemaElementDecl*)elemDecl)); wasAdded = true; - } } @@ -1578,7 +1605,7 @@ bool SGXMLScanner::scanStartTag(bool& gotData) , false , isRoot ); - } + } // may be where we output something... // If empty, validate content right now if we are validating and then // pop the element stack top. Else, we have to update the current stack @@ -1902,6 +1929,7 @@ void SGXMLScanner::commonInit() fEntityTable->put((void*) XMLUni::fgGT, chCloseAngle); fEntityTable->put((void*) XMLUni::fgQuot, chDoubleQuote); fEntityTable->put((void*) XMLUni::fgApos, chSingleQuote); + fElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool<SchemaElementDecl>(29, true, 128, fMemoryManager); } void SGXMLScanner::cleanUp() @@ -1914,6 +1942,7 @@ void SGXMLScanner::cleanUp() delete fFieldActivator; delete fMatcherStack; delete fValueStoreCache; + delete fElemNonDeclPool; } void SGXMLScanner::resizeElemState() { diff --git a/src/xercesc/internal/SGXMLScanner.hpp b/src/xercesc/internal/SGXMLScanner.hpp index 5c5679892e77810614b69e266fec39a56d5f3717..88306791c82ca8b163927bf302dae5195dc9d5c5 100644 --- a/src/xercesc/internal/SGXMLScanner.hpp +++ b/src/xercesc/internal/SGXMLScanner.hpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.9 2003/09/22 19:51:41 neilg + * scanners should maintain their own pools of undeclared elements, rather than requiring grammars to do this. This makes grammar objects stateless with regard to validation. + * * Revision 1.8 2003/07/10 19:47:23 peiyongz * Stateless Grammar: Initialize scanner with grammarResolver, * creating grammar through grammarPool @@ -91,13 +94,14 @@ #include <xercesc/internal/ElemStack.hpp> #include <xercesc/util/KVStringPair.hpp> #include <xercesc/util/ValueHashTableOf.hpp> +#include <xercesc/util/RefHash3KeysIdPool.hpp> #include <xercesc/validators/common/Grammar.hpp> #include <xercesc/validators/schema/SchemaElementDecl.hpp> XERCES_CPP_NAMESPACE_BEGIN -class SchemaValidator; class SchemaGrammar; +class SchemaValidator; class ValueStoreCache; class XPathMatcherStack; class FieldActivator; @@ -306,6 +310,8 @@ private : // fFieldActivator // Activates fields within a certain scope when a selector matches // its xpath. + // fElemNonDeclPool + // registry for elements without decls in the grammar // // ----------------------------------------------------------------------- bool fSeeXsi; @@ -321,6 +327,7 @@ private : XPathMatcherStack* fMatcherStack; ValueStoreCache* fValueStoreCache; FieldActivator* fFieldActivator; + RefHash3KeysIdPool<SchemaElementDecl>* fElemNonDeclPool; }; inline const XMLCh* SGXMLScanner::getName() const