summaryrefslogtreecommitdiffstats
path: root/parser/html/nsHtml5String.cpp
diff options
context:
space:
mode:
authorwin7-7 <win7-7@users.noreply.github.com>2019-07-05 21:58:21 +0300
committerwin7-7 <win7-7@users.noreply.github.com>2019-07-05 21:58:21 +0300
commit7c5a0db237c7a43136ee3cdc6cfb0663778d9e2c (patch)
tree9cd5a806763b73bed3fef3d599f32b525f4c0d7a /parser/html/nsHtml5String.cpp
parent0e54a032624b4ce23a959454047bfd504a734cc0 (diff)
downloadUXP-7c5a0db237c7a43136ee3cdc6cfb0663778d9e2c.tar
UXP-7c5a0db237c7a43136ee3cdc6cfb0663778d9e2c.tar.gz
UXP-7c5a0db237c7a43136ee3cdc6cfb0663778d9e2c.tar.lz
UXP-7c5a0db237c7a43136ee3cdc6cfb0663778d9e2c.tar.xz
UXP-7c5a0db237c7a43136ee3cdc6cfb0663778d9e2c.zip
Introduce a new non-heap-allocated type for holding nsStringBuffer* in the HTML parser.
An innerHTML setter profile shows about 10% of the time being spent under nsHtml5HtmlAttributes::clear, mostly deleting nsStrings.
Diffstat (limited to 'parser/html/nsHtml5String.cpp')
-rw-r--r--parser/html/nsHtml5String.cpp226
1 files changed, 226 insertions, 0 deletions
diff --git a/parser/html/nsHtml5String.cpp b/parser/html/nsHtml5String.cpp
new file mode 100644
index 000000000..d26eeaede
--- /dev/null
+++ b/parser/html/nsHtml5String.cpp
@@ -0,0 +1,226 @@
+/* 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 "nsHtml5String.h"
+#include "nsCharTraits.h"
+#include "nsUTF8Utils.h"
+#include "nsHtml5TreeBuilder.h"
+
+nsHtml5String::nsHtml5String(already_AddRefed<nsStringBuffer> aBuffer,
+ uint32_t aLength)
+ : mBuffer(aBuffer.take())
+ , mLength(aLength)
+{
+ if (mBuffer) {
+ MOZ_ASSERT(aLength);
+ } else {
+ MOZ_ASSERT(!aLength || aLength == UINT32_MAX);
+ }
+}
+
+void
+nsHtml5String::ToString(nsAString& aString)
+{
+ if (mBuffer) {
+ mBuffer->ToString(mLength, aString);
+ } else {
+ aString.Truncate();
+ if (mLength) {
+ aString.SetIsVoid(true);
+ }
+ }
+}
+
+void
+nsHtml5String::CopyToBuffer(char16_t* aBuffer)
+{
+ if (mBuffer) {
+ memcpy(aBuffer, mBuffer->Data(), mLength * sizeof(char16_t));
+ }
+}
+
+bool
+nsHtml5String::LowerCaseEqualsASCII(const char* aLowerCaseLiteral)
+{
+ if (!mBuffer) {
+ if (mLength) {
+ // This string is null
+ return false;
+ }
+ // this string is empty
+ return !(*aLowerCaseLiteral);
+ }
+ return !nsCharTraits<char16_t>::compareLowerCaseToASCIINullTerminated(
+ reinterpret_cast<char16_t*>(mBuffer->Data()), Length(), aLowerCaseLiteral);
+}
+
+bool
+nsHtml5String::EqualsASCII(const char* aLiteral)
+{
+ if (!mBuffer) {
+ if (mLength) {
+ // This string is null
+ return false;
+ }
+ // this string is empty
+ return !(*aLiteral);
+ }
+ return !nsCharTraits<char16_t>::compareASCIINullTerminated(
+ reinterpret_cast<char16_t*>(mBuffer->Data()), Length(), aLiteral);
+}
+
+bool
+nsHtml5String::LowerCaseStartsWithASCII(const char* aLowerCaseLiteral)
+{
+ if (!mBuffer) {
+ if (mLength) {
+ // This string is null
+ return false;
+ }
+ // this string is empty
+ return !(*aLowerCaseLiteral);
+ }
+ const char* litPtr = aLowerCaseLiteral;
+ const char16_t* strPtr = reinterpret_cast<char16_t*>(mBuffer->Data());
+ const char16_t* end = strPtr + Length();
+ char16_t litChar;
+ while ((litChar = *litPtr) && (strPtr != end)) {
+ MOZ_ASSERT(!(litChar >= 'A' && litChar <= 'Z'),
+ "Literal isn't in lower case.");
+ char16_t strChar = *strPtr;
+ if (strChar >= 'A' && strChar <= 'Z') {
+ strChar += 0x20;
+ }
+ if (litChar != strChar) {
+ return false;
+ }
+ ++litPtr;
+ ++strPtr;
+ }
+ return true;
+}
+
+bool
+nsHtml5String::Equals(nsHtml5String aOther)
+{
+ MOZ_ASSERT(operator bool());
+ MOZ_ASSERT(aOther);
+ if (mLength != aOther.mLength) {
+ return false;
+ }
+ if (!mBuffer) {
+ return true;
+ }
+ MOZ_ASSERT(aOther.mBuffer);
+ return !memcmp(
+ mBuffer->Data(), aOther.mBuffer->Data(), Length() * sizeof(char16_t));
+}
+
+nsHtml5String
+nsHtml5String::Clone()
+{
+ MOZ_ASSERT(operator bool());
+ RefPtr<nsStringBuffer> ref(mBuffer);
+ return nsHtml5String(ref.forget(), mLength);
+}
+
+void
+nsHtml5String::Release()
+{
+ if (mBuffer) {
+ mBuffer->Release();
+ mBuffer = nullptr;
+ }
+ mLength = UINT32_MAX;
+}
+
+// static
+nsHtml5String
+nsHtml5String::FromBuffer(char16_t* aBuffer,
+ int32_t aLength,
+ nsHtml5TreeBuilder* aTreeBuilder)
+{
+ if (!aLength) {
+ return nsHtml5String(nullptr, 0U);
+ }
+ // Work with nsStringBuffer directly to make sure that storage is actually
+ // nsStringBuffer and to make sure the allocation strategy matches
+ // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
+ // copy.
+ RefPtr<nsStringBuffer> buffer(
+ nsStringBuffer::Alloc((aLength + 1) * sizeof(char16_t)));
+ if (!buffer) {
+ if (!aTreeBuilder) {
+ MOZ_CRASH("Out of memory.");
+ }
+ aTreeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ buffer = nsStringBuffer::Alloc(2 * sizeof(char16_t));
+ if (!buffer) {
+ MOZ_CRASH(
+ "Out of memory so badly that couldn't even allocate placeholder.");
+ }
+ char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
+ data[0] = 0xFFFD;
+ data[1] = 0;
+ return nsHtml5String(buffer.forget(), 1);
+ }
+ char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
+ memcpy(data, aBuffer, aLength * sizeof(char16_t));
+ data[aLength] = 0;
+ return nsHtml5String(buffer.forget(), aLength);
+}
+
+// static
+nsHtml5String
+nsHtml5String::FromLiteral(const char* aLiteral)
+{
+ size_t length = std::strlen(aLiteral);
+ if (!length) {
+ return nsHtml5String(nullptr, 0U);
+ }
+ // Work with nsStringBuffer directly to make sure that storage is actually
+ // nsStringBuffer and to make sure the allocation strategy matches
+ // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
+ // copy.
+ RefPtr<nsStringBuffer> buffer(
+ nsStringBuffer::Alloc((length + 1) * sizeof(char16_t)));
+ if (!buffer) {
+ MOZ_CRASH("Out of memory.");
+ }
+ char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
+ LossyConvertEncoding8to16 converter(data);
+ converter.write(aLiteral, length);
+ data[length] = 0;
+ return nsHtml5String(buffer.forget(), length);
+}
+
+// static
+nsHtml5String
+nsHtml5String::FromString(const nsAString& aString)
+{
+ auto length = aString.Length();
+ if (!length) {
+ return nsHtml5String(nullptr, 0U);
+ }
+ RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aString);
+ if (buffer) {
+ return nsHtml5String(buffer.forget(), length);
+ }
+ buffer = nsStringBuffer::Alloc((length + 1) * sizeof(char16_t));
+ if (!buffer) {
+ MOZ_CRASH("Out of memory.");
+ }
+ char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
+ memcpy(data, aString.BeginReading(), length * sizeof(char16_t));
+ data[length] = 0;
+ return nsHtml5String(buffer.forget(), length);
+}
+
+// static
+nsHtml5String
+nsHtml5String::EmptyString()
+{
+ return nsHtml5String(nullptr, 0U);
+
+} \ No newline at end of file