/* * Copyright 2001,2004 The Apache Software Foundation. * * Licensed 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: RangeTokenMap.cpp 191691 2005-06-21 17:28:38Z cargilld $ */ // --------------------------------------------------------------------------- // Includes // --------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include XERCES_CPP_NAMESPACE_BEGIN // --------------------------------------------------------------------------- // Local static data // --------------------------------------------------------------------------- static XMLMutex* sRangeTokMapMutex = 0; static XMLRegisterCleanup rangeTokMapRegistryCleanup; static XMLRegisterCleanup rangeTokMapInstanceCleanup; // --------------------------------------------------------------------------- // Local, static functions // --------------------------------------------------------------------------- static void reinitRangeTokMapMutex() { delete sRangeTokMapMutex; sRangeTokMapMutex = 0; } static XMLMutex& getRangeTokMapMutex() { if (!sRangeTokMapMutex) { XMLMutexLock lock(XMLPlatformUtils::fgAtomicMutex); // If we got here first, then register it and set the registered flag if (!sRangeTokMapMutex) { sRangeTokMapMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager); rangeTokMapRegistryCleanup.registerCleanup(reinitRangeTokMapMutex); } } return *sRangeTokMapMutex; } // --------------------------------------------------------------------------- // Static member data initialization // --------------------------------------------------------------------------- RangeTokenMap* RangeTokenMap::fInstance = 0; void XMLInitializer::initializeRangeTokenMap() { RangeTokenMap::fInstance = new RangeTokenMap(XMLPlatformUtils::fgMemoryManager); if (RangeTokenMap::fInstance) { rangeTokMapInstanceCleanup.registerCleanup(RangeTokenMap::reinitInstance); RangeTokenMap::fInstance->buildTokenRanges(); } } // --------------------------------------------------------------------------- // RangeTokenElemMap: Constructors and Destructor // --------------------------------------------------------------------------- RangeTokenElemMap::RangeTokenElemMap(unsigned int categoryId) : fCategoryId(categoryId) , fRange(0) , fNRange(0) { } RangeTokenElemMap::~RangeTokenElemMap() { } // --------------------------------------------------------------------------- // RangeTokenMap: Constructors and Destructor // --------------------------------------------------------------------------- typedef JanitorMemFunCall CleanupType; RangeTokenMap::RangeTokenMap(MemoryManager* manager) : fTokenRegistry(0) , fRangeMap(0) , fCategories(0) , fTokenFactory(0) , fMutex(manager) { CleanupType cleanup(this, &RangeTokenMap::cleanUp); try { fTokenRegistry = new (manager) RefHashTableOf(109, manager); fRangeMap = new (manager) RefHashTableOf(29, manager); fCategories = new (manager) XMLStringPool(109, manager); fTokenFactory = new (manager) TokenFactory(manager); initializeRegistry(); } catch(const OutOfMemoryException&) { cleanup.release(); throw; } cleanup.release(); } RangeTokenMap::~RangeTokenMap() { cleanUp(); } // --------------------------------------------------------------------------- // RangeTokenMap: Getter methods // --------------------------------------------------------------------------- RangeToken* RangeTokenMap::getRange(const XMLCh* const keyword, const bool complement) { if (!fTokenRegistry->containsKey(keyword)) return 0; RangeTokenElemMap* elemMap = fTokenRegistry->get(keyword); RangeToken* rangeTok = elemMap->getRangeToken(complement); if (!rangeTok) { XMLMutexLock lockInit(&fMutex); // make sure that it was not created while we were locked rangeTok = elemMap->getRangeToken(complement); if (!rangeTok) { unsigned int categId = elemMap->getCategoryId(); const XMLCh* categName = fCategories->getValueForId(categId); RangeFactory* rangeFactory = fRangeMap->get(categName); if (rangeFactory) { rangeFactory->buildRanges(this); rangeTok = elemMap->getRangeToken(complement); // see if we are complementing an existing range if (!rangeTok && complement) { rangeTok = elemMap->getRangeToken(); if (rangeTok) { rangeTok = (RangeToken*) RangeToken::complementRanges(rangeTok, fTokenFactory, fTokenRegistry->getMemoryManager()); elemMap->setRangeToken(rangeTok , complement); } } } } } return rangeTok; } // --------------------------------------------------------------------------- // RangeTokenMap: Putter methods // --------------------------------------------------------------------------- void RangeTokenMap::addCategory(const XMLCh* const categoryName) { fCategories->addOrFind(categoryName); } void RangeTokenMap::addRangeMap(const XMLCh* const categoryName, RangeFactory* const rangeFactory) { fRangeMap->put((void*)categoryName, rangeFactory); } void RangeTokenMap::addKeywordMap(const XMLCh* const keyword, const XMLCh* const categoryName) { unsigned int categId = fCategories->getId(categoryName); if (categId == 0) { ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Regex_InvalidCategoryName, categoryName, fTokenRegistry->getMemoryManager()); } if (fTokenRegistry->containsKey(keyword)) { RangeTokenElemMap* elemMap = fTokenRegistry->get(keyword); if (elemMap->getCategoryId() != categId) elemMap->setCategoryId(categId); return; } fTokenRegistry->put((void*) keyword, new RangeTokenElemMap(categId)); } // --------------------------------------------------------------------------- // RangeTokenMap: Setter methods // --------------------------------------------------------------------------- void RangeTokenMap::setRangeToken(const XMLCh* const keyword, RangeToken* const tok,const bool complement) { if (fTokenRegistry->containsKey(keyword)) { fTokenRegistry->get(keyword)->setRangeToken(tok, complement); } else { ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Regex_KeywordNotFound, keyword, fTokenRegistry->getMemoryManager()); } } // --------------------------------------------------------------------------- // RangeTokenMap: Initialization methods // --------------------------------------------------------------------------- void RangeTokenMap::initializeRegistry() { // Add categories fCategories->addOrFind(fgXMLCategory); fCategories->addOrFind(fgASCIICategory); fCategories->addOrFind(fgUnicodeCategory); fCategories->addOrFind(fgBlockCategory); // Add xml range factory RangeFactory* rangeFact = new XMLRangeFactory(); fRangeMap->put((void*)fgXMLCategory, rangeFact); rangeFact->initializeKeywordMap(this); // Add ascii range factory rangeFact = new ASCIIRangeFactory(); fRangeMap->put((void*)fgASCIICategory, rangeFact); rangeFact->initializeKeywordMap(this); // Add unicode range factory rangeFact = new UnicodeRangeFactory(); fRangeMap->put((void*)fgUnicodeCategory, rangeFact); rangeFact->initializeKeywordMap(this); // Add block range factory rangeFact = new BlockRangeFactory(); fRangeMap->put((void*)fgBlockCategory, rangeFact); rangeFact->initializeKeywordMap(this); } void RangeTokenMap::buildTokenRanges() { // Build ranges */ RangeFactory* rangeFactory = fRangeMap->get(fgXMLCategory); rangeFactory->buildRanges(this); rangeFactory = fRangeMap->get(fgASCIICategory); rangeFactory->buildRanges(this); rangeFactory = fRangeMap->get(fgUnicodeCategory); rangeFactory->buildRanges(this); rangeFactory = fRangeMap->get(fgBlockCategory); rangeFactory->buildRanges(this); } // --------------------------------------------------------------------------- // RangeTokenMap: Instance methods // --------------------------------------------------------------------------- RangeTokenMap* RangeTokenMap::instance() { if (!fInstance) { XMLMutexLock lock(&getRangeTokMapMutex()); if (!fInstance) { fInstance = new RangeTokenMap(XMLPlatformUtils::fgMemoryManager); rangeTokMapInstanceCleanup.registerCleanup(RangeTokenMap::reinitInstance); } } return (fInstance); } // --------------------------------------------------------------------------- // RangeTokenMap: helper methods // --------------------------------------------------------------------------- void RangeTokenMap::cleanUp() { delete fTokenRegistry; fTokenRegistry = 0; delete fRangeMap; fRangeMap = 0; delete fCategories; fCategories = 0; delete fTokenFactory; fTokenFactory = 0; } // ----------------------------------------------------------------------- // Notification that lazy data has been deleted // ----------------------------------------------------------------------- void RangeTokenMap::reinitInstance() { delete fInstance; fInstance = 0; } XERCES_CPP_NAMESPACE_END /** * End of file RangeTokenMap.cpp */