GME  13
BMPattern.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  * 
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  * 
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: BMPattern.cpp 678879 2008-07-22 20:05:05Z amassari $
00020  */
00021 
00022 // ---------------------------------------------------------------------------
00023 //  Includes
00024 // ---------------------------------------------------------------------------
00025 #include <xercesc/util/regx/BMPattern.hpp>
00026 #include <xercesc/util/XMLString.hpp>
00027 #include <xercesc/util/Janitor.hpp>
00028 #include <xercesc/framework/MemoryManager.hpp>
00029 #include <xercesc/util/OutOfMemoryException.hpp>
00030 
00031 XERCES_CPP_NAMESPACE_BEGIN
00032 
00033 // ---------------------------------------------------------------------------
00034 //  BMPattern: Constructors
00035 // ---------------------------------------------------------------------------
00036 
00037 typedef JanitorMemFunCall<BMPattern>    CleanupType;
00038 
00039 BMPattern::BMPattern( const XMLCh*         const pattern
00040                     ,       bool                 ignoreCase
00041                     ,       MemoryManager* const manager) :
00042 
00043     fIgnoreCase(ignoreCase)
00044     , fShiftTableLen(256)
00045     , fShiftTable(0)
00046     , fPattern(0)
00047     , fUppercasePattern(0)
00048     , fMemoryManager(manager)
00049 {
00050     CleanupType cleanup(this, &BMPattern::cleanUp);
00051 
00052     try {
00053         fPattern = XMLString::replicate(pattern, fMemoryManager);
00054         initialize();
00055     }
00056     catch(const OutOfMemoryException&)
00057     {
00058         cleanup.release();
00059 
00060         throw;
00061     }
00062 
00063     cleanup.release();
00064 }
00065 
00066 BMPattern::BMPattern( const XMLCh*         const pattern
00067                     ,       int                  tableSize
00068                     ,       bool                 ignoreCase
00069                     ,       MemoryManager* const manager) :
00070 
00071     fIgnoreCase(ignoreCase)
00072     , fShiftTableLen(tableSize)
00073     , fShiftTable(0)
00074     , fPattern(0)
00075     , fUppercasePattern(0)
00076     , fMemoryManager(manager)
00077 {
00078     CleanupType cleanup(this, &BMPattern::cleanUp);
00079 
00080     try {
00081         fPattern = XMLString::replicate(pattern, fMemoryManager);
00082         initialize();
00083     }
00084     catch(const OutOfMemoryException&)
00085     {
00086         cleanup.release();
00087 
00088         throw;
00089     }
00090 
00091     cleanup.release();
00092 }
00093 
00094 BMPattern::~BMPattern() {
00095 
00096     cleanUp();
00097 }
00098 
00099 // ---------------------------------------------------------------------------
00100 //  BMPattern: matches methods
00101 // ---------------------------------------------------------------------------
00102 int BMPattern::matches(const XMLCh* const content, XMLSize_t start, XMLSize_t limit) const {
00103 
00104     const XMLSize_t patternLen = XMLString::stringLen(fPattern);
00105     // Uppercase Content
00106     XMLCh* ucContent = 0;
00107 
00108     if (patternLen == 0)
00109         return (int)start;
00110 
00111     if (fIgnoreCase) {
00112         
00113         ucContent = XMLString::replicate(content, fMemoryManager);
00114         XMLString::upperCase(ucContent);
00115     }
00116 
00117     ArrayJanitor<XMLCh> janUCContent(ucContent, fMemoryManager);
00118 
00119     XMLSize_t index = start + patternLen;
00120 
00121     while (index <= limit) {
00122 
00123         XMLSize_t patternIndex = patternLen;
00124         XMLSize_t nIndex = index + 1;
00125         XMLCh ch = 0;
00126 
00127         while (patternIndex > 0) {
00128 
00129             ch = content[--index];
00130 
00131             if (ch != fPattern[--patternIndex]) {
00132 
00133                 // No match, so we will break. But first we have
00134                 // to check the ignore case flag. If it is set, then
00135                 // we try to match with the case ignored
00136                 if (!fIgnoreCase ||
00137                     (fUppercasePattern[patternIndex] != ucContent[index]))
00138                     break;
00139             }
00140 
00141             if (patternIndex == 0)
00142                 return (int)index;
00143         }
00144 
00145         index += fShiftTable[ch % fShiftTableLen] + 1;
00146 
00147         if (index < nIndex)
00148             index = nIndex;
00149     }
00150 
00151     return -1;
00152 }
00153 
00154 // ---------------------------------------------------------------------------
00155 //  BMPattern: private helpers methods
00156 // ---------------------------------------------------------------------------
00157 void BMPattern::initialize() {
00158 
00159     const XMLSize_t patternLen = XMLString::stringLen(fPattern);
00160     XMLCh* lowercasePattern = 0;
00161 
00162     fShiftTable = (XMLSize_t*) fMemoryManager->allocate(fShiftTableLen*sizeof(XMLSize_t)); //new XMLSize_t[fShiftTableLen];
00163 
00164     if (fIgnoreCase) {
00165 
00166         fUppercasePattern = XMLString::replicate(fPattern, fMemoryManager);
00167         lowercasePattern = XMLString::replicate(fPattern, fMemoryManager);
00168         XMLString::upperCase(fUppercasePattern);
00169         XMLString::lowerCase(lowercasePattern);
00170     }
00171 
00172     ArrayJanitor<XMLCh> janLowercase(lowercasePattern, fMemoryManager);
00173 
00174     for (unsigned int i=0; i< fShiftTableLen; i++)
00175         fShiftTable[i] = patternLen;
00176 
00177     for (unsigned int k=0; k< patternLen; k++) {
00178 
00179         XMLCh      ch = fPattern[k];
00180         XMLSize_t diff = patternLen - k - 1;
00181         int          index = ch % fShiftTableLen;
00182 
00183         if (diff < fShiftTable[index])
00184             fShiftTable[index] = diff;
00185 
00186         if (fIgnoreCase) {
00187 
00188             for (int j=0; j< 2; j++) {
00189 
00190                 ch = (j == 0) ? fUppercasePattern[k] : lowercasePattern[k];
00191                 index = ch % fShiftTableLen;
00192 
00193                 if (diff < fShiftTable[index])
00194                     fShiftTable[index] = diff;
00195             }
00196         }
00197     }
00198 }
00199 
00200 // ---------------------------------------------------------------------------
00201 //  BMPattern: Cleanup
00202 // ---------------------------------------------------------------------------
00203 void BMPattern::cleanUp() {
00204 
00205     fMemoryManager->deallocate(fPattern);//delete [] fPattern;
00206     fMemoryManager->deallocate(fUppercasePattern);//delete [] fUppercasePattern;
00207     fMemoryManager->deallocate(fShiftTable);
00208 }
00209 
00210 XERCES_CPP_NAMESPACE_END
00211