зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1772006 - Part 4: Simplify and move the string comparison APIs from ns[T]StringObsolete, r=xpcom-reviewers,necko-reviewers,dragana,barret
This patch moves EqualsIgnoreCase to ns[T]StringObsolete, and removes the aCount argument, instead migrating callers to use `StringBeginsWith` with a case-insensitive comparator. In addition, nsTStringRepr::Compare was removed and replaced with either calls to methods like `StringBeginsWith` or the global `Compare` method. These changes required some modifications at call-sites but should make the behaviour less surprising and more consistent. Differential Revision: https://phabricator.services.mozilla.com/D148299
This commit is contained in:
Родитель
939c91e1d9
Коммит
997047e2a4
|
@ -195,9 +195,8 @@ void nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
|
|||
nsAutoString styleType;
|
||||
doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType);
|
||||
if (!styleType.IsEmpty()) {
|
||||
static const char textCssStr[] = "text/css";
|
||||
isCSS =
|
||||
(styleType.EqualsIgnoreCase(textCssStr, sizeof(textCssStr) - 1));
|
||||
isCSS = StringBeginsWith(styleType, u"text/css"_ns,
|
||||
nsASCIICaseInsensitiveStringComparator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,9 +72,7 @@ bool SharedStringMap::Find(const nsCString& aKey, size_t* aIndex) {
|
|||
|
||||
return BinarySearchIf(
|
||||
Entries(), 0, EntryCount(),
|
||||
[&](const Entry& aEntry) {
|
||||
return aKey.Compare(keys.GetBare(aEntry.mKey));
|
||||
},
|
||||
[&](const Entry& aEntry) { return Compare(aKey, keys.Get(aEntry.mKey)); },
|
||||
aIndex);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,8 +136,7 @@ static int AudioTrackCompare(const RefPtr<AudioStreamTrack>& aLhs,
|
|||
nsAutoStringN<NSID_LENGTH> IDRhs;
|
||||
aLhs->GetId(IDLhs);
|
||||
aRhs->GetId(IDRhs);
|
||||
return NS_ConvertUTF16toUTF8(IDLhs).Compare(
|
||||
NS_ConvertUTF16toUTF8(IDRhs).get());
|
||||
return Compare(NS_ConvertUTF16toUTF8(IDLhs), NS_ConvertUTF16toUTF8(IDRhs));
|
||||
}
|
||||
|
||||
void MediaStreamAudioSourceNode::AttachToRightTrack(
|
||||
|
|
|
@ -1670,8 +1670,11 @@ nsresult nsPlainTextSerializer::GetAttributeValue(const nsAtom* aName,
|
|||
bool nsPlainTextSerializer::IsCurrentNodeConverted() const {
|
||||
nsAutoString value;
|
||||
nsresult rv = GetAttributeValue(nsGkAtoms::_class, value);
|
||||
return (NS_SUCCEEDED(rv) && (value.EqualsIgnoreCase("moz-txt", 7) ||
|
||||
value.EqualsIgnoreCase("\"moz-txt", 8)));
|
||||
return (NS_SUCCEEDED(rv) &&
|
||||
(StringBeginsWith(value, u"moz-txt"_ns,
|
||||
nsASCIICaseInsensitiveStringComparator) ||
|
||||
StringBeginsWith(value, u"\"moz-txt"_ns,
|
||||
nsASCIICaseInsensitiveStringComparator)));
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -1071,7 +1071,8 @@ Family* FontList::FindFamily(const nsCString& aName, bool aPrimaryNameOnly) {
|
|||
: mList(aList), mTarget(aTarget) {}
|
||||
|
||||
int operator()(const Family& aVal) const {
|
||||
return mTarget.Compare(aVal.Key().BeginReading(mList));
|
||||
return Compare(mTarget,
|
||||
nsDependentCString(aVal.Key().BeginReading(mList)));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1181,7 +1182,8 @@ LocalFaceRec* FontList::FindLocalFace(const nsCString& aName) {
|
|||
: mList(aList), mTarget(aTarget) {}
|
||||
|
||||
int operator()(const LocalFaceRec& aVal) const {
|
||||
return mTarget.Compare(aVal.mKey.BeginReading(mList));
|
||||
return Compare(mTarget,
|
||||
nsDependentCString(aVal.mKey.BeginReading(mList)));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -221,7 +221,7 @@ nsStaticAtom* nsLanguageAtomService::GetUncachedLanguageGroup(
|
|||
if (BinarySearchIf(
|
||||
kScriptLangGroup, 0, ArrayLength(kScriptLangGroup),
|
||||
[script](const auto& entry) -> int {
|
||||
return script.Compare(entry.mTag);
|
||||
return Compare(script, nsDependentCString(entry.mTag));
|
||||
},
|
||||
&foundIndex)) {
|
||||
return kScriptLangGroup[foundIndex].mAtom;
|
||||
|
|
|
@ -13,7 +13,7 @@ struct PropertyComparator {
|
|||
const nsCString& mKey;
|
||||
explicit PropertyComparator(const nsCString& aKey) : mKey(aKey) {}
|
||||
int operator()(const nsUConvProp& aProperty) const {
|
||||
return mKey.Compare(aProperty.mKey);
|
||||
return Compare(mKey, nsDependentCString(aProperty.mKey));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -84,7 +84,10 @@ static bool IsContentBundle(const nsCString& aUrl) {
|
|||
size_t index;
|
||||
return BinarySearchIf(
|
||||
kContentBundles, 0, MOZ_ARRAY_LENGTH(kContentBundles),
|
||||
[&](const char* aElem) { return aUrl.Compare(aElem); }, &index);
|
||||
[&](const char* aElem) {
|
||||
return Compare(aUrl, nsDependentCString(aElem));
|
||||
},
|
||||
&index);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -154,7 +154,7 @@ bool BinarySearch(const Container& aContainer, size_t aBegin, size_t aEnd,
|
|||
* const nsACString& mStr;
|
||||
* explicit Comparator(const nsACString& aStr) : mStr(aStr) {}
|
||||
* int32_t operator()(const char* aVal) const {
|
||||
* return mStr.Compare(aVal);
|
||||
* return Compare(mStr, nsDependentCString(aVal));
|
||||
* }
|
||||
* };
|
||||
*
|
||||
|
|
|
@ -621,7 +621,7 @@ nsresult DNSPacket::DecodeInternal(
|
|||
bool responseMatchesQuestion =
|
||||
(qname.Length() == aHost.Length() ||
|
||||
(aHost.Length() == qname.Length() + 1 && aHost.Last() == '.')) &&
|
||||
qname.Compare(aHost.BeginReading(), true, qname.Length()) == 0;
|
||||
StringBeginsWith(aHost, qname, nsCaseInsensitiveCStringComparator);
|
||||
|
||||
if (responseMatchesQuestion) {
|
||||
// RDATA
|
||||
|
|
|
@ -2558,9 +2558,11 @@ nsresult Http2Session::RecvAltSvc(Http2Session* self) {
|
|||
// a little off main thread origin parser. This is a non critical function
|
||||
// because any alternate route created has to be verified anyhow
|
||||
nsAutoCString specifiedOriginHost;
|
||||
if (origin.EqualsIgnoreCase("https://", 8)) {
|
||||
if (StringBeginsWith(origin, "https://"_ns,
|
||||
nsCaseInsensitiveCStringComparator)) {
|
||||
specifiedOriginHost.Assign(origin.get() + 8, origin.Length() - 8);
|
||||
} else if (origin.EqualsIgnoreCase("http://", 7)) {
|
||||
} else if (StringBeginsWith(origin, "http://"_ns,
|
||||
nsCaseInsensitiveCStringComparator)) {
|
||||
specifiedOriginHost.Assign(origin.get() + 7, origin.Length() - 7);
|
||||
}
|
||||
|
||||
|
|
|
@ -584,7 +584,9 @@ nsresult ExtensionProtocolHandler::SubstituteChannel(nsIURI* aURI,
|
|||
size_t matchIdx;
|
||||
if (BinarySearchIf(
|
||||
sStaticFileExtensions, 0, ArrayLength(sStaticFileExtensions),
|
||||
[&ext](const char* aOther) { return ext.Compare(aOther); },
|
||||
[&ext](const char* aOther) {
|
||||
return Compare(ext, nsDependentCString(aOther));
|
||||
},
|
||||
&matchIdx)) {
|
||||
// This is a static resource that shouldn't depend on the extension being
|
||||
// ready. Don't bother waiting for it.
|
||||
|
|
|
@ -76,7 +76,7 @@ GetFTPFallbackEncodingDoNotAddNewCallersToThisFunction() {
|
|||
if (BinarySearchIf(
|
||||
localesFallbacks, 0, ArrayLength(localesFallbacks),
|
||||
[&locale](const EncodingProp& aProperty) {
|
||||
return locale.Compare(aProperty.mKey);
|
||||
return Compare(locale, nsDependentCString(aProperty.mKey));
|
||||
},
|
||||
&index)) {
|
||||
return localesFallbacks[index].mValue;
|
||||
|
|
|
@ -423,9 +423,7 @@ static nsresult ParseContentSignatureHeader(
|
|||
directive != nullptr; directive = directive->getNext()) {
|
||||
CSVerifier_LOG(
|
||||
("CSVerifier: found directive '%s'", directive->mName.get()));
|
||||
if (directive->mName.Length() == signature_var.Length() &&
|
||||
directive->mName.EqualsIgnoreCase(signature_var.get(),
|
||||
signature_var.Length())) {
|
||||
if (directive->mName.EqualsIgnoreCase(signature_var)) {
|
||||
if (!aSignature.IsEmpty()) {
|
||||
CSVerifier_LOG(("CSVerifier: found two ContentSignatures"));
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
|
|
|
@ -527,9 +527,7 @@ static uint32_t ParseSSSHeaders(const nsCString& aHeader,
|
|||
for (nsSecurityHeaderDirective* directive = directives->getFirst();
|
||||
directive != nullptr; directive = directive->getNext()) {
|
||||
SSSLOG(("SSS: found directive %s\n", directive->mName.get()));
|
||||
if (directive->mName.Length() == max_age_var.Length() &&
|
||||
directive->mName.EqualsIgnoreCase(max_age_var.get(),
|
||||
max_age_var.Length())) {
|
||||
if (directive->mName.EqualsIgnoreCase(max_age_var)) {
|
||||
if (foundMaxAge) {
|
||||
SSSLOG(("SSS: found two max-age directives"));
|
||||
return nsISiteSecurityService::ERROR_MULTIPLE_MAX_AGES;
|
||||
|
@ -550,9 +548,7 @@ static uint32_t ParseSSSHeaders(const nsCString& aHeader,
|
|||
}
|
||||
|
||||
SSSLOG(("SSS: parsed delta-seconds: %" PRIu64, maxAge));
|
||||
} else if (directive->mName.Length() == include_subd_var.Length() &&
|
||||
directive->mName.EqualsIgnoreCase(include_subd_var.get(),
|
||||
include_subd_var.Length())) {
|
||||
} else if (directive->mName.EqualsIgnoreCase(include_subd_var)) {
|
||||
if (foundIncludeSubdomains) {
|
||||
SSSLOG(("SSS: found two includeSubdomains directives"));
|
||||
return nsISiteSecurityService::ERROR_MULTIPLE_INCLUDE_SUBDOMAINS;
|
||||
|
|
|
@ -102,9 +102,8 @@ static inline bool canonicalizeBase(nsAutoCString& spec, nsACString& out) {
|
|||
rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, appBase);
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
bool underGre = !greBase.Compare(spec.get(), false, greBase.Length());
|
||||
bool underApp =
|
||||
appBase.Length() && !appBase.Compare(spec.get(), false, appBase.Length());
|
||||
bool underGre = StringBeginsWith(spec, greBase);
|
||||
bool underApp = appBase.Length() && StringBeginsWith(spec, appBase);
|
||||
|
||||
if (!underGre && !underApp) return false;
|
||||
|
||||
|
|
|
@ -370,7 +370,7 @@ nsresult BackgroundTasks::RemoveStaleEphemeralProfileDirectories(
|
|||
}
|
||||
|
||||
// Find profile folders matching our prefix.
|
||||
if (aPrefix.Compare(entryName.get(), false, aPrefix.Length()) != 0) {
|
||||
if (!StringBeginsWith(entryName, aPrefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -989,7 +989,7 @@ int32_t nsNavHistoryContainerResultNode::SortComparison_TitleLess(
|
|||
if (value == 0) {
|
||||
// resolve by URI
|
||||
if (a->IsURI()) {
|
||||
value = a->mURI.Compare(b->mURI.get());
|
||||
value = Compare(a->mURI, b->mURI);
|
||||
}
|
||||
if (value == 0) {
|
||||
// resolve by date
|
||||
|
@ -1073,7 +1073,7 @@ int32_t nsNavHistoryContainerResultNode::SortComparison_URILess(
|
|||
int32_t value;
|
||||
if (a->IsURI() && b->IsURI()) {
|
||||
// normal URI or visit
|
||||
value = a->mURI.Compare(b->mURI.get());
|
||||
value = Compare(a->mURI, b->mURI);
|
||||
} else if (a->IsContainer() && !b->IsContainer()) {
|
||||
// Containers appear before entries with a uri.
|
||||
return -1;
|
||||
|
|
|
@ -193,18 +193,18 @@ nsresult nsLocalFile::RevealFile(const nsString& aResolvedPath) {
|
|||
|
||||
// static
|
||||
void nsLocalFile::CheckForReservedFileName(nsString& aFileName) {
|
||||
static const char* forbiddenNames[] = {
|
||||
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8",
|
||||
"COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7",
|
||||
"LPT8", "LPT9", "CON", "PRN", "AUX", "NUL", "CLOCK$"};
|
||||
static const nsLiteralString forbiddenNames[] = {
|
||||
u"COM1"_ns, u"COM2"_ns, u"COM3"_ns, u"COM4"_ns, u"COM5"_ns, u"COM6"_ns,
|
||||
u"COM7"_ns, u"COM8"_ns, u"COM9"_ns, u"LPT1"_ns, u"LPT2"_ns, u"LPT3"_ns,
|
||||
u"LPT4"_ns, u"LPT5"_ns, u"LPT6"_ns, u"LPT7"_ns, u"LPT8"_ns, u"LPT9"_ns,
|
||||
u"CON"_ns, u"PRN"_ns, u"AUX"_ns, u"NUL"_ns, u"CLOCK$"_ns};
|
||||
|
||||
uint32_t nameLen;
|
||||
for (size_t n = 0; n < ArrayLength(forbiddenNames); ++n) {
|
||||
nameLen = (uint32_t)strlen(forbiddenNames[n]);
|
||||
if (aFileName.EqualsIgnoreCase(forbiddenNames[n], nameLen)) {
|
||||
for (const nsLiteralString& forbiddenName : forbiddenNames) {
|
||||
if (StringBeginsWith(aFileName, forbiddenName,
|
||||
nsASCIICaseInsensitiveStringComparator)) {
|
||||
// invalid name is either the entire string, or a prefix with a period
|
||||
if (aFileName.Length() == nameLen ||
|
||||
aFileName.CharAt(nameLen) == char16_t('.')) {
|
||||
if (aFileName.Length() == forbiddenName.Length() ||
|
||||
aFileName.CharAt(forbiddenName.Length()) == char16_t('.')) {
|
||||
aFileName.Truncate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -874,62 +874,3 @@ void nsTSubstring<T>::ReplaceChar(const char* aSet, char16_t aNewChar) {
|
|||
lenRemaining -= i;
|
||||
}
|
||||
}
|
||||
|
||||
namespace mozilla::detail {
|
||||
|
||||
template <typename T>
|
||||
template <typename Q, typename EnableIfChar>
|
||||
int32_t nsTStringRepr<T>::Compare(const char_type* aString, bool aIgnoreCase,
|
||||
size_type aCount) const {
|
||||
size_t strLen = char_traits::length(aString);
|
||||
|
||||
size_t minLen = XPCOM_MIN(this->Length(), strLen);
|
||||
|
||||
// NOTE: As `minLen <= this->Length()` this value must fit in a `uint32_t`.
|
||||
uint32_t compareCount =
|
||||
ReleaseAssertedCast<uint32_t>(XPCOM_MIN(minLen, aCount));
|
||||
|
||||
int32_t result = nsBufferRoutines<T>::compare(this->mData, aString,
|
||||
compareCount, aIgnoreCase);
|
||||
|
||||
if (result == 0 && minLen < aCount && this->Length() != strLen) {
|
||||
// Since the caller didn't give us a length to test, or strings shorter
|
||||
// than aCount, and compareCount characters matched, we have to assume
|
||||
// that the longer string is greater.
|
||||
|
||||
return (this->Length() < strLen) ? -1 : 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template int32_t nsTStringRepr<char>::Compare(const char_type*, bool,
|
||||
size_type) const;
|
||||
|
||||
template <typename T>
|
||||
template <typename Q, typename EnableIfChar16>
|
||||
bool nsTStringRepr<T>::EqualsIgnoreCase(const incompatible_char_type* aString,
|
||||
size_type aCount) const {
|
||||
size_t strLen = nsCharTraits<char>::length(aString);
|
||||
|
||||
size_t minLen = XPCOM_MIN(this->Length(), strLen);
|
||||
|
||||
// NOTE: As `minLen <= this->Length()` this value must fit in a `uint32_t`.
|
||||
uint32_t compareCount =
|
||||
ReleaseAssertedCast<uint32_t>(XPCOM_MIN(minLen, aCount));
|
||||
|
||||
int32_t result =
|
||||
nsBufferRoutines<T>::compare(this->mData, aString, compareCount, true);
|
||||
|
||||
if (result == 0 && minLen < aCount && this->Length() != strLen) {
|
||||
// Since the caller didn't give us a length to test, or strings shorter
|
||||
// than aCount, and compareCount characters matched, we have to assume
|
||||
// that the longer string is greater.
|
||||
return false;
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
template bool nsTStringRepr<char16_t>::EqualsIgnoreCase(
|
||||
const incompatible_char_type*, size_type) const;
|
||||
|
||||
} // namespace mozilla::detail
|
||||
|
|
|
@ -107,4 +107,13 @@ bool nsTStringRepr<T>::LowerCaseEqualsASCII(const char* aData) const {
|
|||
this->mData, this->mLength, aData) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::EqualsIgnoreCase(const std::string_view& aString) const {
|
||||
return std::equal(BeginReading(), EndReading(), aString.begin(),
|
||||
aString.end(), [](char_type l, char r) {
|
||||
return char_traits::ASCIIToLower(l) ==
|
||||
char_traits::ASCIIToLower(char_type(r));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mozilla::detail
|
||||
|
|
|
@ -234,37 +234,15 @@ class nsTStringRepr {
|
|||
bool NS_FASTCALL Equals(const char_type* aData, comparator_type) const;
|
||||
|
||||
/**
|
||||
* Compares a given string to this string.
|
||||
* Compare this string and another ASCII-case-insensitively.
|
||||
*
|
||||
* @param aString is the string to be compared
|
||||
* @param aIgnoreCase tells us how to treat case
|
||||
* @param aCount tells us how many chars to compare
|
||||
* @return -1,0,1
|
||||
*/
|
||||
template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>>
|
||||
int32_t Compare(
|
||||
const char_type* aString, bool aIgnoreCase = false,
|
||||
size_type aCount = std::numeric_limits<size_type>::max()) const;
|
||||
|
||||
/**
|
||||
* Equality check between given string and this string.
|
||||
* This method is similar to `LowerCaseEqualsASCII` however both strings are
|
||||
* lowercased, meaning that `aString` need not be all lowercase.
|
||||
*
|
||||
* @param aString is the string to check
|
||||
* @param aIgnoreCase tells us how to treat case
|
||||
* @param aCount tells us how many chars to compare
|
||||
* @return boolean
|
||||
*/
|
||||
template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>>
|
||||
bool EqualsIgnoreCase(
|
||||
const char_type* aString,
|
||||
size_type aCount = std::numeric_limits<size_type>::max()) const {
|
||||
return Compare(aString, true, aCount) == 0;
|
||||
}
|
||||
|
||||
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
bool EqualsIgnoreCase(
|
||||
const incompatible_char_type* aString,
|
||||
size_type aCount = std::numeric_limits<size_type>::max()) const;
|
||||
bool EqualsIgnoreCase(const std::string_view& aString) const;
|
||||
|
||||
#if defined(MOZ_USE_CHAR16_WRAPPER)
|
||||
template <typename Q = T, typename EnableIfChar16 = Char16OnlyT<Q>>
|
||||
|
|
|
@ -238,7 +238,7 @@ class Object {
|
|||
|
||||
bool operator<(const Object& other) const {
|
||||
// sort based on mStr only
|
||||
return mStr.Compare(other.mStr.get()) < 0;
|
||||
return Compare(mStr, other.mStr) < 0;
|
||||
}
|
||||
|
||||
const char* Str() const { return mStr.get(); }
|
||||
|
|
Загрузка…
Ссылка в новой задаче