/* 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 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::compareLowerCaseToASCIINullTerminated( reinterpret_cast(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::compareASCIINullTerminated( reinterpret_cast(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(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 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 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(buffer->Data()); data[0] = 0xFFFD; data[1] = 0; return nsHtml5String(buffer.forget(), 1); } char16_t* data = reinterpret_cast(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 = strlen(aLiteral); /* std:: ?? */ 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 buffer( nsStringBuffer::Alloc((length + 1) * sizeof(char16_t))); if (!buffer) { MOZ_CRASH("Out of memory."); } char16_t* data = reinterpret_cast(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 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(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); }