diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 009e337bcbc0..8fb54b03f383 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1598,7 +1598,43 @@ public: * case for ASCII characters a-z. */ static bool EqualsIgnoreASCIICase(const nsAString& aStr1, - const nsAString& aStr2); + const nsAString& aStr2); + + /** + * Case insensitive comparison between a string and an ASCII literal. + * This must ONLY be applied to an actual literal string. Do not attempt + * to use it with a regular char* pointer, or with a char array variable. + * The template trick to acquire the array length at compile time without + * using a macro is due to Corey Kosak, which much thanks. + */ + static bool EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char* aStr2, + const PRUint32 len); +#ifdef NS_DISABLE_LITERAL_TEMPLATE + static inline bool + EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char* aStr2) + { + PRUint32 len = strlen(aStr2); + return EqualsLiteralIgnoreASCIICase(aStr1, aStr2, len); + } +#else + template + static inline bool + EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char (&aStr2)[N]) + { + return EqualsLiteralIgnoreASCIICase(aStr1, aStr2, N-1); + } + template + static inline bool + EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + char (&aStr2)[N]) + { + const char* s = aStr2; + return EqualsLiteralIgnoreASCIICase(aStr1, s, N-1); + } +#endif /** * Convert ASCII A-Z to a-z. diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 3dfc604ae989..ee75b14368b2 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -5322,6 +5322,7 @@ nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) } } +/* static */ bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, const nsAString& aStr2) @@ -5344,7 +5345,7 @@ nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, return false; } - // We know they only differ in the 0x0020 bit. + // We know they can only differ in the 0x0020 bit. // Likely the two chars are the same, so check that first if (c1 != c2) { // They do differ, but since it's only in the 0x0020 bit, check if it's @@ -5359,6 +5360,44 @@ nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, return true; } +/* static */ +bool +nsContentUtils::EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char* aStr2, + const PRUint32 len) +{ + if (aStr1.Length() != len) { + return false; + } + + const PRUnichar* str1 = aStr1.BeginReading(); + const char* str2 = str2; + const PRUnichar* end = str1 + len; + + while (str1 < end) { + PRUnichar c1 = *str1++; + PRUnichar c2 = *str2++; + + // First check if any bits other than the 0x0020 differs + if ((c1 ^ c2) & 0xffdf) { + return false; + } + + // We know they can only differ in the 0x0020 bit. + // Likely the two chars are the same, so check that first + if (c1 != c2) { + // They do differ, but since it's only in the 0x0020 bit, check if it's + // the same ascii char, but just differing in case + PRUnichar c1Upper = c1 & 0xffdf; + if (!('A' <= c1Upper && c1Upper <= 'Z')) { + return false; + } + } + } + + return true; +} + /* static */ nsIInterfaceRequestor* nsContentUtils::GetSameOriginChecker()