From afaf2552468f79201ac88bb9a4d2b76e7365325a Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 17 Feb 2015 14:45:28 +0100 Subject: [PATCH] CString::WildCmp(): add an optional case-sensitivity argument It's getting a common pattern to call AsLower() or MakeLower() on the arguments passed to WildCmp(), we might as well add this for convenience. It's tempting to make it case-insensitive by default, since pretty much any IRC related comparison should be, but that could potentially break some existing code. --- include/znc/ZNCString.h | 12 +++++++++--- src/ZNCString.cpp | 14 ++++++++++---- test/StringTest.cpp | 31 ++++++++++++++++++++++++++----- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/include/znc/ZNCString.h b/include/znc/ZNCString.h index 32f9b3d6..97f5ecc1 100644 --- a/include/znc/ZNCString.h +++ b/include/znc/ZNCString.h @@ -169,20 +169,26 @@ public: */ bool Equals(const CString& s, bool bCaseSensitive, CString::size_type uLen = CString::npos) const; /** - * Do a wildcard comparision between two strings. + * Do a wildcard comparison between two strings. * For example, the following returns true: * WildCmp("*!?bar@foo", "I_am!~bar@foo"); * @param sWild The wildcards used for the comparison. * @param sString The string that is used for comparing. + * @param cs CaseSensitive (default) if you want the comparison + * to be case sensitive, CaseInsensitive otherwise. + * @todo Make cs CaseInsensitive by default. * @return true if the wildcard matches. */ - static bool WildCmp(const CString& sWild, const CString& sString); + static bool WildCmp(const CString& sWild, const CString& sString, CaseSensitivity cs = CaseSensitive); /** * Do a wild compare on this string. * @param sWild The wildcards used to for the comparison. + * @param cs CaseSensitive (default) if you want the comparison + * to be case sensitive, CaseInsensitive otherwise. + * @todo Make cs CaseInsensitive by default. * @return The result of this->WildCmp(sWild, *this);. */ - bool WildCmp(const CString& sWild) const; + bool WildCmp(const CString& sWild, CaseSensitivity cs = CaseSensitive) const; /** * Turn all characters in this string into their upper-case equivalent. diff --git a/src/ZNCString.cpp b/src/ZNCString.cpp index 8b1ffff6..550a3e8b 100644 --- a/src/ZNCString.cpp +++ b/src/ZNCString.cpp @@ -95,9 +95,15 @@ bool CString::Equals(const CString& s, bool bCaseSensitive, CString::size_type u } } -bool CString::WildCmp(const CString& sWild, const CString& sString) { +bool CString::WildCmp(const CString& sWild, const CString& sString, CaseSensitivity cs) { + // avoid a copy when cs == CaseSensitive (C++ deliberately specifies that binding + // a temporary object to a reference to const on the stack lengthens the lifetime + // of the temporary to the lifetime of the reference itself) + const CString& sWld = (cs == CaseSensitive ? sWild : sWild.AsLower()); + const CString& sStr = (cs == CaseSensitive ? sString : sString.AsLower()); + // Written by Jack Handy - jakkhandy@hotmail.com - const char *wild = sWild.c_str(), *CString = sString.c_str(); + const char *wild = sWld.c_str(), *CString = sStr.c_str(); const char *cp = NULL, *mp = NULL; while ((*CString) && (*wild != '*')) { @@ -133,8 +139,8 @@ bool CString::WildCmp(const CString& sWild, const CString& sString) { return (*wild == 0); } -bool CString::WildCmp(const CString& sWild) const { - return CString::WildCmp(sWild, *this); +bool CString::WildCmp(const CString& sWild, CaseSensitivity cs) const { + return CString::WildCmp(sWild, *this, cs); } CString& CString::MakeUpper() { diff --git a/test/StringTest.cpp b/test/StringTest.cpp index ee20786b..5261c3fd 100644 --- a/test/StringTest.cpp +++ b/test/StringTest.cpp @@ -85,11 +85,32 @@ TEST(StringTest, Cmp) { } TEST(StringTest, Wild) { - EXPECT_TRUE(CString::WildCmp("*!?bar@foo", "I_am!~bar@foo")); - EXPECT_TRUE(CString::WildCmp("", "")); - EXPECT_TRUE(CString::WildCmp("*a*b*c*", "abc")); - EXPECT_TRUE(CString::WildCmp("*a*b*c*", "axbyc")); - EXPECT_FALSE(CString::WildCmp("*a*b*c*", "xy")); + EXPECT_TRUE(CString::WildCmp("", "", CString::CaseSensitive)); + EXPECT_TRUE(CString::WildCmp("", "", CString::CaseInsensitive)); + + EXPECT_FALSE(CString::WildCmp("*a*b*c*", "xy", CString::CaseSensitive)); + EXPECT_FALSE(CString::WildCmp("*a*b*c*", "xy", CString::CaseInsensitive)); + + EXPECT_TRUE(CString::WildCmp("*!?bar@foo", "I_am!~bar@foo", CString::CaseSensitive)); + EXPECT_TRUE(CString::WildCmp("*!?bar@foo", "I_am!~bar@foo", CString::CaseInsensitive)); + + EXPECT_FALSE(CString::WildCmp("*!?BAR@foo", "I_am!~bar@foo", CString::CaseSensitive)); + EXPECT_TRUE (CString::WildCmp("*!?BAR@foo", "I_am!~bar@foo", CString::CaseInsensitive)); + + EXPECT_TRUE(CString::WildCmp("*a*b*c*", "abc", CString::CaseSensitive)); + EXPECT_TRUE(CString::WildCmp("*a*b*c*", "abc", CString::CaseInsensitive)); + + EXPECT_FALSE(CString::WildCmp("*A*b*c*", "abc", CString::CaseSensitive)); + EXPECT_TRUE (CString::WildCmp("*A*b*c*", "abc", CString::CaseInsensitive)); + + EXPECT_FALSE(CString::WildCmp("*a*b*c*", "Abc", CString::CaseSensitive)); + EXPECT_TRUE (CString::WildCmp("*a*b*c*", "Abc", CString::CaseInsensitive)); + + EXPECT_TRUE(CString::WildCmp("*a*b*c*", "axbyc", CString::CaseSensitive)); + EXPECT_TRUE(CString::WildCmp("*a*b*c*", "axbyc", CString::CaseInsensitive)); + + EXPECT_FALSE(CString::WildCmp("*a*B*c*", "AxByC", CString::CaseSensitive)); + EXPECT_TRUE (CString::WildCmp("*a*B*c*", "AxByC", CString::CaseInsensitive)); } TEST(StringTest, Case) {