diff options
author | win7-7 <win7-7@users.noreply.github.com> | 2019-07-05 21:58:21 +0300 |
---|---|---|
committer | win7-7 <win7-7@users.noreply.github.com> | 2019-07-05 21:58:21 +0300 |
commit | 7c5a0db237c7a43136ee3cdc6cfb0663778d9e2c (patch) | |
tree | 9cd5a806763b73bed3fef3d599f32b525f4c0d7a /parser/html/nsHtml5String.cpp | |
parent | 0e54a032624b4ce23a959454047bfd504a734cc0 (diff) | |
download | UXP-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.cpp | 226 |
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 |