/* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #ifndef _VARIABLESTORETEMPLATE_HPP #define _VARIABLESTORETEMPLATE_HPP #include #include #include #include #include #include "VarHashEntry.hpp" #include #include template class VarHashEntry; class XPath2MemoryManager; /** This is the wrapper class for the variable store, which implements the lookup and scoping of simple variables. */ template class VariableStoreTemplate { public: typedef Scope MyScope; VariableStoreTemplate(XPath2MemoryManager *memMgr); /** default destructor */ ~VariableStoreTemplate() {}; void clear(); void addScope(typename MyScope::Type type); /** Removes the top level scope from the store. To be called at the end of methods to implement scoping. */ void removeScope(); /** Declares and/or sets a variable in the global scope. */ void setGlobalVar(const XMLCh* namespaceURI, const XMLCh* name, const TYPE &value); /** Deletes a variable from the global scope. */ void delGlobalVar(const XMLCh* namespaceURI, const XMLCh* name); /** Gets a variable from the global scope */ VarHashEntry* getGlobalVar(const XMLCh* namespaceURI, const XMLCh* name) const; /** Declare a var in the top level scope (A full set of these namespaceURI/name pair methods should be made) */ void declareVar(const XMLCh* namespaceURI, const XMLCh* name, const TYPE &value); /** Declares and/or sets a variable in the top level scope. */ void setVar(const XMLCh* namespaceURI, const XMLCh* name, const TYPE &value); /** Looks up the value of a variable in the current scope, using ident as an qname. Returns the VarHashEntry for the variable, or null if it doesn't exist*/ VarHashEntry* getVar(const XMLCh* namespaceURI, const XMLCh* name) const; /** Deletes a variable from the current scope. */ void delVar(const XMLCh* namespaceURI, const XMLCh* name); const MyScope *getCurrentScope() const { return _current; } const MyScope *getGlobalScope() const { return _global; } const XMLCh *lookUpNamespace(unsigned int nsID) const { return _uriPool.getValueForId(nsID); } private: /** find routine which returns the scope in the hash table which contains the identifiers, or the current/global one if it can't be found. */ MyScope* find(unsigned int nsID, const XMLCh* name) const; XERCES_CPP_NAMESPACE_QUALIFIER XMLStringPool _uriPool; XPath2MemoryManager* _memMgr; MyScope *_global, *_current; }; template VariableStoreTemplate::VariableStoreTemplate(XPath2MemoryManager* memMgr) : _uriPool(17, memMgr) { _memMgr=memMgr; _global=new (_memMgr) MyScope(_memMgr, MyScope::GLOBAL_SCOPE); _current=NULL; } template void VariableStoreTemplate::clear() { // Remove all the scopes while(_current) { removeScope(); } // Clear the global scope _global->clear(); } template void VariableStoreTemplate::addScope(typename MyScope::Type type) { MyScope* newCurrent=new (_memMgr) MyScope(_memMgr, type); newCurrent->setNext(_current); _current=newCurrent; } template void VariableStoreTemplate::removeScope() { assert( _current!=NULL ); MyScope* newCurrent=_current->getNext(); _current->release(); // make it available for reuse _current=newCurrent; } template void VariableStoreTemplate::setGlobalVar(const XMLCh* namespaceURI, const XMLCh* name, const TYPE &value) { if(!_uriPool.exists(namespaceURI)) namespaceURI=_memMgr->getPooledString(namespaceURI); unsigned int nsID=_uriPool.addOrFind(namespaceURI); VarHashEntry* result=_global->get(nsID, name); if(result) result->setValue(value); else _global->put(nsID, name, new (_memMgr) VarHashEntryImpl(value)); } template void VariableStoreTemplate::setVar(const XMLCh* namespaceURI, const XMLCh* name, const TYPE &value) { if(!_uriPool.exists(namespaceURI)) namespaceURI=_memMgr->getPooledString(namespaceURI); unsigned int nsID=_uriPool.addOrFind(namespaceURI); MyScope* scope=find(nsID, name); VarHashEntry* result = scope->get(nsID, name); if(result) result->setValue(value); else scope->put(nsID, name, new (_memMgr) VarHashEntryImpl(value)); } template void VariableStoreTemplate::declareVar(const XMLCh* namespaceURI, const XMLCh* name, const TYPE &value) { if(!_uriPool.exists(namespaceURI)) namespaceURI=_memMgr->getPooledString(namespaceURI); unsigned int nsID=_uriPool.addOrFind(namespaceURI); _current->put(nsID, name, new (_memMgr) VarHashEntryImpl(value)); } /** Returns a null VarHashEntry if unsuccessful */ template VarHashEntry* VariableStoreTemplate::getVar(const XMLCh* namespaceURI, const XMLCh* name) const { unsigned int nsID=_uriPool.getId(namespaceURI); // if the namespace is not in the map, the variable is not there neither if(nsID!=0) return find(nsID, name)->get(nsID, name); return NULL; } template VarHashEntry* VariableStoreTemplate::getGlobalVar(const XMLCh* namespaceURI, const XMLCh* name) const { unsigned int nsID=_uriPool.getId(namespaceURI); // if the namespace is not in the map, the variable is not there neither if(nsID!=0) return _global->get(nsID, name); return 0; } template void VariableStoreTemplate::delVar( const XMLCh* namespaceURI, const XMLCh* name) { unsigned int nsID=_uriPool.getId(namespaceURI); // if the namespace is not in the map, the variable is not there neither if(nsID!=0) find(nsID, name)->remove(nsID, name); } template void VariableStoreTemplate::delGlobalVar( const XMLCh* namespaceURI, const XMLCh* name) { unsigned int nsID=_uriPool.getId(namespaceURI); // if the namespace is not in the map, the variable is not there neither if(nsID!=0) _global->remove(nsID, name); } template typename VariableStoreTemplate::MyScope* VariableStoreTemplate::find(unsigned int nsID, const XMLCh* name) const { // Check the local scopes MyScope* index=_current; while(index) { if(index->get(nsID, name)!=NULL) return index; if(index->getType() == MyScope::LOCAL_SCOPE) break; index=index->getNext(); } // Check the global scope if(_global->get(nsID, name)!=NULL) return _global; // If we can't find it anywhere, then return the top level scope. // This lets us set it in the correct place. // For gets, we could return any scope. return _current==NULL?_global:_current; } #endif