/* * MAPI 1.0 property handling routines * * RK.C - * * Two Rabin/Karp string finding functions * The two are almost identical. */ #include "_apipch.h" #define ulPrime ((ULONG) 0x00FF00F1) #define ulBase ((ULONG) 0x00000100) BOOL FRKFindSubpb(LPBYTE pbTarget, ULONG cbTarget, LPBYTE pbPattern, ULONG cbPattern) { UINT i; LPBYTE pbTargetMax = pbTarget + cbTarget; LPBYTE pbPatternMax = pbPattern + cbPattern; ULONG ulBaseToPowerMod = 1; ULONG ulHashPattern = 0; ULONG ulHashTarget = 0; if (cbPattern > cbTarget) return FALSE; // Compute the power of the left most character in base ulBase for (i = 1; i < cbPattern; i++) ulBaseToPowerMod = (ulBase * ulBaseToPowerMod) % ulPrime; // Calculate the hash function for the src (and the first dst) while (pbPattern < pbPatternMax) { ulHashPattern = (ulHashPattern*ulBase+*pbPattern) % ulPrime; ulHashTarget = (ulHashTarget*ulBase+*pbTarget) % ulPrime; pbPattern++; pbTarget++; } // Dynamically produce hash values for the string as we go for ( ;; ) { // Remember to do the memcmp for the off-chance it doesn't work // according to probability if ( ulHashPattern == ulHashTarget && !memcmp(pbPattern-cbPattern, pbTarget-cbPattern, (UINT)cbPattern)) return TRUE; // Assert because this is very unprobable #ifdef DEBUG if (ulHashPattern == ulHashTarget) DebugTrace( TEXT("This is very unprobable!\n")); #endif if (pbTarget == pbTargetMax) return FALSE; ulHashTarget = (ulHashTarget+ulBase*ulPrime- *(pbTarget-cbPattern)*ulBaseToPowerMod) % ulPrime; ulHashTarget = (ulHashTarget*ulBase+*pbTarget) % ulPrime; pbTarget++; } } // Note - 4/14/97 // Replaced FGLeadByte() with IsDBCSLeadByte() LPSTR LpszRKFindSubpsz(LPSTR pszTarget, ULONG cbTarget, LPSTR pszPattern, ULONG cbPattern, ULONG ulFuzzyLevel) { #ifdef OLDSTUFF_DBCS LCID lcid = GetUserDefaultLCID(); LANGID langID = LANGIDFROMLCID(lcid); LPBYTE pbTarget; LPBYTE pbPattern; BOOL fResult = FALSE; ULONG ulchPattern; // cbPattern in character unit. ULONG ulcbTarget = cbTarget; ULONG ulcbEndTarget; // = cbPattern at the end of pszTarget const ULONG ulCharType = UlGCharType(pszPattern); pbTarget = (LPBYTE) pszTarget; pbPattern = (LPBYTE) pszPattern; ulchPattern = ulchStrCount(pbPattern, cbPattern, langID); ulcbEndTarget = ulcbEndCount(pbTarget, cbTarget, ulchPattern, langID); if (ulcbEndTarget == 0) goto end; while(ulcbEndTarget <= ulcbTarget) { const BOOL fTargetDBCS = IsDBCSLeadByte(*pbTarget); BOOL fCompare = TRUE; if (!fTargetDBCS) { if (ulCharType & (CK_ALPHABET | CK_NUMERIC)) { if (!IsCharAlphaNumeric(*pbTarget)) fCompare = FALSE; } else { if (IsCharAlphaNumeric(*pbTarget)) fCompare = FALSE; } } if (fCompare && CompareStringA(lcid, ((ulFuzzyLevel & FL_IGNORECASE) ? NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH : 0) | ((ulFuzzyLevel & FL_LOOSE) ? NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH : 0) | ((ulFuzzyLevel & FL_IGNORENONSPACE) ? NORM_IGNORENONSPACE : 0), pbPattern, cbPattern, pbTarget, ulcbStrCount(pbTarget, ulchPattern, langID)) == 2 ) { fResult = TRUE; goto end; } // pszTarget may contain the hi-ansi characters. fTargetDBCS may // not be true. if (fTargetDBCS && ulcbTarget > 1) { ulcbTarget -= 2; pbTarget += 2; } else { ulcbTarget --; pbTarget ++; } } #else UINT i; ULONG ulBaseToPowerMod = 1; ULONG ulHashPattern = 0; ULONG ulHashTarget = 0; LCID lcid = GetUserDefaultLCID(); LPBYTE pbTarget; LPBYTE pbPattern; LPBYTE pbTargetMax; LPBYTE pbPatternMax; BOOL fResult = FALSE; CHAR *rgchHash; // Validate parameters switch (ulFuzzyLevel & (FL_IGNORECASE | FL_IGNORENONSPACE)) { default: case 0: rgchHash = (CHAR*)rgchCsds; break; case FL_IGNORECASE: rgchHash = (CHAR*)rgchCids; break; case FL_IGNORENONSPACE: rgchHash = (CHAR*)rgchCsdi; break; case FL_IGNORECASE | FL_IGNORENONSPACE: rgchHash = (CHAR*)rgchCidi; break; } // Special case for single character pattern strings if (cbPattern == 1 && cbTarget >= 1) { BYTE chPattern = (BYTE)*pszPattern; pbTarget = (LPBYTE)pszTarget; while (*pbTarget && *pbTarget != chPattern) { pbTarget++; } if (*pbTarget == chPattern) { return(pbTarget); } else { return(NULL); // not found } } //$ Is this what we want FL_LOOSE to mean? if (ulFuzzyLevel & FL_LOOSE) rgchHash = (CHAR*)rgchCids; pbTarget = (LPBYTE) pszTarget; pbPattern = (LPBYTE) pszPattern; pbTargetMax = pbTarget + cbTarget; pbPatternMax = pbPattern + cbPattern; if (cbPattern > cbTarget) goto end; // Compute the power of the left most character in base ulBase for (i = 1; i < cbPattern; i++) ulBaseToPowerMod = (ulBase * ulBaseToPowerMod) % ulPrime; // Calculate the hash function for the src (and the first dst) while (pbPattern < pbPatternMax) { ulHashPattern = (ulHashPattern*ulBase+rgchHash[*pbPattern]) % ulPrime; ulHashTarget = (ulHashTarget*ulBase+rgchHash[*pbTarget]) % ulPrime; pbPattern++; pbTarget++; } // Dynamically produce hash values for the string as we go for ( ;; ) { if (ulHashPattern == ulHashTarget) { if (CompareStringA(lcid, ((ulFuzzyLevel & FL_IGNORECASE) ? NORM_IGNORECASE : 0) | ((ulFuzzyLevel & FL_LOOSE) ? NORM_IGNORECASE : 0) | ((ulFuzzyLevel & FL_IGNORENONSPACE) ? NORM_IGNORENONSPACE : 0), pbPattern-cbPattern, (UINT)cbPattern, pbTarget-cbPattern, (UINT)cbPattern) == 2) { fResult = TRUE; pbTarget -= cbPattern; goto end; } } #ifdef DEBUG if (ulHashPattern == ulHashTarget) DebugTrace( TEXT("This is very unprobable, unless you are doing ") TEXT("FL_EXACT and an case insensitive match came up ") TEXT("(or you are on DBCS)\n")); #endif if (pbTarget == pbTargetMax) goto end; ulHashTarget = (ulHashTarget+ulBase*ulPrime- rgchHash[*(pbTarget-cbPattern)]*ulBaseToPowerMod) % ulPrime; ulHashTarget = (ulHashTarget*ulBase+rgchHash[*pbTarget]) % ulPrime; pbTarget++; } #endif end: return fResult ? pbTarget : NULL; } BOOL FRKFindSubpsz(LPSTR pszTarget, ULONG cbTarget, LPSTR pszPattern, ULONG cbPattern, ULONG ulFuzzyLevel) { return !!LpszRKFindSubpsz (pszTarget, cbTarget, pszPattern, cbPattern, ulFuzzyLevel); }