From c6b2c5db61c3822fa61d4f1d1b8a87e190c41e77 Mon Sep 17 00:00:00 2001 From: criss Date: Sat, 11 Jun 2022 01:13:42 +0300 Subject: [PATCH] Backed out 9 changesets (bug 1772006) causing build bustages on nsTString.cpp. CLOSED TREE Backed out changeset f17c7565707b (bug 1772006) Backed out changeset c725fe1f5882 (bug 1772006) Backed out changeset d19663161261 (bug 1772006) Backed out changeset b6611ab002d9 (bug 1772006) Backed out changeset 790f42b64af9 (bug 1772006) Backed out changeset 79a734b4e4d9 (bug 1772006) Backed out changeset 42730aae16ea (bug 1772006) Backed out changeset b2542aef3054 (bug 1772006) Backed out changeset 962bfea4a309 (bug 1772006) --- accessible/base/AccAttributes.h | 2 +- accessible/mac/AccessibleWrap.mm | 3 +- accessible/windows/ia2/ia2Accessible.cpp | 8 +- accessible/windows/uia/uiaRawElmProvider.cpp | 2 +- accessible/xul/XULMenuAccessible.cpp | 12 +- caps/OriginAttributes.cpp | 2 +- dom/base/Document.cpp | 4 +- dom/base/nsContentAreaDragDrop.cpp | 6 +- dom/base/nsContentUtils.cpp | 4 +- dom/cache/QuotaClient.cpp | 2 +- dom/canvas/CanvasRenderingContext2D.cpp | 2 +- dom/l10n/DocumentL10n.cpp | 8 +- dom/media/webrtc/jsapi/PeerConnectionCtx.cpp | 6 +- .../webrtc/jsapi/WebrtcGlobalInformation.cpp | 5 +- dom/quota/ActorsParent.cpp | 2 - dom/quota/QuotaManager.h | 1 - dom/security/nsContentSecurityUtils.cpp | 16 +- dom/serializers/nsPlainTextSerializer.cpp | 12 +- dom/webbrowserpersist/nsWebBrowserPersist.cpp | 2 +- dom/xhr/XMLHttpRequestMainThread.cpp | 2 +- editor/libeditor/EditorBase.cpp | 4 +- editor/libeditor/HTMLEditSubActionHandler.cpp | 3 +- editor/libeditor/HTMLEditorDataTransfer.cpp | 4 +- .../spellcheck/hunspell/glue/mozHunspell.cpp | 2 +- gfx/thebes/gfxPlatform.cpp | 2 +- gfx/thebes/gfxPlatformGtk.cpp | 4 +- .../tests/gtest/TestAppDateTimeFormat.cpp | 132 +-- layout/mathml/nsMathMLmtableFrame.cpp | 10 +- layout/style/ServoBindings.toml | 1 - netwerk/base/nsNetUtil.cpp | 2 +- netwerk/dns/DNSPacket.cpp | 2 +- netwerk/protocol/http/Http2Compression.cpp | 7 +- netwerk/protocol/http/OpaqueResponseUtils.cpp | 4 +- .../converters/mozTXTToHTMLConv.cpp | 10 +- security/manager/ssl/nsClientAuthRemember.cpp | 2 +- startupcache/StartupCacheUtils.cpp | 5 +- .../autocomplete/nsAutoCompleteController.cpp | 4 +- .../backgroundtasks/BackgroundTasks.cpp | 2 +- .../components/extensions/MatchPattern.cpp | 2 +- toolkit/system/osxproxy/ProxyUtils.mm | 2 +- toolkit/system/windowsproxy/ProxyUtils.cpp | 2 +- toolkit/xre/nsGDKErrorHandler.cpp | 3 +- toolkit/xre/nsXREDirProvider.cpp | 2 +- .../exthandler/nsExternalHelperAppService.cpp | 16 +- uriloader/exthandler/win/nsMIMEInfoWin.cpp | 2 +- widget/android/GfxInfo.cpp | 64 +- widget/gtk/GfxInfo.cpp | 4 +- widget/gtk/IMContextWrapper.cpp | 11 +- widget/nsNativeTheme.cpp | 2 +- widget/windows/GfxInfo.cpp | 18 +- widget/windows/IMMHandler.cpp | 7 +- widget/windows/nsFilePicker.cpp | 10 +- xpcom/base/nsTraceRefcnt.cpp | 5 +- xpcom/ds/moz.build | 1 - xpcom/io/nsLocalFileWin.cpp | 14 +- xpcom/string/RustStringAPI.cpp | 123 --- xpcom/string/moz.build | 23 +- xpcom/string/nsAString.h | 2 + ...iteralString.cpp => nsDependentString.cpp} | 10 +- .../nsDependentSubstring.cpp} | 10 +- xpcom/string/nsPromiseFlatString.cpp | 9 + xpcom/string/nsString.cpp | 9 + xpcom/string/nsStringBuffer.cpp | 162 --- xpcom/string/nsStringComparator.cpp | 38 + xpcom/string/nsStringFwd.h | 2 - xpcom/string/nsStringObsolete.cpp | 969 ++++++++++++++++++ xpcom/string/nsStringStats.cpp | 66 -- xpcom/string/nsStringStats.h | 32 - xpcom/string/nsSubstring.cpp | 424 ++++++++ xpcom/string/nsTDependentString.cpp | 5 - xpcom/string/nsTDependentString.h | 2 - xpcom/string/nsTDependentSubstring.cpp | 5 - xpcom/string/nsTDependentSubstring.h | 2 - xpcom/string/nsTPromiseFlatString.cpp | 5 - xpcom/string/nsTString.cpp | 61 -- xpcom/string/nsTString.h | 11 +- xpcom/string/nsTStringComparator.cpp | 28 - xpcom/string/nsTStringObsolete.cpp | 406 ++++++++ xpcom/string/nsTStringRepr.cpp | 192 ---- xpcom/string/nsTStringRepr.h | 142 +-- xpcom/string/nsTSubstring.cpp | 490 +++------ xpcom/string/nsTSubstring.h | 28 +- xpcom/string/precompiled_templates.cpp | 40 + xpcom/tests/gtest/TestStrings.cpp | 31 +- xpfe/appshell/AppWindow.cpp | 12 +- xpfe/appshell/nsContentTreeOwner.cpp | 31 +- 86 files changed, 2425 insertions(+), 1411 deletions(-) delete mode 100644 xpcom/string/RustStringAPI.cpp rename xpcom/string/{nsTLiteralString.cpp => nsDependentString.cpp} (58%) rename xpcom/{ds/nsCharSeparatedTokenizer.cpp => string/nsDependentSubstring.cpp} (56%) create mode 100644 xpcom/string/nsPromiseFlatString.cpp create mode 100644 xpcom/string/nsString.cpp delete mode 100644 xpcom/string/nsStringBuffer.cpp create mode 100644 xpcom/string/nsStringComparator.cpp create mode 100644 xpcom/string/nsStringObsolete.cpp delete mode 100644 xpcom/string/nsStringStats.cpp delete mode 100644 xpcom/string/nsStringStats.h create mode 100644 xpcom/string/nsSubstring.cpp create mode 100644 xpcom/string/nsTStringObsolete.cpp delete mode 100644 xpcom/string/nsTStringRepr.cpp create mode 100644 xpcom/string/precompiled_templates.cpp diff --git a/accessible/base/AccAttributes.h b/accessible/base/AccAttributes.h index db8a8542347e..2d651ff0bd56 100644 --- a/accessible/base/AccAttributes.h +++ b/accessible/base/AccAttributes.h @@ -214,7 +214,7 @@ class AccAttributes { void NameAsString(nsString& aName) { mName->ToString(aName); - if (StringBeginsWith(aName, u"aria-"_ns)) { + if (aName.Find("aria-", false, 0, 1) == 0) { // Found 'aria-' aName.ReplaceLiteral(0, 5, u""); } diff --git a/accessible/mac/AccessibleWrap.mm b/accessible/mac/AccessibleWrap.mm index 0e269c3f8980..47af7ee5b123 100644 --- a/accessible/mac/AccessibleWrap.mm +++ b/accessible/mac/AccessibleWrap.mm @@ -8,7 +8,6 @@ #include "DocAccessibleWrap.h" #include "nsObjCExceptions.h" #include "nsCocoaUtils.h" -#include "nsUnicharUtils.h" #include "LocalAccessible-inl.h" #include "nsAccUtils.h" @@ -294,7 +293,7 @@ bool AccessibleWrap::ApplyPostFilter(const EWhichPostFilter& aSearchKey, "Only search text supported"); nsAutoString name; Name(name); - return CaseInsensitiveFindInReadable(aSearchText, name); + return name.Find(aSearchText, true) != kNotFound; } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/windows/ia2/ia2Accessible.cpp b/accessible/windows/ia2/ia2Accessible.cpp index cc8a4f86429a..4c4722a6879c 100644 --- a/accessible/windows/ia2/ia2Accessible.cpp +++ b/accessible/windows/ia2/ia2Accessible.cpp @@ -29,6 +29,9 @@ using namespace mozilla; using namespace mozilla::a11y; +template +static void EscapeAttributeChars(String& aStr); + //////////////////////////////////////////////////////////////////////////////// // ia2Accessible //////////////////////////////////////////////////////////////////////////////// @@ -586,9 +589,10 @@ ia2Accessible::get_selectionRanges(IA2Range** aRanges, long* aNRanges) { //////////////////////////////////////////////////////////////////////////////// // Helpers -static inline void EscapeAttributeChars(nsString& aStr) { +template +static inline void EscapeAttributeChars(String& aStr) { int32_t offset = 0; - static const char16_t kCharsToEscape[] = u":;=,\\"; + static const char kCharsToEscape[] = ":;=,\\"; while ((offset = aStr.FindCharInSet(kCharsToEscape, offset)) != kNotFound) { aStr.Insert('\\', offset); offset += 2; diff --git a/accessible/windows/uia/uiaRawElmProvider.cpp b/accessible/windows/uia/uiaRawElmProvider.cpp index c78dbca7fefb..ef7c4d94109d 100644 --- a/accessible/windows/uia/uiaRawElmProvider.cpp +++ b/accessible/windows/uia/uiaRawElmProvider.cpp @@ -169,7 +169,7 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId, nsAutoString value; attribIter.AttrName()->ToString(attribName); attribIter.AttrValue(attribValue); - if (StringBeginsWith(attribName, u"aria-"_ns)) { + if (attribName.Find("aria-", false, 0, 1) == 0) { // Found 'aria-' attribName.ReplaceLiteral(0, 5, u""); } diff --git a/accessible/xul/XULMenuAccessible.cpp b/accessible/xul/XULMenuAccessible.cpp index 2cd05d65a41a..c105b47a1a4f 100644 --- a/accessible/xul/XULMenuAccessible.cpp +++ b/accessible/xul/XULMenuAccessible.cpp @@ -206,12 +206,12 @@ KeyBinding XULMenuitemAccessible::KeyboardShortcut() const { keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr); uint32_t modifierMask = 0; - if (modifiersStr.Find(u"shift") != -1) modifierMask |= KeyBinding::kShift; - if (modifiersStr.Find(u"alt") != -1) modifierMask |= KeyBinding::kAlt; - if (modifiersStr.Find(u"meta") != -1) modifierMask |= KeyBinding::kMeta; - if (modifiersStr.Find(u"os") != -1) modifierMask |= KeyBinding::kOS; - if (modifiersStr.Find(u"control") != -1) modifierMask |= KeyBinding::kControl; - if (modifiersStr.Find(u"accel") != -1) { + if (modifiersStr.Find("shift") != -1) modifierMask |= KeyBinding::kShift; + if (modifiersStr.Find("alt") != -1) modifierMask |= KeyBinding::kAlt; + if (modifiersStr.Find("meta") != -1) modifierMask |= KeyBinding::kMeta; + if (modifiersStr.Find("os") != -1) modifierMask |= KeyBinding::kOS; + if (modifiersStr.Find("control") != -1) modifierMask |= KeyBinding::kControl; + if (modifiersStr.Find("accel") != -1) { modifierMask |= KeyBinding::AccelModifier(); } diff --git a/caps/OriginAttributes.cpp b/caps/OriginAttributes.cpp index 6fca2c10e4f4..5403868be31e 100644 --- a/caps/OriginAttributes.cpp +++ b/caps/OriginAttributes.cpp @@ -228,7 +228,7 @@ void OriginAttributes::CreateSuffix(nsACString& aStr) const { if (!mGeckoViewSessionContextId.IsEmpty()) { nsAutoString sanitizedGeckoViewUserContextId(mGeckoViewSessionContextId); sanitizedGeckoViewUserContextId.ReplaceChar( - dom::quota::QuotaManager::kReplaceChars16, kSanitizedChar); + dom::quota::QuotaManager::kReplaceChars, kSanitizedChar); params.Set(u"geckoViewUserContextId"_ns, sanitizedGeckoViewUserContextId); } diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 9a0fc9fda85b..88b3c895cc16 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -10456,8 +10456,8 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) { if (RefPtr docType = GetDoctype()) { nsAutoString docId; docType->GetPublicId(docId); - if ((docId.Find(u"WAP") != -1) || (docId.Find(u"Mobile") != -1) || - (docId.Find(u"WML") != -1)) { + if ((docId.Find("WAP") != -1) || (docId.Find("Mobile") != -1) || + (docId.Find("WML") != -1)) { // We're making an assumption that the docType can't change here mViewportType = DisplayWidthHeight; return nsViewportInfo(aDisplaySize, defaultScale, diff --git a/dom/base/nsContentAreaDragDrop.cpp b/dom/base/nsContentAreaDragDrop.cpp index f3afebb4eee8..42e694f66fe8 100644 --- a/dom/base/nsContentAreaDragDrop.cpp +++ b/dom/base/nsContentAreaDragDrop.cpp @@ -274,8 +274,8 @@ nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable* aTransferable, nsIMIMEService::VALIDATE_DEFAULT, targetFilename); } else { // make the filename safe for the filesystem - targetFilename.ReplaceChar( - u"" FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, u'-'); + targetFilename.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, + '-'); } #endif /* defined(XP_MACOSX) */ @@ -745,7 +745,7 @@ nsresult DragDataProducer::AddStringsToDataTransfer( // that expects url\ntitle formatted data for x-moz-url. nsAutoString title(mTitleString); title.Trim("\r\n"); - title.ReplaceChar(u"\r\n", ' '); + title.ReplaceChar("\r\n", ' '); dragData += title; AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kURLMime), dragData, diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index ed9091a1c498..efc42b7f547d 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -10624,7 +10624,7 @@ bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) { ToLowerCase(host); for (;;) { - int32_t index = token.Find(host); + int32_t index = token.Find(host, false); if (index >= 0 && static_cast(index) + host.Length() <= token.Length()) { // If we found a full match, return true. @@ -10653,7 +10653,7 @@ bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) { } int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0; int32_t startIndexOfNextLevel = - host.Find(".", startIndexOfCurrentLevel + 1); + host.Find(".", false, startIndexOfCurrentLevel + 1); if (startIndexOfNextLevel <= 0) { break; } diff --git a/dom/cache/QuotaClient.cpp b/dom/cache/QuotaClient.cpp index b9b5695ee882..d7b36c1d3b9c 100644 --- a/dom/cache/QuotaClient.cpp +++ b/dom/cache/QuotaClient.cpp @@ -281,7 +281,7 @@ Result CacheQuotaClient::InitOrigin( // Ignore transient sqlite files and marker files if (leafName.EqualsLiteral("caches.sqlite-journal") || leafName.EqualsLiteral("caches.sqlite-shm") || - StringBeginsWith(leafName, u"caches.sqlite-mj"_ns) || + leafName.Find("caches.sqlite-mj"_ns, false, 0, 0) == 0 || leafName.EqualsLiteral("context_open.marker")) { break; } diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 20fed5674616..e5ed8b656e6c 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -3559,7 +3559,7 @@ void CanvasRenderingContext2D::GetDirection(nsAString& aDirection) { * @param str The string whose whitespace characters to replace. */ static inline void TextReplaceWhitespaceCharacters(nsAutoString& aStr) { - aStr.ReplaceChar(u"\x09\x0A\x0B\x0C\x0D", char16_t(' ')); + aStr.ReplaceChar("\x09\x0A\x0B\x0C\x0D", char16_t(' ')); } void CanvasRenderingContext2D::FillText(const nsAString& aText, double aX, diff --git a/dom/l10n/DocumentL10n.cpp b/dom/l10n/DocumentL10n.cpp index 0a5a43d5904f..bb8629ae3350 100644 --- a/dom/l10n/DocumentL10n.cpp +++ b/dom/l10n/DocumentL10n.cpp @@ -281,18 +281,18 @@ void DocumentL10n::MaybeRecordTelemetry() { nsCString key; - if (documentURI.Find(u"chrome://browser/content/browser.xhtml") == 0) { + if (documentURI.Find("chrome://browser/content/browser.xhtml") == 0) { if (mIsFirstBrowserWindow) { key = "browser_first_window"; mIsFirstBrowserWindow = false; } else { key = "browser_new_window"; } - } else if (documentURI.Find(u"about:home") == 0) { + } else if (documentURI.Find("about:home") == 0) { key = "about:home"; - } else if (documentURI.Find(u"about:newtab") == 0) { + } else if (documentURI.Find("about:newtab") == 0) { key = "about:newtab"; - } else if (documentURI.Find(u"about:preferences") == 0) { + } else if (documentURI.Find("about:preferences") == 0) { key = "about:preferences"; } else { return; diff --git a/dom/media/webrtc/jsapi/PeerConnectionCtx.cpp b/dom/media/webrtc/jsapi/PeerConnectionCtx.cpp index 78f1a4912db1..9d7db8322693 100644 --- a/dom/media/webrtc/jsapi/PeerConnectionCtx.cpp +++ b/dom/media/webrtc/jsapi/PeerConnectionCtx.cpp @@ -322,7 +322,7 @@ static void RecordCommonRtpTelemetry(const T& list, const T& lastList, const bool isRemote) { using namespace Telemetry; for (const auto& s : list) { - const bool isAudio = s.mKind.Value().Find(u"audio") != -1; + const bool isAudio = s.mKind.Value().Find("audio") != -1; if (s.mPacketsLost.WasPassed() && s.mPacketsReceived.WasPassed()) { if (const uint64_t total = s.mPacketsLost.Value() + s.mPacketsReceived.Value()) { @@ -372,7 +372,7 @@ void PeerConnectionCtx::DeliverStats( // Record bandwidth telemetry for (const auto& s : aReport->mInboundRtpStreamStats) { if (s.mBytesReceived.WasPassed()) { - const bool isAudio = s.mKind.Value().Find(u"audio") != -1; + const bool isAudio = s.mKind.Value().Find("audio") != -1; for (const auto& lastS : lastReport->mInboundRtpStreamStats) { if (lastS.mId == s.mId) { int32_t deltaMs = s.mTimestamp.Value() - lastS.mTimestamp.Value(); @@ -400,7 +400,7 @@ void PeerConnectionCtx::DeliverStats( lastReport->mRemoteInboundRtpStreamStats, true); for (const auto& s : aReport->mRemoteInboundRtpStreamStats) { if (s.mRoundTripTime.WasPassed()) { - const bool isAudio = s.mKind.Value().Find(u"audio") != -1; + const bool isAudio = s.mKind.Value().Find("audio") != -1; HistogramID id = isAudio ? WEBRTC_AUDIO_QUALITY_OUTBOUND_RTT : WEBRTC_VIDEO_QUALITY_OUTBOUND_RTT; Accumulate(id, s.mRoundTripTime.Value() * 1000); diff --git a/dom/media/webrtc/jsapi/WebrtcGlobalInformation.cpp b/dom/media/webrtc/jsapi/WebrtcGlobalInformation.cpp index e9c3d16e4285..791b46c70eb4 100644 --- a/dom/media/webrtc/jsapi/WebrtcGlobalInformation.cpp +++ b/dom/media/webrtc/jsapi/WebrtcGlobalInformation.cpp @@ -418,7 +418,8 @@ void WebrtcGlobalInformation::GetLogging( MOZ_ASSERT(XRE_IsParentProcess()); - nsAutoString pattern(aPattern); + nsAutoCString pattern; + CopyUTF16toUTF8(aPattern, pattern); // CallbackObject does not support threadsafe refcounting, and must be // destroyed on main. @@ -624,7 +625,7 @@ static void StoreLongTermICEStatisticsImpl_m(RTCStatsReportInternal* report) { report->mClosed = true; for (const auto& inboundRtpStats : report->mInboundRtpStreamStats) { - bool isVideo = (inboundRtpStats.mId.Value().Find(u"video") != -1); + bool isVideo = (inboundRtpStats.mId.Value().Find("video") != -1); if (!isVideo) { continue; } diff --git a/dom/quota/ActorsParent.cpp b/dom/quota/ActorsParent.cpp index 9febf9398a7b..0e428f40b289 100644 --- a/dom/quota/ActorsParent.cpp +++ b/dom/quota/ActorsParent.cpp @@ -214,8 +214,6 @@ using mozilla::net::MozURL; // of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and // FILE_PATH_SEPARATOR. const char QuotaManager::kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\"; -const char16_t QuotaManager::kReplaceChars16[] = - u"" CONTROL_CHARACTERS "/:*?\"<>|\\"; namespace { diff --git a/dom/quota/QuotaManager.h b/dom/quota/QuotaManager.h index 0be94e7a13fd..c1e53aa432f4 100644 --- a/dom/quota/QuotaManager.h +++ b/dom/quota/QuotaManager.h @@ -103,7 +103,6 @@ class QuotaManager final : public BackgroundThreadObject { } static const char kReplaceChars[]; - static const char16_t kReplaceChars16[]; static Result>, nsresult> GetOrCreate(); diff --git a/dom/security/nsContentSecurityUtils.cpp b/dom/security/nsContentSecurityUtils.cpp index 7a752b5db12f..8130f0a37efd 100644 --- a/dom/security/nsContentSecurityUtils.cpp +++ b/dom/security/nsContentSecurityUtils.cpp @@ -1122,26 +1122,26 @@ void nsContentSecurityUtils::AssertAboutPageHasCSP(Document* aDocument) { nsAutoString parsedPolicyStr; for (uint32_t i = 0; i < policyCount; ++i) { csp->GetPolicyString(i, parsedPolicyStr); - if (parsedPolicyStr.Find(u"default-src") >= 0) { + if (parsedPolicyStr.Find("default-src") >= 0) { foundDefaultSrc = true; } - if (parsedPolicyStr.Find(u"object-src 'none'") >= 0) { + if (parsedPolicyStr.Find("object-src 'none'") >= 0) { foundObjectSrc = true; } - if (parsedPolicyStr.Find(u"'unsafe-eval'") >= 0) { + if (parsedPolicyStr.Find("'unsafe-eval'") >= 0) { foundUnsafeEval = true; } - if (parsedPolicyStr.Find(u"'unsafe-inline'") >= 0) { + if (parsedPolicyStr.Find("'unsafe-inline'") >= 0) { foundUnsafeInline = true; } - if (parsedPolicyStr.Find(u"script-src") >= 0) { + if (parsedPolicyStr.Find("script-src") >= 0) { foundScriptSrc = true; } - if (parsedPolicyStr.Find(u"worker-src") >= 0) { + if (parsedPolicyStr.Find("worker-src") >= 0) { foundWorkerSrc = true; } - if (parsedPolicyStr.Find(u"http:") >= 0 || - parsedPolicyStr.Find(u"https:") >= 0) { + if (parsedPolicyStr.Find("http:") >= 0 || + parsedPolicyStr.Find("https:") >= 0) { foundWebScheme = true; } } diff --git a/dom/serializers/nsPlainTextSerializer.cpp b/dom/serializers/nsPlainTextSerializer.cpp index 31c7c216c605..958b22ecf093 100644 --- a/dom/serializers/nsPlainTextSerializer.cpp +++ b/dom/serializers/nsPlainTextSerializer.cpp @@ -436,7 +436,7 @@ nsPlainTextSerializer::AppendText(nsIContent* aText, int32_t aStartOffset, // We have to split the string across newlines // to match parser behavior int32_t start = 0; - int32_t offset = textstr.FindCharInSet(u"\n\r"); + int32_t offset = textstr.FindCharInSet("\n\r"); while (offset != kNotFound) { if (offset > start) { // Pass in the line @@ -447,7 +447,7 @@ nsPlainTextSerializer::AppendText(nsIContent* aText, int32_t aStartOffset, DoAddText(); start = offset + 1; - offset = textstr.FindCharInSet(u"\n\r", start); + offset = textstr.FindCharInSet("\n\r", start); } // Consume the last bit of the string if there's any left @@ -644,13 +644,13 @@ nsresult nsPlainTextSerializer::DoOpenContainer(const nsAtom* aTag) { nsAutoString style; int32_t whitespace; if (NS_SUCCEEDED(GetAttributeValue(nsGkAtoms::style, style)) && - (kNotFound != (whitespace = style.Find(u"white-space:")))) { - if (kNotFound != style.LowerCaseFindASCII("pre-wrap", whitespace)) { + (kNotFound != (whitespace = style.Find("white-space:")))) { + if (kNotFound != style.Find("pre-wrap", true, whitespace)) { #ifdef DEBUG_preformatted printf("Set mPreFormattedMail based on style pre-wrap\n"); #endif mPreFormattedMail = true; - } else if (kNotFound != style.LowerCaseFindASCII("pre", whitespace)) { + } else if (kNotFound != style.Find("pre", true, whitespace)) { #ifdef DEBUG_preformatted printf("Set mPreFormattedMail based on style pre\n"); #endif @@ -1583,7 +1583,7 @@ void nsPlainTextSerializer::Write(const nsAString& aStr) { int32_t bol = 0; while (bol < totLen) { // Loop over lines // Find a place where we may have to do whitespace compression - nextpos = str.FindCharInSet(u" \t\n\r", bol); + nextpos = str.FindCharInSet(" \t\n\r", bol); #ifdef DEBUG_wrapping nsAutoString remaining; str.Right(remaining, totLen - bol); diff --git a/dom/webbrowserpersist/nsWebBrowserPersist.cpp b/dom/webbrowserpersist/nsWebBrowserPersist.cpp index 4ee8cde99437..7f304a77e848 100644 --- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp +++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp @@ -1418,7 +1418,7 @@ nsresult nsWebBrowserPersist::SaveURIInternal( const char* kWhitespace = "\b\t\r\n "; nsAutoCString extraHeaders(aExtraHeaders); while (true) { - crlf = extraHeaders.Find("\r\n"); + crlf = extraHeaders.Find("\r\n", true); if (crlf == -1) break; extraHeaders.Mid(oneHeader, 0, crlf); extraHeaders.Cut(0, crlf + 2); diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index ec323cc3ae88..625ab05d3f80 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -1984,7 +1984,7 @@ XMLHttpRequestMainThread::OnStartRequest(nsIRequest* request) { } } else if (!(type.EqualsLiteral("text/xml") || type.EqualsLiteral("application/xml") || - StringEndsWith(type, "+xml"_ns))) { + type.RFind("+xml", true, -1, 4) != kNotFound)) { // Follow https://xhr.spec.whatwg.org/ // If final MIME type is not null, text/html, text/xml, application/xml, // or does not end in +xml, return null. diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp index e641c744ec82..02211c8e7b09 100644 --- a/editor/libeditor/EditorBase.cpp +++ b/editor/libeditor/EditorBase.cpp @@ -5894,9 +5894,9 @@ NS_IMETHODIMP EditorBase::GetWrapWidth(int32_t* aWrapColumn) { // static void CutStyle(const char* stylename, nsString& styleValue) { // Find the current wrapping type: - int32_t styleStart = styleValue.LowerCaseFindASCII(stylename); + int32_t styleStart = styleValue.Find(stylename, true); if (styleStart >= 0) { - int32_t styleEnd = styleValue.Find(u";", styleStart); + int32_t styleEnd = styleValue.Find(";", false, styleStart); if (styleEnd > styleStart) { styleValue.Cut(styleStart, styleEnd - styleStart + 1); } else { diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp index 6dd5a478b05b..b64fc0e9acc6 100644 --- a/editor/libeditor/HTMLEditSubActionHandler.cpp +++ b/editor/libeditor/HTMLEditSubActionHandler.cpp @@ -1268,12 +1268,13 @@ EditActionResult HTMLEditor::HandleInsertText( } constexpr auto tabStr = u"\t"_ns; constexpr auto spacesStr = u" "_ns; + char specialChars[] = {TAB, nsCRT::LF, 0}; nsAutoString insertionString(aInsertionString); // For FindCharInSet(). while (pos != -1 && pos < AssertedCast(insertionString.Length())) { int32_t oldPos = pos; int32_t subStrLen; - pos = insertionString.FindCharInSet(u"\t\n", oldPos); + pos = insertionString.FindCharInSet(specialChars, oldPos); if (pos != -1) { subStrLen = pos - oldPos; diff --git a/editor/libeditor/HTMLEditorDataTransfer.cpp b/editor/libeditor/HTMLEditorDataTransfer.cpp index 9f375684bf5d..c518a47b06df 100644 --- a/editor/libeditor/HTMLEditorDataTransfer.cpp +++ b/editor/libeditor/HTMLEditorDataTransfer.cpp @@ -1449,14 +1449,14 @@ void RemoveFragComments(nsCString& aStr) { // remove the StartFragment/EndFragment comments from the str, if present int32_t startCommentIndx = aStr.Find("", startCommentIndx); + int32_t startCommentEnd = aStr.Find("-->", false, startCommentIndx); if (startCommentEnd > startCommentIndx) { aStr.Cut(startCommentIndx, (startCommentEnd + 3) - startCommentIndx); } } int32_t endCommentIndx = aStr.Find("", endCommentIndx); + int32_t endCommentEnd = aStr.Find("-->", false, endCommentIndx); if (endCommentEnd > endCommentIndx) { aStr.Cut(endCommentIndx, (endCommentEnd + 3) - endCommentIndx); } diff --git a/extensions/spellcheck/hunspell/glue/mozHunspell.cpp b/extensions/spellcheck/hunspell/glue/mozHunspell.cpp index 1565a0d54851..6eb76d3e9f70 100644 --- a/extensions/spellcheck/hunspell/glue/mozHunspell.cpp +++ b/extensions/spellcheck/hunspell/glue/mozHunspell.cpp @@ -354,7 +354,7 @@ mozHunspell::LoadDictionariesFromDir(nsIFile* aDir) { if (NS_FAILED(rv) || !check) continue; // Replace '_' separator with '-' - dict.ReplaceChar('_', '-'); + dict.ReplaceChar("_", '-'); nsCOMPtr uri; rv = NS_NewFileURI(getter_AddRefs(uri), file); diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index d9a4c6beec2f..c9326aa40a2e 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -2857,7 +2857,7 @@ void gfxPlatform::InitWebGLConfig() { // It causes the linking of some shaders to fail. See bug 1485441. nsAutoString renderer; gfxInfo->GetAdapterDeviceID(renderer); - if (renderer.Find(u"Adreno (TM) 630") != -1) { + if (renderer.Find("Adreno (TM) 630") != -1) { gfxVars::SetAllowEglRbab(false); } } diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 57ba1ce5ae0f..9cd78b6a0bda 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -974,10 +974,10 @@ gfxPlatformGtk::CreateGlobalHardwareVsyncSource() { nsCOMPtr gfxInfo = components::GfxInfo::Service(); nsString windowProtocol; gfxInfo->GetWindowProtocol(windowProtocol); - bool isXwayland = windowProtocol.Find(u"xwayland") != -1; + bool isXwayland = windowProtocol.Find("xwayland") != -1; nsString adapterDriverVendor; gfxInfo->GetAdapterDriverVendor(adapterDriverVendor); - bool isMesa = adapterDriverVendor.Find(u"mesa") != -1; + bool isMesa = adapterDriverVendor.Find("mesa") != -1; // Only use GLX vsync when the OpenGL compositor / WebRender is being used. // The extra cost of initializing a GLX context while blocking the main thread diff --git a/intl/locale/tests/gtest/TestAppDateTimeFormat.cpp b/intl/locale/tests/gtest/TestAppDateTimeFormat.cpp index eb5a464891af..75e77782ee46 100644 --- a/intl/locale/tests/gtest/TestAppDateTimeFormat.cpp +++ b/intl/locale/tests/gtest/TestAppDateTimeFormat.cpp @@ -29,68 +29,68 @@ TEST(AppDateTimeFormat, FormatPRExplodedTime) nsresult rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"January") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1970") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"12:00:00 AM") != kNotFound || - formattedTime.Find(u"00:00:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("January") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1970") != kNotFound); + ASSERT_TRUE(formattedTime.Find("12:00:00 AM") != kNotFound || + formattedTime.Find("00:00:00") != kNotFound); prExplodedTime = {0, 0, 19, 0, 1, 0, 1970, 4, 0, {(19 * 60), 0}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"January") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1970") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"12:19:00 AM") != kNotFound || - formattedTime.Find(u"00:19:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("January") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1970") != kNotFound); + ASSERT_TRUE(formattedTime.Find("12:19:00 AM") != kNotFound || + formattedTime.Find("00:19:00") != kNotFound); prExplodedTime = {0, 0, 0, 7, 1, 0, 1970, 4, 0, {(6 * 60 * 60), (1 * 60 * 60)}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"January") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1970") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"7:00:00 AM") != kNotFound || - formattedTime.Find(u"07:00:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("January") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1970") != kNotFound); + ASSERT_TRUE(formattedTime.Find("7:00:00 AM") != kNotFound || + formattedTime.Find("07:00:00") != kNotFound); prExplodedTime = { 0, 0, 29, 11, 1, 0, 1970, 4, 0, {(10 * 60 * 60) + (29 * 60), (1 * 60 * 60)}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"January") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1970") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"11:29:00 AM") != kNotFound || - formattedTime.Find(u"11:29:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("January") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1970") != kNotFound); + ASSERT_TRUE(formattedTime.Find("11:29:00 AM") != kNotFound || + formattedTime.Find("11:29:00") != kNotFound); prExplodedTime = {0, 0, 37, 23, 31, 11, 1969, 3, 364, {-(23 * 60), 0}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"December") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"31") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1969") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"11:37:00 PM") != kNotFound || - formattedTime.Find(u"23:37:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("December") != kNotFound); + ASSERT_TRUE(formattedTime.Find("31") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1969") != kNotFound); + ASSERT_TRUE(formattedTime.Find("11:37:00 PM") != kNotFound || + formattedTime.Find("23:37:00") != kNotFound); prExplodedTime = {0, 0, 0, 17, 31, 11, 1969, 3, 364, {-(7 * 60 * 60), 0}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"December") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"31") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1969") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"5:00:00 PM") != kNotFound || - formattedTime.Find(u"17:00:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("December") != kNotFound); + ASSERT_TRUE(formattedTime.Find("31") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1969") != kNotFound); + ASSERT_TRUE(formattedTime.Find("5:00:00 PM") != kNotFound || + formattedTime.Find("17:00:00") != kNotFound); prExplodedTime = { 0, 0, 47, 14, 31, 11, 1969, 3, 364, {-((10 * 60 * 60) + (13 * 60)), (1 * 60 * 60)}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"December") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"31") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1969") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"2:47:00 PM") != kNotFound || - formattedTime.Find(u"14:47:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("December") != kNotFound); + ASSERT_TRUE(formattedTime.Find("31") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1969") != kNotFound); + ASSERT_TRUE(formattedTime.Find("2:47:00 PM") != kNotFound || + formattedTime.Find("14:47:00") != kNotFound); } TEST(AppDateTimeFormat, DateFormatSelectors) @@ -158,70 +158,70 @@ TEST(AppDateTimeFormat, FormatPRExplodedTimeForeign) nsresult rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"1.") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"Januar") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1970") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"12:00:00 AM") != kNotFound || - formattedTime.Find(u"00:00:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1.") != kNotFound); + ASSERT_TRUE(formattedTime.Find("Januar") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1970") != kNotFound); + ASSERT_TRUE(formattedTime.Find("12:00:00 AM") != kNotFound || + formattedTime.Find("00:00:00") != kNotFound); prExplodedTime = {0, 0, 19, 0, 1, 0, 1970, 4, 0, {(19 * 60), 0}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"1.") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"Januar") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1970") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"12:19:00 AM") != kNotFound || - formattedTime.Find(u"00:19:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1.") != kNotFound); + ASSERT_TRUE(formattedTime.Find("Januar") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1970") != kNotFound); + ASSERT_TRUE(formattedTime.Find("12:19:00 AM") != kNotFound || + formattedTime.Find("00:19:00") != kNotFound); prExplodedTime = {0, 0, 0, 7, 1, 0, 1970, 4, 0, {(6 * 60 * 60), (1 * 60 * 60)}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"1.") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"Januar") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1970") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"7:00:00 AM") != kNotFound || - formattedTime.Find(u"07:00:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1.") != kNotFound); + ASSERT_TRUE(formattedTime.Find("Januar") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1970") != kNotFound); + ASSERT_TRUE(formattedTime.Find("7:00:00 AM") != kNotFound || + formattedTime.Find("07:00:00") != kNotFound); prExplodedTime = { 0, 0, 29, 11, 1, 0, 1970, 4, 0, {(10 * 60 * 60) + (29 * 60), (1 * 60 * 60)}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"1.") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"Januar") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1970") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"11:29:00 AM") != kNotFound || - formattedTime.Find(u"11:29:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1.") != kNotFound); + ASSERT_TRUE(formattedTime.Find("Januar") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1970") != kNotFound); + ASSERT_TRUE(formattedTime.Find("11:29:00 AM") != kNotFound || + formattedTime.Find("11:29:00") != kNotFound); prExplodedTime = {0, 0, 37, 23, 31, 11, 1969, 3, 364, {-(23 * 60), 0}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"31.") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"Dezember") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1969") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"11:37:00 PM") != kNotFound || - formattedTime.Find(u"23:37:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("31.") != kNotFound); + ASSERT_TRUE(formattedTime.Find("Dezember") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1969") != kNotFound); + ASSERT_TRUE(formattedTime.Find("11:37:00 PM") != kNotFound || + formattedTime.Find("23:37:00") != kNotFound); prExplodedTime = {0, 0, 0, 17, 31, 11, 1969, 3, 364, {-(7 * 60 * 60), 0}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"31.") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"Dezember") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1969") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"5:00:00 PM") != kNotFound || - formattedTime.Find(u"17:00:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("31.") != kNotFound); + ASSERT_TRUE(formattedTime.Find("Dezember") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1969") != kNotFound); + ASSERT_TRUE(formattedTime.Find("5:00:00 PM") != kNotFound || + formattedTime.Find("17:00:00") != kNotFound); prExplodedTime = { 0, 0, 47, 14, 31, 11, 1969, 3, 364, {-((10 * 60 * 60) + (13 * 60)), (1 * 60 * 60)}}; rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime); ASSERT_TRUE(NS_SUCCEEDED(rv)); - ASSERT_TRUE(formattedTime.Find(u"31.") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"Dezember") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"1969") != kNotFound); - ASSERT_TRUE(formattedTime.Find(u"2:47:00 PM") != kNotFound || - formattedTime.Find(u"14:47:00") != kNotFound); + ASSERT_TRUE(formattedTime.Find("31.") != kNotFound); + ASSERT_TRUE(formattedTime.Find("Dezember") != kNotFound); + ASSERT_TRUE(formattedTime.Find("1969") != kNotFound); + ASSERT_TRUE(formattedTime.Find("2:47:00 PM") != kNotFound || + formattedTime.Find("14:47:00") != kNotFound); } TEST(AppDateTimeFormat, DateFormatSelectorsForeign) diff --git a/layout/mathml/nsMathMLmtableFrame.cpp b/layout/mathml/nsMathMLmtableFrame.cpp index 6036a45caad8..46e298cc9baa 100644 --- a/layout/mathml/nsMathMLmtableFrame.cpp +++ b/layout/mathml/nsMathMLmtableFrame.cpp @@ -620,19 +620,19 @@ static void ParseAlignAttribute(nsString& aValue, eAlign& aAlign, // ToInteger ignores the whitespaces around the number aValue.CompressWhitespace(true, false); - if (0 == aValue.Find(u"top")) { + if (0 == aValue.Find("top")) { len = 3; // 3 is the length of 'top' aAlign = eAlign_top; - } else if (0 == aValue.Find(u"bottom")) { + } else if (0 == aValue.Find("bottom")) { len = 6; // 6 is the length of 'bottom' aAlign = eAlign_bottom; - } else if (0 == aValue.Find(u"center")) { + } else if (0 == aValue.Find("center")) { len = 6; // 6 is the length of 'center' aAlign = eAlign_center; - } else if (0 == aValue.Find(u"baseline")) { + } else if (0 == aValue.Find("baseline")) { len = 8; // 8 is the length of 'baseline' aAlign = eAlign_baseline; - } else if (0 == aValue.Find(u"axis")) { + } else if (0 == aValue.Find("axis")) { len = 4; // 4 is the length of 'axis' aAlign = eAlign_axis; } diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml index da5bed4270d9..6ed22d360996 100644 --- a/layout/style/ServoBindings.toml +++ b/layout/style/ServoBindings.toml @@ -47,7 +47,6 @@ raw-lines = [ hide-types = [ ".*char_traits", ".*incompatible_char_type", - ".*string_view", # https://github.com/rust-lang/rust-bindgen/issues/1503 "mozilla::StyleTimingFunction.*", # https://github.com/rust-lang/rust-bindgen/issues/1559 diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp index 9f4f60fc1358..c25ae1659f2d 100644 --- a/netwerk/base/nsNetUtil.cpp +++ b/netwerk/base/nsNetUtil.cpp @@ -3810,7 +3810,7 @@ nsresult NS_HasRootDomain(const nsACString& aInput, const nsACString& aHost, } // If aHost is not found, we know we do not have it as a root domain. - int32_t index = nsAutoCString(aInput).Find(aHost); + int32_t index = nsAutoCString(aInput).Find(aHost.BeginReading()); if (index == kNotFound) { return NS_OK; } diff --git a/netwerk/dns/DNSPacket.cpp b/netwerk/dns/DNSPacket.cpp index 31230620a6d9..68565672f74f 100644 --- a/netwerk/dns/DNSPacket.cpp +++ b/netwerk/dns/DNSPacket.cpp @@ -621,7 +621,7 @@ nsresult DNSPacket::DecodeInternal( bool responseMatchesQuestion = (qname.Length() == aHost.Length() || (aHost.Length() == qname.Length() + 1 && aHost.Last() == '.')) && - qname.EqualsIgnoreCase(aHost.BeginReading(), qname.Length()); + qname.Compare(aHost.BeginReading(), true, qname.Length()) == 0; if (responseMatchesQuestion) { // RDATA diff --git a/netwerk/protocol/http/Http2Compression.cpp b/netwerk/protocol/http/Http2Compression.cpp index 44c35055634e..15ca49c20131 100644 --- a/netwerk/protocol/http/Http2Compression.cpp +++ b/netwerk/protocol/http/Http2Compression.cpp @@ -1084,12 +1084,13 @@ nsresult Http2Compressor::EncodeHeaderBlock( while (true) { int32_t startIndex = crlfIndex + 2; - crlfIndex = nvInput.Find("\r\n", startIndex); + crlfIndex = nvInput.Find("\r\n", false, startIndex); if (crlfIndex == -1) { break; } - int32_t colonIndex = Substring(nvInput, 0, crlfIndex).Find(":", startIndex); + int32_t colonIndex = + nvInput.Find(":", false, startIndex, crlfIndex - startIndex); if (colonIndex == -1) { break; } @@ -1150,7 +1151,7 @@ nsresult Http2Compressor::EncodeHeaderBlock( int32_t nextCookie = valueIndex; while (haveMoreCookies) { int32_t semiSpaceIndex = - Substring(nvInput, 0, crlfIndex).Find("; ", nextCookie); + nvInput.Find("; ", false, nextCookie, crlfIndex - nextCookie); if (semiSpaceIndex == -1) { haveMoreCookies = false; semiSpaceIndex = crlfIndex; diff --git a/netwerk/protocol/http/OpaqueResponseUtils.cpp b/netwerk/protocol/http/OpaqueResponseUtils.cpp index 7b122fd25974..62d16a70ef31 100644 --- a/netwerk/protocol/http/OpaqueResponseUtils.cpp +++ b/netwerk/protocol/http/OpaqueResponseUtils.cpp @@ -111,8 +111,8 @@ Result, nsresult> ParseContentRangeHeaderString(const nsAutoCString& aRangeStr) { // Parse the range header: e.g. Content-Range: bytes 7000-7999/8000. const int32_t spacePos = aRangeStr.Find(" "_ns); - const int32_t dashPos = aRangeStr.Find("-"_ns, spacePos); - const int32_t slashPos = aRangeStr.Find("/"_ns, dashPos); + const int32_t dashPos = aRangeStr.Find("-"_ns, true, spacePos); + const int32_t slashPos = aRangeStr.Find("/"_ns, true, dashPos); nsAutoCString rangeStartText; aRangeStr.Mid(rangeStartText, spacePos + 1, dashPos - (spacePos + 1)); diff --git a/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp b/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp index 22a0b9f151b8..5a4f7acbef03 100644 --- a/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp +++ b/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp @@ -1135,7 +1135,7 @@ mozTXTToHTMLConv::ScanHTML(const nsAString& input, uint32_t whattodo, // if a tag, skip until . // Make sure there's a white-space character after, not to match "abbr". { - i = aInString.LowerCaseFindASCII("", i); + i = aInString.Find("", true, i); if (i == kNotFound) { i = lengthOfInString; } else { @@ -1144,7 +1144,7 @@ mozTXTToHTMLConv::ScanHTML(const nsAString& input, uint32_t whattodo, } else if (Substring(aInString, i + 1, 3).LowerCaseEqualsASCII("!--")) // if out-commended code, skip until --> { - i = aInString.Find(u"-->", i); + i = aInString.Find("-->", false, i); if (i == kNotFound) { i = lengthOfInString; } else { @@ -1155,7 +1155,7 @@ mozTXTToHTMLConv::ScanHTML(const nsAString& input, uint32_t whattodo, canFollow.FindChar(aInString[i + 6]) != kNotFound) // if style tag, skip until { - i = aInString.LowerCaseFindASCII("", i); + i = aInString.Find("", true, i); if (i == kNotFound) { i = lengthOfInString; } else { @@ -1167,7 +1167,7 @@ mozTXTToHTMLConv::ScanHTML(const nsAString& input, uint32_t whattodo, canFollow.FindChar(aInString[i + 7]) != kNotFound) // if script tag, skip until { - i = aInString.LowerCaseFindASCII("", i); + i = aInString.Find("", true, i); if (i == kNotFound) { i = lengthOfInString; } else { @@ -1179,7 +1179,7 @@ mozTXTToHTMLConv::ScanHTML(const nsAString& input, uint32_t whattodo, // if head tag, skip until // Make sure not to match
. { - i = aInString.LowerCaseFindASCII("", i); + i = aInString.Find("", true, i); if (i == kNotFound) { i = lengthOfInString; } else { diff --git a/security/manager/ssl/nsClientAuthRemember.cpp b/security/manager/ssl/nsClientAuthRemember.cpp index fd0fce75a270..bd90fc9d004b 100644 --- a/security/manager/ssl/nsClientAuthRemember.cpp +++ b/security/manager/ssl/nsClientAuthRemember.cpp @@ -332,7 +332,7 @@ void nsClientAuthRememberService::GetEntryKey( bool nsClientAuthRememberService::IsPrivateBrowsingKey( const nsCString& entryKey) { - const int32_t separator = entryKey.Find(":"); + const int32_t separator = entryKey.Find(":", false, 0, -1); nsCString suffix; if (separator >= 0) { entryKey.Left(suffix, separator); diff --git a/startupcache/StartupCacheUtils.cpp b/startupcache/StartupCacheUtils.cpp index 8f3622328ded..34ca60204550 100644 --- a/startupcache/StartupCacheUtils.cpp +++ b/startupcache/StartupCacheUtils.cpp @@ -102,8 +102,9 @@ static inline bool canonicalizeBase(nsAutoCString& spec, nsACString& out) { rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, appBase); if (NS_FAILED(rv)) return false; - bool underGre = StringBeginsWith(spec, greBase); - bool underApp = appBase.Length() && StringBeginsWith(spec, appBase); + bool underGre = !greBase.Compare(spec.get(), false, greBase.Length()); + bool underApp = + appBase.Length() && !appBase.Compare(spec.get(), false, appBase.Length()); if (!underGre && !underApp) return false; diff --git a/toolkit/components/autocomplete/nsAutoCompleteController.cpp b/toolkit/components/autocomplete/nsAutoCompleteController.cpp index 994fb48c80a8..a98d2d332958 100644 --- a/toolkit/components/autocomplete/nsAutoCompleteController.cpp +++ b/toolkit/components/autocomplete/nsAutoCompleteController.cpp @@ -597,7 +597,7 @@ nsAutoCompleteController::HandleKeyNavigation(uint32_t aKey, bool* _retval) { input->GetTextValue(inputValue); if (NS_SUCCEEDED(GetDefaultCompleteValue(-1, false, value))) { nsAutoString suggestedValue; - int32_t pos = inputValue.Find(u" >> "); + int32_t pos = inputValue.Find(" >> "); if (pos > 0) { inputValue.Right(suggestedValue, inputValue.Length() - pos - 4); } else { @@ -1231,7 +1231,7 @@ nsresult nsAutoCompleteController::EnterMatch(bool aIsPopupSelection, nsAutoString inputValue; input->GetTextValue(inputValue); nsAutoString suggestedValue; - int32_t pos = inputValue.Find(u" >> "); + int32_t pos = inputValue.Find(" >> "); if (pos > 0) { inputValue.Right(suggestedValue, inputValue.Length() - pos - 4); } else { diff --git a/toolkit/components/backgroundtasks/BackgroundTasks.cpp b/toolkit/components/backgroundtasks/BackgroundTasks.cpp index f59dadff5383..158aca318c53 100644 --- a/toolkit/components/backgroundtasks/BackgroundTasks.cpp +++ b/toolkit/components/backgroundtasks/BackgroundTasks.cpp @@ -276,7 +276,7 @@ nsresult BackgroundTasks::RemoveStaleTemporaryProfileDirectories( } // Find profile folders matching our prefix. - if (!StringBeginsWith(entryName, aPrefix)) { + if (aPrefix.Compare(entryName.get(), false, aPrefix.Length()) != 0) { continue; } diff --git a/toolkit/components/extensions/MatchPattern.cpp b/toolkit/components/extensions/MatchPattern.cpp index 7e3afccaf187..14f527803982 100644 --- a/toolkit/components/extensions/MatchPattern.cpp +++ b/toolkit/components/extensions/MatchPattern.cpp @@ -641,7 +641,7 @@ void MatchGlob::Init(JSContext* aCx, const nsAString& aGlob, mGlob = aGlob; // Check for a literal match with no glob metacharacters. - auto index = mGlob.FindCharInSet(aAllowQuestion ? u"*?" : u"*"); + auto index = mGlob.FindCharInSet(aAllowQuestion ? "*?" : "*"); if (index < 0) { mPathLiteral = mGlob; return; diff --git a/toolkit/system/osxproxy/ProxyUtils.mm b/toolkit/system/osxproxy/ProxyUtils.mm index d3a6b87a39ae..cade1c5faeea 100644 --- a/toolkit/system/osxproxy/ProxyUtils.mm +++ b/toolkit/system/osxproxy/ProxyUtils.mm @@ -128,7 +128,7 @@ static bool IsMatchWildcard(const nsACString& aHost, const nsACString& aOverride tokenEnd = overrideLength; // no '*' char, match rest of string } nsAutoCString token(Substring(override, tokenStart, tokenEnd - tokenStart)); - offset = host.Find(token, offset); + offset = host.Find(token, /* aIgnoreCase = */ false, offset); if (offset == -1 || (!star && offset)) { return false; } diff --git a/toolkit/system/windowsproxy/ProxyUtils.cpp b/toolkit/system/windowsproxy/ProxyUtils.cpp index 2c110db38b3f..ad631395a868 100644 --- a/toolkit/system/windowsproxy/ProxyUtils.cpp +++ b/toolkit/system/windowsproxy/ProxyUtils.cpp @@ -140,7 +140,7 @@ static bool IsMatchWildcard(const nsACString& aHost, } nsAutoCString token( Substring(override, tokenStart, tokenEnd - tokenStart)); - offset = host.Find(token, offset); + offset = host.Find(token, /* aIgnoreCase = */ false, offset); if (offset == -1 || (!star && offset)) { return false; } diff --git a/toolkit/xre/nsGDKErrorHandler.cpp b/toolkit/xre/nsGDKErrorHandler.cpp index 19895cff0afb..0d0088409f00 100644 --- a/toolkit/xre/nsGDKErrorHandler.cpp +++ b/toolkit/xre/nsGDKErrorHandler.cpp @@ -79,7 +79,8 @@ static void GdkErrorHandler(const gchar* log_domain, GLogLevelFlags log_level, } constexpr auto minorCodeString = " minor_code "_ns; - start = buffer.Find(minorCodeString, endptr - buffer.BeginReading()); + start = buffer.Find(minorCodeString, /* aIgnoreCase = */ false, + endptr - buffer.BeginReading()); if (!start) { MOZ_CRASH_UNSAFE(message); } diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index 2bd2754f181f..5536f4423f4a 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -1218,7 +1218,7 @@ nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile** aResult, return NS_ERROR_FAILURE; } - int32_t dotIndex = appDirPath.RFind(u".app"); + int32_t dotIndex = appDirPath.RFind(".app"); if (dotIndex == kNotFound) { dotIndex = appDirPath.Length(); } diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp index f51412b2cf91..3aaf69cd2615 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -310,7 +310,7 @@ static nsresult GetDownloadDirectory(nsIFile** _directory, nsAutoString userDir; userDir.AssignLiteral("mozilla_"); userDir.AppendASCII(userName); - userDir.ReplaceChar(u"" FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '_'); + userDir.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '_'); int counter = 0; bool pathExists; @@ -769,7 +769,7 @@ NS_IMETHODIMP nsExternalHelperAppService::CreateListener( } nsAutoString extension; - int32_t dotidx = fileName.RFind(u"."); + int32_t dotidx = fileName.RFind("."); if (dotidx != -1) { extension = Substring(fileName, dotidx + 1); } @@ -3273,7 +3273,7 @@ nsExternalHelperAppService::ValidateFileNameForSaving( // Just sanitize the filename only. if (aFlags & VALIDATE_SANITIZE_ONLY) { nsAutoString extension; - int32_t dotidx = fileName.RFind(u"."); + int32_t dotidx = fileName.RFind("."); if (dotidx != -1) { extension = Substring(fileName, dotidx + 1); } @@ -3327,7 +3327,7 @@ nsExternalHelperAppService::ValidateFileNameForSaving( } } else { // Determine the current extension for the filename. - int32_t dotidx = fileName.RFind(u"."); + int32_t dotidx = fileName.RFind("."); if (dotidx != -1) { CopyUTF16toUTF8(Substring(fileName, dotidx + 1), extension); } @@ -3420,7 +3420,7 @@ nsExternalHelperAppService::ValidateFileNameForSaving( ModifyExtensionType modify = ShouldModifyExtension(mimeInfo, originalExtension); if (modify == ModifyExtension_Replace) { - int32_t dotidx = fileName.RFind(u"."); + int32_t dotidx = fileName.RFind("."); if (dotidx != -1) { // Remove the existing extension and replace it. fileName.Truncate(dotidx); @@ -3444,7 +3444,7 @@ nsExternalHelperAppService::ValidateFileNameForSaving( // If no filename is present, use a default filename. if (!(aFlags & VALIDATE_NO_DEFAULT_FILENAME) && - (fileName.Length() == 0 || fileName.RFind(u".") == 0)) { + (fileName.Length() == 0 || fileName.RFind(".") == 0)) { nsCOMPtr stringService = mozilla::components::StringBundle::Service(); if (stringService) { @@ -3478,8 +3478,8 @@ void nsExternalHelperAppService::SanitizeFileName(nsAString& aFileName, nsAutoString fileName(aFileName); // Replace characters - fileName.ReplaceChar(u"" KNOWN_PATH_SEPARATORS, u'_'); - fileName.ReplaceChar(u"" FILE_ILLEGAL_CHARACTERS, u' '); + fileName.ReplaceChar(KNOWN_PATH_SEPARATORS, '_'); + fileName.ReplaceChar(FILE_ILLEGAL_CHARACTERS, ' '); fileName.StripChar(char16_t(0)); const char16_t *startStr, *endStr; diff --git a/uriloader/exthandler/win/nsMIMEInfoWin.cpp b/uriloader/exthandler/win/nsMIMEInfoWin.cpp index db3377d1fb9e..ccc04ec96afc 100644 --- a/uriloader/exthandler/win/nsMIMEInfoWin.cpp +++ b/uriloader/exthandler/win/nsMIMEInfoWin.cpp @@ -553,7 +553,7 @@ void nsMIMEInfoWin::ProcessPath(nsCOMPtr& appList, WCHAR exe[MAX_PATH + 1]; uint32_t len = GetModuleFileNameW(nullptr, exe, MAX_PATH); if (len < MAX_PATH && len != 0) { - int32_t index = lower.Find(reinterpret_cast(exe)); + int32_t index = lower.Find(exe); if (index != -1) return; } diff --git a/widget/android/GfxInfo.cpp b/widget/android/GfxInfo.cpp index d868c853dd27..712e79df8946 100644 --- a/widget/android/GfxInfo.cpp +++ b/widget/android/GfxInfo.cpp @@ -481,9 +481,9 @@ nsresult GfxInfo::GetFeatureStatusImpl( // have // manufacturer=amazon - if (cModel.LowerCaseFindASCII("sgh-i717") != -1 || - cModel.LowerCaseFindASCII("sgh-i727") != -1 || - cModel.LowerCaseFindASCII("sgh-i757") != -1) { + if (cModel.Find("SGH-I717", true) != -1 || + cModel.Find("SGH-I727", true) != -1 || + cModel.Find("SGH-I757", true) != -1) { isWhitelisted = false; } @@ -498,13 +498,13 @@ nsresult GfxInfo::GetFeatureStatusImpl( // Blocklist: // Samsung devices from bug 812881 and 853522. // Motorola XT890 from bug 882342. - bool isBlocklisted = cModel.LowerCaseFindASCII("gt-p3100") != -1 || - cModel.LowerCaseFindASCII("gt-p3110") != -1 || - cModel.LowerCaseFindASCII("gt-p3113") != -1 || - cModel.LowerCaseFindASCII("gt-p5100") != -1 || - cModel.LowerCaseFindASCII("gt-p5110") != -1 || - cModel.LowerCaseFindASCII("gt-p5113") != -1 || - cModel.LowerCaseFindASCII("xt890") != -1; + bool isBlocklisted = cModel.Find("GT-P3100", true) != -1 || + cModel.Find("GT-P3110", true) != -1 || + cModel.Find("GT-P3113", true) != -1 || + cModel.Find("GT-P5100", true) != -1 || + cModel.Find("GT-P5110", true) != -1 || + cModel.Find("GT-P5113", true) != -1 || + cModel.Find("XT890", true) != -1; if (isBlocklisted) { *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; @@ -513,7 +513,7 @@ nsresult GfxInfo::GetFeatureStatusImpl( } } else if (CompareVersions(mOSVersion.get(), "4.3.0") < 0) { // Blocklist all Sony devices - if (cManufacturer.LowerCaseFindASCII("sony") != -1) { + if (cManufacturer.Find("Sony", true) != -1) { *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; aFailureId = "FEATURE_FAILURE_4_3_SONY"; return NS_OK; @@ -560,25 +560,27 @@ nsresult GfxInfo::GetFeatureStatusImpl( if (aFeature == FEATURE_WEBRENDER) { const bool isMali4xx = - mGLStrings->Renderer().LowerCaseFindASCII("mali-4") >= 0; + mGLStrings->Renderer().Find("Mali-4", /*ignoreCase*/ true) >= 0; const bool isPowerVrG6110 = - mGLStrings->Renderer().LowerCaseFindASCII("powervr rogue g6110") >= 0; + mGLStrings->Renderer().Find("PowerVR Rogue G6110", + /* ignoreCase */ true) >= 0; const bool isVivanteGC7000UL = - mGLStrings->Renderer().LowerCaseFindASCII("vivante gc7000ul") >= 0; + mGLStrings->Renderer().Find("Vivante GC7000UL", + /* ignoreCase */ true) >= 0; const bool isPowerVrFenceSyncCrash = - (mGLStrings->Renderer().LowerCaseFindASCII("powervr rogue g6200") >= - 0 || - mGLStrings->Renderer().LowerCaseFindASCII("powervr rogue g6430") >= - 0 || - mGLStrings->Renderer().LowerCaseFindASCII("powervr rogue gx6250") >= - 0) && - (mGLStrings->Version().Find("3283119") >= 0 || - mGLStrings->Version().Find("3443629") >= 0 || - mGLStrings->Version().Find("3573678") >= 0 || - mGLStrings->Version().Find("3830101") >= 0); + (mGLStrings->Renderer().Find("PowerVR Rogue G6200", + /* ignoreCase */ true) >= 0 || + mGLStrings->Renderer().Find("PowerVR Rogue G6430", + /* ignoreCase */ true) >= 0 || + mGLStrings->Renderer().Find("PowerVR Rogue GX6250", + /* ignoreCase */ true) >= 0) && + (mGLStrings->Version().Find("3283119", /* ignoreCase */ true) >= 0 || + mGLStrings->Version().Find("3443629", /* ignoreCase */ true) >= 0 || + mGLStrings->Version().Find("3573678", /* ignoreCase */ true) >= 0 || + mGLStrings->Version().Find("3830101", /* ignoreCase */ true) >= 0); if (isMali4xx) { // Mali 4xx does not support GLES 3. @@ -623,8 +625,8 @@ nsresult GfxInfo::GetFeatureStatusImpl( // encountered any correctness or stability issues with them, loading them // fails more often than not, so is a waste of time. Better to just not // even attempt to cache them. See bug 1615574. - const bool isAdreno3xx = - mGLStrings->Renderer().LowerCaseFindASCII("adreno (tm) 3") >= 0; + const bool isAdreno3xx = mGLStrings->Renderer().Find( + "Adreno (TM) 3", /*ignoreCase*/ true) >= 0; if (isAdreno3xx) { *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; aFailureId = "FEATURE_FAILURE_ADRENO_3XX"; @@ -640,7 +642,7 @@ nsresult GfxInfo::GetFeatureStatusImpl( // disable for all Mali-T regardless of version. See bug 1689064 and bug // 1707283 for details. const bool isMaliT = - mGLStrings->Renderer().LowerCaseFindASCII("mali-t") >= 0; + mGLStrings->Renderer().Find("Mali-T", /*ignoreCase*/ true) >= 0; if (isMaliT) { *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; aFailureId = "FEATURE_FAILURE_BUG_1689064"; @@ -655,9 +657,9 @@ nsresult GfxInfo::GetFeatureStatusImpl( // On Mali-Txxx due to bug 1680087 and bug 1707815. // On Adreno 3xx GPUs due to bug 1695771. const bool isMaliT = - mGLStrings->Renderer().LowerCaseFindASCII("mali-t") >= 0; - const bool isAdreno3xx = - mGLStrings->Renderer().LowerCaseFindASCII("adreno (tm) 3") >= 0; + mGLStrings->Renderer().Find("Mali-T", /*ignoreCase*/ true) >= 0; + const bool isAdreno3xx = mGLStrings->Renderer().Find( + "Adreno (TM) 3", /*ignoreCase*/ true) >= 0; if (isMaliT || isAdreno3xx) { *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; aFailureId = "FEATURE_FAILURE_BUG_1680087_1695771_1707815"; @@ -672,7 +674,7 @@ nsresult GfxInfo::GetFeatureStatusImpl( // Swizzling appears to be buggy on PowerVR Rogue devices with webrender. // See bug 1704783. const bool isPowerVRRogue = - mGLStrings->Renderer().LowerCaseFindASCII("powervr rogue") >= 0; + mGLStrings->Renderer().Find("PowerVR Rogue", /*ignoreCase*/ true) >= 0; if (isPowerVRRogue) { *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; aFailureId = "FEATURE_FAILURE_POWERVR_ROGUE"; diff --git a/widget/gtk/GfxInfo.cpp b/widget/gtk/GfxInfo.cpp index 5acff0473dc6..bfa5a5991e69 100644 --- a/widget/gtk/GfxInfo.cpp +++ b/widget/gtk/GfxInfo.cpp @@ -576,13 +576,13 @@ void GfxInfo::GetData() { if (!ddxDriver.IsEmpty()) { PRInt32 start = 0; - PRInt32 loc = ddxDriver.Find(";", start); + PRInt32 loc = ddxDriver.Find(";", PR_FALSE, start); while (loc != kNotFound) { nsCString line(ddxDriver.get() + start, loc - start); mDdxDrivers.AppendElement(std::move(line)); start = loc + 1; - loc = ddxDriver.Find(";", start); + loc = ddxDriver.Find(";", PR_FALSE, start); } } diff --git a/widget/gtk/IMContextWrapper.cpp b/widget/gtk/IMContextWrapper.cpp index 754f70cfd99a..d9e7fe507cba 100644 --- a/widget/gtk/IMContextWrapper.cpp +++ b/widget/gtk/IMContextWrapper.cpp @@ -400,7 +400,7 @@ nsDependentCSubstring IMContextWrapper::GetIMName() const { return im; } - int32_t atIMValueEnd = xmodifiers.Find("@", atIMValueStart); + int32_t atIMValueEnd = xmodifiers.Find("@", false, atIMValueStart); if (atIMValueEnd > atIMValueStart) { return nsDependentCSubstring(xmodifiersChar + atIMValueStart, atIMValueEnd - atIMValueStart); @@ -3039,11 +3039,10 @@ nsresult IMContextWrapper::GetCurrentParagraph(nsAString& aText, } // Get only the focused paragraph, by looking for newlines - int32_t parStart = 0; - if (selOffset > 0) { - parStart = Substring(textContent, 0, selOffset - 1).RFind(u"\n") + 1; - } - int32_t parEnd = textContent.Find(u"\n", selOffset + selLength); + int32_t parStart = + (selOffset == 0) ? 0 + : textContent.RFind("\n", false, selOffset - 1, -1) + 1; + int32_t parEnd = textContent.Find("\n", false, selOffset + selLength, -1); if (parEnd < 0) { parEnd = textContent.Length(); } diff --git a/widget/nsNativeTheme.cpp b/widget/nsNativeTheme.cpp index 82bd7109e003..ce672657a753 100644 --- a/widget/nsNativeTheme.cpp +++ b/widget/nsNativeTheme.cpp @@ -356,7 +356,7 @@ bool nsNativeTheme::IsBottomTab(nsIFrame* aFrame) { nsGkAtoms::_class, classStr); } // FIXME: This looks bogus, shouldn't this be looking at GetClasses()? - return !classStr.IsEmpty() && classStr.Find(u"tab-bottom") != kNotFound; + return !classStr.IsEmpty() && classStr.Find("tab-bottom") != kNotFound; } bool nsNativeTheme::IsFirstTab(nsIFrame* aFrame) { diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp index e999b4153a00..c3e0a36e8226 100644 --- a/widget/windows/GfxInfo.cpp +++ b/widget/windows/GfxInfo.cpp @@ -300,13 +300,13 @@ static nsresult GetKeyValues(const WCHAR* keyLocation, const WCHAR* keyName, // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD // this function is used to extract the id's out of it -uint32_t ParseIDFromDeviceID(const nsAString& key, const nsAString& prefix, +uint32_t ParseIDFromDeviceID(const nsAString& key, const char* prefix, int length) { nsAutoString id(key); ToUpperCase(id); int32_t start = id.Find(prefix); if (start != -1) { - id.Cut(0, start + prefix.Length()); + id.Cut(0, start + strlen(prefix)); id.Truncate(length); } if (id.Equals(L"QCOM", nsCaseInsensitiveStringComparator)) { @@ -605,9 +605,9 @@ nsresult GfxInfo::Init() { uint32_t adapterDeviceID[2] = {0, 0}; uint32_t adapterSubsysID[2] = {0, 0}; - adapterVendorID[0] = ParseIDFromDeviceID(mDeviceID[0], u"VEN_"_ns, 4); - adapterDeviceID[0] = ParseIDFromDeviceID(mDeviceID[0], u"&DEV_"_ns, 4); - adapterSubsysID[0] = ParseIDFromDeviceID(mDeviceID[0], u"&SUBSYS_"_ns, 8); + adapterVendorID[0] = ParseIDFromDeviceID(mDeviceID[0], "VEN_", 4); + adapterDeviceID[0] = ParseIDFromDeviceID(mDeviceID[0], "&DEV_", 4); + adapterSubsysID[0] = ParseIDFromDeviceID(mDeviceID[0], "&SUBSYS_", 8); // Sometimes we don't get the valid device using this method. For now, // allow zero vendor or device as valid, as long as the other value is @@ -660,8 +660,8 @@ nsresult GfxInfo::Init() { continue; } deviceID2 = value; - adapterVendorID[1] = ParseIDFromDeviceID(deviceID2, u"VEN_"_ns, 4); - adapterDeviceID[1] = ParseIDFromDeviceID(deviceID2, u"&DEV_"_ns, 4); + adapterVendorID[1] = ParseIDFromDeviceID(deviceID2, "VEN_", 4); + adapterDeviceID[1] = ParseIDFromDeviceID(deviceID2, "&DEV_", 4); // Skip the devices we already considered, as well as any // "zero" ones. if ((adapterVendorID[0] == adapterVendorID[1] && @@ -717,7 +717,7 @@ nsresult GfxInfo::Init() { mDriverVersion[0] = driverVersion2; mDriverDate[0] = driverDate2; adapterSubsysID[0] = - ParseIDFromDeviceID(mDeviceID[0], u"&SUBSYS_"_ns, 8); + ParseIDFromDeviceID(mDeviceID[0], "&SUBSYS_", 8); continue; } @@ -728,7 +728,7 @@ nsresult GfxInfo::Init() { mDriverVersion[1] = driverVersion2; mDriverDate[1] = driverDate2; adapterSubsysID[1] = - ParseIDFromDeviceID(mDeviceID[1], u"&SUBSYS_"_ns, 8); + ParseIDFromDeviceID(mDeviceID[1], "&SUBSYS_", 8); mAdapterVendorID[1].AppendPrintf("0x%04x", adapterVendorID[1]); mAdapterDeviceID[1].AppendPrintf("0x%04x", adapterDeviceID[1]); mAdapterSubsysID[1].AppendPrintf("%08x", adapterSubsysID[1]); diff --git a/widget/windows/IMMHandler.cpp b/widget/windows/IMMHandler.cpp index a60b4974ca78..1ab373e0ff99 100644 --- a/widget/windows/IMMHandler.cpp +++ b/widget/windows/IMMHandler.cpp @@ -1479,11 +1479,8 @@ bool IMMHandler::HandleDocumentFeed(nsWindow* aWindow, LPARAM lParam, // Get the focused paragraph, we decide that it starts from the previous CRLF // (or start of the editor) to the next one (or the end of the editor). - int32_t paragraphStart = 0; - if (targetOffset > 0) { - paragraphStart = Substring(str, 0, targetOffset).RFind(u"\n") + 1; - } - int32_t paragraphEnd = str.Find(u"\r", targetOffset + targetLength); + int32_t paragraphStart = str.RFind("\n", false, targetOffset, -1) + 1; + int32_t paragraphEnd = str.Find("\r", false, targetOffset + targetLength, -1); if (paragraphEnd < 0) { paragraphEnd = str.Length(); } diff --git a/widget/windows/nsFilePicker.cpp b/widget/windows/nsFilePicker.cpp index 1e3d78195062..f17a759e1aa0 100644 --- a/widget/windows/nsFilePicker.cpp +++ b/widget/windows/nsFilePicker.cpp @@ -458,7 +458,7 @@ nsBaseWinFilePicker::SetDefaultString(const nsAString& aString) { // First, make sure the file name is not too long. int32_t nameLength; - int32_t nameIndex = mDefaultFilePath.RFind(u"\\"); + int32_t nameIndex = mDefaultFilePath.RFind("\\"); if (nameIndex == kNotFound) nameIndex = 0; else @@ -467,7 +467,7 @@ nsBaseWinFilePicker::SetDefaultString(const nsAString& aString) { mDefaultFilename.Assign(Substring(mDefaultFilePath, nameIndex)); if (nameLength > MAX_PATH) { - int32_t extIndex = mDefaultFilePath.RFind(u"."); + int32_t extIndex = mDefaultFilePath.RFind("."); if (extIndex == kNotFound) extIndex = mDefaultFilePath.Length(); // Let's try to shave the needed characters from the name part. @@ -479,8 +479,8 @@ nsBaseWinFilePicker::SetDefaultString(const nsAString& aString) { // Then, we need to replace illegal characters. At this stage, we cannot // replace the backslash as the string might represent a file path. - mDefaultFilePath.ReplaceChar(u"" FILE_ILLEGAL_CHARACTERS, u'-'); - mDefaultFilename.ReplaceChar(u"" FILE_ILLEGAL_CHARACTERS, u'-'); + mDefaultFilePath.ReplaceChar(FILE_ILLEGAL_CHARACTERS, '-'); + mDefaultFilename.ReplaceChar(FILE_ILLEGAL_CHARACTERS, '-'); return NS_OK; } @@ -568,7 +568,7 @@ bool nsFilePicker::IsDefaultPathLink() { } bool nsFilePicker::IsDefaultPathHtml() { - int32_t extIndex = mDefaultFilePath.RFind(u"."); + int32_t extIndex = mDefaultFilePath.RFind("."); if (extIndex >= 0) { nsAutoString ext; mDefaultFilePath.Right(ext, mDefaultFilePath.Length() - extIndex); diff --git a/xpcom/base/nsTraceRefcnt.cpp b/xpcom/base/nsTraceRefcnt.cpp index 0aaf0e1a50ac..b23740319117 100644 --- a/xpcom/base/nsTraceRefcnt.cpp +++ b/xpcom/base/nsTraceRefcnt.cpp @@ -513,9 +513,8 @@ static bool InitLog(const EnvCharType* aEnvVar, const char* aMsg, return true; } if (!XRE_IsParentProcess()) { - nsTString extension; - extension.AssignLiteral(".log"); - bool hasLogExtension = StringEndsWith(fname, extension); + bool hasLogExtension = + fname.RFind(".log", true, -1, 4) == kNotFound ? false : true; if (hasLogExtension) { fname.Cut(fname.Length() - 4, 4); } diff --git a/xpcom/ds/moz.build b/xpcom/ds/moz.build index 1d0488b9b244..323418e3c3a0 100644 --- a/xpcom/ds/moz.build +++ b/xpcom/ds/moz.build @@ -108,7 +108,6 @@ UNIFIED_SOURCES += [ "nsArrayEnumerator.cpp", "nsArrayUtils.cpp", "nsAtomTable.cpp", - "nsCharSeparatedTokenizer.cpp", "nsCOMArray.cpp", "nsCRT.cpp", "nsDeque.cpp", diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp index c20b835d2e81..b0f51dbb2039 100644 --- a/xpcom/io/nsLocalFileWin.cpp +++ b/xpcom/io/nsLocalFileWin.cpp @@ -1105,9 +1105,9 @@ static void CleanupHandlerPath(nsString& aPath) { aPath.Append(' '); // case insensitive - int32_t index = aPath.LowerCaseFindASCII(".exe "); - if (index == kNotFound) index = aPath.LowerCaseFindASCII(".dll "); - if (index == kNotFound) index = aPath.LowerCaseFindASCII(".cpl "); + int32_t index = aPath.Find(".exe ", true); + if (index == kNotFound) index = aPath.Find(".dll ", true); + if (index == kNotFound) index = aPath.Find(".cpl ", true); if (index != kNotFound) aPath.Truncate(index + 4); aPath.Trim(" ", true, true); @@ -1122,15 +1122,15 @@ static void StripRundll32(nsString& aCommandString) { // C:\Windows\System32\rundll32.exe "path to dll", var var // rundll32.exe "path to dll", var var - constexpr auto rundllSegment = "rundll32.exe "_ns; - constexpr auto rundllSegmentShort = "rundll32 "_ns; + constexpr auto rundllSegment = u"rundll32.exe "_ns; + constexpr auto rundllSegmentShort = u"rundll32 "_ns; // case insensitive int32_t strLen = rundllSegment.Length(); - int32_t index = aCommandString.LowerCaseFindASCII(rundllSegment); + int32_t index = aCommandString.Find(rundllSegment, true); if (index == kNotFound) { strLen = rundllSegmentShort.Length(); - index = aCommandString.LowerCaseFindASCII(rundllSegmentShort); + index = aCommandString.Find(rundllSegmentShort, true); } if (index != kNotFound) { diff --git a/xpcom/string/RustStringAPI.cpp b/xpcom/string/RustStringAPI.cpp deleted file mode 100644 index 55ce6b9eeb49..000000000000 --- a/xpcom/string/RustStringAPI.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.h" -#include "nsString.h" - -// Extern "C" utilities used by the rust nsString bindings. - -// Provide rust bindings to the nsA[C]String types -extern "C" { - -// This is a no-op on release, so we ifdef it out such that using it in release -// results in a linker error. -#ifdef DEBUG -void Gecko_IncrementStringAdoptCount(void* aData) { - MOZ_LOG_CTOR(aData, "StringAdopt", 1); -} -#elif defined(MOZ_DEBUG_RUST) -void Gecko_IncrementStringAdoptCount(void* aData) {} -#endif - -void Gecko_FinalizeCString(nsACString* aThis) { aThis->~nsACString(); } - -void Gecko_AssignCString(nsACString* aThis, const nsACString* aOther) { - aThis->Assign(*aOther); -} - -void Gecko_TakeFromCString(nsACString* aThis, nsACString* aOther) { - aThis->Assign(std::move(*aOther)); -} - -void Gecko_AppendCString(nsACString* aThis, const nsACString* aOther) { - aThis->Append(*aOther); -} - -void Gecko_SetLengthCString(nsACString* aThis, uint32_t aLength) { - aThis->SetLength(aLength); -} - -bool Gecko_FallibleAssignCString(nsACString* aThis, const nsACString* aOther) { - return aThis->Assign(*aOther, mozilla::fallible); -} - -bool Gecko_FallibleTakeFromCString(nsACString* aThis, nsACString* aOther) { - return aThis->Assign(std::move(*aOther), mozilla::fallible); -} - -bool Gecko_FallibleAppendCString(nsACString* aThis, const nsACString* aOther) { - return aThis->Append(*aOther, mozilla::fallible); -} - -bool Gecko_FallibleSetLengthCString(nsACString* aThis, uint32_t aLength) { - return aThis->SetLength(aLength, mozilla::fallible); -} - -char* Gecko_BeginWritingCString(nsACString* aThis) { - return aThis->BeginWriting(); -} - -char* Gecko_FallibleBeginWritingCString(nsACString* aThis) { - return aThis->BeginWriting(mozilla::fallible); -} - -uint32_t Gecko_StartBulkWriteCString(nsACString* aThis, uint32_t aCapacity, - uint32_t aUnitsToPreserve, - bool aAllowShrinking) { - return aThis->StartBulkWriteImpl(aCapacity, aUnitsToPreserve, aAllowShrinking) - .unwrapOr(UINT32_MAX); -} - -void Gecko_FinalizeString(nsAString* aThis) { aThis->~nsAString(); } - -void Gecko_AssignString(nsAString* aThis, const nsAString* aOther) { - aThis->Assign(*aOther); -} - -void Gecko_TakeFromString(nsAString* aThis, nsAString* aOther) { - aThis->Assign(std::move(*aOther)); -} - -void Gecko_AppendString(nsAString* aThis, const nsAString* aOther) { - aThis->Append(*aOther); -} - -void Gecko_SetLengthString(nsAString* aThis, uint32_t aLength) { - aThis->SetLength(aLength); -} - -bool Gecko_FallibleAssignString(nsAString* aThis, const nsAString* aOther) { - return aThis->Assign(*aOther, mozilla::fallible); -} - -bool Gecko_FallibleTakeFromString(nsAString* aThis, nsAString* aOther) { - return aThis->Assign(std::move(*aOther), mozilla::fallible); -} - -bool Gecko_FallibleAppendString(nsAString* aThis, const nsAString* aOther) { - return aThis->Append(*aOther, mozilla::fallible); -} - -bool Gecko_FallibleSetLengthString(nsAString* aThis, uint32_t aLength) { - return aThis->SetLength(aLength, mozilla::fallible); -} - -char16_t* Gecko_BeginWritingString(nsAString* aThis) { - return aThis->BeginWriting(); -} - -char16_t* Gecko_FallibleBeginWritingString(nsAString* aThis) { - return aThis->BeginWriting(mozilla::fallible); -} - -uint32_t Gecko_StartBulkWriteString(nsAString* aThis, uint32_t aCapacity, - uint32_t aUnitsToPreserve, - bool aAllowShrinking) { - return aThis->StartBulkWriteImpl(aCapacity, aUnitsToPreserve, aAllowShrinking) - .unwrapOr(UINT32_MAX); -} - -} // extern "C" diff --git a/xpcom/string/moz.build b/xpcom/string/moz.build index fdb1fc74a5ea..dc7b04ce8c19 100644 --- a/xpcom/string/moz.build +++ b/xpcom/string/moz.build @@ -37,22 +37,19 @@ EXPORTS += [ UNIFIED_SOURCES += [ "nsASCIIMask.cpp", + "nsDependentString.cpp", + "nsDependentSubstring.cpp", + "nsPromiseFlatString.cpp", "nsReadableUtils.cpp", - "nsStringBuffer.cpp", - "nsTDependentString.cpp", - "nsTDependentSubstring.cpp", + "nsString.cpp", + "nsStringComparator.cpp", + "nsStringObsolete.cpp", + "nsSubstring.cpp", "nsTextFormatter.cpp", - "nsTLiteralString.cpp", - "nsTPromiseFlatString.cpp", - "nsTString.cpp", - "nsTStringComparator.cpp", - "nsTStringRepr.cpp", - "nsTSubstring.cpp", "nsTSubstringTuple.cpp", - "RustStringAPI.cpp", + "precompiled_templates.cpp", ] -if CONFIG["MOZ_DEBUG"]: - UNIFIED_SOURCES += ["nsStringStats.cpp"] - FINAL_LIBRARY = "xul" + +REQUIRES_UNIFIED_BUILD = True diff --git a/xpcom/string/nsAString.h b/xpcom/string/nsAString.h index 3893ff8e3709..00c54151cfa7 100644 --- a/xpcom/string/nsAString.h +++ b/xpcom/string/nsAString.h @@ -15,6 +15,8 @@ #include #include +#define kNotFound -1 + #include "nsStringFlags.h" #include "nsTStringRepr.h" #include "nsTSubstring.h" diff --git a/xpcom/string/nsTLiteralString.cpp b/xpcom/string/nsDependentString.cpp similarity index 58% rename from xpcom/string/nsTLiteralString.cpp rename to xpcom/string/nsDependentString.cpp index 79454f7783ad..d9707a035683 100644 --- a/xpcom/string/nsTLiteralString.cpp +++ b/xpcom/string/nsDependentString.cpp @@ -1,10 +1,10 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsTLiteralString.h" +#include "nsDependentString.h" +#include "nsAlgorithm.h" -template class nsTLiteralString; -template class nsTLiteralString; +#include "nsTDependentString.cpp" diff --git a/xpcom/ds/nsCharSeparatedTokenizer.cpp b/xpcom/string/nsDependentSubstring.cpp similarity index 56% rename from xpcom/ds/nsCharSeparatedTokenizer.cpp rename to xpcom/string/nsDependentSubstring.cpp index 7288ed070f66..3057c0692a7f 100644 --- a/xpcom/ds/nsCharSeparatedTokenizer.cpp +++ b/xpcom/string/nsDependentSubstring.cpp @@ -1,10 +1,10 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsCharSeparatedTokenizer.h" +#include "nsDependentSubstring.h" +#include "nsAlgorithm.h" -template class nsTSubstringSplitter; -template class nsTSubstringSplitter; +#include "nsTDependentSubstring.cpp" diff --git a/xpcom/string/nsPromiseFlatString.cpp b/xpcom/string/nsPromiseFlatString.cpp new file mode 100644 index 000000000000..e21812061fc6 --- /dev/null +++ b/xpcom/string/nsPromiseFlatString.cpp @@ -0,0 +1,9 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsPromiseFlatString.h" + +#include "nsTPromiseFlatString.cpp" diff --git a/xpcom/string/nsString.cpp b/xpcom/string/nsString.cpp new file mode 100644 index 000000000000..d85eb4b641c9 --- /dev/null +++ b/xpcom/string/nsString.cpp @@ -0,0 +1,9 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsString.h" + +#include "nsTString.cpp" diff --git a/xpcom/string/nsStringBuffer.cpp b/xpcom/string/nsStringBuffer.cpp deleted file mode 100644 index f32b51d3a6ef..000000000000 --- a/xpcom/string/nsStringBuffer.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsStringBuffer.h" - -#include "mozilla/MemoryReporting.h" -#include "nsISupportsImpl.h" -#include "nsString.h" - -#ifdef DEBUG -# include "nsStringStats.h" -#else -# define STRING_STAT_INCREMENT(_s) -#endif - -void nsStringBuffer::AddRef() { - // Memory synchronization is not required when incrementing a - // reference count. The first increment of a reference count on a - // thread is not important, since the first use of the object on a - // thread can happen before it. What is important is the transfer - // of the pointer to that thread, which may happen prior to the - // first increment on that thread. The necessary memory - // synchronization is done by the mechanism that transfers the - // pointer between threads. -#ifdef NS_BUILD_REFCNT_LOGGING - uint32_t count = -#endif - mRefCount.fetch_add(1, std::memory_order_relaxed) -#ifdef NS_BUILD_REFCNT_LOGGING - + 1 -#endif - ; - STRING_STAT_INCREMENT(Share); - NS_LOG_ADDREF(this, count, "nsStringBuffer", sizeof(*this)); -} - -void nsStringBuffer::Release() { - // Since this may be the last release on this thread, we need - // release semantics so that prior writes on this thread are visible - // to the thread that destroys the object when it reads mValue with - // acquire semantics. - uint32_t count = mRefCount.fetch_sub(1, std::memory_order_release) - 1; - NS_LOG_RELEASE(this, count, "nsStringBuffer"); - if (count == 0) { - // We're going to destroy the object on this thread, so we need - // acquire semantics to synchronize with the memory released by - // the last release on other threads, that is, to ensure that - // writes prior to that release are now visible on this thread. - count = mRefCount.load(std::memory_order_acquire); - - STRING_STAT_INCREMENT(Free); - free(this); // we were allocated with |malloc| - } -} - -/** - * Alloc returns a pointer to a new string header with set capacity. - */ -already_AddRefed nsStringBuffer::Alloc(size_t aSize) { - NS_ASSERTION(aSize != 0, "zero capacity allocation not allowed"); - NS_ASSERTION(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && - sizeof(nsStringBuffer) + aSize > aSize, - "mStorageSize will truncate"); - - nsStringBuffer* hdr = (nsStringBuffer*)malloc(sizeof(nsStringBuffer) + aSize); - if (hdr) { - STRING_STAT_INCREMENT(Alloc); - - hdr->mRefCount = 1; - hdr->mStorageSize = aSize; - NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr)); - } - return already_AddRefed(hdr); -} - -nsStringBuffer* nsStringBuffer::Realloc(nsStringBuffer* aHdr, size_t aSize) { - STRING_STAT_INCREMENT(Realloc); - - NS_ASSERTION(aSize != 0, "zero capacity allocation not allowed"); - NS_ASSERTION(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && - sizeof(nsStringBuffer) + aSize > aSize, - "mStorageSize will truncate"); - - // no point in trying to save ourselves if we hit this assertion - NS_ASSERTION(!aHdr->IsReadonly(), "|Realloc| attempted on readonly string"); - - // Treat this as a release and addref for refcounting purposes, since we - // just asserted that the refcount is 1. If we don't do that, refcount - // logging will claim we've leaked all sorts of stuff. - NS_LOG_RELEASE(aHdr, 0, "nsStringBuffer"); - - aHdr = (nsStringBuffer*)realloc(aHdr, sizeof(nsStringBuffer) + aSize); - if (aHdr) { - NS_LOG_ADDREF(aHdr, 1, "nsStringBuffer", sizeof(*aHdr)); - aHdr->mStorageSize = aSize; - } - - return aHdr; -} - -nsStringBuffer* nsStringBuffer::FromString(const nsAString& aStr) { - if (!(aStr.mDataFlags & nsAString::DataFlags::REFCOUNTED)) { - return nullptr; - } - - return FromData(aStr.mData); -} - -nsStringBuffer* nsStringBuffer::FromString(const nsACString& aStr) { - if (!(aStr.mDataFlags & nsACString::DataFlags::REFCOUNTED)) { - return nullptr; - } - - return FromData(aStr.mData); -} - -void nsStringBuffer::ToString(uint32_t aLen, nsAString& aStr, - bool aMoveOwnership) { - char16_t* data = static_cast(Data()); - - MOZ_DIAGNOSTIC_ASSERT(data[aLen] == char16_t(0), - "data should be null terminated"); - - nsAString::DataFlags flags = - nsAString::DataFlags::REFCOUNTED | nsAString::DataFlags::TERMINATED; - - if (!aMoveOwnership) { - AddRef(); - } - aStr.Finalize(); - aStr.SetData(data, aLen, flags); -} - -void nsStringBuffer::ToString(uint32_t aLen, nsACString& aStr, - bool aMoveOwnership) { - char* data = static_cast(Data()); - - MOZ_DIAGNOSTIC_ASSERT(data[aLen] == char(0), - "data should be null terminated"); - - nsACString::DataFlags flags = - nsACString::DataFlags::REFCOUNTED | nsACString::DataFlags::TERMINATED; - - if (!aMoveOwnership) { - AddRef(); - } - aStr.Finalize(); - aStr.SetData(data, aLen, flags); -} - -size_t nsStringBuffer::SizeOfIncludingThisIfUnshared( - mozilla::MallocSizeOf aMallocSizeOf) const { - return IsReadonly() ? 0 : aMallocSizeOf(this); -} - -size_t nsStringBuffer::SizeOfIncludingThisEvenIfShared( - mozilla::MallocSizeOf aMallocSizeOf) const { - return aMallocSizeOf(this); -} diff --git a/xpcom/string/nsStringComparator.cpp b/xpcom/string/nsStringComparator.cpp new file mode 100644 index 000000000000..b421f566ef4f --- /dev/null +++ b/xpcom/string/nsStringComparator.cpp @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include "nsAString.h" +#include "plstr.h" + +#include "nsTStringComparator.cpp" + +int nsCaseInsensitiveCStringComparator(const char* aLhs, const char* aRhs, + size_t aLhsLength, size_t aRhsLength) { +#if defined(LIBFUZZER) && defined(LINUX) + // Make sure libFuzzer can see this string compare by calling the POSIX + // native function which is intercepted. We also call this if the lengths + // don't match so libFuzzer can at least see a partial string, but we throw + // away the result afterwards again. + int32_t result = + int32_t(strncasecmp(aLhs, aRhs, std::min(aLhsLength, aRhsLength))); + + if (aLhsLength != aRhsLength) { + return (aLhsLength > aRhsLength) ? 1 : -1; + } +#else + if (aLhsLength != aRhsLength) { + return (aLhsLength > aRhsLength) ? 1 : -1; + } + int32_t result = int32_t(PL_strncasecmp(aLhs, aRhs, aLhsLength)); +#endif + // Egads. PL_strncasecmp is returning *very* negative numbers. + // Some folks expect -1,0,1, so let's temper its enthusiasm. + if (result < 0) { + result = -1; + } + return result; +} diff --git a/xpcom/string/nsStringFwd.h b/xpcom/string/nsStringFwd.h index f7375451634f..7eb068388b27 100644 --- a/xpcom/string/nsStringFwd.h +++ b/xpcom/string/nsStringFwd.h @@ -11,8 +11,6 @@ #include "nscore.h" -static constexpr int32_t kNotFound = -1; - namespace mozilla { namespace detail { diff --git a/xpcom/string/nsStringObsolete.cpp b/xpcom/string/nsStringObsolete.cpp new file mode 100644 index 000000000000..2aa4925a931f --- /dev/null +++ b/xpcom/string/nsStringObsolete.cpp @@ -0,0 +1,969 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/Casting.h" +#include "nsString.h" + +/** + * nsTString obsolete API support + */ + +#include "nsDependentString.h" +#include "nsDependentSubstring.h" +#include "nsReadableUtils.h" +#include "nsCRT.h" +#include "nsUTF8Utils.h" +#include "prdtoa.h" + +/* ***** BEGIN RICKG BLOCK ***** + * + * NOTE: This section of code was extracted from rickg's bufferRoutines.h file. + * For the most part it remains unmodified. We want to eliminate (or at + * least clean up) this code at some point. If you find the formatting + * in this section somewhat inconsistent, don't blame me! ;-) + */ + +// avoid STDC's tolower since it may do weird things with non-ASCII bytes +inline char ascii_tolower(char aChar) { + if (aChar >= 'A' && aChar <= 'Z') return aChar + ('a' - 'A'); + return aChar; +} + +//----------------------------------------------------------------------------- +// +// This set of methods is used to search a buffer looking for a char. +// + +/** + * This methods cans the given buffer for the given char + * + * @update gess 02/17/00 + * @param aDest is the buffer to be searched + * @param aDestLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aCount tells us how many characters to iterate through (which may + * be different than aLength); -1 means use full length. + * @return index of pos if found, else -1 (kNotFound) + */ +static int32_t FindChar1(const char* aDest, uint32_t aDestLength, + int32_t anOffset, const char16_t aChar, + int32_t aCount) { + if (anOffset < 0) anOffset = 0; + + if (aCount < 0) aCount = (int32_t)aDestLength; + + if ((aChar < 256) && (0 < aDestLength) && + ((uint32_t)anOffset < aDestLength)) { + // We'll only search if the given aChar is within the normal ascii a range, + //(Since this string is definitely within the ascii range). + + if (0 < aCount) { + const char* left = aDest + anOffset; + const char* last = left + aCount; + const char* max = aDest + aDestLength; + const char* end = (last < max) ? last : max; + + int32_t theMax = end - left; + if (0 < theMax) { + unsigned char theChar = (unsigned char)aChar; + const char* result = (const char*)memchr(left, (int)theChar, theMax); + + if (result) return result - aDest; + } + } + } + + return kNotFound; +} + +/** + * This methods cans the given buffer for the given char + * + * @update gess 3/25/98 + * @param aDest is the buffer to be searched + * @param aDestLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aCount tells us how many characters to iterate through (which may + * be different than aLength); -1 means use full length. + * @return index of pos if found, else -1 (kNotFound) + */ +static int32_t FindChar2(const char16_t* aDest, uint32_t aDestLength, + int32_t anOffset, const char16_t aChar, + int32_t aCount) { + if (anOffset < 0) anOffset = 0; + + if (aCount < 0) aCount = (int32_t)aDestLength; + + if ((0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) { + if (0 < aCount) { + const char16_t* root = aDest; + const char16_t* left = root + anOffset; + const char16_t* last = left + aCount; + const char16_t* max = root + aDestLength; + const char16_t* end = (last < max) ? last : max; + + while (left < end) { + if (*left == aChar) return (left - root); + + ++left; + } + } + } + + return kNotFound; +} + +/** + * This methods cans the given buffer (in reverse) for the given char + * + * @update gess 02/17/00 + * @param aDest is the buffer to be searched + * @param aDestLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aCount tells us how many characters to iterate through (which may + * be different than aLength); -1 means use full length. + * @return index of pos if found, else -1 (kNotFound) + */ + +static int32_t RFindChar1(const char* aDest, uint32_t aDestLength, + int32_t anOffset, const char16_t aChar, + int32_t aCount) { + if (anOffset < 0) anOffset = (int32_t)aDestLength - 1; + + if (aCount < 0) aCount = int32_t(aDestLength); + + if ((aChar < 256) && (0 < aDestLength) && + ((uint32_t)anOffset < aDestLength)) { + // We'll only search if the given aChar is within the normal ascii a range, + //(Since this string is definitely within the ascii range). + + if (0 < aCount) { + const char* rightmost = aDest + anOffset; + const char* min = rightmost - aCount + 1; + const char* leftmost = (min < aDest) ? aDest : min; + + char theChar = (char)aChar; + while (leftmost <= rightmost) { + if ((*rightmost) == theChar) return rightmost - aDest; + + --rightmost; + } + } + } + + return kNotFound; +} + +/** + * This methods cans the given buffer for the given char + * + * @update gess 3/25/98 + * @param aDest is the buffer to be searched + * @param aDestLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aCount tells us how many characters to iterate through (which may + * be different than aLength); -1 means use full length. + * @return index of pos if found, else -1 (kNotFound) + */ +static int32_t RFindChar2(const char16_t* aDest, uint32_t aDestLength, + int32_t anOffset, const char16_t aChar, + int32_t aCount) { + if (anOffset < 0) anOffset = (int32_t)aDestLength - 1; + + if (aCount < 0) aCount = int32_t(aDestLength); + + if ((0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) { + if (0 < aCount) { + const char16_t* root = aDest; + const char16_t* rightmost = root + anOffset; + const char16_t* min = rightmost - aCount + 1; + const char16_t* leftmost = (min < root) ? root : min; + + while (leftmost <= rightmost) { + if ((*rightmost) == aChar) return rightmost - root; + + --rightmost; + } + } + } + + return kNotFound; +} + +//----------------------------------------------------------------------------- +// +// This set of methods is used to compare one buffer onto another. The +// functions are differentiated by the size of source and dest character +// sizes. WARNING: Your destination buffer MUST be big enough to hold all the +// source bytes. We don't validate these ranges here (this should be done in +// higher level routines). +// + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnoreCase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +static +#ifdef __SUNPRO_CC + inline +#endif /* __SUNPRO_CC */ + int32_t + Compare1To1(const char* aStr1, const char* aStr2, uint32_t aCount, + bool aIgnoreCase) { + int32_t result = 0; + if (aIgnoreCase) +#if defined(LIBFUZZER) && defined(LINUX) + result = int32_t(strncasecmp(aStr1, aStr2, aCount)); +#else + result = int32_t(PL_strncasecmp(aStr1, aStr2, aCount)); +#endif + else + result = nsCharTraits::compare(aStr1, aStr2, aCount); + + // alien comparisons may return out-of-bound answers + // instead of the -1, 0, 1 expected by most clients + if (result < -1) + result = -1; + else if (result > 1) + result = 1; + return result; +} + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnoreCase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +static +#ifdef __SUNPRO_CC + inline +#endif /* __SUNPRO_CC */ + int32_t + Compare2To2(const char16_t* aStr1, const char16_t* aStr2, uint32_t aCount) { + int32_t result; + + if (aStr1 && aStr2) + result = nsCharTraits::compare(aStr1, aStr2, aCount); + + // The following cases are rare and survivable caller errors. + // Two null pointers are equal, but any string, even 0 length + // is greater than a null pointer. It might not really matter, + // but we pick something reasonable anyway. + else if (!aStr1 && !aStr2) + result = 0; + else if (aStr1) + result = 1; + else + result = -1; + + // alien comparisons may give answers outside the -1, 0, 1 expected by callers + if (result < -1) + result = -1; + else if (result > 1) + result = 1; + return result; +} + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnoreCase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +static +#ifdef __SUNPRO_CC + inline +#endif /* __SUNPRO_CC */ + int32_t + Compare2To1(const char16_t* aStr1, const char* aStr2, uint32_t aCount, + bool aIgnoreCase) { + const char16_t* s1 = aStr1; + const char* s2 = aStr2; + + if (aStr1 && aStr2) { + if (aCount != 0) { + do { + char16_t c1 = *s1++; + char16_t c2 = char16_t((unsigned char)*s2++); + + if (c1 != c2) { +#ifdef DEBUG + // we won't warn on c1>=128 (the 2-byte value) because often + // it is just fine to compare an constant, ascii value (i.e. "body") + // against some non-ascii value (i.e. a unicode string that + // was downloaded from a web page) + if (aIgnoreCase && c2 >= 128) + NS_WARNING( + "got a non-ASCII string, but we can't do an accurate case " + "conversion!"); +#endif + + // can't do case conversion on characters out of our range + if (aIgnoreCase && c1 < 128 && c2 < 128) { + c1 = ascii_tolower(char(c1)); + c2 = ascii_tolower(char(c2)); + + if (c1 == c2) continue; + } + + if (c1 < c2) return -1; + return 1; + } + } while (--aCount); + } + } + return 0; +} + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnoreCase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +inline int32_t Compare1To2(const char* aStr1, const char16_t* aStr2, + uint32_t aCount, bool aIgnoreCase) { + return Compare2To1(aStr2, aStr1, aCount, aIgnoreCase) * -1; +} + +//----------------------------------------------------------------------------- +// +// This set of methods is used compress char sequences in a buffer... +// + +/** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update rickg 03.23.2000 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of + * the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start + * of the buffer + * @return the new length of the given buffer + */ +static int32_t CompressChars1(char* aString, uint32_t aLength, + const char* aSet) { + char* from = aString; + char* end = aString + aLength; + char* to = from; + + // this code converts /n, /t, /r into normal space ' '; + // it also compresses runs of whitespace down to a single char... + if (aSet && aString && (0 < aLength)) { + uint32_t aSetLen = strlen(aSet); + + while (from < end) { + char theChar = *from++; + + *to++ = theChar; // always copy this char... + + if ((kNotFound != FindChar1(aSet, aSetLen, 0, theChar, aSetLen))) { + while (from < end) { + theChar = *from++; + if (kNotFound == FindChar1(aSet, aSetLen, 0, theChar, aSetLen)) { + *to++ = theChar; + break; + } + } // while + } // if + } // if + *to = 0; + } + return to - aString; +} + +/** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update rickg 03.23.2000 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of + * the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start + * of the buffer + * @return the new length of the given buffer + */ +static int32_t CompressChars2(char16_t* aString, uint32_t aLength, + const char* aSet) { + char16_t* from = aString; + char16_t* end = from + aLength; + char16_t* to = from; + + // this code converts /n, /t, /r into normal space ' '; + // it also compresses runs of whitespace down to a single char... + if (aSet && aString && (0 < aLength)) { + uint32_t aSetLen = strlen(aSet); + + while (from < end) { + char16_t theChar = *from++; + + *to++ = theChar; // always copy this char... + + if ((theChar < 256) && + (kNotFound != FindChar1(aSet, aSetLen, 0, theChar, aSetLen))) { + while (from < end) { + theChar = *from++; + if (kNotFound == FindChar1(aSet, aSetLen, 0, theChar, aSetLen)) { + *to++ = theChar; + break; + } + } // while + } // if + } // if + *to = 0; + } + return to - (char16_t*)aString; +} + +/** + * This method strips chars in a given set from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of + * the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start + * of the buffer + * @return the new length of the given buffer + */ +static int32_t StripChars1(char* aString, uint32_t aLength, const char* aSet) { + // XXX(darin): this code should defer writing until necessary. + + char* to = aString; + char* from = aString - 1; + char* end = aString + aLength; + + if (aSet && aString && (0 < aLength)) { + uint32_t aSetLen = strlen(aSet); + while (++from < end) { + char theChar = *from; + if (kNotFound == FindChar1(aSet, aSetLen, 0, theChar, aSetLen)) { + *to++ = theChar; + } + } + *to = 0; + } + return to - (char*)aString; +} + +/** + * This method strips chars in a given set from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of + * the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start + * of the buffer + * @return the new length of the given buffer + */ +static int32_t StripChars2(char16_t* aString, uint32_t aLength, + const char* aSet) { + // XXX(darin): this code should defer writing until necessary. + + char16_t* to = aString; + char16_t* from = aString - 1; + char16_t* end = to + aLength; + + if (aSet && aString && (0 < aLength)) { + uint32_t aSetLen = strlen(aSet); + while (++from < end) { + char16_t theChar = *from; + // Note the test for ascii range below. If you have a real unicode char, + // and you're searching for chars in the (given) ascii string, there's no + // point in doing the real search since it's out of the ascii range. + if ((255 < theChar) || + (kNotFound == FindChar1(aSet, aSetLen, 0, theChar, aSetLen))) { + *to++ = theChar; + } + } + *to = 0; + } + return to - (char16_t*)aString; +} + +/* ***** END RICKG BLOCK ***** */ + +// This function is used to implement FindCharInSet and friends +template +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ + CharT + GetFindInSetFilter(const CharT* set) { + CharT filter = ~CharT(0); // All bits set + while (*set) { + filter &= ~(*set); + ++set; + } + return filter; +} + +// This template class is used by our code to access rickg's buffer routines. +template +struct nsBufferRoutines {}; + +template <> +struct nsBufferRoutines { + static int32_t compare(const char* a, const char* b, uint32_t max, bool ic) { + return Compare1To1(a, b, max, ic); + } + + static int32_t compare(const char* a, const char16_t* b, uint32_t max, + bool ic) { + return Compare1To2(a, b, max, ic); + } + + static int32_t find_char(const char* s, uint32_t max, int32_t offset, + const char16_t c, int32_t count) { + return FindChar1(s, max, offset, c, count); + } + + static int32_t rfind_char(const char* s, uint32_t max, int32_t offset, + const char16_t c, int32_t count) { + return RFindChar1(s, max, offset, c, count); + } + + static char get_find_in_set_filter(const char* set) { + return GetFindInSetFilter(set); + } + + static int32_t strip_chars(char* s, uint32_t len, const char* set) { + return StripChars1(s, len, set); + } + + static int32_t compress_chars(char* s, uint32_t len, const char* set) { + return CompressChars1(s, len, set); + } +}; + +template <> +struct nsBufferRoutines { + static int32_t compare(const char16_t* a, const char16_t* b, uint32_t max, + bool ic) { + NS_ASSERTION(!ic, "no case-insensitive compare here"); + return Compare2To2(a, b, max); + } + + static int32_t compare(const char16_t* a, const char* b, uint32_t max, + bool ic) { + return Compare2To1(a, b, max, ic); + } + + static int32_t find_char(const char16_t* s, uint32_t max, int32_t offset, + const char16_t c, int32_t count) { + return FindChar2(s, max, offset, c, count); + } + + static int32_t rfind_char(const char16_t* s, uint32_t max, int32_t offset, + const char16_t c, int32_t count) { + return RFindChar2(s, max, offset, c, count); + } + + static char16_t get_find_in_set_filter(const char16_t* set) { + return GetFindInSetFilter(set); + } + + static char16_t get_find_in_set_filter(const char* set) { + return (~char16_t(0) ^ ~char(0)) | GetFindInSetFilter(set); + } + + static int32_t strip_chars(char16_t* s, uint32_t max, const char* set) { + return StripChars2(s, max, set); + } + + static int32_t compress_chars(char16_t* s, uint32_t len, const char* set) { + return CompressChars2(s, len, set); + } +}; + +//----------------------------------------------------------------------------- + +template +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ + int32_t + FindSubstring(const L* big, uint32_t bigLen, const R* little, + uint32_t littleLen, bool ignoreCase) { + if (littleLen > bigLen) return kNotFound; + + int32_t i, max = int32_t(bigLen - littleLen); + for (i = 0; i <= max; ++i, ++big) { + if (nsBufferRoutines::compare(big, little, littleLen, ignoreCase) == 0) + return i; + } + + return kNotFound; +} + +template +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ + int32_t + RFindSubstring(const L* big, uint32_t bigLen, const R* little, + uint32_t littleLen, bool ignoreCase) { + if (littleLen > bigLen) return kNotFound; + + int32_t i, max = int32_t(bigLen - littleLen); + + const L* iter = big + max; + for (i = max; iter >= big; --i, --iter) { + if (nsBufferRoutines::compare(iter, little, littleLen, ignoreCase) == 0) + return i; + } + + return kNotFound; +} + +template +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ + int32_t + FindCharInSet(const CharT* data, uint32_t dataLen, const SetCharT* set) { + CharT filter = nsBufferRoutines::get_find_in_set_filter(set); + + const CharT* end = data + dataLen; + for (const CharT* iter = data; iter < end; ++iter) { + CharT currentChar = *iter; + if (currentChar & filter) + continue; // char is not in filter set; go on with next char. + + // test all chars + const SetCharT* charInSet = set; + CharT setChar = CharT(*charInSet); + while (setChar) { + if (setChar == currentChar) + return iter - data; // found it! return index of the found char. + + setChar = CharT(*(++charInSet)); + } + } + return kNotFound; +} + +template +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ + int32_t + RFindCharInSet(const CharT* data, uint32_t dataLen, const SetCharT* set) { + CharT filter = nsBufferRoutines::get_find_in_set_filter(set); + + for (const CharT* iter = data + dataLen - 1; iter >= data; --iter) { + CharT currentChar = *iter; + if (currentChar & filter) + continue; // char is not in filter set; go on with next char. + + // test all chars + const CharT* charInSet = set; + CharT setChar = *charInSet; + while (setChar) { + if (setChar == currentChar) + return iter - data; // found it! return index of the found char. + + setChar = *(++charInSet); + } + } + return kNotFound; +} + +/** + * this method changes the meaning of |offset| and |count|: + * + * upon return, + * |offset| specifies start of search range + * |count| specifies length of search range + */ +static void Find_ComputeSearchRange(uint32_t bigLen, uint32_t littleLen, + int32_t& offset, int32_t& count) { + // |count| specifies how many iterations to make from |offset| + + if (offset < 0) { + offset = 0; + } else if (uint32_t(offset) > bigLen) { + count = 0; + return; + } + + int32_t maxCount = bigLen - offset; + if (count < 0 || count > maxCount) { + count = maxCount; + } else { + count += littleLen; + if (count > maxCount) count = maxCount; + } +} + +/** + * this method changes the meaning of |offset| and |count|: + * + * upon entry, + * |offset| specifies the end point from which to search backwards + * |count| specifies the number of iterations from |offset| + * + * upon return, + * |offset| specifies start of search range + * |count| specifies length of search range + * + * + * EXAMPLE + * + * + -- littleLen=4 -- + + * : : + * |____|____|____|____|____|____|____|____|____|____|____|____| + * : : + * offset=5 bigLen=12 + * + * if count = 4, then we expect this function to return offset = 2 and + * count = 7. + * + */ +static void RFind_ComputeSearchRange(uint32_t bigLen, uint32_t littleLen, + int32_t& offset, int32_t& count) { + if (littleLen > bigLen) { + offset = 0; + count = 0; + return; + } + + if (offset < 0) offset = bigLen - littleLen; + if (count < 0) count = offset + 1; + + int32_t start = offset - count + 1; + if (start < 0) start = 0; + + count = offset + littleLen - start; + offset = start; +} + +//----------------------------------------------------------------------------- + +#include "nsTStringObsolete.cpp" + +//----------------------------------------------------------------------------- + +// specialized methods: + +namespace mozilla::detail { + +template +template +int32_t nsTStringRepr::Find(const self_type& aString, int32_t aOffset, + int32_t aCount) const { + // this method changes the meaning of aOffset and aCount: + Find_ComputeSearchRange(this->mLength, aString.Length(), aOffset, aCount); + + // Capture the raw buffer locally to help msvc deduce the type. + const char_type* str = aString.BeginReading(); + int32_t result = FindSubstring(this->mData + aOffset, aCount, str, + aString.Length(), false); + if (result != kNotFound) result += aOffset; + return result; +} + +template int32_t nsTStringRepr::Find(const self_type&, int32_t, + int32_t) const; + +template +template +int32_t nsTStringRepr::Find(const char_type* aString, int32_t aOffset, + int32_t aCount) const { + return Find(nsTDependentString(aString), aOffset, aCount); +} + +template int32_t nsTStringRepr::Find(const char_type*, int32_t, + int32_t) const; + +template +template +int32_t nsTStringRepr::RFind(const self_type& aString, int32_t aOffset, + int32_t aCount) const { + // this method changes the meaning of aOffset and aCount: + RFind_ComputeSearchRange(this->mLength, aString.Length(), aOffset, aCount); + + // Capture the raw buffer locally to help msvc deduce the type. + const char_type* str = aString.BeginReading(); + int32_t result = RFindSubstring(this->mData + aOffset, aCount, str, + aString.Length(), false); + if (result != kNotFound) result += aOffset; + return result; +} + +template int32_t nsTStringRepr::RFind(const self_type&, int32_t, + int32_t) const; + +template +template +int32_t nsTStringRepr::RFind(const char_type* aString, int32_t aOffset, + int32_t aCount) const { + return RFind(nsTDependentString(aString), aOffset, aCount); +} + +template int32_t nsTStringRepr::RFind(const char_type*, int32_t, + int32_t) const; + +template +template +int32_t nsTStringRepr::FindCharInSet(const char* aSet, + int32_t aOffset) const { + if (aOffset < 0) + aOffset = 0; + else if (aOffset >= int32_t(this->mLength)) + return kNotFound; + + int32_t result = + ::FindCharInSet(this->mData + aOffset, this->mLength - aOffset, aSet); + if (result != kNotFound) result += aOffset; + return result; +} + +template int32_t nsTStringRepr::FindCharInSet(const char*, + int32_t) const; + +} // namespace mozilla::detail + +template +template +void nsTSubstring::ReplaceChar(const char* aSet, char16_t aNewChar) { + if (!this->EnsureMutable()) // XXX do this lazily? + this->AllocFailed(this->mLength); + + char16_t* data = this->mData; + uint32_t lenRemaining = this->mLength; + + while (lenRemaining) { + int32_t i = ::FindCharInSet(data, lenRemaining, aSet); + if (i == kNotFound) break; + + data[i++] = aNewChar; + data += i; + lenRemaining -= i; + } +} + +namespace mozilla::detail { + +template +template +int32_t nsTStringRepr::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(XPCOM_MIN(minLen, aCount)); + + int32_t result = nsBufferRoutines::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::Compare(const char_type*, bool, + size_type) const; + +template +template +bool nsTStringRepr::EqualsIgnoreCase(const incompatible_char_type* aString, + size_type aCount) const { + size_t strLen = nsCharTraits::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(XPCOM_MIN(minLen, aCount)); + + int32_t result = + nsBufferRoutines::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::EqualsIgnoreCase( + const incompatible_char_type*, size_type) const; + +} // namespace mozilla::detail + +/** + * nsTString::ToDouble + */ +template <> +double nsTString::ToDouble(bool aAllowTrailingChars, + nsresult* aErrorCode) const { + double res = 0.0; + if (this->Length() > 0) { + char* conv_stopped; + const char* str = this->get(); + // Use PR_strtod, not strtod, since we don't want locale involved. + res = PR_strtod(str, &conv_stopped); + if (aAllowTrailingChars && conv_stopped != str) { + *aErrorCode = NS_OK; + } else if (!aAllowTrailingChars && conv_stopped == str + this->Length()) { + *aErrorCode = NS_OK; + } else { + *aErrorCode = NS_ERROR_ILLEGAL_VALUE; + } + } else { + // The string was too short (0 characters) + *aErrorCode = NS_ERROR_ILLEGAL_VALUE; + } + return res; +} + +template <> +double nsTString::ToDouble(bool aAllowTrailingChars, + nsresult* aErrorCode) const { + NS_LossyConvertUTF16toASCII cString(BeginReading(), Length()); + return aAllowTrailingChars ? cString.ToDoubleAllowTrailingChars(aErrorCode) + : cString.ToDouble(aErrorCode); +} diff --git a/xpcom/string/nsStringStats.cpp b/xpcom/string/nsStringStats.cpp deleted file mode 100644 index 7fc3d82ad5aa..000000000000 --- a/xpcom/string/nsStringStats.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsStringStats.h" - -#include "mozilla/IntegerPrintfMacros.h" -#include "mozilla/MemoryReporting.h" -#include "nsString.h" - -#include -#include - -#ifdef XP_WIN -# include -# include -#else -# include -# include -#endif - -nsStringStats gStringStats; - -nsStringStats::~nsStringStats() { - // this is a hack to suppress duplicate string stats printing - // in seamonkey as a result of the string code being linked - // into seamonkey and libxpcom! :-( - if (!mAllocCount && !mAdoptCount) { - return; - } - - // Only print the stats if we detect a leak. - if (mAllocCount <= mFreeCount && mAdoptCount <= mAdoptFreeCount) { - return; - } - - printf("nsStringStats\n"); - printf(" => mAllocCount: % 10d\n", int(mAllocCount)); - printf(" => mReallocCount: % 10d\n", int(mReallocCount)); - printf(" => mFreeCount: % 10d", int(mFreeCount)); - if (mAllocCount > mFreeCount) { - printf(" -- LEAKED %d !!!\n", mAllocCount - mFreeCount); - } else { - printf("\n"); - } - printf(" => mShareCount: % 10d\n", int(mShareCount)); - printf(" => mAdoptCount: % 10d\n", int(mAdoptCount)); - printf(" => mAdoptFreeCount: % 10d", int(mAdoptFreeCount)); - if (mAdoptCount > mAdoptFreeCount) { - printf(" -- LEAKED %d !!!\n", mAdoptCount - mAdoptFreeCount); - } else { - printf("\n"); - } - -#ifdef XP_WIN - auto pid = uintptr_t(_getpid()); - auto tid = uintptr_t(GetCurrentThreadId()); -#else - auto pid = uintptr_t(getpid()); - auto tid = uintptr_t(pthread_self()); -#endif - - printf(" => Process ID: %" PRIuPTR ", Thread ID: %" PRIuPTR "\n", pid, tid); -} diff --git a/xpcom/string/nsStringStats.h b/xpcom/string/nsStringStats.h deleted file mode 100644 index a38304c2b71e..000000000000 --- a/xpcom/string/nsStringStats.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsStringStats_h -#define nsStringStats_h - -#include "mozilla/Atomics.h" - -class nsStringStats { - public: - nsStringStats() = default; - - ~nsStringStats(); - - using AtomicInt = mozilla::Atomic; - - AtomicInt mAllocCount{0}; - AtomicInt mReallocCount{0}; - AtomicInt mFreeCount{0}; - AtomicInt mShareCount{0}; - AtomicInt mAdoptCount{0}; - AtomicInt mAdoptFreeCount{0}; -}; - -extern nsStringStats gStringStats; - -#define STRING_STAT_INCREMENT(_s) (gStringStats.m##_s##Count)++ - -#endif // nsStringStats_h diff --git a/xpcom/string/nsSubstring.cpp b/xpcom/string/nsSubstring.cpp new file mode 100644 index 000000000000..6c194638029a --- /dev/null +++ b/xpcom/string/nsSubstring.cpp @@ -0,0 +1,424 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifdef DEBUG +# define ENABLE_STRING_STATS +#endif + +#include "mozilla/Atomics.h" +#include "mozilla/MemoryReporting.h" + +#ifdef ENABLE_STRING_STATS +# include +#endif + +#include +#include "nsAString.h" +#include "nsString.h" +#include "nsStringBuffer.h" +#include "nsDependentString.h" +#include "nsMemory.h" +#include "prprf.h" +#include "nsCOMPtr.h" + +#include "mozilla/IntegerPrintfMacros.h" +#ifdef XP_WIN +# include +# include +# define getpid() _getpid() +# define pthread_self() GetCurrentThreadId() +#else +# include +# include +#endif + +using mozilla::Atomic; + +// --------------------------------------------------------------------------- + +static const char16_t gNullChar = 0; + +char* const nsCharTraits::sEmptyBuffer = + (char*)const_cast(&gNullChar); +char16_t* const nsCharTraits::sEmptyBuffer = + const_cast(&gNullChar); + +// --------------------------------------------------------------------------- + +#ifdef ENABLE_STRING_STATS +class nsStringStats { + public: + nsStringStats() + : mAllocCount(0), mReallocCount(0), mFreeCount(0), mShareCount(0) {} + + ~nsStringStats() { + // this is a hack to suppress duplicate string stats printing + // in seamonkey as a result of the string code being linked + // into seamonkey and libxpcom! :-( + if (!mAllocCount && !mAdoptCount) { + return; + } + + // Only print the stats if we detect a leak. + if (mAllocCount <= mFreeCount && mAdoptCount <= mAdoptFreeCount) { + return; + } + + printf("nsStringStats\n"); + printf(" => mAllocCount: % 10d\n", int(mAllocCount)); + printf(" => mReallocCount: % 10d\n", int(mReallocCount)); + printf(" => mFreeCount: % 10d", int(mFreeCount)); + if (mAllocCount > mFreeCount) { + printf(" -- LEAKED %d !!!\n", mAllocCount - mFreeCount); + } else { + printf("\n"); + } + printf(" => mShareCount: % 10d\n", int(mShareCount)); + printf(" => mAdoptCount: % 10d\n", int(mAdoptCount)); + printf(" => mAdoptFreeCount: % 10d", int(mAdoptFreeCount)); + if (mAdoptCount > mAdoptFreeCount) { + printf(" -- LEAKED %d !!!\n", mAdoptCount - mAdoptFreeCount); + } else { + printf("\n"); + } + printf(" => Process ID: %" PRIuPTR ", Thread ID: %" PRIuPTR "\n", + uintptr_t(getpid()), uintptr_t(pthread_self())); + } + + typedef Atomic AtomicInt; + + AtomicInt mAllocCount; + AtomicInt mReallocCount; + AtomicInt mFreeCount; + AtomicInt mShareCount; + AtomicInt mAdoptCount; + AtomicInt mAdoptFreeCount; +}; +static nsStringStats gStringStats; +# define STRING_STAT_INCREMENT(_s) (gStringStats.m##_s##Count)++ +#else +# define STRING_STAT_INCREMENT(_s) +#endif + +// --------------------------------------------------------------------------- + +void ReleaseData(void* aData, nsAString::DataFlags aFlags) { + if (aFlags & nsAString::DataFlags::REFCOUNTED) { + nsStringBuffer::FromData(aData)->Release(); + } else if (aFlags & nsAString::DataFlags::OWNED) { + free(aData); + STRING_STAT_INCREMENT(AdoptFree); + // Treat this as destruction of a "StringAdopt" object for leak + // tracking purposes. + MOZ_LOG_DTOR(aData, "StringAdopt", 1); + } + // otherwise, nothing to do. +} + +// --------------------------------------------------------------------------- + +// XXX or we could make nsStringBuffer be a friend of nsTAString + +class nsAStringAccessor : public nsAString { + private: + nsAStringAccessor(); // NOT IMPLEMENTED + + public: + char_type* data() const { return mData; } + size_type length() const { return mLength; } + DataFlags flags() const { return mDataFlags; } + + void set(char_type* aData, size_type aLen, DataFlags aDataFlags) { + ReleaseData(mData, mDataFlags); + SetData(aData, aLen, aDataFlags); + } +}; + +class nsACStringAccessor : public nsACString { + private: + nsACStringAccessor(); // NOT IMPLEMENTED + + public: + char_type* data() const { return mData; } + size_type length() const { return mLength; } + DataFlags flags() const { return mDataFlags; } + + void set(char_type* aData, size_type aLen, DataFlags aDataFlags) { + ReleaseData(mData, mDataFlags); + SetData(aData, aLen, aDataFlags); + } +}; + +// --------------------------------------------------------------------------- + +void nsStringBuffer::AddRef() { + // Memory synchronization is not required when incrementing a + // reference count. The first increment of a reference count on a + // thread is not important, since the first use of the object on a + // thread can happen before it. What is important is the transfer + // of the pointer to that thread, which may happen prior to the + // first increment on that thread. The necessary memory + // synchronization is done by the mechanism that transfers the + // pointer between threads. +#ifdef NS_BUILD_REFCNT_LOGGING + uint32_t count = +#endif + mRefCount.fetch_add(1, std::memory_order_relaxed) +#ifdef NS_BUILD_REFCNT_LOGGING + + 1 +#endif + ; + STRING_STAT_INCREMENT(Share); + NS_LOG_ADDREF(this, count, "nsStringBuffer", sizeof(*this)); +} + +void nsStringBuffer::Release() { + // Since this may be the last release on this thread, we need + // release semantics so that prior writes on this thread are visible + // to the thread that destroys the object when it reads mValue with + // acquire semantics. + uint32_t count = mRefCount.fetch_sub(1, std::memory_order_release) - 1; + NS_LOG_RELEASE(this, count, "nsStringBuffer"); + if (count == 0) { + // We're going to destroy the object on this thread, so we need + // acquire semantics to synchronize with the memory released by + // the last release on other threads, that is, to ensure that + // writes prior to that release are now visible on this thread. + count = mRefCount.load(std::memory_order_acquire); + + STRING_STAT_INCREMENT(Free); + free(this); // we were allocated with |malloc| + } +} + +/** + * Alloc returns a pointer to a new string header with set capacity. + */ +already_AddRefed nsStringBuffer::Alloc(size_t aSize) { + NS_ASSERTION(aSize != 0, "zero capacity allocation not allowed"); + NS_ASSERTION(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && + sizeof(nsStringBuffer) + aSize > aSize, + "mStorageSize will truncate"); + + nsStringBuffer* hdr = (nsStringBuffer*)malloc(sizeof(nsStringBuffer) + aSize); + if (hdr) { + STRING_STAT_INCREMENT(Alloc); + + hdr->mRefCount = 1; + hdr->mStorageSize = aSize; + NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr)); + } + return dont_AddRef(hdr); +} + +nsStringBuffer* nsStringBuffer::Realloc(nsStringBuffer* aHdr, size_t aSize) { + STRING_STAT_INCREMENT(Realloc); + + NS_ASSERTION(aSize != 0, "zero capacity allocation not allowed"); + NS_ASSERTION(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && + sizeof(nsStringBuffer) + aSize > aSize, + "mStorageSize will truncate"); + + // no point in trying to save ourselves if we hit this assertion + NS_ASSERTION(!aHdr->IsReadonly(), "|Realloc| attempted on readonly string"); + + // Treat this as a release and addref for refcounting purposes, since we + // just asserted that the refcount is 1. If we don't do that, refcount + // logging will claim we've leaked all sorts of stuff. + NS_LOG_RELEASE(aHdr, 0, "nsStringBuffer"); + + aHdr = (nsStringBuffer*)realloc(aHdr, sizeof(nsStringBuffer) + aSize); + if (aHdr) { + NS_LOG_ADDREF(aHdr, 1, "nsStringBuffer", sizeof(*aHdr)); + aHdr->mStorageSize = aSize; + } + + return aHdr; +} + +nsStringBuffer* nsStringBuffer::FromString(const nsAString& aStr) { + const nsAStringAccessor* accessor = + static_cast(&aStr); + + if (!(accessor->flags() & nsAString::DataFlags::REFCOUNTED)) { + return nullptr; + } + + return FromData(accessor->data()); +} + +nsStringBuffer* nsStringBuffer::FromString(const nsACString& aStr) { + const nsACStringAccessor* accessor = + static_cast(&aStr); + + if (!(accessor->flags() & nsACString::DataFlags::REFCOUNTED)) { + return nullptr; + } + + return FromData(accessor->data()); +} + +void nsStringBuffer::ToString(uint32_t aLen, nsAString& aStr, + bool aMoveOwnership) { + char16_t* data = static_cast(Data()); + + nsAStringAccessor* accessor = static_cast(&aStr); + MOZ_DIAGNOSTIC_ASSERT(data[aLen] == char16_t(0), + "data should be null terminated"); + + nsAString::DataFlags flags = + nsAString::DataFlags::REFCOUNTED | nsAString::DataFlags::TERMINATED; + + if (!aMoveOwnership) { + AddRef(); + } + accessor->set(data, aLen, flags); +} + +void nsStringBuffer::ToString(uint32_t aLen, nsACString& aStr, + bool aMoveOwnership) { + char* data = static_cast(Data()); + + nsACStringAccessor* accessor = static_cast(&aStr); + MOZ_DIAGNOSTIC_ASSERT(data[aLen] == char(0), + "data should be null terminated"); + + nsACString::DataFlags flags = + nsACString::DataFlags::REFCOUNTED | nsACString::DataFlags::TERMINATED; + + if (!aMoveOwnership) { + AddRef(); + } + accessor->set(data, aLen, flags); +} + +size_t nsStringBuffer::SizeOfIncludingThisIfUnshared( + mozilla::MallocSizeOf aMallocSizeOf) const { + return IsReadonly() ? 0 : aMallocSizeOf(this); +} + +size_t nsStringBuffer::SizeOfIncludingThisEvenIfShared( + mozilla::MallocSizeOf aMallocSizeOf) const { + return aMallocSizeOf(this); +} + +// --------------------------------------------------------------------------- + +// define nsAString +#include "nsTSubstring.cpp" + +// Provide rust bindings to the nsA[C]String types +extern "C" { + +// This is a no-op on release, so we ifdef it out such that using it in release +// results in a linker error. +#ifdef DEBUG +void Gecko_IncrementStringAdoptCount(void* aData) { + MOZ_LOG_CTOR(aData, "StringAdopt", 1); +} +#elif defined(MOZ_DEBUG_RUST) +void Gecko_IncrementStringAdoptCount(void* aData) {} +#endif + +void Gecko_FinalizeCString(nsACString* aThis) { aThis->~nsACString(); } + +void Gecko_AssignCString(nsACString* aThis, const nsACString* aOther) { + aThis->Assign(*aOther); +} + +void Gecko_TakeFromCString(nsACString* aThis, nsACString* aOther) { + aThis->Assign(std::move(*aOther)); +} + +void Gecko_AppendCString(nsACString* aThis, const nsACString* aOther) { + aThis->Append(*aOther); +} + +void Gecko_SetLengthCString(nsACString* aThis, uint32_t aLength) { + aThis->SetLength(aLength); +} + +bool Gecko_FallibleAssignCString(nsACString* aThis, const nsACString* aOther) { + return aThis->Assign(*aOther, mozilla::fallible); +} + +bool Gecko_FallibleTakeFromCString(nsACString* aThis, nsACString* aOther) { + return aThis->Assign(std::move(*aOther), mozilla::fallible); +} + +bool Gecko_FallibleAppendCString(nsACString* aThis, const nsACString* aOther) { + return aThis->Append(*aOther, mozilla::fallible); +} + +bool Gecko_FallibleSetLengthCString(nsACString* aThis, uint32_t aLength) { + return aThis->SetLength(aLength, mozilla::fallible); +} + +char* Gecko_BeginWritingCString(nsACString* aThis) { + return aThis->BeginWriting(); +} + +char* Gecko_FallibleBeginWritingCString(nsACString* aThis) { + return aThis->BeginWriting(mozilla::fallible); +} + +uint32_t Gecko_StartBulkWriteCString(nsACString* aThis, uint32_t aCapacity, + uint32_t aUnitsToPreserve, + bool aAllowShrinking) { + return aThis->StartBulkWriteImpl(aCapacity, aUnitsToPreserve, aAllowShrinking) + .unwrapOr(UINT32_MAX); +} + +void Gecko_FinalizeString(nsAString* aThis) { aThis->~nsAString(); } + +void Gecko_AssignString(nsAString* aThis, const nsAString* aOther) { + aThis->Assign(*aOther); +} + +void Gecko_TakeFromString(nsAString* aThis, nsAString* aOther) { + aThis->Assign(std::move(*aOther)); +} + +void Gecko_AppendString(nsAString* aThis, const nsAString* aOther) { + aThis->Append(*aOther); +} + +void Gecko_SetLengthString(nsAString* aThis, uint32_t aLength) { + aThis->SetLength(aLength); +} + +bool Gecko_FallibleAssignString(nsAString* aThis, const nsAString* aOther) { + return aThis->Assign(*aOther, mozilla::fallible); +} + +bool Gecko_FallibleTakeFromString(nsAString* aThis, nsAString* aOther) { + return aThis->Assign(std::move(*aOther), mozilla::fallible); +} + +bool Gecko_FallibleAppendString(nsAString* aThis, const nsAString* aOther) { + return aThis->Append(*aOther, mozilla::fallible); +} + +bool Gecko_FallibleSetLengthString(nsAString* aThis, uint32_t aLength) { + return aThis->SetLength(aLength, mozilla::fallible); +} + +char16_t* Gecko_BeginWritingString(nsAString* aThis) { + return aThis->BeginWriting(); +} + +char16_t* Gecko_FallibleBeginWritingString(nsAString* aThis) { + return aThis->BeginWriting(mozilla::fallible); +} + +uint32_t Gecko_StartBulkWriteString(nsAString* aThis, uint32_t aCapacity, + uint32_t aUnitsToPreserve, + bool aAllowShrinking) { + return aThis->StartBulkWriteImpl(aCapacity, aUnitsToPreserve, aAllowShrinking) + .unwrapOr(UINT32_MAX); +} + +} // extern "C" diff --git a/xpcom/string/nsTDependentString.cpp b/xpcom/string/nsTDependentString.cpp index 83cfa3968737..6c16a17f6299 100644 --- a/xpcom/string/nsTDependentString.cpp +++ b/xpcom/string/nsTDependentString.cpp @@ -4,8 +4,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsTDependentString.h" - template nsTDependentString::nsTDependentString(const char_type* aStart, const char_type* aEnd) @@ -45,6 +43,3 @@ void nsTDependentString::Rebind(const char_type* aStart, MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!"); this->Rebind(aStart, aEnd - aStart); } - -template class nsTDependentString; -template class nsTDependentString; diff --git a/xpcom/string/nsTDependentString.h b/xpcom/string/nsTDependentString.h index c7194a677f82..5c2116370de1 100644 --- a/xpcom/string/nsTDependentString.h +++ b/xpcom/string/nsTDependentString.h @@ -43,8 +43,6 @@ class nsTDependentString : public nsTString { typedef typename base_string_type::const_char_iterator const_char_iterator; - typedef typename base_string_type::string_view string_view; - typedef typename base_string_type::index_type index_type; typedef typename base_string_type::size_type size_type; diff --git a/xpcom/string/nsTDependentSubstring.cpp b/xpcom/string/nsTDependentSubstring.cpp index ba1620f98b13..3b1fe4e199db 100644 --- a/xpcom/string/nsTDependentSubstring.cpp +++ b/xpcom/string/nsTDependentSubstring.cpp @@ -4,8 +4,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// FIXME: Due to an include cycle, we need to include `nsTSubstring` first. -#include "nsTSubstring.h" #include "nsTDependentSubstring.h" template @@ -101,6 +99,3 @@ const nsTDependentSubstring Substring(char16ptr_t aStart, static_cast(aEnd)); } #endif - -template class nsTDependentSubstring; -template class nsTDependentSubstring; diff --git a/xpcom/string/nsTDependentSubstring.h b/xpcom/string/nsTDependentSubstring.h index b5198ff2b500..5108c28de29d 100644 --- a/xpcom/string/nsTDependentSubstring.h +++ b/xpcom/string/nsTDependentSubstring.h @@ -44,8 +44,6 @@ class nsTDependentSubstring : public nsTSubstring { typedef typename substring_type::const_char_iterator const_char_iterator; - typedef typename substring_type::string_view string_view; - typedef typename substring_type::index_type index_type; typedef typename substring_type::size_type size_type; diff --git a/xpcom/string/nsTPromiseFlatString.cpp b/xpcom/string/nsTPromiseFlatString.cpp index 12433000337a..1e0fde7ec60c 100644 --- a/xpcom/string/nsTPromiseFlatString.cpp +++ b/xpcom/string/nsTPromiseFlatString.cpp @@ -4,8 +4,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsTPromiseFlatString.h" - template void nsTPromiseFlatString::Init(const substring_type& str) { if (str.IsTerminated()) { @@ -21,6 +19,3 @@ void nsTPromiseFlatString::Init(const substring_type& str) { this->Assign(str); } } - -template class nsTPromiseFlatString; -template class nsTPromiseFlatString; diff --git a/xpcom/string/nsTString.cpp b/xpcom/string/nsTString.cpp index 11ef53bd27ae..0af6116a7fa8 100644 --- a/xpcom/string/nsTString.cpp +++ b/xpcom/string/nsTString.cpp @@ -4,61 +4,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsTString.h" -#include "prdtoa.h" - -/** - * nsTString::SetCharAt - */ - -template -bool nsTString::SetCharAt(char16_t aChar, index_type aIndex) { - if (aIndex >= this->mLength) { - return false; - } - - if (!this->EnsureMutable()) { - this->AllocFailed(this->mLength); - } - - this->mData[aIndex] = char_type(aChar); - return true; -} - -/** - * nsTString::ToDouble - */ -template <> -double nsTString::ToDouble(bool aAllowTrailingChars, - nsresult* aErrorCode) const { - double res = 0.0; - if (this->Length() > 0) { - char* conv_stopped; - const char* str = this->get(); - // Use PR_strtod, not strtod, since we don't want locale involved. - res = PR_strtod(str, &conv_stopped); - if (aAllowTrailingChars && conv_stopped != str) { - *aErrorCode = NS_OK; - } else if (!aAllowTrailingChars && conv_stopped == str + this->Length()) { - *aErrorCode = NS_OK; - } else { - *aErrorCode = NS_ERROR_ILLEGAL_VALUE; - } - } else { - // The string was too short (0 characters) - *aErrorCode = NS_ERROR_ILLEGAL_VALUE; - } - return res; -} - -template <> -double nsTString::ToDouble(bool aAllowTrailingChars, - nsresult* aErrorCode) const { - NS_LossyConvertUTF16toASCII cString(BeginReading(), Length()); - return aAllowTrailingChars ? cString.ToDoubleAllowTrailingChars(aErrorCode) - : cString.ToDouble(aErrorCode); -} - template void nsTString::Rebind(const char_type* data, size_type length) { // If we currently own a buffer, release it. @@ -67,9 +12,3 @@ void nsTString::Rebind(const char_type* data, size_type length) { this->SetData(const_cast(data), length, DataFlags::TERMINATED); this->AssertValidDependentString(); } - -template class nsTString; -template class nsTString; - -template class nsTAutoStringN; -template class nsTAutoStringN; diff --git a/xpcom/string/nsTString.h b/xpcom/string/nsTString.h index 453436f2dccf..b647c10bab26 100644 --- a/xpcom/string/nsTString.h +++ b/xpcom/string/nsTString.h @@ -54,8 +54,6 @@ class nsTString : public nsTSubstring { typedef typename substring_type::const_char_iterator const_char_iterator; - typedef typename substring_type::string_view string_view; - typedef typename substring_type::index_type index_type; typedef typename substring_type::size_type size_type; @@ -180,6 +178,15 @@ class nsTString : public nsTSubstring { char_type operator[](index_type aIndex) const { return CharAt(aIndex); } + int32_t RFindCharInSet(const self_type& aString, int32_t aOffset = -1) const { + return repr_type::RFindCharInSet(aString.get(), aOffset); + } + using repr_type::RFindCharInSet; + int32_t FindCharInSet(const self_type& aString, int32_t aOffset = 0) const { + return repr_type::FindCharInSet(aString.get(), aOffset); + } + using repr_type::FindCharInSet; + /** * Perform string to double-precision float conversion. * diff --git a/xpcom/string/nsTStringComparator.cpp b/xpcom/string/nsTStringComparator.cpp index 801a3623b940..d4b3aa7a6588 100644 --- a/xpcom/string/nsTStringComparator.cpp +++ b/xpcom/string/nsTStringComparator.cpp @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsString.h" -#include "plstr.h" template int NS_FASTCALL Compare(const mozilla::detail::nsTStringRepr& aLhs, @@ -62,30 +61,3 @@ template int nsTDefaultStringComparator(const char*, const char*, size_t, size_t); template int nsTDefaultStringComparator(const char16_t*, const char16_t*, size_t, size_t); - -int nsCaseInsensitiveCStringComparator(const char* aLhs, const char* aRhs, - size_t aLhsLength, size_t aRhsLength) { -#if defined(LIBFUZZER) && defined(LINUX) - // Make sure libFuzzer can see this string compare by calling the POSIX - // native function which is intercepted. We also call this if the lengths - // don't match so libFuzzer can at least see a partial string, but we throw - // away the result afterwards again. - int32_t result = - int32_t(strncasecmp(aLhs, aRhs, std::min(aLhsLength, aRhsLength))); - - if (aLhsLength != aRhsLength) { - return (aLhsLength > aRhsLength) ? 1 : -1; - } -#else - if (aLhsLength != aRhsLength) { - return (aLhsLength > aRhsLength) ? 1 : -1; - } - int32_t result = int32_t(PL_strncasecmp(aLhs, aRhs, aLhsLength)); -#endif - // Egads. PL_strncasecmp is returning *very* negative numbers. - // Some folks expect -1,0,1, so let's temper its enthusiasm. - if (result < 0) { - result = -1; - } - return result; -} diff --git a/xpcom/string/nsTStringObsolete.cpp b/xpcom/string/nsTStringObsolete.cpp new file mode 100644 index 000000000000..d1e7a9bb3ef7 --- /dev/null +++ b/xpcom/string/nsTStringObsolete.cpp @@ -0,0 +1,406 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsTArray.h" +#include "nsASCIIMask.h" +#include "mozilla/CheckedInt.h" + +namespace mozilla::detail { + +template +int32_t nsTStringRepr::Find(const nsTStringRepr& aString, + bool aIgnoreCase, int32_t aOffset, + int32_t aCount) const { + // this method changes the meaning of aOffset and aCount: + Find_ComputeSearchRange(this->mLength, aString.Length(), aOffset, aCount); + + int32_t result = + FindSubstring(this->mData + aOffset, aCount, aString.BeginReading(), + aString.Length(), aIgnoreCase); + if (result != kNotFound) result += aOffset; + return result; +} + +template +int32_t nsTStringRepr::Find(const char* aString, bool aIgnoreCase, + int32_t aOffset, int32_t aCount) const { + return Find(nsTDependentString(aString), aIgnoreCase, aOffset, aCount); +} + +template +int32_t nsTStringRepr::RFind(const nsTStringRepr& aString, + bool aIgnoreCase, int32_t aOffset, + int32_t aCount) const { + // this method changes the meaning of aOffset and aCount: + RFind_ComputeSearchRange(this->mLength, aString.Length(), aOffset, aCount); + + int32_t result = + RFindSubstring(this->mData + aOffset, aCount, aString.BeginReading(), + aString.Length(), aIgnoreCase); + if (result != kNotFound) result += aOffset; + return result; +} + +template +int32_t nsTStringRepr::RFind(const char* aString, bool aIgnoreCase, + int32_t aOffset, int32_t aCount) const { + return RFind(nsTDependentString(aString), aIgnoreCase, aOffset, aCount); +} + +template +int32_t nsTStringRepr::RFindChar(char16_t aChar, int32_t aOffset, + int32_t aCount) const { + return nsBufferRoutines::rfind_char(this->mData, this->mLength, aOffset, + aChar, aCount); +} + +template +int32_t nsTStringRepr::FindCharInSet(const char_type* aSet, + int32_t aOffset) const { + if (aOffset < 0) + aOffset = 0; + else if (aOffset >= int32_t(this->mLength)) + return kNotFound; + + int32_t result = + ::FindCharInSet(this->mData + aOffset, this->mLength - aOffset, aSet); + if (result != kNotFound) result += aOffset; + return result; +} + +/** + * nsTString::RFindCharInSet + */ + +template +int32_t nsTStringRepr::RFindCharInSet(const char_type* aSet, + int32_t aOffset) const { + // We want to pass a "data length" to ::RFindCharInSet + if (aOffset < 0 || aOffset > int32_t(this->mLength)) + aOffset = this->mLength; + else + ++aOffset; + + return ::RFindCharInSet(this->mData, aOffset, aSet); +} + +} // namespace mozilla::detail + +/** + * nsTString::Mid + */ +template +typename nsTSubstring::size_type nsTSubstring::Mid( + self_type& aResult, index_type aStartPos, size_type aLengthToCopy) const { + if (aStartPos == 0 && aLengthToCopy >= this->mLength) + aResult = *this; + else + aResult = Substring(*this, aStartPos, aLengthToCopy); + + return aResult.mLength; +} + +/** + * nsTString::SetCharAt + */ + +template +bool nsTString::SetCharAt(char16_t aChar, index_type aIndex) { + if (aIndex >= this->mLength) return false; + + if (!this->EnsureMutable()) this->AllocFailed(this->mLength); + + this->mData[aIndex] = char_type(aChar); + return true; +} + +/** + * nsTSubstring::StripWhitespace + */ + +template +void nsTSubstring::StripWhitespace() { + if (!StripWhitespace(mozilla::fallible)) { + this->AllocFailed(this->mLength); + } +} + +template +bool nsTSubstring::StripWhitespace(const fallible_t&) { + if (!this->EnsureMutable()) { + return false; + } + + this->StripTaggedASCII(mozilla::ASCIIMask::MaskWhitespace()); + return true; +} + +/** + * nsTSubstring::ReplaceChar,ReplaceSubstring + */ + +template +void nsTSubstring::ReplaceChar(char_type aOldChar, char_type aNewChar) { + if (!this->EnsureMutable()) // XXX do this lazily? + this->AllocFailed(this->mLength); + + for (uint32_t i = 0; i < this->mLength; ++i) { + if (this->mData[i] == aOldChar) this->mData[i] = aNewChar; + } +} + +template +void nsTSubstring::ReplaceChar(const char_type* aSet, char_type aNewChar) { + if (!this->EnsureMutable()) // XXX do this lazily? + this->AllocFailed(this->mLength); + + char_type* data = this->mData; + uint32_t lenRemaining = this->mLength; + + while (lenRemaining) { + int32_t i = ::FindCharInSet(data, lenRemaining, aSet); + if (i == kNotFound) break; + + data[i++] = aNewChar; + data += i; + lenRemaining -= i; + } +} + +template void nsTSubstring::ReplaceChar(const char*, char16_t); + +void ReleaseData(void* aData, nsAString::DataFlags aFlags); + +template +void nsTSubstring::ReplaceSubstring(const char_type* aTarget, + const char_type* aNewValue) { + ReplaceSubstring(nsTDependentString(aTarget), + nsTDependentString(aNewValue)); +} + +template +bool nsTSubstring::ReplaceSubstring(const char_type* aTarget, + const char_type* aNewValue, + const fallible_t& aFallible) { + return ReplaceSubstring(nsTDependentString(aTarget), + nsTDependentString(aNewValue), aFallible); +} + +template +void nsTSubstring::ReplaceSubstring(const self_type& aTarget, + const self_type& aNewValue) { + if (!ReplaceSubstring(aTarget, aNewValue, mozilla::fallible)) { + // Note that this may wildly underestimate the allocation that failed, as + // we could have been replacing multiple copies of aTarget. + this->AllocFailed(this->mLength + (aNewValue.Length() - aTarget.Length())); + } +} + +template +bool nsTSubstring::ReplaceSubstring(const self_type& aTarget, + const self_type& aNewValue, + const fallible_t&) { + struct Segment { + uint32_t mBegin, mLength; + Segment(uint32_t aBegin, uint32_t aLength) + : mBegin(aBegin), mLength(aLength) {} + }; + + if (aTarget.Length() == 0) return true; + + // Remember all of the non-matching parts. + AutoTArray nonMatching; + uint32_t i = 0; + mozilla::CheckedUint32 newLength; + while (true) { + int32_t r = FindSubstring(this->mData + i, this->mLength - i, + static_cast(aTarget.Data()), + aTarget.Length(), false); + int32_t until = (r == kNotFound) ? this->mLength - i : r; + nonMatching.AppendElement(Segment(i, until)); + newLength += until; + if (r == kNotFound) { + break; + } + + newLength += aNewValue.Length(); + i += r + aTarget.Length(); + if (i >= this->mLength) { + // Add an auxiliary entry at the end of the list to help as an edge case + // for the algorithms below. + nonMatching.AppendElement(Segment(this->mLength, 0)); + break; + } + } + + if (!newLength.isValid()) { + return false; + } + + // If there's only one non-matching segment, then the target string was not + // found, and there's nothing to do. + if (nonMatching.Length() == 1) { + MOZ_ASSERT( + nonMatching[0].mBegin == 0 && nonMatching[0].mLength == this->mLength, + "We should have the correct non-matching segment."); + return true; + } + + // Make sure that we can mutate our buffer. + // Note that we always allocate at least an this->mLength sized buffer, + // because the rest of the algorithm relies on having access to all of the + // original string. In other words, we over-allocate in the shrinking case. + uint32_t oldLen = this->mLength; + auto r = + this->StartBulkWriteImpl(XPCOM_MAX(oldLen, newLength.value()), oldLen); + if (r.isErr()) { + return false; + } + + if (aTarget.Length() >= aNewValue.Length()) { + // In the shrinking case, start filling the buffer from the beginning. + const uint32_t delta = (aTarget.Length() - aNewValue.Length()); + for (i = 1; i < nonMatching.Length(); ++i) { + // When we move the i'th non-matching segment into position, we need to + // account for the characters deleted by the previous |i| replacements by + // subtracting |i * delta|. + const char_type* sourceSegmentPtr = this->mData + nonMatching[i].mBegin; + char_type* destinationSegmentPtr = + this->mData + nonMatching[i].mBegin - i * delta; + // Write the i'th replacement immediately before the new i'th non-matching + // segment. + char_traits::copy(destinationSegmentPtr - aNewValue.Length(), + aNewValue.Data(), aNewValue.Length()); + char_traits::move(destinationSegmentPtr, sourceSegmentPtr, + nonMatching[i].mLength); + } + } else { + // In the growing case, start filling the buffer from the end. + const uint32_t delta = (aNewValue.Length() - aTarget.Length()); + for (i = nonMatching.Length() - 1; i > 0; --i) { + // When we move the i'th non-matching segment into position, we need to + // account for the characters added by the previous |i| replacements by + // adding |i * delta|. + const char_type* sourceSegmentPtr = this->mData + nonMatching[i].mBegin; + char_type* destinationSegmentPtr = + this->mData + nonMatching[i].mBegin + i * delta; + char_traits::move(destinationSegmentPtr, sourceSegmentPtr, + nonMatching[i].mLength); + // Write the i'th replacement immediately before the new i'th non-matching + // segment. + char_traits::copy(destinationSegmentPtr - aNewValue.Length(), + aNewValue.Data(), aNewValue.Length()); + } + } + + // Adjust the length and make sure the string is null terminated. + this->FinishBulkWriteImpl(newLength.value()); + + return true; +} + +/** + * nsTSubstring::Trim + */ + +template +void nsTSubstring::Trim(const char* aSet, bool aTrimLeading, + bool aTrimTrailing, bool aIgnoreQuotes) { + // the old implementation worried about aSet being null :-/ + if (!aSet) return; + + char_type* start = this->mData; + char_type* end = this->mData + this->mLength; + + // skip over quotes if requested + if (aIgnoreQuotes && this->mLength > 2 && + this->mData[0] == this->mData[this->mLength - 1] && + (this->mData[0] == '\'' || this->mData[0] == '"')) { + ++start; + --end; + } + + uint32_t setLen = nsCharTraits::length(aSet); + + if (aTrimLeading) { + uint32_t cutStart = start - this->mData; + uint32_t cutLength = 0; + + // walk forward from start to end + for (; start != end; ++start, ++cutLength) { + int32_t pos = FindChar1(aSet, setLen, 0, *start, setLen); + if (pos == kNotFound) break; + } + + if (cutLength) { + this->Cut(cutStart, cutLength); + + // reset iterators + start = this->mData + cutStart; + end = this->mData + this->mLength - cutStart; + } + } + + if (aTrimTrailing) { + uint32_t cutEnd = end - this->mData; + uint32_t cutLength = 0; + + // walk backward from end to start + --end; + for (; end >= start; --end, ++cutLength) { + int32_t pos = FindChar1(aSet, setLen, 0, *end, setLen); + if (pos == kNotFound) break; + } + + if (cutLength) this->Cut(cutEnd - cutLength, cutLength); + } +} + +/** + * nsTSubstring::CompressWhitespace. + */ + +template +void nsTSubstring::CompressWhitespace(bool aTrimLeading, + bool aTrimTrailing) { + // Quick exit + if (this->mLength == 0) { + return; + } + + if (!this->EnsureMutable()) this->AllocFailed(this->mLength); + + const ASCIIMaskArray& mask = mozilla::ASCIIMask::MaskWhitespace(); + + char_type* to = this->mData; + char_type* from = this->mData; + char_type* end = this->mData + this->mLength; + + // Compresses runs of whitespace down to a normal space ' ' and convert + // any whitespace to a normal space. This assumes that whitespace is + // all standard 7-bit ASCII. + bool skipWS = aTrimLeading; + while (from < end) { + uint32_t theChar = *from++; + if (mozilla::ASCIIMask::IsMasked(mask, theChar)) { + if (!skipWS) { + *to++ = ' '; + skipWS = true; + } + } else { + *to++ = theChar; + skipWS = false; + } + } + + // If we need to trim the trailing whitespace, back up one character. + if (aTrimTrailing && skipWS && to > this->mData) { + to--; + } + + *to = char_type(0); // add the null + this->mLength = to - this->mData; +} diff --git a/xpcom/string/nsTStringRepr.cpp b/xpcom/string/nsTStringRepr.cpp deleted file mode 100644 index 05ac98aa2235..000000000000 --- a/xpcom/string/nsTStringRepr.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsTStringRepr.h" - -#include "nsString.h" - -namespace mozilla::detail { - -template -typename nsTStringRepr::char_type nsTStringRepr::First() const { - MOZ_RELEASE_ASSERT(this->mLength > 0, "|First()| called on an empty string"); - return this->mData[0]; -} - -template -typename nsTStringRepr::char_type nsTStringRepr::Last() const { - MOZ_RELEASE_ASSERT(this->mLength > 0, "|Last()| called on an empty string"); - return this->mData[this->mLength - 1]; -} - -template -bool nsTStringRepr::Equals(const self_type& aStr) const { - return this->mLength == aStr.mLength && - char_traits::compare(this->mData, aStr.mData, this->mLength) == 0; -} - -template -bool nsTStringRepr::Equals(const self_type& aStr, - comparator_type aComp) const { - return this->mLength == aStr.mLength && - aComp(this->mData, aStr.mData, this->mLength, aStr.mLength) == 0; -} - -template -bool nsTStringRepr::Equals(const substring_tuple_type& aTuple) const { - return Equals(substring_type(aTuple)); -} - -template -bool nsTStringRepr::Equals(const substring_tuple_type& aTuple, - comparator_type aComp) const { - return Equals(substring_type(aTuple), aComp); -} - -template -bool nsTStringRepr::Equals(const char_type* aData) const { - // unfortunately, some callers pass null :-( - if (!aData) { - MOZ_ASSERT_UNREACHABLE("null data pointer"); - return this->mLength == 0; - } - - // XXX avoid length calculation? - size_type length = char_traits::length(aData); - return this->mLength == length && - char_traits::compare(this->mData, aData, this->mLength) == 0; -} - -template -bool nsTStringRepr::Equals(const char_type* aData, - comparator_type aComp) const { - // unfortunately, some callers pass null :-( - if (!aData) { - MOZ_ASSERT_UNREACHABLE("null data pointer"); - return this->mLength == 0; - } - - // XXX avoid length calculation? - size_type length = char_traits::length(aData); - return this->mLength == length && - aComp(this->mData, aData, this->mLength, length) == 0; -} - -template -bool nsTStringRepr::EqualsASCII(const char* aData, size_type aLen) const { - return this->mLength == aLen && - char_traits::compareASCII(this->mData, aData, aLen) == 0; -} - -template -bool nsTStringRepr::EqualsASCII(const char* aData) const { - return char_traits::compareASCIINullTerminated(this->mData, this->mLength, - aData) == 0; -} - -template -bool nsTStringRepr::EqualsLatin1(const char* aData, - const size_type aLength) const { - return (this->mLength == aLength) && - char_traits::equalsLatin1(this->mData, aData, aLength); -} - -template -bool nsTStringRepr::LowerCaseEqualsASCII(const char* aData, - size_type aLen) const { - return this->mLength == aLen && - char_traits::compareLowerCaseToASCII(this->mData, aData, aLen) == 0; -} - -template -bool nsTStringRepr::LowerCaseEqualsASCII(const char* aData) const { - return char_traits::compareLowerCaseToASCIINullTerminated( - this->mData, this->mLength, aData) == 0; -} - -template -int32_t nsTStringRepr::Find(const string_view& aString, - index_type aOffset) const { - auto idx = View().find(aString, aOffset); - return idx == string_view::npos ? kNotFound : idx; -} - -template -int32_t nsTStringRepr::LowerCaseFindASCII(const std::string_view& aString, - index_type aOffset) const { - if (aOffset > Length()) { - return kNotFound; - } - auto begin = BeginReading(); - auto end = EndReading(); - auto it = - std::search(begin + aOffset, end, aString.begin(), aString.end(), - [](char_type l, char r) { - MOZ_ASSERT(!(r & ~0x7F), "Unexpected non-ASCII character"); - MOZ_ASSERT(char_traits::ASCIIToLower(r) == char_type(r), - "Search string must be ASCII lowercase"); - return char_traits::ASCIIToLower(l) == char_type(r); - }); - return it == end ? kNotFound : std::distance(begin, it); -} - -template -int32_t nsTStringRepr::RFind(const string_view& aString) const { - auto idx = View().rfind(aString); - return idx == string_view::npos ? kNotFound : idx; -} - -template -typename nsTStringRepr::size_type nsTStringRepr::CountChar( - char_type aChar) const { - return std::count(BeginReading(), EndReading(), aChar); -} - -template -int32_t nsTStringRepr::FindChar(char_type aChar, index_type aOffset) const { - auto idx = View().find(aChar, aOffset); - return idx == string_view::npos ? kNotFound : idx; -} - -template -int32_t nsTStringRepr::RFindChar(char_type aChar, int32_t aOffset) const { - auto idx = View().rfind(aChar, aOffset != -1 ? aOffset : string_view::npos); - return idx == string_view::npos ? kNotFound : idx; -} - -template -int32_t nsTStringRepr::FindCharInSet(const string_view& aSet, - index_type aOffset) const { - auto idx = View().find_first_of(aSet, aOffset); - return idx == string_view::npos ? kNotFound : idx; -} - -template -int32_t nsTStringRepr::RFindCharInSet(const string_view& aSet, - int32_t aOffset) const { - auto idx = - View().find_last_of(aSet, aOffset != -1 ? aOffset : string_view::npos); - return idx == string_view::npos ? kNotFound : idx; -} - -template -int32_t nsTStringRepr::Compare(const string_view& aString) const { - return View().compare(aString); -} - -template -bool nsTStringRepr::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 - -template class mozilla::detail::nsTStringRepr; -template class mozilla::detail::nsTStringRepr; diff --git a/xpcom/string/nsTStringRepr.h b/xpcom/string/nsTStringRepr.h index cc6e383d7f89..8aa5a1ff2919 100644 --- a/xpcom/string/nsTStringRepr.h +++ b/xpcom/string/nsTStringRepr.h @@ -8,7 +8,6 @@ #define nsTStringRepr_h #include -#include #include // std::enable_if #include "mozilla/Char16.h" @@ -16,7 +15,6 @@ #include "mozilla/fallible.h" #include "nsStringBuffer.h" #include "nsStringFlags.h" -#include "nsStringFwd.h" #include "nsStringIterator.h" #include "nsCharTraits.h" @@ -133,8 +131,6 @@ class nsTStringRepr { typedef const char_type* const_char_iterator; - typedef std::basic_string_view string_view; - typedef size_t index_type; typedef size_t size_type; @@ -183,14 +179,10 @@ class nsTStringRepr { #endif // Returns pointer to string data (not necessarily null-terminated) - constexpr typename raw_type::type Data() const { return mData; } + constexpr const typename raw_type::type Data() const { return mData; } constexpr size_type Length() const { return static_cast(mLength); } - constexpr string_view View() const { return string_view(Data(), Length()); } - - constexpr operator string_view() const { return View(); } - constexpr DataFlags GetDataFlags() const { return mDataFlags; } constexpr bool IsEmpty() const { return mLength == 0; } @@ -218,6 +210,11 @@ class nsTStringRepr { char_type Last() const; + size_type NS_FASTCALL CountChar(char_type) const; + int32_t NS_FASTCALL FindChar(char_type, index_type aOffset = 0) const; + + bool Contains(char_type aChar) const; + // Equality. bool NS_FASTCALL Equals(const self_type&) const; bool NS_FASTCALL Equals(const self_type&, comparator_type) const; @@ -233,23 +230,35 @@ class nsTStringRepr { * Compares a given string to this string. * * @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 */ - int32_t Compare(const string_view& aString) const; + template > + int32_t Compare( + const char_type* aString, bool aIgnoreCase = false, + size_type aCount = std::numeric_limits::max()) const; /** * Equality check between given string and this string. * * @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 */ - bool EqualsIgnoreCase(const std::string_view& aString) const; - bool EqualsIgnoreCase(const char* aString, size_type aCount) const { - MOZ_DIAGNOSTIC_ASSERT(aCount != std::numeric_limits::max()); - return EqualsIgnoreCase(std::string_view(aString, aCount)); + template > + bool EqualsIgnoreCase( + const char_type* aString, + size_type aCount = std::numeric_limits::max()) const { + return Compare(aString, true, aCount) == 0; } + template > + bool EqualsIgnoreCase( + const incompatible_char_type* aString, + size_type aCount = std::numeric_limits::max()) const; + #if defined(MOZ_USE_CHAR16_WRAPPER) template > bool NS_FASTCALL Equals(char16ptr_t aData) const { @@ -347,88 +356,99 @@ class nsTStringRepr { } /** - * Search for the given substring within this string. + * Search for the given substring within this string. * - * @param aString is substring to be sought in this - * @param aOffset tells us where in this string to start searching - * @return offset in string, or kNotFound + * @param aString is substring to be sought in this + * @param aIgnoreCase selects case sensitivity + * @param aOffset tells us where in this string to start searching + * @param aCount tells us how far from the offset we are to search. Use + * -1 to search the whole string. + * @return offset in string, or kNotFound */ - int32_t Find(const string_view& aString, index_type aOffset = 0) const; + int32_t Find(const nsTStringRepr& aString, bool aIgnoreCase = false, + int32_t aOffset = 0, int32_t aCount = -1) const; + int32_t Find(const char* aString, bool aIgnoreCase = false, + int32_t aOffset = 0, int32_t aCount = -1) const; - // Previously there was an overload of `Find()` which took a bool second - // argument. Avoid issues by explicitly preventing that overload. - // TODO: Remove this at some point. - template && - std::is_convertible_v>> - int32_t Find(const string_view& aString, I aOffset) const { - static_assert(!std::is_same_v, "offset must not be `bool`"); - return Find(aString, static_cast(aOffset)); + template > + int32_t Find(const self_type& aString, int32_t aOffset = 0, + int32_t aCount = -1) const; + template > + int32_t Find(const char_type* aString, int32_t aOffset = 0, + int32_t aCount = -1) const; +#ifdef MOZ_USE_CHAR16_WRAPPER + template > + int32_t Find(char16ptr_t aString, int32_t aOffset = 0, + int32_t aCount = -1) const { + return Find(static_cast(aString), aOffset, aCount); } +#endif /** - * Search for the given ASCII substring within this string, ignoring case. + * This methods scans the string backwards, looking for the given string * * @param aString is substring to be sought in this - * @param aOffset tells us where in this string to start searching + * @param aIgnoreCase tells us whether or not to do caseless compare + * @param aOffset tells us where in this string to start searching. + * Use -1 to search from the end of the string. + * @param aCount tells us how many iterations to make starting at the + * given offset. * @return offset in string, or kNotFound */ - int32_t LowerCaseFindASCII(const std::string_view& aString, - index_type aOffset = 0) const; + + // Case aIgnoreCase option only with char versions + int32_t RFind(const nsTStringRepr& aString, bool aIgnoreCase = false, + int32_t aOffset = -1, int32_t aCount = -1) const; + int32_t RFind(const char* aCString, bool aIgnoreCase = false, + int32_t aOffset = -1, int32_t aCount = -1) const; + + template > + int32_t RFind(const self_type& aString, int32_t aOffset = -1, + int32_t aCount = -1) const; + template > + int32_t RFind(const char_type* aString, int32_t aOffset = -1, + int32_t aCount = -1) const; /** - * Scan the string backwards, looking for the given substring. + * Search for given char within this string * - * @param aString is substring to be sought in this - * @return offset in string, or kNotFound + * @param aChar is the character to search for + * @param aOffset tells us where in this string to start searching + * @param aCount tells us how far from the offset we are to search. + * Use -1 to search the whole string. + * @return offset in string, or kNotFound */ - int32_t RFind(const string_view& aString) const; - size_type CountChar(char_type) const; - - bool Contains(char_type aChar) const { return FindChar(aChar) != kNotFound; } - - /** - * Search for the first instance of a given char within this string - * - * @param aChar is the character to search for - * @param aOffset tells us where in this string to start searching - * @return offset in string, or kNotFound - */ - int32_t FindChar(char_type aChar, index_type aOffset = 0) const; - - /** - * Search for the last instance of a given char within this string - * - * @param aChar is the character to search for - * @param aOffset tells us where in this string to start searching - * @return offset in string, or kNotFound - */ - int32_t RFindChar(char_type aChar, int32_t aOffset = -1) const; + // int32_t FindChar( char16_t aChar, int32_t aOffset=0, + // int32_t aCount=-1 ) const; + int32_t RFindChar(char16_t aChar, int32_t aOffset = -1, + int32_t aCount = -1) const; /** * This method searches this string for the first character found in * the given string. * - * @param aSet contains set of chars to be found + * @param aString contains set of chars to be found * @param aOffset tells us where in this string to start searching * (counting from left) * @return offset in string, or kNotFound */ - int32_t FindCharInSet(const string_view& aSet, index_type aOffset = 0) const; + int32_t FindCharInSet(const char_type* aString, int32_t aOffset = 0) const; + template > + int32_t FindCharInSet(const char* aSet, int32_t aOffset = 0) const; /** * This method searches this string for the last character found in * the given string. * - * @param aSet contains set of chars to be found + * @param aString contains set of chars to be found * @param aOffset tells us where in this string to start searching * (counting from left) * @return offset in string, or kNotFound */ - int32_t RFindCharInSet(const string_view& aSet, int32_t aOffset = -1) const; + int32_t RFindCharInSet(const char_type* aString, int32_t aOffset = -1) const; protected: nsTStringRepr() = delete; // Never instantiate directly diff --git a/xpcom/string/nsTSubstring.cpp b/xpcom/string/nsTSubstring.cpp index 6dcf933629a1..d8fdb6e58c2c 100644 --- a/xpcom/string/nsTSubstring.cpp +++ b/xpcom/string/nsTSubstring.cpp @@ -12,16 +12,6 @@ #include "mozilla/ResultExtensions.h" #include "nsASCIIMask.h" -#include "nsCharTraits.h" -#include "nsISupports.h" -#include "nsString.h" -#include "nsTArray.h" - -#ifdef DEBUG -# include "nsStringStats.h" -#else -# define STRING_STAT_INCREMENT(_s) -#endif // It's not worthwhile to reallocate the buffer and memcpy the // contents over when the size difference isn't large. With @@ -43,32 +33,6 @@ const uint32_t kNsStringBufferShrinkingThreshold = 384; using double_conversion::DoubleToStringConverter; -// --------------------------------------------------------------------------- - -static const char16_t gNullChar = 0; - -char* const nsCharTraits::sEmptyBuffer = - (char*)const_cast(&gNullChar); -char16_t* const nsCharTraits::sEmptyBuffer = - const_cast(&gNullChar); - -// --------------------------------------------------------------------------- - -static void ReleaseData(void* aData, nsAString::DataFlags aFlags) { - if (aFlags & nsAString::DataFlags::REFCOUNTED) { - nsStringBuffer::FromData(aData)->Release(); - } else if (aFlags & nsAString::DataFlags::OWNED) { - free(aData); - STRING_STAT_INCREMENT(AdoptFree); - // Treat this as destruction of a "StringAdopt" object for leak - // tracking purposes. - MOZ_LOG_DTOR(aData, "StringAdopt", 1); - } - // otherwise, nothing to do. -} - -// --------------------------------------------------------------------------- - #ifdef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE template nsTSubstring::nsTSubstring(char_type* aData, size_type aLength, @@ -123,7 +87,7 @@ auto nsTSubstring::StartBulkWriteImpl(size_type aCapacity, // If zero capacity is requested, set the string to the special empty // string. if (MOZ_UNLIKELY(!aCapacity)) { - ReleaseData(this->mData, this->mDataFlags); + ::ReleaseData(this->mData, this->mDataFlags); SetToEmptyBuffer(); return 0; } @@ -272,7 +236,7 @@ auto nsTSubstring::StartBulkWriteImpl(size_type aCapacity, char_traits::copy(newData, oldData, aPrefixToPreserve); char_traits::copy(newData + aNewSuffixStart, oldData + aOldSuffixStart, aSuffixLength); - ReleaseData(oldData, oldFlags); + ::ReleaseData(oldData, oldFlags); } return newCapacity; @@ -283,7 +247,7 @@ void nsTSubstring::FinishBulkWriteImpl(size_type aLength) { if (aLength) { FinishBulkWriteImplImpl(aLength); } else { - ReleaseData(this->mData, this->mDataFlags); + ::ReleaseData(this->mData, this->mDataFlags); SetToEmptyBuffer(); } AssertValid(); @@ -291,7 +255,7 @@ void nsTSubstring::FinishBulkWriteImpl(size_type aLength) { template void nsTSubstring::Finalize() { - ReleaseData(this->mData, this->mDataFlags); + ::ReleaseData(this->mData, this->mDataFlags); // this->mData, this->mLength, and this->mDataFlags are purposefully left // dangling } @@ -472,7 +436,7 @@ bool nsTSubstring::AssignASCII(const char* aData, size_type aLength, template void nsTSubstring::AssignLiteral(const char_type* aData, size_type aLength) { - ReleaseData(this->mData, this->mDataFlags); + ::ReleaseData(this->mData, this->mDataFlags); SetData(const_cast(aData), aLength, DataFlags::TERMINATED | DataFlags::LITERAL); } @@ -507,7 +471,7 @@ bool nsTSubstring::Assign(const self_type& aStr, NS_ASSERTION(aStr.mDataFlags & DataFlags::TERMINATED, "shared, but not terminated"); - ReleaseData(this->mData, this->mDataFlags); + ::ReleaseData(this->mData, this->mDataFlags); SetData(aStr.mData, aStr.mLength, DataFlags::TERMINATED | DataFlags::REFCOUNTED); @@ -545,7 +509,7 @@ void nsTSubstring::AssignOwned(self_type&& aStr) { MOZ_ASSERT(aStr.mDataFlags & DataFlags::TERMINATED, "shared or owned, but not terminated"); - ReleaseData(this->mData, this->mDataFlags); + ::ReleaseData(this->mData, this->mDataFlags); SetData(aStr.mData, aStr.mLength, aStr.mDataFlags); aStr.SetToEmptyBuffer(); @@ -621,7 +585,7 @@ bool nsTSubstring::Assign(const substring_tuple_type& aTuple, template void nsTSubstring::Adopt(char_type* aData, size_type aLength) { if (aData) { - ReleaseData(this->mData, this->mDataFlags); + ::ReleaseData(this->mData, this->mDataFlags); if (aLength == size_type(-1)) { aLength = char_traits::length(aData); @@ -969,7 +933,7 @@ bool nsTSubstring::SetLength(size_type aLength, template void nsTSubstring::Truncate() { - ReleaseData(this->mData, this->mDataFlags); + ::ReleaseData(this->mData, this->mDataFlags); SetToEmptyBuffer(); AssertValid(); } @@ -984,6 +948,135 @@ void nsTSubstring::SetIsVoid(bool aVal) { } } +namespace mozilla { +namespace detail { + +template +typename nsTStringRepr::char_type nsTStringRepr::First() const { + MOZ_RELEASE_ASSERT(this->mLength > 0, "|First()| called on an empty string"); + return this->mData[0]; +} + +template +typename nsTStringRepr::char_type nsTStringRepr::Last() const { + MOZ_RELEASE_ASSERT(this->mLength > 0, "|Last()| called on an empty string"); + return this->mData[this->mLength - 1]; +} + +template +bool nsTStringRepr::Equals(const self_type& aStr) const { + return this->mLength == aStr.mLength && + char_traits::compare(this->mData, aStr.mData, this->mLength) == 0; +} + +template +bool nsTStringRepr::Equals(const self_type& aStr, + comparator_type aComp) const { + return this->mLength == aStr.mLength && + aComp(this->mData, aStr.mData, this->mLength, aStr.mLength) == 0; +} + +template +bool nsTStringRepr::Equals(const substring_tuple_type& aTuple) const { + return Equals(substring_type(aTuple)); +} + +template +bool nsTStringRepr::Equals(const substring_tuple_type& aTuple, + comparator_type aComp) const { + return Equals(substring_type(aTuple), aComp); +} + +template +bool nsTStringRepr::Equals(const char_type* aData) const { + // unfortunately, some callers pass null :-( + if (!aData) { + MOZ_ASSERT_UNREACHABLE("null data pointer"); + return this->mLength == 0; + } + + // XXX avoid length calculation? + size_type length = char_traits::length(aData); + return this->mLength == length && + char_traits::compare(this->mData, aData, this->mLength) == 0; +} + +template +bool nsTStringRepr::Equals(const char_type* aData, + comparator_type aComp) const { + // unfortunately, some callers pass null :-( + if (!aData) { + MOZ_ASSERT_UNREACHABLE("null data pointer"); + return this->mLength == 0; + } + + // XXX avoid length calculation? + size_type length = char_traits::length(aData); + return this->mLength == length && + aComp(this->mData, aData, this->mLength, length) == 0; +} + +template +bool nsTStringRepr::EqualsASCII(const char* aData, size_type aLen) const { + return this->mLength == aLen && + char_traits::compareASCII(this->mData, aData, aLen) == 0; +} + +template +bool nsTStringRepr::EqualsASCII(const char* aData) const { + return char_traits::compareASCIINullTerminated(this->mData, this->mLength, + aData) == 0; +} + +template +bool nsTStringRepr::EqualsLatin1(const char* aData, + const size_type aLength) const { + return (this->mLength == aLength) && + char_traits::equalsLatin1(this->mData, aData, aLength); +} + +template +bool nsTStringRepr::LowerCaseEqualsASCII(const char* aData, + size_type aLen) const { + return this->mLength == aLen && + char_traits::compareLowerCaseToASCII(this->mData, aData, aLen) == 0; +} + +template +bool nsTStringRepr::LowerCaseEqualsASCII(const char* aData) const { + return char_traits::compareLowerCaseToASCIINullTerminated( + this->mData, this->mLength, aData) == 0; +} + +template +typename nsTStringRepr::size_type nsTStringRepr::CountChar( + char_type aChar) const { + const char_type* start = this->mData; + const char_type* end = this->mData + this->mLength; + + return NS_COUNT(start, end, aChar); +} + +template +int32_t nsTStringRepr::FindChar(char_type aChar, index_type aOffset) const { + if (aOffset < this->mLength) { + const char_type* result = char_traits::find(this->mData + aOffset, + this->mLength - aOffset, aChar); + if (result) { + return result - this->mData; + } + } + return -1; +} + +template +bool nsTStringRepr::Contains(char_type aChar) const { + return FindChar(aChar) != kNotFound; +} + +} // namespace detail +} // namespace mozilla + template void nsTSubstring::StripChar(char_type aChar) { if (this->mLength == 0) { @@ -1385,310 +1478,3 @@ int64_t nsTSubstring::ToInteger64(nsresult* aErrorCode, uint32_t aRadix) const { return ToIntegerCommon(*this, aErrorCode, aRadix); } - -/** - * nsTSubstring::Mid - */ -template -typename nsTSubstring::size_type nsTSubstring::Mid( - self_type& aResult, index_type aStartPos, size_type aLengthToCopy) const { - if (aStartPos == 0 && aLengthToCopy >= this->mLength) { - aResult = *this; - } else { - aResult = Substring(*this, aStartPos, aLengthToCopy); - } - - return aResult.mLength; -} - -/** - * nsTSubstring::StripWhitespace - */ - -template -void nsTSubstring::StripWhitespace() { - if (!StripWhitespace(mozilla::fallible)) { - this->AllocFailed(this->mLength); - } -} - -template -bool nsTSubstring::StripWhitespace(const fallible_t&) { - if (!this->EnsureMutable()) { - return false; - } - - this->StripTaggedASCII(mozilla::ASCIIMask::MaskWhitespace()); - return true; -} - -/** - * nsTSubstring::ReplaceChar,ReplaceSubstring - */ - -template -void nsTSubstring::ReplaceChar(char_type aOldChar, char_type aNewChar) { - int32_t i = this->FindChar(aOldChar); - if (i == kNotFound) { - return; - } - - if (!this->EnsureMutable()) { - this->AllocFailed(this->mLength); - } - for (; i != kNotFound; i = this->FindChar(aOldChar, i + 1)) { - this->mData[i] = aNewChar; - } -} - -template -void nsTSubstring::ReplaceChar(const string_view& aSet, char_type aNewChar) { - int32_t i = this->FindCharInSet(aSet); - if (i == kNotFound) { - return; - } - - if (!this->EnsureMutable()) { - this->AllocFailed(this->mLength); - } - for (; i != kNotFound; i = this->FindCharInSet(aSet, i + 1)) { - this->mData[i] = aNewChar; - } -} - -template -void nsTSubstring::ReplaceSubstring(const char_type* aTarget, - const char_type* aNewValue) { - ReplaceSubstring(nsTDependentString(aTarget), - nsTDependentString(aNewValue)); -} - -template -bool nsTSubstring::ReplaceSubstring(const char_type* aTarget, - const char_type* aNewValue, - const fallible_t& aFallible) { - return ReplaceSubstring(nsTDependentString(aTarget), - nsTDependentString(aNewValue), aFallible); -} - -template -void nsTSubstring::ReplaceSubstring(const self_type& aTarget, - const self_type& aNewValue) { - if (!ReplaceSubstring(aTarget, aNewValue, mozilla::fallible)) { - // Note that this may wildly underestimate the allocation that failed, as - // we could have been replacing multiple copies of aTarget. - this->AllocFailed(this->mLength + (aNewValue.Length() - aTarget.Length())); - } -} - -template -bool nsTSubstring::ReplaceSubstring(const self_type& aTarget, - const self_type& aNewValue, - const fallible_t&) { - struct Segment { - uint32_t mBegin, mLength; - Segment(uint32_t aBegin, uint32_t aLength) - : mBegin(aBegin), mLength(aLength) {} - }; - - if (aTarget.Length() == 0) { - return true; - } - - // Remember all of the non-matching parts. - AutoTArray nonMatching; - uint32_t i = 0; - mozilla::CheckedUint32 newLength; - while (true) { - int32_t r = this->Find(aTarget, i); - int32_t until = (r == kNotFound) ? this->Length() - i : r - i; - nonMatching.AppendElement(Segment(i, until)); - newLength += until; - if (r == kNotFound) { - break; - } - - newLength += aNewValue.Length(); - i = r + aTarget.Length(); - if (i >= this->Length()) { - // Add an auxiliary entry at the end of the list to help as an edge case - // for the algorithms below. - nonMatching.AppendElement(Segment(this->Length(), 0)); - break; - } - } - - if (!newLength.isValid()) { - return false; - } - - // If there's only one non-matching segment, then the target string was not - // found, and there's nothing to do. - if (nonMatching.Length() == 1) { - MOZ_ASSERT( - nonMatching[0].mBegin == 0 && nonMatching[0].mLength == this->Length(), - "We should have the correct non-matching segment."); - return true; - } - - // Make sure that we can mutate our buffer. - // Note that we always allocate at least an this->mLength sized buffer, - // because the rest of the algorithm relies on having access to all of the - // original string. In other words, we over-allocate in the shrinking case. - uint32_t oldLen = this->Length(); - auto r = - this->StartBulkWriteImpl(XPCOM_MAX(oldLen, newLength.value()), oldLen); - if (r.isErr()) { - return false; - } - - if (aTarget.Length() >= aNewValue.Length()) { - // In the shrinking case, start filling the buffer from the beginning. - const uint32_t delta = (aTarget.Length() - aNewValue.Length()); - for (i = 1; i < nonMatching.Length(); ++i) { - // When we move the i'th non-matching segment into position, we need to - // account for the characters deleted by the previous |i| replacements by - // subtracting |i * delta|. - const char_type* sourceSegmentPtr = this->mData + nonMatching[i].mBegin; - char_type* destinationSegmentPtr = - this->mData + nonMatching[i].mBegin - i * delta; - // Write the i'th replacement immediately before the new i'th non-matching - // segment. - char_traits::copy(destinationSegmentPtr - aNewValue.Length(), - aNewValue.Data(), aNewValue.Length()); - char_traits::move(destinationSegmentPtr, sourceSegmentPtr, - nonMatching[i].mLength); - } - } else { - // In the growing case, start filling the buffer from the end. - const uint32_t delta = (aNewValue.Length() - aTarget.Length()); - for (i = nonMatching.Length() - 1; i > 0; --i) { - // When we move the i'th non-matching segment into position, we need to - // account for the characters added by the previous |i| replacements by - // adding |i * delta|. - const char_type* sourceSegmentPtr = this->mData + nonMatching[i].mBegin; - char_type* destinationSegmentPtr = - this->mData + nonMatching[i].mBegin + i * delta; - char_traits::move(destinationSegmentPtr, sourceSegmentPtr, - nonMatching[i].mLength); - // Write the i'th replacement immediately before the new i'th non-matching - // segment. - char_traits::copy(destinationSegmentPtr - aNewValue.Length(), - aNewValue.Data(), aNewValue.Length()); - } - } - - // Adjust the length and make sure the string is null terminated. - this->FinishBulkWriteImpl(newLength.value()); - - return true; -} - -/** - * nsTSubstring::Trim - */ - -template -void nsTSubstring::Trim(const std::string_view& aSet, bool aTrimLeading, - bool aTrimTrailing, bool aIgnoreQuotes) { - char_type* start = this->mData; - char_type* end = this->mData + this->mLength; - - // skip over quotes if requested - if (aIgnoreQuotes && this->mLength > 2 && - this->mData[0] == this->mData[this->mLength - 1] && - (this->mData[0] == '\'' || this->mData[0] == '"')) { - ++start; - --end; - } - - if (aTrimLeading) { - uint32_t cutStart = start - this->mData; - uint32_t cutLength = 0; - - // walk forward from start to end - for (; start != end; ++start, ++cutLength) { - if ((*start & ~0x7F) || // non-ascii - aSet.find(char(*start)) == std::string_view::npos) { - break; - } - } - - if (cutLength) { - this->Cut(cutStart, cutLength); - - // reset iterators - start = this->mData + cutStart; - end = this->mData + this->mLength - cutStart; - } - } - - if (aTrimTrailing) { - uint32_t cutEnd = end - this->mData; - uint32_t cutLength = 0; - - // walk backward from end to start - --end; - for (; end >= start; --end, ++cutLength) { - if ((*end & ~0x7F) || // non-ascii - aSet.find(char(*end)) == std::string_view::npos) { - break; - } - } - - if (cutLength) { - this->Cut(cutEnd - cutLength, cutLength); - } - } -} - -/** - * nsTSubstring::CompressWhitespace. - */ - -template -void nsTSubstring::CompressWhitespace(bool aTrimLeading, - bool aTrimTrailing) { - // Quick exit - if (this->mLength == 0) { - return; - } - - if (!this->EnsureMutable()) { - this->AllocFailed(this->mLength); - } - - const ASCIIMaskArray& mask = mozilla::ASCIIMask::MaskWhitespace(); - - char_type* to = this->mData; - char_type* from = this->mData; - char_type* end = this->mData + this->mLength; - - // Compresses runs of whitespace down to a normal space ' ' and convert - // any whitespace to a normal space. This assumes that whitespace is - // all standard 7-bit ASCII. - bool skipWS = aTrimLeading; - while (from < end) { - uint32_t theChar = *from++; - if (mozilla::ASCIIMask::IsMasked(mask, theChar)) { - if (!skipWS) { - *to++ = ' '; - skipWS = true; - } - } else { - *to++ = theChar; - skipWS = false; - } - } - - // If we need to trim the trailing whitespace, back up one character. - if (aTrimTrailing && skipWS && to > this->mData) { - to--; - } - - *to = char_type(0); // add the null - this->mLength = to - this->mData; -} - -template class nsTSubstring; -template class nsTSubstring; diff --git a/xpcom/string/nsTSubstring.h b/xpcom/string/nsTSubstring.h index d54dcafd7b12..d76730d46ea9 100644 --- a/xpcom/string/nsTSubstring.h +++ b/xpcom/string/nsTSubstring.h @@ -34,7 +34,6 @@ // memory checking. (Limited to avoid quadratic behavior.) const size_t kNsStringBufferMaxPoison = 16; -class nsStringBuffer; template class nsTSubstringSplitter; template @@ -286,7 +285,6 @@ class BulkWriteHandle final { template class nsTSubstring : public mozilla::detail::nsTStringRepr { friend class mozilla::BulkWriteHandle; - friend class nsStringBuffer; public: typedef nsTSubstring self_type; @@ -312,8 +310,6 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr { typedef typename base_string_type::const_char_iterator const_char_iterator; - typedef typename base_string_type::string_view string_view; - typedef typename base_string_type::index_type index_type; typedef typename base_string_type::size_type size_type; @@ -637,7 +633,10 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr { * swaps occurence of 1 string for another */ void ReplaceChar(char_type aOldChar, char_type aNewChar); - void ReplaceChar(const string_view& aSet, char_type aNewChar); + void ReplaceChar(const char_type* aSet, char_type aNewChar); + + template > + void ReplaceChar(const char* aSet, char16_t aNewChar); /** * Replace all occurrences of aTarget with aNewValue. @@ -654,27 +653,28 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr { const fallible_t&); /** - * This method trims characters found in aSet from either end of the - * underlying string. + * This method trims characters found in aTrimSet from + * either end of the underlying string. * * @param aSet -- contains chars to be trimmed from both ends - * @param aTrimLeading - * @param aTrimTrailing + * @param aEliminateLeading + * @param aEliminateTrailing * @param aIgnoreQuotes -- if true, causes surrounding quotes to be ignored * @return this */ - void Trim(const std::string_view& aSet, bool aTrimLeading = true, - bool aTrimTrailing = true, bool aIgnoreQuotes = false); + void Trim(const char* aSet, bool aEliminateLeading = true, + bool aEliminateTrailing = true, bool aIgnoreQuotes = false); /** * This method strips whitespace from string. * You can control whether whitespace is yanked from start and end of * string as well. * - * @param aTrimLeading controls stripping of leading ws - * @param aTrimTrailing controls stripping of trailing ws + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws */ - void CompressWhitespace(bool aTrimLeading = true, bool aTrimTrailing = true); + void CompressWhitespace(bool aEliminateLeading = true, + bool aEliminateTrailing = true); void Append(char_type aChar); diff --git a/xpcom/string/precompiled_templates.cpp b/xpcom/string/precompiled_templates.cpp new file mode 100644 index 000000000000..edc9812d3080 --- /dev/null +++ b/xpcom/string/precompiled_templates.cpp @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsString.h" + +// This file provides concrete instantiations for externed string template +// classes. + +// ================ +// Template classes +// ================ +template class mozilla::detail::nsTStringRepr; +template class mozilla::detail::nsTStringRepr; + +template class nsTLiteralString; +template class nsTLiteralString; + +template class nsTSubstring; +template class nsTSubstring; + +template class nsTDependentSubstring; +template class nsTDependentSubstring; + +template class nsTString; +template class nsTString; + +template class nsTAutoStringN; +template class nsTAutoStringN; + +template class nsTDependentString; +template class nsTDependentString; + +template class nsTPromiseFlatString; +template class nsTPromiseFlatString; + +template class nsTSubstringSplitter; +template class nsTSubstringSplitter; diff --git a/xpcom/tests/gtest/TestStrings.cpp b/xpcom/tests/gtest/TestStrings.cpp index bea3a62423aa..701ea35fe89a 100644 --- a/xpcom/tests/gtest/TestStrings.cpp +++ b/xpcom/tests/gtest/TestStrings.cpp @@ -613,42 +613,33 @@ TEST_F(Strings, test2) { TEST_F(Strings, find) { nsCString src(""); - int32_t i = src.Find("DOCTYPE", 2); - EXPECT_EQ(i, 2); - - i = src.Find("DOCTYPE"); - EXPECT_EQ(i, 2); -} - -TEST_F(Strings, lower_case_find) { - nsCString src(""); - - int32_t i = src.LowerCaseFindASCII("doctype", 2); - EXPECT_EQ(i, 2); - - i = src.LowerCaseFindASCII("doctype"); + int32_t i = src.Find("DOCTYPE", true, 2, 1); EXPECT_EQ(i, 2); } TEST_F(Strings, rfind) { - const char text[] = ""; + const char text[] = ""; + const char term[] = "bLaH"; nsCString src(text); int32_t i; - i = src.RFind("bLaH"); + i = src.RFind(term, true, 3, -1); + EXPECT_EQ(i, kNotFound); + + i = src.RFind(term, true, -1, -1); EXPECT_EQ(i, 20); - i = src.RFind("blah"); + i = src.RFind(term, true, 13, -1); EXPECT_EQ(i, 10); - i = src.RFind("BLAH"); - EXPECT_EQ(i, kNotFound); + i = src.RFind(term, true, 22, 3); + EXPECT_EQ(i, 20); } TEST_F(Strings, rfind_2) { const char text[] = ""; nsCString src(text); - int32_t i = src.RFind("TYPE"); + int32_t i = src.RFind("TYPE", false, 5, -1); EXPECT_EQ(i, 5); } diff --git a/xpfe/appshell/AppWindow.cpp b/xpfe/appshell/AppWindow.cpp index 46a12508720d..fb36837f23da 100644 --- a/xpfe/appshell/AppWindow.cpp +++ b/xpfe/appshell/AppWindow.cpp @@ -2041,7 +2041,7 @@ NS_IMETHODIMP AppWindow::SavePersistentAttributes() { ErrorResult rv; // (only for size elements which are persisted) if ((mPersistentAttributesDirty & PAD_POSITION) && gotRestoredBounds) { - if (persistString.Find(u"screenX") >= 0) { + if (persistString.Find("screenX") >= 0) { sizeString.Truncate(); sizeString.AppendInt(NSToIntRound(rect.X() / posScale.scale)); docShellElement->SetAttribute(SCREENX_ATTRIBUTE, sizeString, rv); @@ -2049,7 +2049,7 @@ NS_IMETHODIMP AppWindow::SavePersistentAttributes() { Unused << SetPersistentValue(nsGkAtoms::screenX, sizeString); } } - if (persistString.Find(u"screenY") >= 0) { + if (persistString.Find("screenY") >= 0) { sizeString.Truncate(); sizeString.AppendInt(NSToIntRound(rect.Y() / posScale.scale)); docShellElement->SetAttribute(SCREENY_ATTRIBUTE, sizeString, rv); @@ -2062,7 +2062,7 @@ NS_IMETHODIMP AppWindow::SavePersistentAttributes() { if ((mPersistentAttributesDirty & PAD_SIZE) && gotRestoredBounds) { LayoutDeviceIntRect innerRect = rect - GetOuterToInnerSizeDifference(mWindow); - if (persistString.Find(u"width") >= 0) { + if (persistString.Find("width") >= 0) { sizeString.Truncate(); sizeString.AppendInt(NSToIntRound(innerRect.Width() / sizeScale.scale)); docShellElement->SetAttribute(WIDTH_ATTRIBUTE, sizeString, rv); @@ -2070,7 +2070,7 @@ NS_IMETHODIMP AppWindow::SavePersistentAttributes() { Unused << SetPersistentValue(nsGkAtoms::width, sizeString); } } - if (persistString.Find(u"height") >= 0) { + if (persistString.Find("height") >= 0) { sizeString.Truncate(); sizeString.AppendInt(NSToIntRound(innerRect.Height() / sizeScale.scale)); docShellElement->SetAttribute(HEIGHT_ATTRIBUTE, sizeString, rv); @@ -2093,7 +2093,7 @@ NS_IMETHODIMP AppWindow::SavePersistentAttributes() { else sizeString.Assign(SIZEMODE_NORMAL); docShellElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv); - if (shouldPersist && persistString.Find(u"sizemode") >= 0) { + if (shouldPersist && persistString.Find("sizemode") >= 0) { Unused << SetPersistentValue(nsGkAtoms::sizemode, sizeString); } } @@ -2104,7 +2104,7 @@ NS_IMETHODIMP AppWindow::SavePersistentAttributes() { sizeString.Assign(u"false"_ns); } docShellElement->SetAttribute(TILED_ATTRIBUTE, sizeString, rv); - if (persistString.Find(u"zlevel") >= 0) { + if (persistString.Find("zlevel") >= 0) { uint32_t zLevel; nsCOMPtr mediator( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); diff --git a/xpfe/appshell/nsContentTreeOwner.cpp b/xpfe/appshell/nsContentTreeOwner.cpp index a9302bff559e..e98baac37001 100644 --- a/xpfe/appshell/nsContentTreeOwner.cpp +++ b/xpfe/appshell/nsContentTreeOwner.cpp @@ -242,7 +242,7 @@ nsContentTreeOwner::SetPersistence(bool aPersistPosition, bool aPersistSize, int32_t index; // Set X - index = persistString.Find(u"screenX"); + index = persistString.Find("screenX"); if (!aPersistPosition && index >= 0) { persistString.Cut(index, 7); saveString = true; @@ -251,7 +251,7 @@ nsContentTreeOwner::SetPersistence(bool aPersistPosition, bool aPersistSize, saveString = true; } // Set Y - index = persistString.Find(u"screenY"); + index = persistString.Find("screenY"); if (!aPersistPosition && index >= 0) { persistString.Cut(index, 7); saveString = true; @@ -260,7 +260,7 @@ nsContentTreeOwner::SetPersistence(bool aPersistPosition, bool aPersistSize, saveString = true; } // Set CX - index = persistString.Find(u"width"); + index = persistString.Find("width"); if (!aPersistSize && index >= 0) { persistString.Cut(index, 5); saveString = true; @@ -269,7 +269,7 @@ nsContentTreeOwner::SetPersistence(bool aPersistPosition, bool aPersistSize, saveString = true; } // Set CY - index = persistString.Find(u"height"); + index = persistString.Find("height"); if (!aPersistSize && index >= 0) { persistString.Cut(index, 6); saveString = true; @@ -278,7 +278,7 @@ nsContentTreeOwner::SetPersistence(bool aPersistPosition, bool aPersistSize, saveString = true; } // Set SizeMode - index = persistString.Find(u"sizemode"); + index = persistString.Find("sizemode"); if (!aPersistSizeMode && (index >= 0)) { persistString.Cut(index, 8); saveString = true; @@ -307,17 +307,18 @@ nsContentTreeOwner::GetPersistence(bool* aPersistPosition, bool* aPersistSize, // data structure doesn't quite match the question, but it's close enough // for what we want (since this method is never actually called...) - if (aPersistPosition) { - *aPersistPosition = persistString.Find(u"screenX") >= 0 || - persistString.Find(u"screenY") >= 0; - } - if (aPersistSize) { + if (aPersistPosition) + *aPersistPosition = + persistString.Find("screenX") >= 0 || persistString.Find("screenY") >= 0 + ? true + : false; + if (aPersistSize) *aPersistSize = - persistString.Find(u"width") >= 0 || persistString.Find(u"height") >= 0; - } - if (aPersistSizeMode) { - *aPersistSizeMode = persistString.Find(u"sizemode") >= 0; - } + persistString.Find("width") >= 0 || persistString.Find("height") >= 0 + ? true + : false; + if (aPersistSizeMode) + *aPersistSizeMode = persistString.Find("sizemode") >= 0 ? true : false; return NS_OK; }