You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
6.6 KiB
262 lines
6.6 KiB
/*
|
|
* 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);
|
|
}
|
|
|