diff --git a/base/files/file_path.cc b/base/files/file_path.cc index 92123533aaa55..51656d26d3af5 100644 --- a/base/files/file_path.cc +++ b/base/files/file_path.cc @@ -10,9 +10,6 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/pickle.h" - -// These includes are just for the *Hack functions, and should be removed -// when those functions are removed. #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" @@ -1259,11 +1256,12 @@ int FilePath::CompareIgnoreCase(StringPieceType string1, #else // << WIN. MACOSX | other (POSIX) >> -// Generic (POSIX) implementation of file string comparison. -// TODO(rolandsteiner) check if this is sufficient/correct. +// Generic Posix system comparisons. int FilePath::CompareIgnoreCase(StringPieceType string1, StringPieceType string2) { - int comparison = strcasecmp(string1.data(), string2.data()); + // Specifically need null termianted strings for this API call. + int comparison = strcasecmp(string1.as_string().c_str(), + string2.as_string().c_str()); if (comparison < 0) return -1; if (comparison > 0) diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc index 5b727ce0b4e2a..fcd8ddf12e4ed 100644 --- a/base/strings/string_util.cc +++ b/base/strings/string_util.cc @@ -140,6 +140,53 @@ bool IsWprintfFormatPortable(const wchar_t* format) { return true; } +template<class StringType> +int CompareCaseInsensitiveASCIIT(BasicStringPiece<StringType> a, + BasicStringPiece<StringType> b) { + // Find the first characters that aren't equal and compare them. If the end + // of one of the strings is found before a nonequal character, the lengths + // of the strings are compared. + size_t i = 0; + while (i < a.length() && i < b.length()) { + typename StringType::value_type lower_a = ToLowerASCII(a[i]); + typename StringType::value_type lower_b = ToLowerASCII(b[i]); + if (lower_a < lower_b) + return -1; + if (lower_a > lower_b) + return 1; + i++; + } + + // End of one string hit before finding a different character. Expect the + // common case to be "strings equal" at this point so check that first. + if (a.length() == b.length()) + return 0; + + if (a.length() < b.length()) + return -1; + return 1; +} + +int CompareCaseInsensitiveASCII(base::StringPiece a, base::StringPiece b) { + return CompareCaseInsensitiveASCIIT<std::string>(a, b); +} + +int CompareCaseInsensitiveASCII(base::StringPiece16 a, base::StringPiece16 b) { + return CompareCaseInsensitiveASCIIT<base::string16>(a, b); +} + +bool EqualsCaseInsensitiveASCII(base::StringPiece a, base::StringPiece b) { + if (a.length() != b.length()) + return false; + return CompareCaseInsensitiveASCIIT<std::string>(a, b) == 0; +} + +bool EqualsCaseInsensitiveASCII(base::StringPiece16 a, base::StringPiece16 b) { + if (a.length() != b.length()) + return false; + return CompareCaseInsensitiveASCIIT<base::string16>(a, b) == 0; +} + const std::string& EmptyString() { return EmptyStrings::GetInstance()->s; } diff --git a/base/strings/string_util.h b/base/strings/string_util.h index 62b3605a8933b..5d26f1c54142f 100644 --- a/base/strings/string_util.h +++ b/base/strings/string_util.h @@ -21,20 +21,10 @@ namespace base { -// C standard-library functions like "strncasecmp" and "snprintf" that aren't -// cross-platform are provided as "base::strncasecmp", and their prototypes -// are listed below. These functions are then implemented as inline calls -// to the platform-specific equivalents in the platform-specific headers. - -// Compares the two strings s1 and s2 without regard to case using -// the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if -// s2 > s1 according to a lexicographic comparison. -int strcasecmp(const char* s1, const char* s2); - -// Compares up to count characters of s1 and s2 without regard to case using -// the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if -// s2 > s1 according to a lexicographic comparison. -int strncasecmp(const char* s1, const char* s2, size_t count); +// C standard-library functions that aren't cross-platform are provided as +// "base::...", and their prototypes are listed below. These functions are +// then implemented as inline calls to the platform-specific equivalents in the +// platform-specific headers. // Wrapper for vsnprintf that always null-terminates and always returns the // number of characters that would be in an untruncated formatted @@ -56,6 +46,19 @@ inline int snprintf(char* buffer, size_t size, const char* format, ...) { return result; } +// TODO(mark) http://crbug.com/472900 crashpad shouldn't use base while +// being DEPSed in. This backwards-compat hack is provided until crashpad is +// updated. +#if defined(OS_WIN) +inline int strcasecmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +#else // Posix +inline int strcasecmp(const char* string1, const char* string2) { + return ::strcasecmp(string1, string2); +} +#endif + // BSD-style safe and consistent string copy functions. // Copies |src| to |dst|, where |dst_size| is the total allocated size of |dst|. // Copies at most |dst_size|-1 characters, and always NULL terminates |dst|, as @@ -102,10 +105,13 @@ template <class Char> inline Char ToUpperASCII(Char c) { // Function objects to aid in comparing/searching strings. +// DO NOT USE. tolower() will given incorrect results for non-ASCII characters. +// Use the ASCII version, base::i18n::ToLower, or base::i18n::FoldCase. template<typename Char> struct CaseInsensitiveCompare { public: bool operator()(Char x, Char y) const { // TODO(darin): Do we really want to do locale sensitive comparisons here? + // ANSWER(brettw): No. // See http://crbug.com/24917 return tolower(x) == tolower(y); } @@ -118,6 +124,22 @@ template<typename Char> struct CaseInsensitiveCompareASCII { } }; +// Like strcasecmp for case-insensitive ASCII characters only. Returns: +// -1 (a < b) +// 0 (a == b) +// 1 (a > b) +// (unlike strcasecmp which can return values greater or less than 1/-1). For +// full Unicode support, use base::i18n::ToLower or base::i18h::FoldCase +// and then just call the normal string operators on the result. +BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b); +BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b); + +// Equality for ASCII case-insensitive comparisons. For full Unicode support, +// use base::i18n::ToLower or base::i18h::FoldCase and then compare with either +// == or !=. +BASE_EXPORT bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b); +BASE_EXPORT bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b); + // These threadsafe functions return references to globally unique empty // strings. // diff --git a/base/strings/string_util_posix.h b/base/strings/string_util_posix.h index d31a9fcbefd28..9e96697ff5625 100644 --- a/base/strings/string_util_posix.h +++ b/base/strings/string_util_posix.h @@ -20,14 +20,6 @@ inline char* strdup(const char* str) { return ::strdup(str); } -inline int strcasecmp(const char* string1, const char* string2) { - return ::strcasecmp(string1, string2); -} - -inline int strncasecmp(const char* string1, const char* string2, size_t count) { - return ::strncasecmp(string1, string2, count); -} - inline int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) { return ::vsnprintf(buffer, size, format, arguments); diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc index 02b184cc62023..1593f8189679a 100644 --- a/base/strings/string_util_unittest.cc +++ b/base/strings/string_util_unittest.cc @@ -1056,6 +1056,26 @@ TEST(StringUtilTest, ContainsOnlyChars) { kWhitespaceUTF16)); } +TEST(StringUtilTest, CompareCaseInsensitiveASCII) { + EXPECT_EQ(0, CompareCaseInsensitiveASCII("", "")); + EXPECT_EQ(0, CompareCaseInsensitiveASCII("Asdf", "aSDf")); + + // Differing lengths. + EXPECT_EQ(-1, CompareCaseInsensitiveASCII("Asdf", "aSDfA")); + EXPECT_EQ(1, CompareCaseInsensitiveASCII("AsdfA", "aSDf")); + + // Differing values. + EXPECT_EQ(-1, CompareCaseInsensitiveASCII("AsdfA", "aSDfb")); + EXPECT_EQ(1, CompareCaseInsensitiveASCII("Asdfb", "aSDfA")); +} + +TEST(StringUtilTest, EqualsCaseInsensitiveASCII) { + EXPECT_TRUE(EqualsCaseInsensitiveASCII("", "")); + EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", "aSDF")); + EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", "aSDF")); + EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", "aSDFz")); +} + class WriteIntoTest : public testing::Test { protected: static void WritesCorrectly(size_t num_chars) { diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h index 7c1e34cf8fcff..839a799a157f0 100644 --- a/base/strings/string_util_win.h +++ b/base/strings/string_util_win.h @@ -20,14 +20,6 @@ inline char* strdup(const char* str) { return _strdup(str); } -inline int strcasecmp(const char* s1, const char* s2) { - return _stricmp(s1, s2); -} - -inline int strncasecmp(const char* s1, const char* s2, size_t count) { - return _strnicmp(s1, s2, count); -} - inline int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) { int length = vsnprintf_s(buffer, size, size - 1, format, arguments); diff --git a/chrome/browser/media_galleries/fileapi/media_path_filter.cc b/chrome/browser/media_galleries/fileapi/media_path_filter.cc index 0212e11136035..5b27f1019ab28 100644 --- a/chrome/browser/media_galleries/fileapi/media_path_filter.cc +++ b/chrome/browser/media_galleries/fileapi/media_path_filter.cc @@ -126,15 +126,12 @@ bool MediaPathFilter::ShouldSkip(const base::FilePath& path) { const char win_98_recycle_bin_name[] = "RECYCLED"; const char win_xp_recycle_bin_name[] = "RECYCLER"; const char win_vista_recycle_bin_name[] = "$Recycle.bin"; - if ((base::strncasecmp(base_name.c_str(), - win_98_recycle_bin_name, - strlen(win_98_recycle_bin_name)) == 0) || - (base::strncasecmp(base_name.c_str(), - win_xp_recycle_bin_name, - strlen(win_xp_recycle_bin_name)) == 0) || - (base::strncasecmp(base_name.c_str(), - win_vista_recycle_bin_name, - strlen(win_vista_recycle_bin_name)) == 0)) + if (base::StartsWith(base_name, win_98_recycle_bin_name, + base::CompareCase::INSENSITIVE_ASCII) || + base::StartsWith(base_name, win_xp_recycle_bin_name, + base::CompareCase::INSENSITIVE_ASCII) || + base::StartsWith(base_name, win_vista_recycle_bin_name, + base::CompareCase::INSENSITIVE_ASCII)) return true; #endif // defined(OS_WIN) return false; diff --git a/chrome/browser/net/sdch_browsertest.cc b/chrome/browser/net/sdch_browsertest.cc index 7a1cb7b69211d..9c93d6b841dda 100644 --- a/chrome/browser/net/sdch_browsertest.cc +++ b/chrome/browser/net/sdch_browsertest.cc @@ -108,7 +108,7 @@ bool GetRequestHeader(const HttpRequestHeaderMap& map, std::string* value) { for (HttpRequestHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it) { - if (!base::strcasecmp(it->first.c_str(), header)) { + if (base::EqualsCaseInsensitiveASCII(it->first, header)) { *value = it->second; return true; } @@ -170,7 +170,7 @@ class SdchResponseHandler { return false; base::StringTokenizer tokenizer(value, " ,"); while (tokenizer.GetNext()) { - if (base::strcasecmp(tokenizer.token().c_str(), "sdch")) + if (base::EqualsCaseInsensitiveASCII(tokenizer.token(), "sdch")) return true; } return false; diff --git a/chrome/browser/printing/printing_layout_browsertest.cc b/chrome/browser/printing/printing_layout_browsertest.cc index 4e1d2b731d83b..4755a18a00755 100644 --- a/chrome/browser/printing/printing_layout_browsertest.cc +++ b/chrome/browser/printing/printing_layout_browsertest.cc @@ -207,7 +207,7 @@ class PrintingLayoutTest : public PrintingTest<InProcessBrowserTest>, base::FilePath file; while (!(file = enumerator.Next()).empty()) { std::wstring ext = file.Extension(); - if (base::strcasecmp(base::WideToUTF8(ext).c_str(), ".emf") == 0) { + if (base::EqualsCaseInsensitiveASCII(base::WideToUTF8(ext), ".emf")) { EXPECT_FALSE(found_emf) << "Found a leftover .EMF file: \"" << emf_file << "\" and \"" << file.value() << "\" when looking for \"" << verification_name << "\""; @@ -215,7 +215,7 @@ class PrintingLayoutTest : public PrintingTest<InProcessBrowserTest>, emf_file = file.value(); continue; } - if (base::strcasecmp(base::WideToUTF8(ext).c_str(), ".prn") == 0) { + if (base::EqualsCaseInsensitiveASCII(base::WideToUTF8(ext), ".prn")) { EXPECT_FALSE(found_prn) << "Found a leftover .PRN file: \"" << prn_file << "\" and \"" << file.value() << "\" when looking for \"" << verification_name << "\""; diff --git a/chrome/service/cloud_print/cloud_print_connector.cc b/chrome/service/cloud_print/cloud_print_connector.cc index a1f6be7f667ae..f53c865e6abe7 100644 --- a/chrome/service/cloud_print/cloud_print_connector.cc +++ b/chrome/service/cloud_print/cloud_print_connector.cc @@ -653,7 +653,7 @@ void CloudPrintConnector::OnReceivePrinterCaps( bool CloudPrintConnector::IsSamePrinter(const std::string& name1, const std::string& name2) const { - return (0 == base::strcasecmp(name1.c_str(), name2.c_str())); + return base::EqualsCaseInsensitiveASCII(name1, name2); } } // namespace cloud_print diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc index f93215dbd66fb..53485ccdf1618 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc @@ -550,8 +550,8 @@ void CloudPrintProxyBackend::Core::OnIncomingNotification( DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); VLOG(1) << "CP_CONNECTOR: Incoming notification."; - if (0 == base::strcasecmp(kCloudPrintPushNotificationsSource, - notification.channel.c_str())) + if (base::EqualsCaseInsensitiveASCII(kCloudPrintPushNotificationsSource, + notification.channel)) HandlePrinterNotification(notification.data); } diff --git a/chrome/test/chromedriver/performance_logger.cc b/chrome/test/chromedriver/performance_logger.cc index 37e66f40f2803..f97385b6d9143 100644 --- a/chrome/test/chromedriver/performance_logger.cc +++ b/chrome/test/chromedriver/performance_logger.cc @@ -43,7 +43,8 @@ bool IsEnabled(const PerfLoggingPrefs::InspectorDomainStatus& domain_status) { bool ShouldRequestTraceEvents(const std::string& command) { for (size_t i_domain = 0; i_domain < arraysize(kRequestTraceCommands); ++i_domain) { - if (base::strcasecmp(command.c_str(), kRequestTraceCommands[i_domain]) == 0) + if (base::EqualsCaseInsensitiveASCII(command, + kRequestTraceCommands[i_domain])) return true; } return false; diff --git a/components/mime_util/mime_util.cc b/components/mime_util/mime_util.cc index 3841fbbb69074..ef5e0daaefdda 100644 --- a/components/mime_util/mime_util.cc +++ b/components/mime_util/mime_util.cc @@ -221,8 +221,8 @@ net::CertificateMimeType GetCertificateMimeTypeForMimeType( // Don't create a map, there is only one entry in the table, // except on Android. for (size_t i = 0; i < arraysize(kSupportedCertificateTypes); ++i) { - if (base::strcasecmp(mime_type.c_str(), - kSupportedCertificateTypes[i].mime_type) == 0) { + if (base::EqualsCaseInsensitiveASCII( + mime_type, kSupportedCertificateTypes[i].mime_type)) { return kSupportedCertificateTypes[i].cert_type; } } diff --git a/components/policy/core/common/registry_dict_win.cc b/components/policy/core/common/registry_dict_win.cc index 132adcaddea05..dd04beec1ab68 100644 --- a/components/policy/core/common/registry_dict_win.cc +++ b/components/policy/core/common/registry_dict_win.cc @@ -136,7 +136,7 @@ scoped_ptr<base::Value> ConvertValue(const base::Value& value, bool CaseInsensitiveStringCompare::operator()(const std::string& a, const std::string& b) const { - return base::strcasecmp(a.c_str(), b.c_str()) < 0; + return base::CompareCaseInsensitiveASCII(a, b) < 0; } RegistryDict::RegistryDict() {} diff --git a/content/common/service_worker/service_worker_types.h b/content/common/service_worker/service_worker_types.h index 917c9ed9ff405..631c56320deb2 100644 --- a/content/common/service_worker/service_worker_types.h +++ b/content/common/service_worker/service_worker_types.h @@ -102,7 +102,7 @@ enum ServiceWorkerFetchEventResult { struct ServiceWorkerCaseInsensitiveCompare { bool operator()(const std::string& lhs, const std::string& rhs) const { - return base::strcasecmp(lhs.c_str(), rhs.c_str()) < 0; + return base::CompareCaseInsensitiveASCII(lhs, rhs) < 0; } }; diff --git a/content/plugin/webplugin_proxy.cc b/content/plugin/webplugin_proxy.cc index 3c607143ee892..6b6d696ca5da8 100644 --- a/content/plugin/webplugin_proxy.cc +++ b/content/plugin/webplugin_proxy.cc @@ -280,7 +280,7 @@ void WebPluginProxy::HandleURLRequest(const char* url, int notify_id, bool popups_allowed, bool notify_redirects) { - if (!target && (0 == base::strcasecmp(method, "GET"))) { + if (!target && base::EqualsCaseInsensitiveASCII(method, "GET")) { // Please refer to https://bugzilla.mozilla.org/show_bug.cgi?id=366082 // for more details on this. if (delegate_->GetQuirks() & diff --git a/device/usb/usb_service_impl.cc b/device/usb/usb_service_impl.cc index ea7ad7f498108..2261ad6930bdd 100644 --- a/device/usb/usb_service_impl.cc +++ b/device/usb/usb_service_impl.cc @@ -127,10 +127,9 @@ bool IsWinUsbInterface(const std::string& device_path) { } USB_LOG(DEBUG) << "Driver for " << device_path << " is " << buffer << "."; - if (base::strncasecmp("WinUSB", (const char*)&buffer[0], sizeof "WinUSB") == - 0) { + if (base::StartsWith(reinterpret_cast<const char*>(buffer), "WinUSB", + base::CompareCase::INSENSITIVE_ASCII)) return true; - } return false; } diff --git a/extensions/browser/api/web_request/form_data_parser.cc b/extensions/browser/api/web_request/form_data_parser.cc index 31b6fe8aadfa1..f12c34face959 100644 --- a/extensions/browser/api/web_request/form_data_parser.cc +++ b/extensions/browser/api/web_request/form_data_parser.cc @@ -315,11 +315,11 @@ scoped_ptr<FormDataParser> FormDataParser::CreateFromContentTypeHeader( const std::string content_type( content_type_header->substr(0, content_type_header->find(';'))); - if (base::strcasecmp( - content_type.c_str(), "application/x-www-form-urlencoded") == 0) { + if (base::EqualsCaseInsensitiveASCII(content_type, + "application/x-www-form-urlencoded")) { choice = URL_ENCODED; - } else if (base::strcasecmp( - content_type.c_str(), "multipart/form-data") == 0) { + } else if (base::EqualsCaseInsensitiveASCII(content_type, + "multipart/form-data")) { static const char kBoundaryString[] = "boundary="; size_t offset = content_type_header->find(kBoundaryString); if (offset == std::string::npos) { diff --git a/media/video/capture/fake_video_capture_device_factory.cc b/media/video/capture/fake_video_capture_device_factory.cc index a9d32dee2eda1..302223fd7ed43 100644 --- a/media/video/capture/fake_video_capture_device_factory.cc +++ b/media/video/capture/fake_video_capture_device_factory.cc @@ -26,7 +26,7 @@ scoped_ptr<VideoCaptureDevice> FakeVideoCaptureDeviceFactory::Create( FakeVideoCaptureDevice::FakeVideoCaptureDeviceType fake_vcd_type; if (option.empty()) fake_vcd_type = FakeVideoCaptureDevice::USING_OWN_BUFFERS; - else if (base:: strcasecmp(option.c_str(), "triplanar") == 0) + else if (base::EqualsCaseInsensitiveASCII(option, "triplanar")) fake_vcd_type = FakeVideoCaptureDevice::USING_OWN_BUFFERS_TRIPLANAR; else fake_vcd_type = FakeVideoCaptureDevice::USING_CLIENT_BUFFERS; diff --git a/mojo/services/network/http_connection_impl.cc b/mojo/services/network/http_connection_impl.cc index 2df12aa7b50d7..ad3347d9d43ca 100644 --- a/mojo/services/network/http_connection_impl.cc +++ b/mojo/services/network/http_connection_impl.cc @@ -375,11 +375,12 @@ void HttpConnectionImpl::OnFinishedReadingResponseBody( // // TODO(yzshen): Consider adding to net::HttpServerResponseInfo a simple // setter for body which doesn't fiddle with headers. - if (base::strcasecmp(header.name.data(), - net::HttpRequestHeaders::kContentLength) == 0) { + base::StringPiece name_piece(header.name.data(), header.name.size()); + if (base::EqualsCaseInsensitiveASCII( + name_piece, net::HttpRequestHeaders::kContentLength)) { continue; - } else if (base::strcasecmp(header.name.data(), - net::HttpRequestHeaders::kContentType) == 0) { + } else if (base::EqualsCaseInsensitiveASCII( + name_piece, net::HttpRequestHeaders::kContentType)) { content_type = header.value; continue; } diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc index 907c7c4f09989..668e89831f808 100644 --- a/net/base/mime_sniffer.cc +++ b/net/base/mime_sniffer.cc @@ -344,8 +344,10 @@ static bool MatchMagicNumber(const char* content, bool match = false; if (magic_entry.is_string) { if (content_strlen >= len) { - // String comparisons are case-insensitive - match = (base::strncasecmp(magic_entry.magic, content, len) == 0); + // Do a case-insensitive prefix comparison. + DCHECK_EQ(strlen(magic_entry.magic), len); + match = base::EqualsCaseInsensitiveASCII(magic_entry.magic, + base::StringPiece(content, len)); } } else { if (size >= len) { @@ -462,11 +464,12 @@ static bool SniffForOfficeDocs(const char* content, if (url_path.length() < kOfficeExtensionTypes[i].extension_len) continue; - const char* extension = - &url_path[url_path.length() - kOfficeExtensionTypes[i].extension_len]; - - if (0 == base::strncasecmp(extension, kOfficeExtensionTypes[i].extension, - kOfficeExtensionTypes[i].extension_len)) { + base::StringPiece extension = base::StringPiece(url_path).substr( + url_path.length() - kOfficeExtensionTypes[i].extension_len); + if (base::EqualsCaseInsensitiveASCII( + extension, + base::StringPiece(kOfficeExtensionTypes[i].extension, + kOfficeExtensionTypes[i].extension_len))) { type = kOfficeExtensionTypes[i].doc_type; break; } @@ -608,14 +611,22 @@ static bool SniffXML(const char* content, if (!pos) return false; - if ((pos + sizeof("<?xml") - 1 <= end) && - (base::strncasecmp(pos, "<?xml", sizeof("<?xml") - 1) == 0)) { + static const char kXmlPrefix[] = "<?xml"; + static const size_t kXmlPrefixLength = arraysize(kXmlPrefix) - 1; + static const char kDocTypePrefix[] = "<!DOCTYPE"; + static const size_t kDocTypePrefixLength = arraysize(kDocTypePrefix) - 1; + + if ((pos + kXmlPrefixLength <= end) && + base::EqualsCaseInsensitiveASCII( + base::StringPiece(pos, kXmlPrefixLength), + base::StringPiece(kXmlPrefix, kXmlPrefixLength))) { // Skip XML declarations. ++pos; continue; - } else if ((pos + sizeof("<!DOCTYPE") - 1 <= end) && - (base::strncasecmp(pos, "<!DOCTYPE", sizeof("<!DOCTYPE") - 1) == - 0)) { + } else if ((pos + kDocTypePrefixLength <= end) && + base::EqualsCaseInsensitiveASCII( + base::StringPiece(pos, kDocTypePrefixLength), + base::StringPiece(kDocTypePrefix, kDocTypePrefixLength))) { // Skip DOCTYPE declarations. ++pos; continue; diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc index ae4781a68ae82..27c547b6e0b37 100644 --- a/net/base/mime_util.cc +++ b/net/base/mime_util.cc @@ -116,8 +116,11 @@ const char* FindMimeType(const MimeInfo* mappings, const char* extensions = mappings[i].extensions; for (;;) { size_t end_pos = strcspn(extensions, ","); + // The length check is required to prevent the StringPiece below from + // including uninitialized memory if ext is longer than extensions. if (end_pos == ext.size() && - base::strncasecmp(extensions, ext.data(), ext.size()) == 0) + base::EqualsCaseInsensitiveASCII( + base::StringPiece(extensions, ext.size()), ext)) return mappings[i].mime_type; extensions += end_pos; if (!*extensions) @@ -268,13 +271,10 @@ bool MimeUtil::MatchesMimeType(const std::string& mime_type_pattern, const std::string::size_type star = base_pattern.find('*'); if (star == std::string::npos) { - if (base_pattern.size() == base_type.size() && - base::strncasecmp(base_pattern.data(), base_type.data(), - base_pattern.size()) == 0) { + if (base::EqualsCaseInsensitiveASCII(base_pattern, base_type)) return MatchesMimeTypeParameters(mime_type_pattern, mime_type); - } else { + else return false; - } } // Test length to prevent overlap between |left| and |right|. diff --git a/net/cookies/cookie_util.cc b/net/cookies/cookie_util.cc index 2723363e2fb4e..b9c7e8d601f8e 100644 --- a/net/cookies/cookie_util.cc +++ b/net/cookies/cookie_util.cc @@ -125,7 +125,8 @@ base::Time ParseCookieTime(const std::string& time_string) { if (!found_month) { for (int i = 0; i < kMonthsLen; ++i) { // Match prefix, so we could match January, etc - if (base::strncasecmp(token.c_str(), kMonths[i], 3) == 0) { + if (base::StartsWith(token, base::StringPiece(kMonths[i], 3), + base::CompareCase::INSENSITIVE_ASCII)) { exploded.month = i + 1; found_month = true; break; diff --git a/net/dns/dns_response.cc b/net/dns/dns_response.cc index 64db818b2b942..730206ca60801 100644 --- a/net/dns/dns_response.cc +++ b/net/dns/dns_response.cc @@ -303,7 +303,7 @@ DnsResponse::Result DnsResponse::ParseToAddressList( if (!ip_addresses.empty()) return DNS_CNAME_AFTER_ADDRESS; - if (base::strcasecmp(record.name.c_str(), expected_name.c_str()) != 0) + if (!base::EqualsCaseInsensitiveASCII(record.name, expected_name)) return DNS_NAME_MISMATCH; if (record.rdata.size() != @@ -315,7 +315,7 @@ DnsResponse::Result DnsResponse::ParseToAddressList( if (record.rdata.size() != expected_size) return DNS_SIZE_MISMATCH; - if (base::strcasecmp(record.name.c_str(), expected_name.c_str()) != 0) + if (!base::EqualsCaseInsensitiveASCII(record.name, expected_name)) return DNS_NAME_MISMATCH; ttl_sec = std::min(ttl_sec, record.ttl); diff --git a/net/http/http_log_util.cc b/net/http/http_log_util.cc index 0467fb605ab40..8e071e34109a7 100644 --- a/net/http/http_log_util.cc +++ b/net/http/http_log_util.cc @@ -45,15 +45,15 @@ std::string ElideHeaderValueForNetLog(NetLogCaptureMode capture_mode, // Note: this logic should be kept in sync with stripCookiesAndLoginInfo in // chrome/browser/resources/net_internals/log_view_painter.js. - if (!base::strcasecmp(header.c_str(), "set-cookie") || - !base::strcasecmp(header.c_str(), "set-cookie2") || - !base::strcasecmp(header.c_str(), "cookie") || - !base::strcasecmp(header.c_str(), "authorization") || - !base::strcasecmp(header.c_str(), "proxy-authorization")) { + if (base::EqualsCaseInsensitiveASCII(header, "set-cookie") || + base::EqualsCaseInsensitiveASCII(header, "set-cookie2") || + base::EqualsCaseInsensitiveASCII(header, "cookie") || + base::EqualsCaseInsensitiveASCII(header, "authorization") || + base::EqualsCaseInsensitiveASCII(header, "proxy-authorization")) { redact_begin = value.begin(); redact_end = value.end(); - } else if (!base::strcasecmp(header.c_str(), "www-authenticate") || - !base::strcasecmp(header.c_str(), "proxy-authenticate")) { + } else if (base::EqualsCaseInsensitiveASCII(header, "www-authenticate") || + base::EqualsCaseInsensitiveASCII(header, "proxy-authenticate")) { // Look for authentication information from data received from the server // in multi-round Negotiate authentication. HttpAuthChallengeTokenizer challenge(value.begin(), value.end()); diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc index 004d0659512c6..c2eee59af95f8 100644 --- a/net/http/http_request_headers.cc +++ b/net/http/http_request_headers.cc @@ -241,8 +241,7 @@ HttpRequestHeaders::HeaderVector::iterator HttpRequestHeaders::FindHeader(const base::StringPiece& key) { for (HeaderVector::iterator it = headers_.begin(); it != headers_.end(); ++it) { - if (key.length() == it->key.length() && - !base::strncasecmp(key.data(), it->key.data(), key.length())) + if (base::EqualsCaseInsensitiveASCII(key, it->key)) return it; } @@ -253,8 +252,7 @@ HttpRequestHeaders::HeaderVector::const_iterator HttpRequestHeaders::FindHeader(const base::StringPiece& key) const { for (HeaderVector::const_iterator it = headers_.begin(); it != headers_.end(); ++it) { - if (key.length() == it->key.length() && - !base::strncasecmp(key.data(), it->key.data(), key.length())) + if (base::EqualsCaseInsensitiveASCII(key, it->key)) return it; } diff --git a/net/tools/balsa/balsa_headers.h b/net/tools/balsa/balsa_headers.h index 3edcf677703b7..3fc01c4c157a0 100644 --- a/net/tools/balsa/balsa_headers.h +++ b/net/tools/balsa/balsa_headers.h @@ -538,7 +538,7 @@ class BalsaHeaders { do { iterator_base::increment(); } while (!AtEnd() && - !StringPieceUtils::EqualIgnoreCase(key_, (**this).first)); + !base::EqualsCaseInsensitiveASCII(key_, (**this).first)); return *this; } diff --git a/net/tools/balsa/string_piece_utils.h b/net/tools/balsa/string_piece_utils.h index 7d8a1aaaee287..6d8967a014219 100644 --- a/net/tools/balsa/string_piece_utils.h +++ b/net/tools/balsa/string_piece_utils.h @@ -65,31 +65,10 @@ struct StringPieceCaseHash { }; #endif // COMPILER_MSVC -struct StringPieceUtils { - // ASCII case-insensitive equality. - static bool EqualIgnoreCase(const base::StringPiece& piece1, - const base::StringPiece& piece2) { - base::StringPiece::const_iterator p1i = piece1.begin(); - base::StringPiece::const_iterator p2i = piece2.begin(); - if (piece1.empty() && piece2.empty()) { - return true; - } else if (piece1.size() != piece2.size()) { - return false; - } - while (p1i != piece1.end() && p2i != piece2.end()) { - if (base::ToLowerASCII(*p1i) != base::ToLowerASCII(*p2i)) - return false; - ++p1i; - ++p2i; - } - return true; - } -}; - struct StringPieceCaseEqual { bool operator()(const base::StringPiece& piece1, const base::StringPiece& piece2) const { - return StringPieceUtils::EqualIgnoreCase(piece1, piece2); + return base::EqualsCaseInsensitiveASCII(piece1, piece2); } }; diff --git a/net/tools/quic/test_tools/http_message.cc b/net/tools/quic/test_tools/http_message.cc index ad13f5c2f45d3..b1520917b43cb 100644 --- a/net/tools/quic/test_tools/http_message.cc +++ b/net/tools/quic/test_tools/http_message.cc @@ -158,8 +158,8 @@ void HTTPMessage::ValidateMessage() const { for (vector<StringPiece>::iterator it = transfer_encodings.begin(); it != transfer_encodings.end(); ++it) { - CHECK(StringPieceUtils::EqualIgnoreCase("identity", *it) || - StringPieceUtils::EqualIgnoreCase("chunked", *it)) << *it; + CHECK(base::EqualsCaseInsensitiveASCII("identity", *it) || + base::EqualsCaseInsensitiveASCII("chunked", *it)) << *it; } vector<StringPiece> content_lengths; diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc index fde6568d73916..80e421628a48d 100644 --- a/net/url_request/url_request_http_job_unittest.cc +++ b/net/url_request/url_request_http_job_unittest.cc @@ -77,7 +77,7 @@ class URLRequestHttpJobTest : public ::testing::Test { for (const std::string& token : base::SplitString(encoding_headers, ", ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { - if (!base::strncasecmp(token.data(), "sdch", token.length())) + if (base::EqualsCaseInsensitiveASCII(token, "sdch")) return true; } return false; diff --git a/printing/backend/cups_helper.cc b/printing/backend/cups_helper.cc index c0271b2a2872f..79e33fcf705b8 100644 --- a/printing/backend/cups_helper.cc +++ b/printing/backend/cups_helper.cc @@ -49,48 +49,45 @@ void ParseLpOptions(const base::FilePath& filepath, const char kDefault[] = "default"; const size_t kDestLen = sizeof(kDest) - 1; const size_t kDefaultLen = sizeof(kDefault) - 1; - std::vector<std::string> lines; - base::SplitString(content, '\n', &lines); - for (size_t i = 0; i < lines.size(); ++i) { - std::string line = lines[i]; - if (line.empty()) - continue; - - if (base::strncasecmp (line.c_str(), kDefault, kDefaultLen) == 0 && + for (base::StringPiece line : + base::SplitStringPiece(content, "\n", base::KEEP_WHITESPACE, + base::SPLIT_WANT_NONEMPTY)) { + if (base::StartsWith(line, base::StringPiece(kDefault, kDefaultLen), + base::CompareCase::INSENSITIVE_ASCII) && isspace(line[kDefaultLen])) { line = line.substr(kDefaultLen); - } else if (base::strncasecmp (line.c_str(), kDest, kDestLen) == 0 && + } else if (base::StartsWith(line, base::StringPiece(kDest, kDestLen), + base::CompareCase::INSENSITIVE_ASCII) && isspace(line[kDestLen])) { line = line.substr(kDestLen); } else { continue; } - base::TrimWhitespaceASCII(line, base::TRIM_ALL, &line); + line = base::TrimWhitespaceASCII(line, base::TRIM_ALL); if (line.empty()) continue; size_t space_found = line.find(' '); - if (space_found == std::string::npos) + if (space_found == base::StringPiece::npos) continue; - std::string name = line.substr(0, space_found); + base::StringPiece name = line.substr(0, space_found); if (name.empty()) continue; - if (base::strncasecmp(printer_name.c_str(), name.c_str(), - name.length()) != 0) { + if (!base::EqualsCaseInsensitiveASCII(printer_name, name)) continue; // This is not the required printer. - } line = line.substr(space_found + 1); // Remove extra spaces. - base::TrimWhitespaceASCII(line, base::TRIM_ALL, &line); + line = base::TrimWhitespaceASCII(line, base::TRIM_ALL); if (line.empty()) continue; - // Parse the selected printer custom options. - *num_options = cupsParseOptions(line.c_str(), 0, options); + // Parse the selected printer custom options. Need to pass a + // null-terminated string. + *num_options = cupsParseOptions(line.as_string().c_str(), 0, options); } } @@ -157,9 +154,12 @@ bool GetBasicColorModelSettings(ppd_file_t* ppd, if (marked_choice) { *color_is_default = - (base::strcasecmp(marked_choice->choice, printing::kBlack) != 0) && - (base::strcasecmp(marked_choice->choice, printing::kGray) != 0) && - (base::strcasecmp(marked_choice->choice, printing::kGrayscale) != 0); + !base::EqualsCaseInsensitiveASCII(marked_choice->choice, + printing::kBlack) && + !base::EqualsCaseInsensitiveASCII(marked_choice->choice, + printing::kGray) && + !base::EqualsCaseInsensitiveASCII(marked_choice->choice, + printing::kGrayscale); } return true; } @@ -190,10 +190,12 @@ bool GetPrintOutModeColorSettings(ppd_file_t* ppd, printout_mode->defchoice); } if (printout_mode_choice) { - if ((base::strcasecmp(printout_mode_choice->choice, - printing::kNormalGray) == 0) || - (base::strcasecmp(printout_mode_choice->choice, kHighGray) == 0) || - (base::strcasecmp(printout_mode_choice->choice, kDraftGray) == 0)) { + if (base::EqualsCaseInsensitiveASCII(printout_mode_choice->choice, + printing::kNormalGray) || + base::EqualsCaseInsensitiveASCII(printout_mode_choice->choice, + kHighGray) || + base::EqualsCaseInsensitiveASCII(printout_mode_choice->choice, + kDraftGray)) { *color_model_for_black = printing::PRINTOUTMODE_NORMAL_GRAY; *color_is_default = false; } @@ -223,8 +225,8 @@ bool GetColorModeSettings(ppd_file_t* ppd, } if (mode_choice) { - *color_is_default = - (base::strcasecmp(mode_choice->choice, printing::kColor) == 0); + *color_is_default = base::EqualsCaseInsensitiveASCII( + mode_choice->choice, printing::kColor); } return true; } @@ -249,8 +251,8 @@ bool GetHPColorSettings(ppd_file_t* ppd, color_mode_option->defchoice); } if (mode_choice) { - *color_is_default = - (base::strcasecmp(mode_choice->choice, printing::kColor) == 0); + *color_is_default = base::EqualsCaseInsensitiveASCII( + mode_choice->choice, printing::kColor); } return true; } @@ -279,8 +281,8 @@ bool GetProcessColorModelSettings(ppd_file_t* ppd, } if (mode_choice) { - *color_is_default = - (base::strcasecmp(mode_choice->choice, printing::kGreyscale) != 0); + *color_is_default = !base::EqualsCaseInsensitiveASCII( + mode_choice->choice, printing::kGreyscale); } return true; } @@ -383,7 +385,7 @@ bool ParsePpdCapabilities( if (duplex_choice) { caps.duplex_capable = true; - if (base::strcasecmp(duplex_choice->choice, kDuplexNone) != 0) + if (!base::EqualsCaseInsensitiveASCII(duplex_choice->choice, kDuplexNone)) caps.duplex_default = printing::LONG_EDGE; else caps.duplex_default = printing::SIMPLEX; diff --git a/skia/ext/image_operations_bench.cc b/skia/ext/image_operations_bench.cc index 4fd81bc0b331f..b5464c64d37f7 100644 --- a/skia/ext/image_operations_bench.cc +++ b/skia/ext/image_operations_bench.cc @@ -50,7 +50,7 @@ const StringMethodPair resize_methods[] = { bool StringToMethod(const std::string& arg, skia::ImageOperations::ResizeMethod* method) { for (size_t i = 0; i < arraysize(resize_methods); ++i) { - if (base::strcasecmp(arg.c_str(), resize_methods[i].name) == 0) { + if (base::EqualsCaseInsensitiveASCII(arg, resize_methods[i].name)) { *method = resize_methods[i].method; return true; } diff --git a/sql/connection.cc b/sql/connection.cc index d1b104908c988..d07d425eb1721 100644 --- a/sql/connection.cc +++ b/sql/connection.cc @@ -992,7 +992,8 @@ bool Connection::DoesColumnExist(const char* table_name, return false; while (statement.Step()) { - if (!base::strcasecmp(statement.ColumnString(1).c_str(), column_name)) + if (base::EqualsCaseInsensitiveASCII(statement.ColumnString(1), + column_name)) return true; } return false; diff --git a/tools/gn/filesystem_utils.cc b/tools/gn/filesystem_utils.cc index c98db86484c1a..42736c9fbfa69 100644 --- a/tools/gn/filesystem_utils.cc +++ b/tools/gn/filesystem_utils.cc @@ -83,7 +83,7 @@ bool AreAbsoluteWindowsPathsEqual(const base::StringPiece& a, return false; // For now, just do a case-insensitive ASCII comparison. We could convert to - // UTF-16 and use ICU if necessary. Or maybe base::strcasecmp is good enough? + // UTF-16 and use ICU if necessary. for (size_t i = 0; i < a.size(); i++) { if (NormalizeWindowsPathChar(a[i]) != NormalizeWindowsPathChar(b[i])) return false; diff --git a/ui/base/l10n/l10n_util.cc b/ui/base/l10n/l10n_util.cc index 4182f42ec6d46..0ef20ba41b235 100644 --- a/ui/base/l10n/l10n_util.cc +++ b/ui/base/l10n/l10n_util.cc @@ -205,7 +205,7 @@ bool IsDuplicateName(const std::string& locale_name) { return !base::EndsWith(locale_name, "419", true); for (size_t i = 0; i < arraysize(kDuplicateNames); ++i) { - if (base::strcasecmp(kDuplicateNames[i], locale_name.c_str()) == 0) + if (base::EqualsCaseInsensitiveASCII(kDuplicateNames[i], locale_name)) return true; } return false; diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc index 543c62596bc19..775fb1c38c577 100644 --- a/ui/gfx/render_text_harfbuzz.cc +++ b/ui/gfx/render_text_harfbuzz.cc @@ -530,7 +530,7 @@ class HarfBuzzLineBreaker { // Function object for case insensitive string comparison. struct CaseInsensitiveCompare { bool operator() (const std::string& a, const std::string& b) const { - return base::strncasecmp(a.c_str(), b.c_str(), b.length()) < 0; + return base::CompareCaseInsensitiveASCII(a, b) < 0; } }; diff --git a/ui/gfx/test/fontconfig_util_linux.cc b/ui/gfx/test/fontconfig_util_linux.cc index e2f5140b682cf..609a3fca8bdae 100644 --- a/ui/gfx/test/fontconfig_util_linux.cc +++ b/ui/gfx/test/fontconfig_util_linux.cc @@ -100,8 +100,7 @@ bool LoadFontIntoFontconfig(const base::FilePath& path) { bool LoadSystemFontIntoFontconfig(const std::string& basename) { for (size_t i = 0; i < kNumSystemFontsForFontconfig; ++i) { base::FilePath path(kSystemFontsForFontconfig[i]); - if (base::strcasecmp(path.BaseName().value().c_str(), basename.c_str()) == - 0) + if (base::EqualsCaseInsensitiveASCII(path.BaseName().value(), basename)) return LoadFontIntoFontconfig(path); } LOG(ERROR) << "Unable to find system font named " << basename;