diff options
Diffstat (limited to 'parser/html/nsHtml5String.cpp')
-rw-r--r-- | parser/html/nsHtml5String.cpp | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/parser/html/nsHtml5String.cpp b/parser/html/nsHtml5String.cpp new file mode 100644 index 0000000000..5f30869cbb --- /dev/null +++ b/parser/html/nsHtml5String.cpp @@ -0,0 +1,188 @@ +/* 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 "nsHtml5TreeBuilder.h" +#include "nsUTF8Utils.h" + +void nsHtml5String::ToString(nsAString& aString) { + switch (GetKind()) { + case eStringBuffer: + return AsStringBuffer()->ToString(Length(), aString); + case eAtom: + return AsAtom()->ToString(aString); + case eEmpty: + aString.Truncate(); + return; + default: + aString.Truncate(); + aString.SetIsVoid(true); + return; + } +} + +void nsHtml5String::CopyToBuffer(char16_t* aBuffer) const { + memcpy(aBuffer, AsPtr(), Length() * sizeof(char16_t)); +} + +bool nsHtml5String::LowerCaseEqualsASCII(const char* aLowerCaseLiteral) const { + return !nsCharTraits<char16_t>::compareLowerCaseToASCIINullTerminated( + AsPtr(), Length(), aLowerCaseLiteral); +} + +bool nsHtml5String::EqualsASCII(const char* aLiteral) const { + return !nsCharTraits<char16_t>::compareASCIINullTerminated(AsPtr(), Length(), + aLiteral); +} + +bool nsHtml5String::LowerCaseStartsWithASCII( + const char* aLowerCaseLiteral) const { + const char* litPtr = aLowerCaseLiteral; + const char16_t* strPtr = AsPtr(); + const char16_t* end = strPtr + Length(); + char16_t litChar; + while ((litChar = *litPtr)) { + MOZ_ASSERT(!(litChar >= 'A' && litChar <= 'Z'), + "Literal isn't in lower case."); + if (strPtr == end) { + return false; + } + 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) const { + MOZ_ASSERT(operator bool()); + MOZ_ASSERT(aOther); + if (Length() != aOther.Length()) { + return false; + } + return !memcmp(AsPtr(), aOther.AsPtr(), Length() * sizeof(char16_t)); +} + +nsHtml5String nsHtml5String::Clone() { + switch (GetKind()) { + case eStringBuffer: + AsStringBuffer()->AddRef(); + break; + case eAtom: + AsAtom()->AddRef(); + break; + default: + break; + } + return nsHtml5String(mBits); +} + +void nsHtml5String::Release() { + switch (GetKind()) { + case eStringBuffer: + AsStringBuffer()->Release(); + break; + case eAtom: + AsAtom()->Release(); + break; + default: + break; + } + mBits = eNull; +} + +// static +nsHtml5String nsHtml5String::FromBuffer(char16_t* aBuffer, int32_t aLength, + nsHtml5TreeBuilder* aTreeBuilder) { + if (!aLength) { + return nsHtml5String(eEmpty); + } + // 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(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); + } + char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); + memcpy(data, aBuffer, aLength * sizeof(char16_t)); + data[aLength] = 0; + return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); +} + +// static +nsHtml5String nsHtml5String::FromLiteral(const char* aLiteral) { + size_t length = std::strlen(aLiteral); + if (!length) { + return nsHtml5String(eEmpty); + } + // 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()); + ConvertAsciitoUtf16(mozilla::Span(aLiteral, length), + mozilla::Span(data, length)); + data[length] = 0; + return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); +} + +// static +nsHtml5String nsHtml5String::FromString(const nsAString& aString) { + auto length = aString.Length(); + if (!length) { + return nsHtml5String(eEmpty); + } + RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aString); + if (buffer && (length == buffer->StorageSize() / sizeof(char16_t) - 1)) { + return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); + } + 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(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); +} + +// static +nsHtml5String nsHtml5String::FromAtom(already_AddRefed<nsAtom> aAtom) { + return nsHtml5String(reinterpret_cast<uintptr_t>(aAtom.take()) | eAtom); +} + +// static +nsHtml5String nsHtml5String::EmptyString() { return nsHtml5String(eEmpty); } |