#include "../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "../simpleVariables/VarStoreImpl.hpp" #include "../simpleVariables/VarTypeStoreImpl.hpp" #include "../functionAPI/FunctionLookupImpl.hpp" #include // for datatype-uri #include "../items/impl/NodeImpl.hpp" #include // template class HashXMLChN : public XERCES_CPP_NAMESPACE_QUALIFIER HashXMLCh { // virtual unsigned int getHashVal(const void *const key, unsigned int mod, XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* const manager) { // unsigned int hashVal = 0; // if(key) { // const XMLCh* curCh = (const XMLCh *)key; // const XMLCh* end = curCh + NoOfChars; // while(*curCh && curCh < end) { // unsigned int top = hashVal >> 24; // hashVal += (hashVal * 37) + top + (unsigned int)(*curCh); // ++curCh; // } // } // // Divide by modulus // return hashVal % mod; // } // }; XPath2MemoryManagerImpl::XPath2MemoryManagerImpl() { initialise(); } XPath2MemoryManagerImpl::~XPath2MemoryManagerImpl() { releaseAll(); } void XPath2MemoryManagerImpl::reset() { releaseAll(); initialise(); } void XPath2MemoryManagerImpl::initialise() { #ifdef WIN32 fHeap=HeapCreate(HEAP_NO_SERIALIZE,128*1024,0); #else fCurrentBlock = 0; #endif fToBeReleased = 0; // fStringPool = new (this) StringPool(17, false, new (this) HashXMLChN<25>, this); fStringPool = new (this) StringPool(17, false, this); } void XPath2MemoryManagerImpl::releaseAll() { // Delete the heap for this document. This uncerimoniously yanks the storage // out from under all of the nodes in the document. Destructors are NOT called. ItemList *prev; while(fToBeReleased) { fToBeReleased->item->release(); prev = fToBeReleased->prev; delete fToBeReleased; fToBeReleased = prev; } #ifdef WIN32 HeapDestroy(fHeap); #else // Run backwards through the linked list, deleting the blocks of memory while(fCurrentBlock) { MemList *prev = fCurrentBlock->prev; delete [] ((char *)fCurrentBlock); fCurrentBlock = prev; } #endif } void *XPath2MemoryManagerImpl::allocate(size_t amount) { #ifdef WIN32 return HeapAlloc(fHeap,HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY,amount); #else char *newBlock = 0; try { newBlock = new char[amount + sizeof(MemList)]; } catch (...) {} if(!newBlock) { //ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory); throw PathanException(PathanException::RUNTIME_ERR, X("XPath2MemoryManagerImpl::allocate(): Out of memory")); } MemList *newMemList = (MemList *)newBlock; newMemList->prev = fCurrentBlock; newMemList->next = 0; if(fCurrentBlock) { fCurrentBlock->next = newMemList; } fCurrentBlock = newMemList; return (void *)(newBlock + sizeof(MemList)); #endif } void XPath2MemoryManagerImpl::deallocate(void* p) { #ifdef WIN32 HeapFree(fHeap,HEAP_NO_SERIALIZE,p); #else if(p) { char *oldBlock = ((char *)p) - sizeof(MemList); MemList *oldMemList = (MemList *)oldBlock; // Decouple the old block from the list if(oldMemList->prev) { oldMemList->prev->next = oldMemList->next; } if(oldMemList->next) { oldMemList->next->prev = oldMemList->prev; } else { // If the old block doesn't have a next, it must currently be fCurrentBlock fCurrentBlock = oldMemList->prev; } delete [] oldBlock; } #endif } void XPath2MemoryManagerImpl::markForRelease(Item* p) { ItemList *newEntry = new ItemList; newEntry->item = p; newEntry->prev = fToBeReleased; fToBeReleased = newEntry; } const XMLCh *XPath2MemoryManagerImpl::getPooledString(const XMLCh *src) { if(!src) return 0; // strings longer than 128 bytes are not pooled, as it is not probable they can be recycled if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(src) > 128) return XERCES_CPP_NAMESPACE_QUALIFIER XMLString::replicate(src, this); const XMLCh *found = fStringPool->get(src); if(found) { return found; } else { XMLCh *cloned = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::replicate(src, this); fStringPool->put(cloned, cloned); return cloned; } } const XMLCh *XPath2MemoryManagerImpl::getPooledString(const char *src) { if(!src) return 0; XMLCh *transcoded = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(src, this); if(!transcoded) return 0; // strings longer than 128 bytes are not pooled, as it is not probable they can be recycled if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(transcoded) > 128) return transcoded; const XMLCh *found = fStringPool->get(transcoded); if(found) { deallocate(transcoded); return found; } else { fStringPool->put(transcoded, transcoded); return transcoded; } } void XPath2MemoryManagerImpl::dumpStatistics() { std::cout << "Memory statistics:" << std::endl; StringPoolEnumerator e(fStringPool); unsigned int nStringCount = 0; while(e.hasMoreElements()) { e.nextElement(); ++nStringCount; } std::cout << "\tStrings in pool: " << nStringCount << std::endl; ItemList *pItemCursor = fToBeReleased; unsigned int nItemCount = 0; while(pItemCursor) { ++nItemCount; pItemCursor = pItemCursor->prev; } std::cout << "\tItems to be released: " << nItemCount << std::endl; #ifndef WIN32 MemList* pBlockCursor = fCurrentBlock; unsigned int nBlockCount=0; while(pBlockCursor) { ++nBlockCount; pBlockCursor = pBlockCursor->prev; } std::cout << "\tAllocated objects: " << nBlockCount << std::endl; #endif } const Node* XPath2MemoryManagerImpl::createNode(const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *newNode) { return new (this) NodeImpl(newNode, this); } /** create a context with parameters */ DynamicContext* XPath2MemoryManagerImpl::createContext(XERCES_CPP_NAMESPACE_QUALIFIER XMLGrammarPool* xmlgr) { return new (this) XPath2ContextImpl(this, xmlgr, 0); } /** create a collation */ Collation* XPath2MemoryManagerImpl::createCollation(CollationHelper* helper) { return new (this) CollationImpl(this,helper); } /** create a resolver */ PathanNSResolver* XPath2MemoryManagerImpl::createNSResolver(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *resolverNode) { return new (this) PathanNSResolverImpl(this, resolverNode); } /** create a store for variables */ VariableStore* XPath2MemoryManagerImpl::createVariableStore() { return new (this) VarStoreImpl(this); } /** create a store for variables */ VariableTypeStore* XPath2MemoryManagerImpl::createVariableTypeStore() { return new (this) VarTypeStoreImpl(this); } /** create a function table */ FunctionLookup* XPath2MemoryManagerImpl::createFunctionTable() { return new (this) FunctionLookupImpl(this); }