зеркало из https://github.com/mozilla/gecko-dev.git
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)
This commit is contained in:
Родитель
480cd06cd9
Коммит
c6b2c5db61
|
@ -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"");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
template <typename String>
|
||||
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 <typename String>
|
||||
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;
|
||||
|
|
|
@ -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"");
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -10456,8 +10456,8 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) {
|
|||
if (RefPtr<DocumentType> 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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<uint32_t>(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;
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ Result<UsageInfo, nsresult> 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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@ class QuotaManager final : public BackgroundThreadObject {
|
|||
}
|
||||
|
||||
static const char kReplaceChars[];
|
||||
static const char16_t kReplaceChars16[];
|
||||
|
||||
static Result<MovingNotNull<RefPtr<QuotaManager>>, nsresult> GetOrCreate();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<int32_t>(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;
|
||||
|
|
|
@ -1449,14 +1449,14 @@ void RemoveFragComments(nsCString& aStr) {
|
|||
// remove the StartFragment/EndFragment comments from the str, if present
|
||||
int32_t startCommentIndx = aStr.Find("<!--StartFragment");
|
||||
if (startCommentIndx >= 0) {
|
||||
int32_t startCommentEnd = aStr.Find("-->", startCommentIndx);
|
||||
int32_t startCommentEnd = aStr.Find("-->", false, startCommentIndx);
|
||||
if (startCommentEnd > startCommentIndx) {
|
||||
aStr.Cut(startCommentIndx, (startCommentEnd + 3) - startCommentIndx);
|
||||
}
|
||||
}
|
||||
int32_t endCommentIndx = aStr.Find("<!--EndFragment");
|
||||
if (endCommentIndx >= 0) {
|
||||
int32_t endCommentEnd = aStr.Find("-->", endCommentIndx);
|
||||
int32_t endCommentEnd = aStr.Find("-->", false, endCommentIndx);
|
||||
if (endCommentEnd > endCommentIndx) {
|
||||
aStr.Cut(endCommentIndx, (endCommentEnd + 3) - endCommentIndx);
|
||||
}
|
||||
|
|
|
@ -354,7 +354,7 @@ mozHunspell::LoadDictionariesFromDir(nsIFile* aDir) {
|
|||
if (NS_FAILED(rv) || !check) continue;
|
||||
|
||||
// Replace '_' separator with '-'
|
||||
dict.ReplaceChar('_', '-');
|
||||
dict.ReplaceChar("_", '-');
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewFileURI(getter_AddRefs(uri), file);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -974,10 +974,10 @@ gfxPlatformGtk::CreateGlobalHardwareVsyncSource() {
|
|||
nsCOMPtr<nsIGfxInfo> 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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -111,8 +111,8 @@ Result<std::tuple<int64_t, int64_t, int64_t>, 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));
|
||||
|
|
|
@ -1135,7 +1135,7 @@ mozTXTToHTMLConv::ScanHTML(const nsAString& input, uint32_t whattodo,
|
|||
// if a tag, skip until </a>.
|
||||
// Make sure there's a white-space character after, not to match "abbr".
|
||||
{
|
||||
i = aInString.LowerCaseFindASCII("</a>", i);
|
||||
i = aInString.Find("</a>", 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 </style>
|
||||
{
|
||||
i = aInString.LowerCaseFindASCII("</style>", i);
|
||||
i = aInString.Find("</style>", 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 </script>
|
||||
{
|
||||
i = aInString.LowerCaseFindASCII("</script>", i);
|
||||
i = aInString.Find("</script>", 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 </head>
|
||||
// Make sure not to match <header>.
|
||||
{
|
||||
i = aInString.LowerCaseFindASCII("</head>", i);
|
||||
i = aInString.Find("</head>", true, i);
|
||||
if (i == kNotFound) {
|
||||
i = lengthOfInString;
|
||||
} else {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<nsIStringBundleService> 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;
|
||||
|
|
|
@ -553,7 +553,7 @@ void nsMIMEInfoWin::ProcessPath(nsCOMPtr<nsIMutableArray>& 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<const char16_t*>(exe));
|
||||
int32_t index = lower.Find(exe);
|
||||
if (index != -1) return;
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -513,9 +513,8 @@ static bool InitLog(const EnvCharType* aEnvVar, const char* aMsg,
|
|||
return true;
|
||||
}
|
||||
if (!XRE_IsParentProcess()) {
|
||||
nsTString<EnvCharType> 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);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,6 @@ UNIFIED_SOURCES += [
|
|||
"nsArrayEnumerator.cpp",
|
||||
"nsArrayUtils.cpp",
|
||||
"nsAtomTable.cpp",
|
||||
"nsCharSeparatedTokenizer.cpp",
|
||||
"nsCOMArray.cpp",
|
||||
"nsCRT.cpp",
|
||||
"nsDeque.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) {
|
||||
|
|
|
@ -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"
|
|
@ -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
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define kNotFound -1
|
||||
|
||||
#include "nsStringFlags.h"
|
||||
#include "nsTStringRepr.h"
|
||||
#include "nsTSubstring.h"
|
||||
|
|
|
@ -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<char>;
|
||||
template class nsTLiteralString<char16_t>;
|
||||
#include "nsTDependentString.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<char>;
|
||||
template class nsTSubstringSplitter<char16_t>;
|
||||
#include "nsTDependentSubstring.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"
|
|
@ -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"
|
|
@ -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> 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<char16_t*>(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<char*>(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);
|
||||
}
|
|
@ -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 <ctype.h>
|
||||
#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;
|
||||
}
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
#include "nscore.h"
|
||||
|
||||
static constexpr int32_t kNotFound = -1;
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
|
|
|
@ -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<char>::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<char16_t>::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 <class CharT>
|
||||
#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 <class CharT>
|
||||
struct nsBufferRoutines {};
|
||||
|
||||
template <>
|
||||
struct nsBufferRoutines<char> {
|
||||
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<char16_t> {
|
||||
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 <class L, class R>
|
||||
#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<L>::compare(big, little, littleLen, ignoreCase) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
template <class L, class R>
|
||||
#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<L>::compare(iter, little, littleLen, ignoreCase) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
template <class CharT, class SetCharT>
|
||||
#ifndef __SUNPRO_CC
|
||||
static
|
||||
#endif /* !__SUNPRO_CC */
|
||||
int32_t
|
||||
FindCharInSet(const CharT* data, uint32_t dataLen, const SetCharT* set) {
|
||||
CharT filter = nsBufferRoutines<CharT>::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 <class CharT, class SetCharT>
|
||||
#ifndef __SUNPRO_CC
|
||||
static
|
||||
#endif /* !__SUNPRO_CC */
|
||||
int32_t
|
||||
RFindCharInSet(const CharT* data, uint32_t dataLen, const SetCharT* set) {
|
||||
CharT filter = nsBufferRoutines<CharT>::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 <typename T>
|
||||
template <typename Q, typename EnableIfChar16>
|
||||
int32_t nsTStringRepr<T>::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<char16_t>::Find(const self_type&, int32_t,
|
||||
int32_t) const;
|
||||
|
||||
template <typename T>
|
||||
template <typename Q, typename EnableIfChar16>
|
||||
int32_t nsTStringRepr<T>::Find(const char_type* aString, int32_t aOffset,
|
||||
int32_t aCount) const {
|
||||
return Find(nsTDependentString<T>(aString), aOffset, aCount);
|
||||
}
|
||||
|
||||
template int32_t nsTStringRepr<char16_t>::Find(const char_type*, int32_t,
|
||||
int32_t) const;
|
||||
|
||||
template <typename T>
|
||||
template <typename Q, typename EnableIfChar16>
|
||||
int32_t nsTStringRepr<T>::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<char16_t>::RFind(const self_type&, int32_t,
|
||||
int32_t) const;
|
||||
|
||||
template <typename T>
|
||||
template <typename Q, typename EnableIfChar16>
|
||||
int32_t nsTStringRepr<T>::RFind(const char_type* aString, int32_t aOffset,
|
||||
int32_t aCount) const {
|
||||
return RFind(nsTDependentString<T>(aString), aOffset, aCount);
|
||||
}
|
||||
|
||||
template int32_t nsTStringRepr<char16_t>::RFind(const char_type*, int32_t,
|
||||
int32_t) const;
|
||||
|
||||
template <typename T>
|
||||
template <typename Q, typename EnableIfChar16>
|
||||
int32_t nsTStringRepr<T>::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<char16_t>::FindCharInSet(const char*,
|
||||
int32_t) const;
|
||||
|
||||
} // namespace mozilla::detail
|
||||
|
||||
template <typename T>
|
||||
template <typename Q, typename EnableIfChar16>
|
||||
void nsTSubstring<T>::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 <typename T>
|
||||
template <typename Q, typename EnableIfChar>
|
||||
int32_t nsTStringRepr<T>::Compare(const char_type* aString, bool aIgnoreCase,
|
||||
size_type aCount) const {
|
||||
size_t strLen = char_traits::length(aString);
|
||||
|
||||
size_t minLen = XPCOM_MIN(this->Length(), strLen);
|
||||
|
||||
// NOTE: As `minLen <= this->Length()` this value must fit in a `uint32_t`.
|
||||
uint32_t compareCount =
|
||||
ReleaseAssertedCast<uint32_t>(XPCOM_MIN(minLen, aCount));
|
||||
|
||||
int32_t result = nsBufferRoutines<T>::compare(this->mData, aString,
|
||||
compareCount, aIgnoreCase);
|
||||
|
||||
if (result == 0 && minLen < aCount && this->Length() != strLen) {
|
||||
// Since the caller didn't give us a length to test, or strings shorter
|
||||
// than aCount, and compareCount characters matched, we have to assume
|
||||
// that the longer string is greater.
|
||||
|
||||
return (this->Length() < strLen) ? -1 : 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template int32_t nsTStringRepr<char>::Compare(const char_type*, bool,
|
||||
size_type) const;
|
||||
|
||||
template <typename T>
|
||||
template <typename Q, typename EnableIfChar16>
|
||||
bool nsTStringRepr<T>::EqualsIgnoreCase(const incompatible_char_type* aString,
|
||||
size_type aCount) const {
|
||||
size_t strLen = nsCharTraits<char>::length(aString);
|
||||
|
||||
size_t minLen = XPCOM_MIN(this->Length(), strLen);
|
||||
|
||||
// NOTE: As `minLen <= this->Length()` this value must fit in a `uint32_t`.
|
||||
uint32_t compareCount =
|
||||
ReleaseAssertedCast<uint32_t>(XPCOM_MIN(minLen, aCount));
|
||||
|
||||
int32_t result =
|
||||
nsBufferRoutines<T>::compare(this->mData, aString, compareCount, true);
|
||||
|
||||
if (result == 0 && minLen < aCount && this->Length() != strLen) {
|
||||
// Since the caller didn't give us a length to test, or strings shorter
|
||||
// than aCount, and compareCount characters matched, we have to assume
|
||||
// that the longer string is greater.
|
||||
return false;
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
template bool nsTStringRepr<char16_t>::EqualsIgnoreCase(
|
||||
const incompatible_char_type*, size_type) const;
|
||||
|
||||
} // namespace mozilla::detail
|
||||
|
||||
/**
|
||||
* nsTString::ToDouble
|
||||
*/
|
||||
template <>
|
||||
double nsTString<char>::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<char16_t>::ToDouble(bool aAllowTrailingChars,
|
||||
nsresult* aErrorCode) const {
|
||||
NS_LossyConvertUTF16toASCII cString(BeginReading(), Length());
|
||||
return aAllowTrailingChars ? cString.ToDoubleAllowTrailingChars(aErrorCode)
|
||||
: cString.ToDouble(aErrorCode);
|
||||
}
|
|
@ -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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include <windows.h>
|
||||
# include <process.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <pthread.h>
|
||||
#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);
|
||||
}
|
|
@ -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<int32_t, mozilla::SequentiallyConsistent>;
|
||||
|
||||
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
|
|
@ -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 <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#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 <windows.h>
|
||||
# include <process.h>
|
||||
# define getpid() _getpid()
|
||||
# define pthread_self() GetCurrentThreadId()
|
||||
#else
|
||||
# include <pthread.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
using mozilla::Atomic;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static const char16_t gNullChar = 0;
|
||||
|
||||
char* const nsCharTraits<char>::sEmptyBuffer =
|
||||
(char*)const_cast<char16_t*>(&gNullChar);
|
||||
char16_t* const nsCharTraits<char16_t>::sEmptyBuffer =
|
||||
const_cast<char16_t*>(&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<int32_t, mozilla::SequentiallyConsistent> 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> 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<const nsAStringAccessor*>(&aStr);
|
||||
|
||||
if (!(accessor->flags() & nsAString::DataFlags::REFCOUNTED)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return FromData(accessor->data());
|
||||
}
|
||||
|
||||
nsStringBuffer* nsStringBuffer::FromString(const nsACString& aStr) {
|
||||
const nsACStringAccessor* accessor =
|
||||
static_cast<const nsACStringAccessor*>(&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<char16_t*>(Data());
|
||||
|
||||
nsAStringAccessor* accessor = static_cast<nsAStringAccessor*>(&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<char*>(Data());
|
||||
|
||||
nsACStringAccessor* accessor = static_cast<nsACStringAccessor*>(&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"
|
|
@ -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 <typename T>
|
||||
nsTDependentString<T>::nsTDependentString(const char_type* aStart,
|
||||
const char_type* aEnd)
|
||||
|
@ -45,6 +43,3 @@ void nsTDependentString<T>::Rebind(const char_type* aStart,
|
|||
MOZ_RELEASE_ASSERT(aStart <= aEnd, "Overflow!");
|
||||
this->Rebind(aStart, aEnd - aStart);
|
||||
}
|
||||
|
||||
template class nsTDependentString<char>;
|
||||
template class nsTDependentString<char16_t>;
|
||||
|
|
|
@ -43,8 +43,6 @@ class nsTDependentString : public nsTString<T> {
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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 <typename T>
|
||||
|
@ -101,6 +99,3 @@ const nsTDependentSubstring<char16_t> Substring(char16ptr_t aStart,
|
|||
static_cast<const char16_t*>(aEnd));
|
||||
}
|
||||
#endif
|
||||
|
||||
template class nsTDependentSubstring<char>;
|
||||
template class nsTDependentSubstring<char16_t>;
|
||||
|
|
|
@ -44,8 +44,6 @@ class nsTDependentSubstring : public nsTSubstring<T> {
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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 <typename T>
|
||||
void nsTPromiseFlatString<T>::Init(const substring_type& str) {
|
||||
if (str.IsTerminated()) {
|
||||
|
@ -21,6 +19,3 @@ void nsTPromiseFlatString<T>::Init(const substring_type& str) {
|
|||
this->Assign(str);
|
||||
}
|
||||
}
|
||||
|
||||
template class nsTPromiseFlatString<char>;
|
||||
template class nsTPromiseFlatString<char16_t>;
|
||||
|
|
|
@ -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 <typename T>
|
||||
bool nsTString<T>::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<char>::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<char16_t>::ToDouble(bool aAllowTrailingChars,
|
||||
nsresult* aErrorCode) const {
|
||||
NS_LossyConvertUTF16toASCII cString(BeginReading(), Length());
|
||||
return aAllowTrailingChars ? cString.ToDoubleAllowTrailingChars(aErrorCode)
|
||||
: cString.ToDouble(aErrorCode);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTString<T>::Rebind(const char_type* data, size_type length) {
|
||||
// If we currently own a buffer, release it.
|
||||
|
@ -67,9 +12,3 @@ void nsTString<T>::Rebind(const char_type* data, size_type length) {
|
|||
this->SetData(const_cast<char_type*>(data), length, DataFlags::TERMINATED);
|
||||
this->AssertValidDependentString();
|
||||
}
|
||||
|
||||
template class nsTString<char>;
|
||||
template class nsTString<char16_t>;
|
||||
|
||||
template class nsTAutoStringN<char, 64>;
|
||||
template class nsTAutoStringN<char16_t, 64>;
|
||||
|
|
|
@ -54,8 +54,6 @@ class nsTString : public nsTSubstring<T> {
|
|||
|
||||
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<T> {
|
|||
|
||||
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.
|
||||
*
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsString.h"
|
||||
#include "plstr.h"
|
||||
|
||||
template <typename T>
|
||||
int NS_FASTCALL Compare(const mozilla::detail::nsTStringRepr<T>& 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;
|
||||
}
|
||||
|
|
|
@ -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 <typename T>
|
||||
int32_t nsTStringRepr<T>::Find(const nsTStringRepr<char>& 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 <typename T>
|
||||
int32_t nsTStringRepr<T>::Find(const char* aString, bool aIgnoreCase,
|
||||
int32_t aOffset, int32_t aCount) const {
|
||||
return Find(nsTDependentString<char>(aString), aIgnoreCase, aOffset, aCount);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int32_t nsTStringRepr<T>::RFind(const nsTStringRepr<char>& 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 <typename T>
|
||||
int32_t nsTStringRepr<T>::RFind(const char* aString, bool aIgnoreCase,
|
||||
int32_t aOffset, int32_t aCount) const {
|
||||
return RFind(nsTDependentString<char>(aString), aIgnoreCase, aOffset, aCount);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int32_t nsTStringRepr<T>::RFindChar(char16_t aChar, int32_t aOffset,
|
||||
int32_t aCount) const {
|
||||
return nsBufferRoutines<T>::rfind_char(this->mData, this->mLength, aOffset,
|
||||
aChar, aCount);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int32_t nsTStringRepr<T>::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 <typename T>
|
||||
int32_t nsTStringRepr<T>::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 T>
|
||||
typename nsTSubstring<T>::size_type nsTSubstring<T>::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 <typename T>
|
||||
bool nsTString<T>::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 <typename T>
|
||||
void nsTSubstring<T>::StripWhitespace() {
|
||||
if (!StripWhitespace(mozilla::fallible)) {
|
||||
this->AllocFailed(this->mLength);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTSubstring<T>::StripWhitespace(const fallible_t&) {
|
||||
if (!this->EnsureMutable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->StripTaggedASCII(mozilla::ASCIIMask::MaskWhitespace());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* nsTSubstring::ReplaceChar,ReplaceSubstring
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::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 <typename T>
|
||||
void nsTSubstring<T>::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<char16_t>::ReplaceChar(const char*, char16_t);
|
||||
|
||||
void ReleaseData(void* aData, nsAString::DataFlags aFlags);
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::ReplaceSubstring(const char_type* aTarget,
|
||||
const char_type* aNewValue) {
|
||||
ReplaceSubstring(nsTDependentString<T>(aTarget),
|
||||
nsTDependentString<T>(aNewValue));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTSubstring<T>::ReplaceSubstring(const char_type* aTarget,
|
||||
const char_type* aNewValue,
|
||||
const fallible_t& aFallible) {
|
||||
return ReplaceSubstring(nsTDependentString<T>(aTarget),
|
||||
nsTDependentString<T>(aNewValue), aFallible);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::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 <typename T>
|
||||
bool nsTSubstring<T>::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<Segment, 16> nonMatching;
|
||||
uint32_t i = 0;
|
||||
mozilla::CheckedUint32 newLength;
|
||||
while (true) {
|
||||
int32_t r = FindSubstring(this->mData + i, this->mLength - i,
|
||||
static_cast<const char_type*>(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 <typename T>
|
||||
void nsTSubstring<T>::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<char>::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 <typename T>
|
||||
void nsTSubstring<T>::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;
|
||||
}
|
|
@ -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 T>
|
||||
typename nsTStringRepr<T>::char_type nsTStringRepr<T>::First() const {
|
||||
MOZ_RELEASE_ASSERT(this->mLength > 0, "|First()| called on an empty string");
|
||||
return this->mData[0];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename nsTStringRepr<T>::char_type nsTStringRepr<T>::Last() const {
|
||||
MOZ_RELEASE_ASSERT(this->mLength > 0, "|Last()| called on an empty string");
|
||||
return this->mData[this->mLength - 1];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::Equals(const self_type& aStr) const {
|
||||
return this->mLength == aStr.mLength &&
|
||||
char_traits::compare(this->mData, aStr.mData, this->mLength) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::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 <typename T>
|
||||
bool nsTStringRepr<T>::Equals(const substring_tuple_type& aTuple) const {
|
||||
return Equals(substring_type(aTuple));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::Equals(const substring_tuple_type& aTuple,
|
||||
comparator_type aComp) const {
|
||||
return Equals(substring_type(aTuple), aComp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::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 <typename T>
|
||||
bool nsTStringRepr<T>::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 <typename T>
|
||||
bool nsTStringRepr<T>::EqualsASCII(const char* aData, size_type aLen) const {
|
||||
return this->mLength == aLen &&
|
||||
char_traits::compareASCII(this->mData, aData, aLen) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::EqualsASCII(const char* aData) const {
|
||||
return char_traits::compareASCIINullTerminated(this->mData, this->mLength,
|
||||
aData) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::EqualsLatin1(const char* aData,
|
||||
const size_type aLength) const {
|
||||
return (this->mLength == aLength) &&
|
||||
char_traits::equalsLatin1(this->mData, aData, aLength);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::LowerCaseEqualsASCII(const char* aData,
|
||||
size_type aLen) const {
|
||||
return this->mLength == aLen &&
|
||||
char_traits::compareLowerCaseToASCII(this->mData, aData, aLen) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::LowerCaseEqualsASCII(const char* aData) const {
|
||||
return char_traits::compareLowerCaseToASCIINullTerminated(
|
||||
this->mData, this->mLength, aData) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int32_t nsTStringRepr<T>::Find(const string_view& aString,
|
||||
index_type aOffset) const {
|
||||
auto idx = View().find(aString, aOffset);
|
||||
return idx == string_view::npos ? kNotFound : idx;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int32_t nsTStringRepr<T>::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 <typename T>
|
||||
int32_t nsTStringRepr<T>::RFind(const string_view& aString) const {
|
||||
auto idx = View().rfind(aString);
|
||||
return idx == string_view::npos ? kNotFound : idx;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename nsTStringRepr<T>::size_type nsTStringRepr<T>::CountChar(
|
||||
char_type aChar) const {
|
||||
return std::count(BeginReading(), EndReading(), aChar);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int32_t nsTStringRepr<T>::FindChar(char_type aChar, index_type aOffset) const {
|
||||
auto idx = View().find(aChar, aOffset);
|
||||
return idx == string_view::npos ? kNotFound : idx;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int32_t nsTStringRepr<T>::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 <typename T>
|
||||
int32_t nsTStringRepr<T>::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 <typename T>
|
||||
int32_t nsTStringRepr<T>::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 <typename T>
|
||||
int32_t nsTStringRepr<T>::Compare(const string_view& aString) const {
|
||||
return View().compare(aString);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::EqualsIgnoreCase(const std::string_view& aString) const {
|
||||
return std::equal(BeginReading(), EndReading(), aString.begin(),
|
||||
aString.end(), [](char_type l, char r) {
|
||||
return char_traits::ASCIIToLower(l) ==
|
||||
char_traits::ASCIIToLower(char_type(r));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mozilla::detail
|
||||
|
||||
template class mozilla::detail::nsTStringRepr<char>;
|
||||
template class mozilla::detail::nsTStringRepr<char16_t>;
|
|
@ -8,7 +8,6 @@
|
|||
#define nsTStringRepr_h
|
||||
|
||||
#include <limits>
|
||||
#include <string_view>
|
||||
#include <type_traits> // 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<char_type> 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<T, int>::type Data() const { return mData; }
|
||||
constexpr const typename raw_type<T, int>::type Data() const { return mData; }
|
||||
|
||||
constexpr size_type Length() const { return static_cast<size_type>(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 <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>>
|
||||
int32_t Compare(
|
||||
const char_type* aString, bool aIgnoreCase = false,
|
||||
size_type aCount = std::numeric_limits<size_type>::max()) const;
|
||||
|
||||
/**
|
||||
* Equality check between given string and this string.
|
||||
*
|
||||
* @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<size_type>::max());
|
||||
return EqualsIgnoreCase(std::string_view(aString, aCount));
|
||||
template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>>
|
||||
bool EqualsIgnoreCase(
|
||||
const char_type* aString,
|
||||
size_type aCount = std::numeric_limits<size_type>::max()) const {
|
||||
return Compare(aString, true, aCount) == 0;
|
||||
}
|
||||
|
||||
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
bool EqualsIgnoreCase(
|
||||
const incompatible_char_type* aString,
|
||||
size_type aCount = std::numeric_limits<size_type>::max()) const;
|
||||
|
||||
#if defined(MOZ_USE_CHAR16_WRAPPER)
|
||||
template <typename Q = T, typename EnableIfChar16 = Char16OnlyT<Q>>
|
||||
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<char>& 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 <typename I,
|
||||
typename = std::enable_if_t<!std::is_same_v<I, index_type> &&
|
||||
std::is_convertible_v<I, index_type>>>
|
||||
int32_t Find(const string_view& aString, I aOffset) const {
|
||||
static_assert(!std::is_same_v<I, bool>, "offset must not be `bool`");
|
||||
return Find(aString, static_cast<index_type>(aOffset));
|
||||
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
int32_t Find(const self_type& aString, int32_t aOffset = 0,
|
||||
int32_t aCount = -1) const;
|
||||
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
int32_t Find(const char_type* aString, int32_t aOffset = 0,
|
||||
int32_t aCount = -1) const;
|
||||
#ifdef MOZ_USE_CHAR16_WRAPPER
|
||||
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
int32_t Find(char16ptr_t aString, int32_t aOffset = 0,
|
||||
int32_t aCount = -1) const {
|
||||
return Find(static_cast<const char16_t*>(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<char>& 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 <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
int32_t RFind(const self_type& aString, int32_t aOffset = -1,
|
||||
int32_t aCount = -1) const;
|
||||
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
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 <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
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
|
||||
|
|
|
@ -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<char>::sEmptyBuffer =
|
||||
(char*)const_cast<char16_t*>(&gNullChar);
|
||||
char16_t* const nsCharTraits<char16_t>::sEmptyBuffer =
|
||||
const_cast<char16_t*>(&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 <typename T>
|
||||
nsTSubstring<T>::nsTSubstring(char_type* aData, size_type aLength,
|
||||
|
@ -123,7 +87,7 @@ auto nsTSubstring<T>::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<T>::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<T>::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<T>::FinishBulkWriteImpl(size_type aLength) {
|
|||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::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<T>::AssignASCII(const char* aData, size_type aLength,
|
|||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AssignLiteral(const char_type* aData, size_type aLength) {
|
||||
ReleaseData(this->mData, this->mDataFlags);
|
||||
::ReleaseData(this->mData, this->mDataFlags);
|
||||
SetData(const_cast<char_type*>(aData), aLength,
|
||||
DataFlags::TERMINATED | DataFlags::LITERAL);
|
||||
}
|
||||
|
@ -507,7 +471,7 @@ bool nsTSubstring<T>::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<T>::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<T>::Assign(const substring_tuple_type& aTuple,
|
|||
template <typename T>
|
||||
void nsTSubstring<T>::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<T>::SetLength(size_type aLength,
|
|||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::Truncate() {
|
||||
ReleaseData(this->mData, this->mDataFlags);
|
||||
::ReleaseData(this->mData, this->mDataFlags);
|
||||
SetToEmptyBuffer();
|
||||
AssertValid();
|
||||
}
|
||||
|
@ -984,6 +948,135 @@ void nsTSubstring<T>::SetIsVoid(bool aVal) {
|
|||
}
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
typename nsTStringRepr<T>::char_type nsTStringRepr<T>::First() const {
|
||||
MOZ_RELEASE_ASSERT(this->mLength > 0, "|First()| called on an empty string");
|
||||
return this->mData[0];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename nsTStringRepr<T>::char_type nsTStringRepr<T>::Last() const {
|
||||
MOZ_RELEASE_ASSERT(this->mLength > 0, "|Last()| called on an empty string");
|
||||
return this->mData[this->mLength - 1];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::Equals(const self_type& aStr) const {
|
||||
return this->mLength == aStr.mLength &&
|
||||
char_traits::compare(this->mData, aStr.mData, this->mLength) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::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 <typename T>
|
||||
bool nsTStringRepr<T>::Equals(const substring_tuple_type& aTuple) const {
|
||||
return Equals(substring_type(aTuple));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::Equals(const substring_tuple_type& aTuple,
|
||||
comparator_type aComp) const {
|
||||
return Equals(substring_type(aTuple), aComp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::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 <typename T>
|
||||
bool nsTStringRepr<T>::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 <typename T>
|
||||
bool nsTStringRepr<T>::EqualsASCII(const char* aData, size_type aLen) const {
|
||||
return this->mLength == aLen &&
|
||||
char_traits::compareASCII(this->mData, aData, aLen) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::EqualsASCII(const char* aData) const {
|
||||
return char_traits::compareASCIINullTerminated(this->mData, this->mLength,
|
||||
aData) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::EqualsLatin1(const char* aData,
|
||||
const size_type aLength) const {
|
||||
return (this->mLength == aLength) &&
|
||||
char_traits::equalsLatin1(this->mData, aData, aLength);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::LowerCaseEqualsASCII(const char* aData,
|
||||
size_type aLen) const {
|
||||
return this->mLength == aLen &&
|
||||
char_traits::compareLowerCaseToASCII(this->mData, aData, aLen) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTStringRepr<T>::LowerCaseEqualsASCII(const char* aData) const {
|
||||
return char_traits::compareLowerCaseToASCIINullTerminated(
|
||||
this->mData, this->mLength, aData) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename nsTStringRepr<T>::size_type nsTStringRepr<T>::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 <typename T>
|
||||
int32_t nsTStringRepr<T>::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 <typename T>
|
||||
bool nsTStringRepr<T>::Contains(char_type aChar) const {
|
||||
return FindChar(aChar) != kNotFound;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::StripChar(char_type aChar) {
|
||||
if (this->mLength == 0) {
|
||||
|
@ -1385,310 +1478,3 @@ int64_t nsTSubstring<T>::ToInteger64(nsresult* aErrorCode,
|
|||
uint32_t aRadix) const {
|
||||
return ToIntegerCommon<T, int64_t>(*this, aErrorCode, aRadix);
|
||||
}
|
||||
|
||||
/**
|
||||
* nsTSubstring::Mid
|
||||
*/
|
||||
template <typename T>
|
||||
typename nsTSubstring<T>::size_type nsTSubstring<T>::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 <typename T>
|
||||
void nsTSubstring<T>::StripWhitespace() {
|
||||
if (!StripWhitespace(mozilla::fallible)) {
|
||||
this->AllocFailed(this->mLength);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTSubstring<T>::StripWhitespace(const fallible_t&) {
|
||||
if (!this->EnsureMutable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->StripTaggedASCII(mozilla::ASCIIMask::MaskWhitespace());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* nsTSubstring::ReplaceChar,ReplaceSubstring
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::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 <typename T>
|
||||
void nsTSubstring<T>::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 <typename T>
|
||||
void nsTSubstring<T>::ReplaceSubstring(const char_type* aTarget,
|
||||
const char_type* aNewValue) {
|
||||
ReplaceSubstring(nsTDependentString<T>(aTarget),
|
||||
nsTDependentString<T>(aNewValue));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool nsTSubstring<T>::ReplaceSubstring(const char_type* aTarget,
|
||||
const char_type* aNewValue,
|
||||
const fallible_t& aFallible) {
|
||||
return ReplaceSubstring(nsTDependentString<T>(aTarget),
|
||||
nsTDependentString<T>(aNewValue), aFallible);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::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 <typename T>
|
||||
bool nsTSubstring<T>::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<Segment, 16> 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 <typename T>
|
||||
void nsTSubstring<T>::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 <typename T>
|
||||
void nsTSubstring<T>::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<char>;
|
||||
template class nsTSubstring<char16_t>;
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
// memory checking. (Limited to avoid quadratic behavior.)
|
||||
const size_t kNsStringBufferMaxPoison = 16;
|
||||
|
||||
class nsStringBuffer;
|
||||
template <typename T>
|
||||
class nsTSubstringSplitter;
|
||||
template <typename T>
|
||||
|
@ -286,7 +285,6 @@ class BulkWriteHandle final {
|
|||
template <typename T>
|
||||
class nsTSubstring : public mozilla::detail::nsTStringRepr<T> {
|
||||
friend class mozilla::BulkWriteHandle<T>;
|
||||
friend class nsStringBuffer;
|
||||
|
||||
public:
|
||||
typedef nsTSubstring<T> self_type;
|
||||
|
@ -312,8 +310,6 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr<T> {
|
|||
|
||||
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<T> {
|
|||
* 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 <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
|
||||
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<T> {
|
|||
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);
|
||||
|
||||
|
|
|
@ -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<char>;
|
||||
template class mozilla::detail::nsTStringRepr<char16_t>;
|
||||
|
||||
template class nsTLiteralString<char>;
|
||||
template class nsTLiteralString<char16_t>;
|
||||
|
||||
template class nsTSubstring<char>;
|
||||
template class nsTSubstring<char16_t>;
|
||||
|
||||
template class nsTDependentSubstring<char>;
|
||||
template class nsTDependentSubstring<char16_t>;
|
||||
|
||||
template class nsTString<char>;
|
||||
template class nsTString<char16_t>;
|
||||
|
||||
template class nsTAutoStringN<char, 64>;
|
||||
template class nsTAutoStringN<char16_t, 64>;
|
||||
|
||||
template class nsTDependentString<char>;
|
||||
template class nsTDependentString<char16_t>;
|
||||
|
||||
template class nsTPromiseFlatString<char>;
|
||||
template class nsTPromiseFlatString<char16_t>;
|
||||
|
||||
template class nsTSubstringSplitter<char>;
|
||||
template class nsTSubstringSplitter<char16_t>;
|
|
@ -613,42 +613,33 @@ TEST_F(Strings, test2) {
|
|||
TEST_F(Strings, find) {
|
||||
nsCString src("<!DOCTYPE blah blah blah>");
|
||||
|
||||
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("<!DOCTYPE blah blah blah>");
|
||||
|
||||
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[] = "<!DOCTYPE blah bLaH bLaH>";
|
||||
const char text[] = "<!DOCTYPE blah blah blah>";
|
||||
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[] = "<!DOCTYPE blah blah blah>";
|
||||
nsCString src(text);
|
||||
int32_t i = src.RFind("TYPE");
|
||||
int32_t i = src.RFind("TYPE", false, 5, -1);
|
||||
EXPECT_EQ(i, 5);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<nsIWindowMediator> mediator(
|
||||
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче