Bug 1358297: Part 3. Create special case for stripping CR and LF on TSubstring, and use it in all the places that it is called. Use ASCIIMask to make it fast. r=froydnj

MozReview-Commit-ID: 5ugh3Ma0OtH

--HG--
extra : rebase_source : 956a7a0535c3b7433fadfa65d0cfc26d9915f61a
This commit is contained in:
Milan Sreckovic 2017-05-10 13:12:36 -04:00
parent 40b6fdfb4b
commit 725d1c193f
12 changed files with 184 additions and 24 deletions

View File

@ -167,7 +167,7 @@ nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI,
nsAutoCString uriString(aStringURI); nsAutoCString uriString(aStringURI);
// Eliminate embedded newlines, which single-line text fields now allow: // Eliminate embedded newlines, which single-line text fields now allow:
uriString.StripChars("\r\n"); uriString.StripCRLF();
// Cleanup the empty spaces that might be on each end: // Cleanup the empty spaces that might be on each end:
uriString.Trim(" "); uriString.Trim(" ");

View File

@ -4780,7 +4780,7 @@ nsDocShell::LoadURIWithOptions(const char16_t* aURI,
// Cleanup the empty spaces that might be on each end. // Cleanup the empty spaces that might be on each end.
uriString.Trim(" "); uriString.Trim(" ");
// Eliminate embedded newlines, which single-line text fields now allow: // Eliminate embedded newlines, which single-line text fields now allow:
uriString.StripChars("\r\n"); uriString.StripCRLF();
NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE); NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
rv = NS_NewURI(getter_AddRefs(uri), uriString); rv = NS_NewURI(getter_AddRefs(uri), uriString);

View File

@ -6723,9 +6723,7 @@ nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow)
void nsContentUtils::RemoveNewlines(nsString &aString) void nsContentUtils::RemoveNewlines(nsString &aString)
{ {
// strip CR/LF and null aString.StripCRLF();
static const char badChars[] = {'\r', '\n', 0};
aString.StripChars(badChars);
} }
void void

View File

@ -9,6 +9,7 @@
#include "nsFrameMessageManager.h" #include "nsFrameMessageManager.h"
#include "ContentChild.h" #include "ContentChild.h"
#include "nsASCIIMask.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsDOMClassInfoID.h" #include "nsDOMClassInfoID.h"
#include "nsError.h" #include "nsError.h"
@ -586,7 +587,7 @@ AllowMessage(size_t aDataLength, const nsAString& aMessageName)
} }
NS_ConvertUTF16toUTF8 messageName(aMessageName); NS_ConvertUTF16toUTF8 messageName(aMessageName);
messageName.StripChars("0123456789"); messageName.StripTaggedASCII(ASCIIMask::Mask0to9());
Telemetry::Accumulate(Telemetry::REJECTED_MESSAGE_MANAGER_MESSAGE, Telemetry::Accumulate(Telemetry::REJECTED_MESSAGE_MANAGER_MESSAGE,
messageName); messageName);
@ -661,7 +662,7 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
// NOTE: We need to strip digit characters from the message name in order to // NOTE: We need to strip digit characters from the message name in order to
// avoid a large number of buckets due to generated names from addons (such // avoid a large number of buckets due to generated names from addons (such
// as "ublock:sb:{N}"). See bug 1348113 comment 10. // as "ublock:sb:{N}"). See bug 1348113 comment 10.
messageName.StripChars("0123456789"); messageName.StripTaggedASCII(ASCIIMask::Mask0to9());
Telemetry::Accumulate(Telemetry::IPC_SYNC_MESSAGE_MANAGER_LATENCY_MS, Telemetry::Accumulate(Telemetry::IPC_SYNC_MESSAGE_MANAGER_LATENCY_MS,
messageName, latencyMs); messageName, latencyMs);
} }

View File

@ -5327,15 +5327,13 @@ HTMLInputElement::SanitizeValue(nsAString& aValue)
case NS_FORM_INPUT_TEL: case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_PASSWORD: case NS_FORM_INPUT_PASSWORD:
{ {
char16_t crlf[] = { char16_t('\r'), char16_t('\n'), 0 }; aValue.StripCRLF();
aValue.StripChars(crlf);
} }
break; break;
case NS_FORM_INPUT_EMAIL: case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL: case NS_FORM_INPUT_URL:
{ {
char16_t crlf[] = { char16_t('\r'), char16_t('\n'), 0 }; aValue.StripCRLF();
aValue.StripChars(crlf);
aValue = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aValue); aValue = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aValue);
} }

View File

@ -533,7 +533,7 @@ TextEditRules::HandleNewLines(nsString& aString,
aString.ReplaceChar(CRLF, ' '); aString.ReplaceChar(CRLF, ' ');
break; break;
case nsIPlaintextEditor::eNewlinesStrip: case nsIPlaintextEditor::eNewlinesStrip:
aString.StripChars(CRLF); aString.StripCRLF();
break; break;
case nsIPlaintextEditor::eNewlinesPasteToFirst: case nsIPlaintextEditor::eNewlinesPasteToFirst:
default: { default: {

View File

@ -9,6 +9,7 @@
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include "nsASCIIMask.h"
#include "nsURLHelper.h" #include "nsURLHelper.h"
#include "nsIFile.h" #include "nsIFile.h"
#include "nsIURLParser.h" #include "nsIURLParser.h"
@ -522,7 +523,7 @@ net_ExtractURLScheme(const nsACString &inURI,
} }
p.Claim(scheme); p.Claim(scheme);
scheme.StripChars("\r\n\t"); scheme.StripTaggedASCII(ASCIIMask::MaskCRLFTab());
return NS_OK; return NS_OK;
} }
@ -591,8 +592,6 @@ net_IsAbsoluteURL(const nsACString& uri)
void void
net_FilterURIString(const nsACString& input, nsACString& result) net_FilterURIString(const nsACString& input, nsACString& result)
{ {
const char kCharsToStrip[] = "\r\n\t";
result.Truncate(); result.Truncate();
auto start = input.BeginReading(); auto start = input.BeginReading();
@ -607,9 +606,14 @@ net_FilterURIString(const nsACString& input, nsACString& result)
charFilter).base(); charFilter).base();
// Check if chars need to be stripped. // Check if chars need to be stripped.
auto itr = std::find_first_of( bool needsStrip = false;
newStart, newEnd, std::begin(kCharsToStrip), std::end(kCharsToStrip)); const ASCIIMaskArray& mask = ASCIIMask::MaskCRLFTab();
const bool needsStrip = itr != newEnd; for (auto itr = start; itr != end; ++itr) {
if (ASCIIMask::IsMasked(mask, *itr)) {
needsStrip = true;
break;
}
}
// Just use the passed in string rather than creating new copies if no // Just use the passed in string rather than creating new copies if no
// changes are necessary. // changes are necessary.
@ -620,7 +624,7 @@ net_FilterURIString(const nsACString& input, nsACString& result)
result.Assign(Substring(newStart, newEnd)); result.Assign(Substring(newStart, newEnd));
if (needsStrip) { if (needsStrip) {
result.StripChars(kCharsToStrip); result.StripTaggedASCII(mask);
} }
} }

View File

@ -518,7 +518,7 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
// if the parameter spans across multiple lines we have to strip out the // if the parameter spans across multiple lines we have to strip out the
// line continuation -- jht 4/29/98 // line continuation -- jht 4/29/98
nsAutoCString tempStr(valueStart, valueEnd - valueStart); nsAutoCString tempStr(valueStart, valueEnd - valueStart);
tempStr.StripChars("\r\n"); tempStr.StripCRLF();
char *res = ToNewCString(tempStr); char *res = ToNewCString(tempStr);
NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY);
@ -761,7 +761,7 @@ internalDecodeRFC2047Header(const char* aHeaderVal, const char* aDefaultCharset,
nsAutoCString temp(aResult); nsAutoCString temp(aResult);
temp.ReplaceSubstring("\n\t", " "); temp.ReplaceSubstring("\n\t", " ");
temp.ReplaceSubstring("\r\t", " "); temp.ReplaceSubstring("\r\t", " ");
temp.StripChars("\r\n"); temp.StripCRLF();
aResult = temp; aResult = temp;
} }

View File

@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsASCIIMask.h"
#include "mozilla/CheckedInt.h" #include "mozilla/CheckedInt.h"
#include "mozilla/double-conversion.h" #include "mozilla/double-conversion.h"
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
@ -881,7 +882,8 @@ nsTStringRepr_CharT::FindChar(char_type aChar, index_type aOffset) const
void void
nsTSubstring_CharT::StripChar(char_type aChar, int32_t aOffset) nsTSubstring_CharT::StripChar(char_type aChar, int32_t aOffset)
{ {
if (mLength == 0 || aOffset >= int32_t(mLength)) { // Note that this implicitly guarantees mLength > 0
if (aOffset >= int32_t(mLength)) {
return; return;
} }
@ -908,6 +910,7 @@ nsTSubstring_CharT::StripChar(char_type aChar, int32_t aOffset)
void void
nsTSubstring_CharT::StripChars(const char_type* aChars, uint32_t aOffset) nsTSubstring_CharT::StripChars(const char_type* aChars, uint32_t aOffset)
{ {
// Note that this implicitly guarantees mLength > 0
if (aOffset >= uint32_t(mLength)) { if (aOffset >= uint32_t(mLength)) {
return; return;
} }
@ -937,6 +940,45 @@ nsTSubstring_CharT::StripChars(const char_type* aChars, uint32_t aOffset)
mLength = to - mData; mLength = to - mData;
} }
void
nsTSubstring_CharT::StripTaggedASCII(const ASCIIMaskArray& aToStrip,
uint32_t aOffset)
{
// Note that this implicitly guarantees mLength > 0
if (aOffset >= uint32_t(mLength)) {
return;
}
if (!EnsureMutable()) {
AllocFailed(mLength);
}
char_type* to = mData + aOffset;
char_type* from = mData + aOffset;
char_type* end = mData + mLength;
while (from < end) {
uint32_t theChar = (uint32_t)*from++;
// Replacing this with a call to ASCIIMask::IsMasked
// regresses performance somewhat, so leaving it inlined.
if (!mozilla::ASCIIMask::IsMasked(aToStrip, theChar)) {
// Not stripped, copy this char.
*to++ = (char_type)theChar;
}
}
*to = char_type(0); // add the null
mLength = to - mData;
}
void
nsTSubstring_CharT::StripCRLF(uint32_t aOffset)
{
// Expanding this call to copy the code from StripTaggedASCII
// instead of just calling it does somewhat help with performance
// but it is not worth it given the duplicated code.
StripTaggedASCII(mozilla::ASCIIMask::MaskCRLF(), aOffset);
}
struct MOZ_STACK_CLASS PrintfAppend_CharT : public mozilla::PrintfTarget struct MOZ_STACK_CLASS PrintfAppend_CharT : public mozilla::PrintfTarget
{ {
explicit PrintfAppend_CharT(nsTSubstring_CharT* aString) explicit PrintfAppend_CharT(nsTSubstring_CharT* aString)

View File

@ -1014,6 +1014,31 @@ public:
void StripChars(const char_type* aChars, uint32_t aOffset = 0); void StripChars(const char_type* aChars, uint32_t aOffset = 0);
/**
* This method is used to remove all occurrences of some characters this
* from this string. The characters removed have the corresponding
* entries in the bool array set to true; we retain all characters
* with code beyond 127.
* THE CALLER IS RESPONSIBLE for making sure the complete boolean
* array, 128 entries, is properly initialized.
*
* See also: ASCIIMask class.
*
* @param aToStrip -- Array where each entry is true if the
* corresponding ASCII character is to be stripped. All
* characters beyond code 127 are retained. Note that this
* parameter is of ASCIIMaskArray type, but we expand the typedef
* to avoid having to include nsASCIIMask.h in this include file
* as it brings other includes.
* @param aOffset -- where in this string to start stripping chars
*/
void StripTaggedASCII(const std::array<bool, 128>& aToStrip, uint32_t aOffset = 0);
/**
* A shortcut to strip \r and \n.
*/
void StripCRLF(uint32_t aOffset = 0);
/** /**
* If the string uses a shared buffer, this method * If the string uses a shared buffer, this method
* clears the pointer without releasing the buffer. * clears the pointer without releasing the buffer.

View File

@ -1135,7 +1135,6 @@ TEST(Strings,ASCIIMask)
EXPECT_FALSE(mozilla::ASCIIMask::IsMasked(maskCRLF, 14324)); EXPECT_FALSE(mozilla::ASCIIMask::IsMasked(maskCRLF, 14324));
} }
template <typename T> void template <typename T> void
CompressWhitespaceHelper() CompressWhitespaceHelper()
{ {
@ -1225,6 +1224,67 @@ TEST(Strings, CompressWhitespaceW)
EXPECT_TRUE(str == result); EXPECT_TRUE(str == result);
} }
template <typename T> void
StripCRLFHelper()
{
T s;
s.AssignLiteral("abcabcabc");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral("abcabcabc"));
s.AssignLiteral(" \n\rabcabcabc\r\n");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(" abcabcabc"));
s.AssignLiteral(" \n\rabc abc abc\r\n");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(" abc abc abc"));
s.AssignLiteral(" \n\rabc\r abc\n abc\r\n");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(" abc abc abc"));
s.AssignLiteral(" \n\rabc\r \nabc\n \rabc\r\n");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(" abc abc abc"));
s.AssignLiteral(" \n\rabc\r abc\n abc\r\n");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(" abc abc abc"));
s.AssignLiteral(" \r\n ");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(" "));
s.AssignLiteral(" \r\n \t");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(" \t"));
s.AssignLiteral("\n \r\n \t");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(" \t"));
s.AssignLiteral("");
s.StripCRLF();
EXPECT_TRUE(s.EqualsLiteral(""));
}
TEST(Strings, StripCRLF)
{
StripCRLFHelper<nsCString>();
}
TEST(Strings, StripCRLFW)
{
StripCRLFHelper<nsString>();
nsString str, result;
str.AssignLiteral(u"\u263A is\r\n ;-)");
result.AssignLiteral(u"\u263A is ;-)");
str.StripCRLF();
EXPECT_TRUE(str == result);
}
#define TestExample1 "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,\n totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi\r architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur\n aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui\r\n\r dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?" #define TestExample1 "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,\n totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi\r architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur\n aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui\r\n\r dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
#define TestExample2 "At vero eos et accusamus et iusto odio dignissimos ducimus\n\n qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt\r\r \n mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat." #define TestExample2 "At vero eos et accusamus et iusto odio dignissimos ducimus\n\n qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt\r\r \n mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."
@ -1283,4 +1343,36 @@ MOZ_GTEST_BENCH(Strings, PerfCompressWhitespace, [] {
} }
}); });
MOZ_GTEST_BENCH(Strings, PerfStripCRLF, [] {
nsCString test1(TestExample1);
nsCString test2(TestExample2);
nsCString test3(TestExample3);
nsCString test4(TestExample4);
nsCString test5(TestExample5);
for (int i = 0; i < 20000; i++) {
test1.StripCRLF();
test2.StripCRLF();
test3.StripCRLF();
test4.StripCRLF();
test5.StripCRLF();
}
});
MOZ_GTEST_BENCH(Strings, PerfStripCharsCRLF, [] {
// This is the unoptimized (original) version of
// stripping \r\n using StripChars.
nsCString test1(TestExample1);
nsCString test2(TestExample2);
nsCString test3(TestExample3);
nsCString test4(TestExample4);
nsCString test5(TestExample5);
for (int i = 0; i < 20000; i++) {
test1.StripChars("\r\n");
test2.StripChars("\r\n");
test3.StripChars("\r\n");
test4.StripChars("\r\n");
test5.StripChars("\r\n");
}
});
} // namespace TestStrings } // namespace TestStrings

View File

@ -915,7 +915,7 @@ NS_IMETHODIMP nsXULWindow::SetTitle(const char16_t* aTitle)
{ {
NS_ENSURE_STATE(mWindow); NS_ENSURE_STATE(mWindow);
mTitle.Assign(aTitle); mTitle.Assign(aTitle);
mTitle.StripChars("\n\r"); mTitle.StripCRLF();
NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE);
// Tell the window mediator that a title has changed // Tell the window mediator that a title has changed