| /* |
| * 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: RangeTokenMap.cpp 568078 2007-08-21 11:43:25Z amassari $ |
| */ |
| |
| // --------------------------------------------------------------------------- |
| // Includes |
| // --------------------------------------------------------------------------- |
| #include <xercesc/util/regx/RangeTokenMap.hpp> |
| #include <xercesc/util/regx/RangeToken.hpp> |
| #include <xercesc/util/regx/RegxDefs.hpp> |
| #include <xercesc/util/regx/TokenFactory.hpp> |
| #include <xercesc/util/regx/XMLRangeFactory.hpp> |
| #include <xercesc/util/regx/ASCIIRangeFactory.hpp> |
| #include <xercesc/util/regx/UnicodeRangeFactory.hpp> |
| #include <xercesc/util/regx/BlockRangeFactory.hpp> |
| #include <xercesc/util/PlatformUtils.hpp> |
| #include <xercesc/util/XMLExceptMsgs.hpp> |
| #include <xercesc/util/XMLRegisterCleanup.hpp> |
| #include <xercesc/util/StringPool.hpp> |
| #include <xercesc/util/XMLInitializer.hpp> |
| #include <xercesc/util/OutOfMemoryException.hpp> |
| |
| 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<RangeTokenMap> 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<RangeTokenElemMap>(109, manager); |
| fRangeMap = new (manager) RefHashTableOf<RangeFactory>(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 |
| */ |