Windows-Server-2003/base/bcl/bcl_stringalgorithms.h

778 lines
20 KiB
C++

#if !defined(_WINDOWS_BCL_STRINGALGORITHMS_H_INCLUDED_)
#define _WINDOWS_BCL_STRINGALGORITHMS_H_INCLUDED_
#pragma once
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
bcl_stringalgorithms.h
Abstract:
Abstract algorithms and definitions for a string class.
Author:
Michael Grier (MGrier) 2/6/2002
Revision History:
--*/
#include <bcl_common.h>
namespace BCL {
//
// CCharacterListMatcher and friends:
//
// Matchers in general are classes which you can use as input
// to find first/span/etc. as a generalized mechanism to find
// a string or a set of characters etc.
//
// The idea is that matchers are associated with some pattern.
// This may be a literal string to match, or a set of
// characters to match or a regular expression or whatever.
//
// They have one public method, Match() which takes a
// TConstantPair and a bool ref. If the matcher object's
// pattern matches the string, the bool ref is set to true;
// otherwise false.
//
// CCharacterListMatcher treats its pattern as a set of
// characters to match; specifically ala Span/wcsspn.
//
// CCharacterStringMatcher looks rather like CCharacterListMatcher,
// but instead of a list of candidate characters to match against,
// its pattern is a literal string and a match is when the beginning
// of the candidate string passed in to Match() is equal to the
// pattern string.
//
template <typename TCallDisposition, typename TConstantPair>
class CCharacterListMatcher
{
public:
CCharacterListMatcher(const TConstantPair &rpair) : m_pair(rpair) { }
inline bool MatchesEverything() const { return m_pair.GetCount() == 0; }
inline typename TConstantPair::TCount RequiredSourceCch() const { return (m_pair.GetCount() == 0) ? 0 : 1; }
inline TCallDisposition Matches(const TConstantPair &rpair, bool &rfMatches)
{
BCL_MAYFAIL_PROLOG
rfMatches = false;
BCL_PARAMETER_CHECK(rpair.Valid());
const TConstantPair::TCount limit = m_pair.GetCount();
// If there are no characters to match against, then we could not have
// matched.
if ((limit > 0) && (rpair.GetCount() > 0))
{
const TConstantPair::TPointee ch = rpair.GetPointer()[0];
const TConstantPair::TConstantArray prgchPattern = m_pair.GetPointer();
TConstantPair::TCount i;
for (i=0; i<limit; i++)
{
if (prgchPattern[i] == ch)
{
rfMatches = true;
break;
}
}
}
BCL_MAYFAIL_EPILOG
}
protected:
TConstantPair m_pair;
}; // class CCharacterListMatcher
template <typename TCallDisposition, typename TConstantPair>
class CCharacterStringMatcher
{
public:
CCharacterStringMatcher(const TConstantPair &rpair) : m_pair(rpair) { }
inline TCallDisposition Matches(const TConstantPair &rpair, bool &rfMatches)
{
BCL_MAYFAIL_PROLOG
rfMatches = false;
BCL_PARAMETER_CHECK(rpair.Valid());
const TConstantPair::TCount cchCandidate = rpair.GetCount();
const TConstantPair::TCount cchPattern = m_pair.GetCount();
if (cchCandidate >= cchPattern)
{
if (BCL::IsMemoryEqual(rpair.GetPointer(), m_pair.GetPointer(), cchPattern * sizeof(TConstantPair::TPointee)))
{
rfMatches = true;
break;
}
}
BCL_MAYFAIL_EPILOG
}
protected:
TConstantPair m_pair;
}; // class CCharacterStringMatcher
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
__fastcall
EqualStrings(
const TConstantPair &rpair1,
const TConstantPair &rpair2,
bool &rfEquals
)
{
BCL_MAYFAIL_PROLOG
BCL_PARAMETER_CHECK(rpair1.Valid());
BCL_PARAMETER_CHECK(rpair2.Valid());
rfEquals = ((rpair1.GetCount() == rpair2.GetCount()) &&
(BCL::IsMemoryEqual(rpair1.GetPointer(), rpair2.GetPointer(), rpair1.GetCount() * sizeof(TConstantPair::TPointee))));
BCL_MAYFAIL_EPILOG_INTERNAL
} // EqualStrings()
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
__fastcall
EqualStrings(
const TConstantPair &rpair1,
typename TConstantPair::TPointee tch,
bool &rfEquals
)
{
BCL_MAYFAIL_PROLOG
BCL_PARAMETER_CHECK(rpair1.Valid());
rfEquals = ((rpair1.GetCount() == 1) && (rpair1.GetPointer()[0] == tch));
BCL_MAYFAIL_EPILOG_INTERNAL
} // EqualStrings
template <typename TCallDisposition, typename TConstantPair, typename TComparisonResult>
inline
TCallDisposition
__fastcall
CompareStrings(
const TConstantPair &rpair1,
const TConstantPair &rpair2,
TComparisonResult &rcr
)
{
BCL_MAYFAIL_PROLOG
BCL_PARAMETER_CHECK(rpair1.Valid());
BCL_PARAMETER_CHECK(rpair2.Valid());
rcr = BCL::CompareBytes<TConstantPair::TPointee, TConstantPair::TCount, TComparisonResult>(rpair1, rpair2);
BCL_MAYFAIL_EPILOG_INTERNAL
} // CompareStrings
template <typename TCallDisposition, typename TConstantPair, typename TComparisonResult>
inline
TCallDisposition
__fastcall
CompareStrings(
const TConstantPair &rpair1,
typename TConstantPair::TPointee tch,
TComparisonResult &rcr
)
{
BCL_MAYFAIL_PROLOG
BCL_PARAMETER_CHECK(rpair1.Valid());
rcr = BCL::CompareBytes<TConstantPair::TPointee, TConstantPair::TCount, TComparisonResult>(rpair1, TConstantPair(&tch, 1));
BCL_MAYFAIL_EPILOG_INTERNAL
} // CompareStrings()
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
Count(
const TConstantPair &rpair,
typename TConstantPair::TPointee tch,
typename TConstantPair::TCount &rcchFound
)
{
BCL_MAYFAIL_PROLOG;
TConstantPair::TCount i, cch = rpair.GetCount();
TConstantPair::TConstantArray prgwch = rpair.GetPointer();
rcchFound = 0;
for (i = 0; i < cch; i++)
{
if (prgwch[i] == tch)
rcchFound++;
}
BCL_MAYFAIL_EPILOG_INTERNAL;
} // Count()
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
FindFirst(
const TConstantPair &rpair,
typename TConstantPair::TPointee tch,
typename TConstantPair::TCount &richFound
)
{
BCL_MAYFAIL_PROLOG
// There doesn't seem to be a builtin to do this...
typename TConstantPair::TCount i;
typename TConstantPair::TCount cch = rpair.GetCount();
typename TConstantPair::TConstantArray prgwch = rpair.GetPointer();
richFound = cch;
for (i=0; i<cch; i++)
{
if (prgwch[i] == tch)
break;
}
richFound = i;
BCL_MAYFAIL_EPILOG_INTERNAL
} // FindFirst()
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
FindFirst(
const TConstantPair &rpair,
const TConstantPair &rpairCandidate,
typename TConstantPair::TCount &richFound
)
{
BCL_MAYFAIL_PROLOG
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
TSizeT cch = rpair.GetCount();
richFound = cch;
BCL_PARAMETER_CHECK(rpair.Valid());
BCL_PARAMETER_CHECK(rpairCandidate.Valid());
// There are some really good string searching algorithms out there.
//
// This isn't one of them. -mgrier 2/3/2002
TSizeT i;
TConstantString prgch = rpair.GetPointer();
TSizeT cchToFind = rpairCandidate.GetCount();
if (cchToFind == 0)
{
// Every string has a substring that's the null string
richFound = 0;
}
else
{
if (cchToFind <= cch)
{
TConstantString prgwchCandidate = rpairCandidate.GetPointer();
TChar ch = prgwchCandidate[0];
TSizeT cchMax = (cch - cchToFind) + 1;
for (i=0; i<cchMax; i++)
{
if (prgch[i] == ch)
{
// Hmmm... a hit. Let's look more.
if (BCL::IsMemoryEqual(&prgch[i], prgwchCandidate, cchToFind * sizeof(TChar)))
{
// well done!
richFound = i;
break;
}
}
}
}
}
BCL_MAYFAIL_EPILOG_INTERNAL
} // FindFirst()
template <typename TCallDisposition, typename TConstantPair, typename TMatcher>
inline
TCallDisposition
FindFirstMatch(
const TConstantPair &rpair,
const TMatcher &rmatcher,
typename TConstantPair::TCount &richFound
)
{
BCL_MAYFAIL_PROLOG
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
TSizeT cch = rpair.GetCount();
richFound = cch;
BCL_PARAMETER_CHECK(rpair.Valid());
// There are some really good string searching algorithms out there.
//
// This isn't one of them. -mgrier 2/3/2002
TSizeT i;
TConstantString prgch = rpair.GetPointer();
if (rmatcher.MatchesEverything())
{
richFound = 0;
}
else
{
TSizeT cchMax = (cch - rmatcher.RequiredSourceCch()) + 1;
for (i=0; i<cchMax; i++)
{
bool fFound = false;
BCL_IFCALLFAILED_EXIT(rmatcher.Matches(rpair.GetOffsetPair(i), fFound));
if (fFound)
{
// well done!
richFound = i;
break;
}
}
}
BCL_MAYFAIL_EPILOG_INTERNAL
} // FindFirst()
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
FindLast(
const TConstantPair &rpair,
typename TConstantPair::TPointee ch,
typename TConstantPair::TCount &richFound
)
{
BCL_MAYFAIL_PROLOG
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
// There doesn't seem to be a builtin to do this...
TSizeT i;
TSizeT cch = rpair.GetCount();
TConstantString prgwch = rpair.GetPointer() + cch;
richFound = cch;
for (i=cch; i>0; i--)
{
if (*--prgwch == ch)
break;
}
if (i == 0)
richFound = cch;
else
richFound = i - 1;
BCL_MAYFAIL_EPILOG_INTERNAL
} // FindLast()
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
FindLast(
const TConstantPair &rpair,
const TConstantPair &rpairCandidate,
typename TConstantPair::TCount &richFound
)
{
BCL_MAYFAIL_PROLOG
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
TSizeT cch = rpair.GetCount();
richFound = cch;
BCL_PARAMETER_CHECK(rpair.Valid());
BCL_PARAMETER_CHECK(rpairCandidate.Valid());
// There are some really good string searching algorithms out there.
//
// This isn't one of them. -mgrier 2/3/2002
TSizeT i;
TConstantString prgch = rpair.GetPointer();
TSizeT cchToFind = rpairCandidate.GetCount();
if (cchToFind == 0)
{
// Every string has a substring that's the null string. Since
// we're interested in the index of it, it's at the end of
// the string which is what richFound already is.
richFound = cch;
}
else
{
if (cchToFind <= cch)
{
TConstantString prgwchToFind = rpairCandidate.GetPointer();
TChar ch = prgwchToFind[0];
TSizeT cchMax = (cch - cchToFind) + 1;
for (i=0; i<cchMax; i++)
{
if (prgch[i] == ch)
{
// Hmmm... a hit. Let's look more.
if (BCL::IsMemoryEqual(&prgch[i], prgwchToFind, cchToFind * sizeof(TChar)))
{
// well done! Keep looking though; we want the last one...
richFound = i;
}
}
}
}
}
BCL_MAYFAIL_EPILOG_INTERNAL
} // FindLast()
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
Contains(
const TConstantPair &rpair,
typename TConstantPair::TPointee ch,
bool &rfFound
)
{
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
BCL_MAYFAIL_PROLOG
rfFound = false;
BCL_PARAMETER_CHECK(rpair.Valid());
TSizeT cch = rpair.GetCount();
TSizeT i;
TConstantString prgch = rpair.GetPointer();
for (i=0; i<cch; i++)
{
if (prgch[i] == ch)
break;
}
if (i != cch)
rfFound = true;
BCL_MAYFAIL_EPILOG_INTERNAL
}
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
Contains(
const TConstantPair &rpair,
const TConstantPair &rpairCandidate,
bool &rfFound
)
{
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
BCL_MAYFAIL_PROLOG
rfFound = false;
BCL_PARAMETER_CHECK(rpair.Valid());
BCL_PARAMETER_CHECK(rpairCandidate.Valid());
// There are some really good string searching algorithms out there.
//
// This isn't one of them. -mgrier 2/3/2002
TSizeT cch = rpair.GetCount();
TSizeT i;
TConstantString prgch = rpair.GetPointer();
TSizeT cchToFind = rpairCandidate.GetCount();
if (cchToFind == 0)
{
// Every string has a substring that's the null string
rfFound = true;
}
else
{
if (cchToFind <= cch)
{
TConstantString prgwchToFind = rpairCandidate.GetPointer();
TChar ch = prgwchToFind[0];
TSizeT cchMax = (cch - cchToFind) + 1;
for (i=0; i<cch; i++)
{
if (prgch[i] == ch)
{
// Hmmm... a hit. Let's look more.
if (BCL::IsMemoryEqual(&prgch[i], prgwchToFind, cchToFind * sizeof(TChar)))
{
// well done!
rfFound = true;
break;
}
}
}
}
}
BCL_MAYFAIL_EPILOG_INTERNAL
}
template <typename TCallDisposition, typename TConstantPair, typename TMatcher>
inline
TCallDisposition
ContainsMatch(
const TConstantPair &rpair,
const TMatcher &rmatcher,
bool &rfFound
)
{
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
BCL_MAYFAIL_PROLOG
rfFound = false;
BCL_PARAMETER_CHECK(rpair.Valid());
BCL_PARAMETER_CHECK(rpairCandidate.Valid());
// There are some really good string searching algorithms out there.
//
// This isn't one of them. -mgrier 2/3/2002
TSizeT cch = rpair.GetCount();
TSizeT i;
TConstantString prgch = rpair.GetPointer();
for (i=0; i<cch; i++)
{
bool fFound; // use a local so optimizer isn't forced to modify via ref every iteration
BCL_IFCALLFAILED_EXIT(rmatcher.Match(&prgch[i], fFound));
if (fFound)
{
rfFound = true;
break;
}
}
BCL_MAYFAIL_EPILOG_INTERNAL
}
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
__fastcall
Span(
const TConstantPair &rpairBuffer,
const TConstantPair &rpairSet,
typename TConstantPair::TCount &rich
)
{
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
BCL_MAYFAIL_PROLOG
TSizeT i;
TSizeT cchBuffer = rpairBuffer.GetCount();
TConstantString prgwchBuffer = rpairBuffer.GetPointer();
bool fFound;
for (i=0; i<cchBuffer; i++)
{
BCL_IFCALLFAILED_EXIT((BCL::Contains<TCallDisposition, TConstantPair>(rpairSet, prgwchBuffer[i], fFound)));
if (!fFound)
break;
}
rich = i;
BCL_MAYFAIL_EPILOG_INTERNAL
}
template <typename TCallDisposition, typename TConstantPair, typename TMatcher>
inline
TCallDisposition
__fastcall
SpanMatch(
const TConstantPair &rpairBuffer,
const TMatcher &rmatcher,
typename TConstantPair::TCount &rich
)
{
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
BCL_MAYFAIL_PROLOG
TSizeT i;
TSizeT cchBuffer = rpairBuffer.GetCount();
TConstantString prgwchBuffer = rpairBuffer.GetPointer();
bool fFound;
for (i=0; i<cchBuffer; i++)
{
BCL_IFCALLFAILED_EXIT(rmatcher.Match(rpairBuffer.GetOffsetPair(i), fFound));
if (!fFound)
break;
}
rich = i;
BCL_MAYFAIL_EPILOG_INTERNAL
}
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
__fastcall
ComplementSpan(
const TConstantPair &rpairBuffer,
const TConstantPair &rpairSet,
typename TConstantPair::TCount &rich
)
{
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
BCL_MAYFAIL_PROLOG
TSizeT i;
TSizeT cchBuffer = rpairBuffer.GetCount();
TConstantString prgwchBuffer = rpairBuffer.GetPointer();
bool fFound;
// This does not handle surrogates correctly
for (i=0; i<cchBuffer; i++)
{
BCL_IFCALLFAILED_EXIT((BCL::Contains<TCallDisposition, TConstantPair>(rpairSet, prgwchBuffer[i], fFound)));
if (fFound)
break;
}
rich = i;
BCL_MAYFAIL_EPILOG_INTERNAL
}
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
__fastcall
ReverseSpan(
const TConstantPair &rpairBuffer,
const TConstantPair &rpairSet,
typename TConstantPair::TCount &rich
)
{
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
BCL_MAYFAIL_PROLOG
TSizeT i;
TSizeT cchBuffer = rpairBuffer.GetCount();
TConstantString prgwchBuffer = rpairBuffer.GetPointer();
bool fFound;
// This does not handle surrogates correctly
for (i = cchBuffer; i>0; i--)
{
BCL_IFCALLFAILED_EXIT((BCL::Contains<TCallDisposition, TConstantPair>(rpairSet, prgwchBuffer[i-1], fFound)));
if (!fFound)
break;
}
rich = i;
BCL_MAYFAIL_EPILOG_INTERNAL
}
template <typename TCallDisposition, typename TConstantPair>
inline
TCallDisposition
__fastcall
ReverseComplementSpan(
const TConstantPair &rpairBuffer,
const TConstantPair &rpairSet,
typename TConstantPair::TCount &rich
)
{
typedef typename TConstantPair::TPointee TChar;
typedef typename TConstantPair::TCount TSizeT;
typedef typename TConstantPair::TConstantArray TConstantString;
BCL_MAYFAIL_PROLOG
TSizeT i;
TSizeT cchBuffer = rpairBuffer.GetCount();
TConstantString prgwchBuffer = rpairBuffer.GetPointer();
bool fFound;
// This does not handle surrogates correctly
for (i = cchBuffer; i>0; i--)
{
BCL_IFCALLFAILED_EXIT((BCL::Contains<TCallDisposition, TConstantPair>(rpairSet, prgwchBuffer[i], fFound)));
if (fFound)
break;
}
rich = i;
BCL_MAYFAIL_EPILOG_INTERNAL
}
}; // namespace BCL
#endif // !defined(_WINDOWS_BCL_STRINGALGORITHMS_H_INCLUDED_)