#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 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 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 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 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 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 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(rpair1, rpair2); BCL_MAYFAIL_EPILOG_INTERNAL } // CompareStrings template inline TCallDisposition __fastcall CompareStrings( const TConstantPair &rpair1, typename TConstantPair::TPointee tch, TComparisonResult &rcr ) { BCL_MAYFAIL_PROLOG BCL_PARAMETER_CHECK(rpair1.Valid()); rcr = BCL::CompareBytes(rpair1, TConstantPair(&tch, 1)); BCL_MAYFAIL_EPILOG_INTERNAL } // CompareStrings() template 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 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 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 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 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 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 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 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 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 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(rpairSet, prgwchBuffer[i], fFound))); if (!fFound) break; } rich = i; BCL_MAYFAIL_EPILOG_INTERNAL } template 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 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(rpairSet, prgwchBuffer[i], fFound))); if (fFound) break; } rich = i; BCL_MAYFAIL_EPILOG_INTERNAL } template 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(rpairSet, prgwchBuffer[i-1], fFound))); if (!fFound) break; } rich = i; BCL_MAYFAIL_EPILOG_INTERNAL } template 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(rpairSet, prgwchBuffer[i], fFound))); if (fFound) break; } rich = i; BCL_MAYFAIL_EPILOG_INTERNAL } }; // namespace BCL #endif // !defined(_WINDOWS_BCL_STRINGALGORITHMS_H_INCLUDED_)