Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / parser / html / nsHtml5String.cpp
blobbc01ff3444164d2270adc39b307d0e3c42d694b6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsHtml5String.h"
6 #include "nsCharTraits.h"
7 #include "nsHtml5TreeBuilder.h"
8 #include "mozilla/StringBuffer.h"
10 using mozilla::StringBuffer;
12 void nsHtml5String::ToString(nsAString& aString) {
13 switch (GetKind()) {
14 case eStringBuffer:
15 return aString.Assign(AsStringBuffer(), Length());
16 case eAtom:
17 return AsAtom()->ToString(aString);
18 case eEmpty:
19 aString.Truncate();
20 return;
21 default:
22 aString.Truncate();
23 aString.SetIsVoid(true);
24 return;
28 void nsHtml5String::CopyToBuffer(char16_t* aBuffer) const {
29 memcpy(aBuffer, AsPtr(), Length() * sizeof(char16_t));
32 bool nsHtml5String::LowerCaseEqualsASCII(const char* aLowerCaseLiteral) const {
33 return !nsCharTraits<char16_t>::compareLowerCaseToASCIINullTerminated(
34 AsPtr(), Length(), aLowerCaseLiteral);
37 bool nsHtml5String::EqualsASCII(const char* aLiteral) const {
38 return !nsCharTraits<char16_t>::compareASCIINullTerminated(AsPtr(), Length(),
39 aLiteral);
42 bool nsHtml5String::LowerCaseStartsWithASCII(
43 const char* aLowerCaseLiteral) const {
44 const char* litPtr = aLowerCaseLiteral;
45 const char16_t* strPtr = AsPtr();
46 const char16_t* end = strPtr + Length();
47 char16_t litChar;
48 while ((litChar = *litPtr)) {
49 MOZ_ASSERT(!(litChar >= 'A' && litChar <= 'Z'),
50 "Literal isn't in lower case.");
51 if (strPtr == end) {
52 return false;
54 char16_t strChar = *strPtr;
55 if (strChar >= 'A' && strChar <= 'Z') {
56 strChar += 0x20;
58 if (litChar != strChar) {
59 return false;
61 ++litPtr;
62 ++strPtr;
64 return true;
67 bool nsHtml5String::Equals(nsHtml5String aOther) const {
68 MOZ_ASSERT(operator bool());
69 MOZ_ASSERT(aOther);
70 if (Length() != aOther.Length()) {
71 return false;
73 return !memcmp(AsPtr(), aOther.AsPtr(), Length() * sizeof(char16_t));
76 nsHtml5String nsHtml5String::Clone() {
77 switch (GetKind()) {
78 case eStringBuffer:
79 AsStringBuffer()->AddRef();
80 break;
81 case eAtom:
82 AsAtom()->AddRef();
83 break;
84 default:
85 break;
87 return nsHtml5String(mBits);
90 void nsHtml5String::Release() {
91 switch (GetKind()) {
92 case eStringBuffer:
93 AsStringBuffer()->Release();
94 break;
95 case eAtom:
96 AsAtom()->Release();
97 break;
98 default:
99 break;
101 mBits = eNull;
104 // static
105 nsHtml5String nsHtml5String::FromBuffer(char16_t* aBuffer, int32_t aLength,
106 nsHtml5TreeBuilder* aTreeBuilder) {
107 if (!aLength) {
108 return nsHtml5String(eEmpty);
110 // Work with StringBuffer directly to make sure that storage is actually
111 // StringBuffer and to make sure the allocation strategy matches
112 // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
113 // copy.
114 RefPtr<StringBuffer> buffer = StringBuffer::Create(aBuffer, aLength);
115 if (MOZ_UNLIKELY(!buffer)) {
116 if (!aTreeBuilder) {
117 MOZ_CRASH("Out of memory.");
119 aTreeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
120 buffer = StringBuffer::Alloc(2 * sizeof(char16_t));
121 if (!buffer) {
122 MOZ_CRASH(
123 "Out of memory so badly that couldn't even allocate placeholder.");
125 char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
126 data[0] = 0xFFFD;
127 data[1] = 0;
129 return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) |
130 eStringBuffer);
133 // static
134 nsHtml5String nsHtml5String::FromLiteral(const char* aLiteral) {
135 size_t length = std::strlen(aLiteral);
136 if (!length) {
137 return nsHtml5String(eEmpty);
139 // Work with StringBuffer directly to make sure that storage is actually
140 // StringBuffer and to make sure the allocation strategy matches
141 // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
142 // copy.
143 RefPtr<StringBuffer> buffer(
144 StringBuffer::Alloc((length + 1) * sizeof(char16_t)));
145 if (!buffer) {
146 MOZ_CRASH("Out of memory.");
148 char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
149 ConvertAsciitoUtf16(mozilla::Span(aLiteral, length),
150 mozilla::Span(data, length));
151 data[length] = 0;
152 return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) |
153 eStringBuffer);
156 // static
157 nsHtml5String nsHtml5String::FromString(const nsAString& aString) {
158 auto length = aString.Length();
159 if (!length) {
160 return nsHtml5String(eEmpty);
162 if (StringBuffer* buffer = aString.GetStringBuffer()) {
163 if (length == buffer->StorageSize() / sizeof(char16_t) - 1) {
164 buffer->AddRef();
165 return nsHtml5String(reinterpret_cast<uintptr_t>(buffer) | eStringBuffer);
168 RefPtr<StringBuffer> buffer =
169 StringBuffer::Alloc((length + 1) * sizeof(char16_t));
170 if (!buffer) {
171 MOZ_CRASH("Out of memory.");
173 char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
174 memcpy(data, aString.BeginReading(), length * sizeof(char16_t));
175 data[length] = 0;
176 return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) |
177 eStringBuffer);
180 // static
181 nsHtml5String nsHtml5String::FromAtom(already_AddRefed<nsAtom> aAtom) {
182 return nsHtml5String(reinterpret_cast<uintptr_t>(aAtom.take()) | eAtom);
185 // static
186 nsHtml5String nsHtml5String::EmptyString() { return nsHtml5String(eEmpty); }