/src/mozilla-central/parser/html/nsHtml5String.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
4 | | |
5 | | #include "nsHtml5String.h" |
6 | | #include "nsCharTraits.h" |
7 | | #include "nsHtml5TreeBuilder.h" |
8 | | #include "nsUTF8Utils.h" |
9 | | |
10 | | void |
11 | | nsHtml5String::ToString(nsAString& aString) |
12 | | { |
13 | | switch (GetKind()) { |
14 | | case eStringBuffer: |
15 | | return AsStringBuffer()->ToString(Length(), aString); |
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; |
25 | | } |
26 | | } |
27 | | |
28 | | void |
29 | | nsHtml5String::CopyToBuffer(char16_t* aBuffer) const |
30 | 0 | { |
31 | 0 | memcpy(aBuffer, AsPtr(), Length() * sizeof(char16_t)); |
32 | 0 | } |
33 | | |
34 | | bool |
35 | | nsHtml5String::LowerCaseEqualsASCII(const char* aLowerCaseLiteral) const |
36 | 0 | { |
37 | 0 | return !nsCharTraits<char16_t>::compareLowerCaseToASCIINullTerminated( |
38 | 0 | AsPtr(), Length(), aLowerCaseLiteral); |
39 | 0 | } |
40 | | |
41 | | bool |
42 | | nsHtml5String::EqualsASCII(const char* aLiteral) const |
43 | 0 | { |
44 | 0 | return !nsCharTraits<char16_t>::compareASCIINullTerminated( |
45 | 0 | AsPtr(), Length(), aLiteral); |
46 | 0 | } |
47 | | |
48 | | bool |
49 | | nsHtml5String::LowerCaseStartsWithASCII(const char* aLowerCaseLiteral) const |
50 | 0 | { |
51 | 0 | const char* litPtr = aLowerCaseLiteral; |
52 | 0 | const char16_t* strPtr = AsPtr(); |
53 | 0 | const char16_t* end = strPtr + Length(); |
54 | 0 | char16_t litChar; |
55 | 0 | while ((litChar = *litPtr)) { |
56 | 0 | MOZ_ASSERT(!(litChar >= 'A' && litChar <= 'Z'), |
57 | 0 | "Literal isn't in lower case."); |
58 | 0 | if (strPtr == end) { |
59 | 0 | return false; |
60 | 0 | } |
61 | 0 | char16_t strChar = *strPtr; |
62 | 0 | if (strChar >= 'A' && strChar <= 'Z') { |
63 | 0 | strChar += 0x20; |
64 | 0 | } |
65 | 0 | if (litChar != strChar) { |
66 | 0 | return false; |
67 | 0 | } |
68 | 0 | ++litPtr; |
69 | 0 | ++strPtr; |
70 | 0 | } |
71 | 0 | return true; |
72 | 0 | } |
73 | | |
74 | | bool |
75 | | nsHtml5String::Equals(nsHtml5String aOther) const |
76 | 0 | { |
77 | 0 | MOZ_ASSERT(operator bool()); |
78 | 0 | MOZ_ASSERT(aOther); |
79 | 0 | if (Length() != aOther.Length()) { |
80 | 0 | return false; |
81 | 0 | } |
82 | 0 | return !memcmp(AsPtr(), aOther.AsPtr(), Length() * sizeof(char16_t)); |
83 | 0 | } |
84 | | |
85 | | nsHtml5String |
86 | | nsHtml5String::Clone() |
87 | 0 | { |
88 | 0 | switch (GetKind()) { |
89 | 0 | case eStringBuffer: |
90 | 0 | AsStringBuffer()->AddRef(); |
91 | 0 | break; |
92 | 0 | case eAtom: |
93 | 0 | AsAtom()->AddRef(); |
94 | 0 | break; |
95 | 0 | default: |
96 | 0 | break; |
97 | 0 | } |
98 | 0 | return nsHtml5String(mBits); |
99 | 0 | } |
100 | | |
101 | | void |
102 | | nsHtml5String::Release() |
103 | 0 | { |
104 | 0 | switch (GetKind()) { |
105 | 0 | case eStringBuffer: |
106 | 0 | AsStringBuffer()->Release(); |
107 | 0 | break; |
108 | 0 | case eAtom: |
109 | 0 | AsAtom()->Release(); |
110 | 0 | break; |
111 | 0 | default: |
112 | 0 | break; |
113 | 0 | } |
114 | 0 | mBits = eNull; |
115 | 0 | } |
116 | | |
117 | | // static |
118 | | nsHtml5String |
119 | | nsHtml5String::FromBuffer(char16_t* aBuffer, |
120 | | int32_t aLength, |
121 | | nsHtml5TreeBuilder* aTreeBuilder) |
122 | 0 | { |
123 | 0 | if (!aLength) { |
124 | 0 | return nsHtml5String(eEmpty); |
125 | 0 | } |
126 | 0 | // Work with nsStringBuffer directly to make sure that storage is actually |
127 | 0 | // nsStringBuffer and to make sure the allocation strategy matches |
128 | 0 | // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and |
129 | 0 | // copy. |
130 | 0 | RefPtr<nsStringBuffer> buffer( |
131 | 0 | nsStringBuffer::Alloc((aLength + 1) * sizeof(char16_t))); |
132 | 0 | if (!buffer) { |
133 | 0 | if (!aTreeBuilder) { |
134 | 0 | MOZ_CRASH("Out of memory."); |
135 | 0 | } |
136 | 0 | aTreeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); |
137 | 0 | buffer = nsStringBuffer::Alloc(2 * sizeof(char16_t)); |
138 | 0 | if (!buffer) { |
139 | 0 | MOZ_CRASH( |
140 | 0 | "Out of memory so badly that couldn't even allocate placeholder."); |
141 | 0 | } |
142 | 0 | char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); |
143 | 0 | data[0] = 0xFFFD; |
144 | 0 | data[1] = 0; |
145 | 0 | return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | |
146 | 0 | eStringBuffer); |
147 | 0 | } |
148 | 0 | char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); |
149 | 0 | memcpy(data, aBuffer, aLength * sizeof(char16_t)); |
150 | 0 | data[aLength] = 0; |
151 | 0 | return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | |
152 | 0 | eStringBuffer); |
153 | 0 | } |
154 | | |
155 | | // static |
156 | | nsHtml5String |
157 | | nsHtml5String::FromLiteral(const char* aLiteral) |
158 | 0 | { |
159 | 0 | size_t length = std::strlen(aLiteral); |
160 | 0 | if (!length) { |
161 | 0 | return nsHtml5String(eEmpty); |
162 | 0 | } |
163 | 0 | // Work with nsStringBuffer directly to make sure that storage is actually |
164 | 0 | // nsStringBuffer and to make sure the allocation strategy matches |
165 | 0 | // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and |
166 | 0 | // copy. |
167 | 0 | RefPtr<nsStringBuffer> buffer( |
168 | 0 | nsStringBuffer::Alloc((length + 1) * sizeof(char16_t))); |
169 | 0 | if (!buffer) { |
170 | 0 | MOZ_CRASH("Out of memory."); |
171 | 0 | } |
172 | 0 | char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); |
173 | 0 | ConvertLatin1toUTF16(MakeSpan(aLiteral, length), MakeSpan(data, length)); |
174 | 0 | data[length] = 0; |
175 | 0 | return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | |
176 | 0 | eStringBuffer); |
177 | 0 | } |
178 | | |
179 | | // static |
180 | | nsHtml5String |
181 | | nsHtml5String::FromString(const nsAString& aString) |
182 | 0 | { |
183 | 0 | auto length = aString.Length(); |
184 | 0 | if (!length) { |
185 | 0 | return nsHtml5String(eEmpty); |
186 | 0 | } |
187 | 0 | RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aString); |
188 | 0 | if (buffer && (length == buffer->StorageSize() / sizeof(char16_t) - 1)) { |
189 | 0 | return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | |
190 | 0 | eStringBuffer); |
191 | 0 | } |
192 | 0 | buffer = nsStringBuffer::Alloc((length + 1) * sizeof(char16_t)); |
193 | 0 | if (!buffer) { |
194 | 0 | MOZ_CRASH("Out of memory."); |
195 | 0 | } |
196 | 0 | char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); |
197 | 0 | memcpy(data, aString.BeginReading(), length * sizeof(char16_t)); |
198 | 0 | data[length] = 0; |
199 | 0 | return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | |
200 | 0 | eStringBuffer); |
201 | 0 | } |
202 | | |
203 | | // static |
204 | | nsHtml5String |
205 | | nsHtml5String::FromAtom(already_AddRefed<nsAtom> aAtom) |
206 | 0 | { |
207 | 0 | return nsHtml5String(reinterpret_cast<uintptr_t>(aAtom.take()) | eAtom); |
208 | 0 | } |
209 | | |
210 | | // static |
211 | | nsHtml5String |
212 | | nsHtml5String::EmptyString() |
213 | 0 | { |
214 | 0 | return nsHtml5String(eEmpty); |
215 | 0 | } |