OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights
reserved. | 3 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights
reserved. |
4 * Copyright (C) 2009 Google Inc. All rights reserved. | 4 * Copyright (C) 2009 Google Inc. All rights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 NEW_DELETE_SAME_AS_MALLOC_FREE; | 107 NEW_DELETE_SAME_AS_MALLOC_FREE; |
108 friend struct WTF::CStringTranslator; | 108 friend struct WTF::CStringTranslator; |
109 template<typename CharacterType> friend struct WTF::HashAndCharactersTransla
tor; | 109 template<typename CharacterType> friend struct WTF::HashAndCharactersTransla
tor; |
110 friend struct WTF::HashAndUTF8CharactersTranslator; | 110 friend struct WTF::HashAndUTF8CharactersTranslator; |
111 friend struct WTF::CharBufferFromLiteralDataTranslator; | 111 friend struct WTF::CharBufferFromLiteralDataTranslator; |
112 friend struct WTF::LCharBufferTranslator; | 112 friend struct WTF::LCharBufferTranslator; |
113 friend struct WTF::SubstringTranslator; | 113 friend struct WTF::SubstringTranslator; |
114 friend struct WTF::UCharBufferTranslator; | 114 friend struct WTF::UCharBufferTranslator; |
115 | 115 |
116 private: | 116 private: |
117 enum BufferOwnership { | |
118 BufferInternal, | |
119 BufferOwned, | |
120 // NOTE: Adding more ownership types needs to extend m_hashAndFlags as w
e're at capacity | |
121 }; | |
122 | |
123 // Used to construct static strings, which have an special refCount that can
never hit zero. | 117 // Used to construct static strings, which have an special refCount that can
never hit zero. |
124 // This means that the static string will never be destroyed, which is impor
tant because | 118 // This means that the static string will never be destroyed, which is impor
tant because |
125 // static strings will be shared across threads & ref-counted in a non-threa
dsafe manner. | 119 // static strings will be shared across threads & ref-counted in a non-threa
dsafe manner. |
126 enum ConstructStaticStringTag { ConstructStaticString }; | 120 enum ConstructStaticStringTag { ConstructStaticString }; |
127 StringImpl(const UChar* characters, unsigned length, ConstructStaticStringTa
g) | |
128 : m_data16(characters) | |
129 , m_refCount(s_refCountFlagIsStaticString) | |
130 , m_length(length) | |
131 , m_hashAndFlags(BufferOwned) | |
132 { | |
133 // Ensure that the hash is computed so that AtomicStringHash can call ex
istingHash() | |
134 // with impunity. The empty string is special because it is never entere
d into | |
135 // AtomicString's HashKey, but still needs to compare correctly. | |
136 STRING_STATS_ADD_16BIT_STRING(m_length); | |
137 | |
138 hash(); | |
139 } | |
140 | |
141 // Used to construct static strings, which have an special refCount that can
never hit zero. | |
142 // This means that the static string will never be destroyed, which is impor
tant because | |
143 // static strings will be shared across threads & ref-counted in a non-threa
dsafe manner. | |
144 StringImpl(const LChar* characters, unsigned length, ConstructStaticStringTa
g) | 121 StringImpl(const LChar* characters, unsigned length, ConstructStaticStringTa
g) |
145 : m_data8(characters) | 122 : m_data8(characters) |
146 , m_refCount(s_refCountFlagIsStaticString) | 123 , m_refCount(s_refCountFlagIsStaticString) |
147 , m_length(length) | 124 , m_length(length) |
148 , m_hashAndFlags(s_hashFlag8BitBuffer | BufferOwned) | 125 , m_hashAndFlags(s_hashFlag8BitBuffer) |
149 { | 126 { |
150 // Ensure that the hash is computed so that AtomicStringHash can call ex
istingHash() | 127 // Ensure that the hash is computed so that AtomicStringHash can call ex
istingHash() |
151 // with impunity. The empty string is special because it is never entere
d into | 128 // with impunity. The empty string is special because it is never entere
d into |
152 // AtomicString's HashKey, but still needs to compare correctly. | 129 // AtomicString's HashKey, but still needs to compare correctly. |
153 STRING_STATS_ADD_8BIT_STRING(m_length); | 130 STRING_STATS_ADD_8BIT_STRING(m_length); |
154 | 131 |
155 hash(); | 132 hash(); |
156 } | 133 } |
157 | 134 |
158 // FIXME: there has to be a less hacky way to do this. | 135 // FIXME: there has to be a less hacky way to do this. |
159 enum Force8Bit { Force8BitConstructor }; | 136 enum Force8Bit { Force8BitConstructor }; |
160 // Create a normal 8-bit string with internal storage (BufferInternal) | |
161 StringImpl(unsigned length, Force8Bit) | 137 StringImpl(unsigned length, Force8Bit) |
162 : m_data8(reinterpret_cast<const LChar*>(this + 1)) | 138 : m_data8(reinterpret_cast<const LChar*>(this + 1)) |
163 , m_refCount(s_refCountIncrement) | 139 , m_refCount(s_refCountIncrement) |
164 , m_length(length) | 140 , m_length(length) |
165 , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal) | 141 , m_hashAndFlags(s_hashFlag8BitBuffer) |
166 { | 142 { |
167 ASSERT(m_data8); | 143 ASSERT(m_data8); |
168 ASSERT(m_length); | 144 ASSERT(m_length); |
169 | 145 |
170 STRING_STATS_ADD_8BIT_STRING(m_length); | 146 STRING_STATS_ADD_8BIT_STRING(m_length); |
171 } | 147 } |
172 | 148 |
173 // Create a normal 16-bit string with internal storage (BufferInternal) | |
174 StringImpl(unsigned length) | 149 StringImpl(unsigned length) |
175 : m_data16(reinterpret_cast<const UChar*>(this + 1)) | 150 : m_data16(reinterpret_cast<const UChar*>(this + 1)) |
176 , m_refCount(s_refCountIncrement) | 151 , m_refCount(s_refCountIncrement) |
177 , m_length(length) | 152 , m_length(length) |
178 , m_hashAndFlags(BufferInternal) | 153 , m_hashAndFlags(0) |
179 { | 154 { |
180 ASSERT(m_data16); | 155 ASSERT(m_data16); |
181 ASSERT(m_length); | 156 ASSERT(m_length); |
182 | 157 |
183 STRING_STATS_ADD_16BIT_STRING(m_length); | 158 STRING_STATS_ADD_16BIT_STRING(m_length); |
184 } | 159 } |
185 | 160 |
186 // Create a StringImpl adopting ownership of the provided buffer (BufferOwne
d) | |
187 StringImpl(const LChar* characters, unsigned length) | |
188 : m_data8(characters) | |
189 , m_refCount(s_refCountIncrement) | |
190 , m_length(length) | |
191 , m_hashAndFlags(s_hashFlag8BitBuffer | BufferOwned) | |
192 { | |
193 ASSERT(m_data8); | |
194 ASSERT(m_length); | |
195 | |
196 STRING_STATS_ADD_8BIT_STRING(m_length); | |
197 } | |
198 | |
199 enum ConstructFromLiteralTag { ConstructFromLiteral }; | 161 enum ConstructFromLiteralTag { ConstructFromLiteral }; |
200 StringImpl(const char* characters, unsigned length, ConstructFromLiteralTag) | 162 StringImpl(const char* characters, unsigned length, ConstructFromLiteralTag) |
201 : m_data8(reinterpret_cast<const LChar*>(characters)) | 163 : m_data8(reinterpret_cast<const LChar*>(characters)) |
202 , m_refCount(s_refCountIncrement) | 164 , m_refCount(s_refCountIncrement) |
203 , m_length(length) | 165 , m_length(length) |
204 , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal) | 166 , m_hashAndFlags(s_hashFlag8BitBuffer) |
205 { | 167 { |
206 ASSERT(m_data8); | 168 ASSERT(m_data8); |
207 ASSERT(m_length); | 169 ASSERT(m_length); |
208 ASSERT(!characters[length]); | 170 ASSERT(!characters[length]); |
209 | 171 |
210 STRING_STATS_ADD_8BIT_STRING(0); | 172 STRING_STATS_ADD_8BIT_STRING(0); |
211 } | 173 } |
212 | 174 |
213 // Create a StringImpl adopting ownership of the provided buffer (BufferOwne
d) | |
214 StringImpl(const UChar* characters, unsigned length) | |
215 : m_data16(characters) | |
216 , m_refCount(s_refCountIncrement) | |
217 , m_length(length) | |
218 , m_hashAndFlags(BufferOwned) | |
219 { | |
220 ASSERT(m_data16); | |
221 ASSERT(m_length); | |
222 | |
223 STRING_STATS_ADD_16BIT_STRING(m_length); | |
224 } | |
225 | |
226 enum CreateEmptyUnique_T { CreateEmptyUnique }; | |
227 StringImpl(CreateEmptyUnique_T) | |
228 : m_data16(reinterpret_cast<const UChar*>(1)) | |
229 , m_refCount(s_refCountIncrement) | |
230 , m_length(0) | |
231 { | |
232 ASSERT(m_data16); | |
233 // Set the hash early, so that all empty unique StringImpls have a hash, | |
234 // and don't use the normal hashing algorithm - the unique nature of the
se | |
235 // keys means that we don't need them to match any other string (in fact
, | |
236 // that's exactly the oposite of what we want!), and teh normal hash wou
ld | |
237 // lead to lots of conflicts. | |
238 unsigned hash = reinterpret_cast<uintptr_t>(this); | |
239 hash <<= s_flagCount; | |
240 if (!hash) | |
241 hash = 1 << s_flagCount; | |
242 m_hashAndFlags = hash | BufferInternal; | |
243 | |
244 STRING_STATS_ADD_16BIT_STRING(m_length); | |
245 } | |
246 public: | 175 public: |
247 ~StringImpl(); | 176 ~StringImpl(); |
248 | 177 |
249 static PassRefPtr<StringImpl> create(const UChar*, unsigned length); | 178 static PassRefPtr<StringImpl> create(const UChar*, unsigned length); |
250 static PassRefPtr<StringImpl> create(const LChar*, unsigned length); | 179 static PassRefPtr<StringImpl> create(const LChar*, unsigned length); |
251 static PassRefPtr<StringImpl> create8BitIfPossible(const UChar*, unsigned le
ngth); | 180 static PassRefPtr<StringImpl> create8BitIfPossible(const UChar*, unsigned le
ngth); |
252 template<size_t inlineCapacity> | 181 template<size_t inlineCapacity> |
253 static PassRefPtr<StringImpl> create8BitIfPossible(const Vector<UChar, inlin
eCapacity>& vector) | 182 static PassRefPtr<StringImpl> create8BitIfPossible(const Vector<UChar, inlin
eCapacity>& vector) |
254 { | 183 { |
255 return create8BitIfPossible(vector.data(), vector.size()); | 184 return create8BitIfPossible(vector.data(), vector.size()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 return 0; | 218 return 0; |
290 } | 219 } |
291 output = reinterpret_cast<T*>(resultImpl + 1); | 220 output = reinterpret_cast<T*>(resultImpl + 1); |
292 | 221 |
293 if (sizeof(T) == sizeof(char)) | 222 if (sizeof(T) == sizeof(char)) |
294 return adoptRef(new (NotNull, resultImpl) StringImpl(length, Force8B
itConstructor)); | 223 return adoptRef(new (NotNull, resultImpl) StringImpl(length, Force8B
itConstructor)); |
295 | 224 |
296 return adoptRef(new (NotNull, resultImpl) StringImpl(length)); | 225 return adoptRef(new (NotNull, resultImpl) StringImpl(length)); |
297 } | 226 } |
298 | 227 |
299 static PassRefPtr<StringImpl> createEmptyUnique() | 228 // Reallocate the StringImpl. The originalString must be only owned by the P
assRefPtr. |
300 { | 229 // Just like the input pointer of realloc(), the originalString can't be use
d after this function. |
301 return adoptRef(new StringImpl(CreateEmptyUnique)); | |
302 } | |
303 | |
304 // Reallocate the StringImpl. The originalString must be only owned by the P
assRefPtr, | |
305 // and the buffer ownership must be BufferInternal. Just like the input poin
ter of realloc(), | |
306 // the originalString can't be used after this function. | |
307 static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalStri
ng, unsigned length, LChar*& data); | 230 static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalStri
ng, unsigned length, LChar*& data); |
308 static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalStri
ng, unsigned length, UChar*& data); | 231 static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalStri
ng, unsigned length, UChar*& data); |
309 | 232 |
310 // If this StringImpl has only one reference, we can truncate the string by
updating | 233 // If this StringImpl has only one reference, we can truncate the string by
updating |
311 // its m_length property without actually re-allocating its buffer. | 234 // its m_length property without actually re-allocating its buffer. |
312 void truncateAssumingIsolated(unsigned length) | 235 void truncateAssumingIsolated(unsigned length) |
313 { | 236 { |
314 ASSERT(hasOneRef()); | 237 ASSERT(hasOneRef()); |
| 238 ASSERT(!isASCIILiteral()); |
315 ASSERT(length <= m_length); | 239 ASSERT(length <= m_length); |
316 ASSERT(bufferOwnership() == BufferInternal); | |
317 m_length = length; | 240 m_length = length; |
318 } | 241 } |
319 | 242 |
320 static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAnd
Flags); } | |
321 static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; } | |
322 static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8);
} | |
323 | |
324 template<typename CharType, size_t inlineCapacity> | |
325 static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity>& vector
) | |
326 { | |
327 if (size_t size = vector.size()) { | |
328 ASSERT(vector.data()); | |
329 RELEASE_ASSERT(size <= std::numeric_limits<unsigned>::max()); | |
330 return adoptRef(new StringImpl(vector.releaseBuffer(), size)); | |
331 } | |
332 return empty(); | |
333 } | |
334 | |
335 unsigned length() const { return m_length; } | 243 unsigned length() const { return m_length; } |
336 bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; } | 244 bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; } |
337 bool hasInternalBuffer() const { return bufferOwnership() == BufferInternal;
} | |
338 bool hasOwnedBuffer() const { return bufferOwnership() == BufferOwned; } | |
339 | 245 |
340 ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return m_
data8; } | 246 ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return m_
data8; } |
341 ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return
m_data16; } | 247 ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return
m_data16; } |
342 | 248 |
343 template <typename CharType> | 249 template <typename CharType> |
344 ALWAYS_INLINE const CharType * getCharacters() const; | 250 ALWAYS_INLINE const CharType * getCharacters() const; |
345 | 251 |
346 size_t cost() | 252 size_t cost() |
347 { | 253 { |
348 if (m_hashAndFlags & s_hashFlagDidReportCost) | 254 if (m_hashAndFlags & s_hashFlagDidReportCost) |
349 return 0; | 255 return 0; |
350 | 256 |
351 m_hashAndFlags |= s_hashFlagDidReportCost; | 257 m_hashAndFlags |= s_hashFlagDidReportCost; |
352 return m_length; | 258 return m_length; |
353 } | 259 } |
354 | 260 |
355 size_t sizeInBytes() const; | 261 size_t sizeInBytes() const; |
356 | 262 |
357 bool isEmptyUnique() const | |
358 { | |
359 return !length() && !isStatic(); | |
360 } | |
361 | |
362 bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; } | 263 bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; } |
363 void setIsAtomic(bool isAtomic) | 264 void setIsAtomic(bool isAtomic) |
364 { | 265 { |
365 if (isAtomic) | 266 if (isAtomic) |
366 m_hashAndFlags |= s_hashFlagIsAtomic; | 267 m_hashAndFlags |= s_hashFlagIsAtomic; |
367 else | 268 else |
368 m_hashAndFlags &= ~s_hashFlagIsAtomic; | 269 m_hashAndFlags &= ~s_hashFlagIsAtomic; |
369 } | 270 } |
370 | 271 |
371 bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; } | 272 bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; } |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 #endif | 469 #endif |
569 #ifdef __OBJC__ | 470 #ifdef __OBJC__ |
570 operator NSString*(); | 471 operator NSString*(); |
571 #endif | 472 #endif |
572 | 473 |
573 #ifdef STRING_STATS | 474 #ifdef STRING_STATS |
574 ALWAYS_INLINE static StringStats& stringStats() { return m_stringStats; } | 475 ALWAYS_INLINE static StringStats& stringStats() { return m_stringStats; } |
575 #endif | 476 #endif |
576 | 477 |
577 private: | 478 private: |
578 | |
579 bool isASCIILiteral() const | 479 bool isASCIILiteral() const |
580 { | 480 { |
581 return is8Bit() && hasInternalBuffer() && reinterpret_cast<const void*>(
m_data8) != reinterpret_cast<const void*>(this + 1); | 481 return is8Bit() && length() && reinterpret_cast<const void*>(m_data8) !=
reinterpret_cast<const void*>(this + 1); |
582 } | 482 } |
583 | 483 |
584 // This number must be at least 2 to avoid sharing empty, null as well as 1
character strings from SmallStrings. | 484 // This number must be at least 2 to avoid sharing empty, null as well as 1
character strings from SmallStrings. |
585 static const unsigned s_copyCharsInlineCutOff = 20; | 485 static const unsigned s_copyCharsInlineCutOff = 20; |
586 | 486 |
587 BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership
>(m_hashAndFlags & s_hashMaskBufferOwnership); } | |
588 template <class UCharPredicate> PassRefPtr<StringImpl> stripMatchedCharacter
s(UCharPredicate); | 487 template <class UCharPredicate> PassRefPtr<StringImpl> stripMatchedCharacter
s(UCharPredicate); |
589 template <typename CharType, class UCharPredicate> PassRefPtr<StringImpl> si
mplifyMatchedCharactersToSpace(UCharPredicate); | 488 template <typename CharType, class UCharPredicate> PassRefPtr<StringImpl> si
mplifyMatchedCharactersToSpace(UCharPredicate); |
590 NEVER_INLINE unsigned hashSlowCase() const; | 489 NEVER_INLINE unsigned hashSlowCase() const; |
591 | 490 |
592 // The bottom bit in the ref count indicates a static (immortal) string. | 491 // The bottom bit in the ref count indicates a static (immortal) string. |
593 static const unsigned s_refCountFlagIsStaticString = 0x1; | 492 static const unsigned s_refCountFlagIsStaticString = 0x1; |
594 static const unsigned s_refCountIncrement = 0x2; // This allows us to ref /
deref without disturbing the static string flag. | 493 static const unsigned s_refCountIncrement = 0x2; // This allows us to ref /
deref without disturbing the static string flag. |
595 | 494 |
596 // The bottom 8 bits in the hash are flags, of which only 4 are currently in
use. | 495 // The bottom 8 bits in the hash are flags, of which only 3 are currently in
use. |
597 static const unsigned s_flagCount = 8; | 496 static const unsigned s_flagCount = 8; |
598 static const unsigned s_flagMask = (1u << s_flagCount) - 1; | 497 static const unsigned s_flagMask = (1u << s_flagCount) - 1; |
599 COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves
_enough_bits_for_StringImpl_flags); | 498 COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves
_enough_bits_for_StringImpl_flags); |
600 | 499 |
601 static const unsigned s_hashFlagDidReportCost = 1u << 3; | 500 static const unsigned s_hashFlagDidReportCost = 1u << 2; |
602 static const unsigned s_hashFlagIsAtomic = 1u << 2; | 501 static const unsigned s_hashFlagIsAtomic = 1u << 1; |
603 static const unsigned s_hashFlag8BitBuffer = 1u << 1; | 502 static const unsigned s_hashFlag8BitBuffer = 1u << 0; |
604 static const unsigned s_hashMaskBufferOwnership = 1u; | |
605 | 503 |
606 #ifdef STRING_STATS | 504 #ifdef STRING_STATS |
607 static StringStats m_stringStats; | 505 static StringStats m_stringStats; |
608 #endif | 506 #endif |
609 | 507 |
610 public: | 508 public: |
611 struct StaticASCIILiteral { | 509 struct StaticASCIILiteral { |
612 // These member variables must match the layout of StringImpl. | 510 // These member variables must match the layout of StringImpl. |
613 const LChar* m_data8; | 511 const LChar* m_data8; |
614 unsigned m_refCount; | 512 unsigned m_refCount; |
615 unsigned m_length; | 513 unsigned m_length; |
616 unsigned m_hashAndFlags; | 514 unsigned m_hashAndFlags; |
617 | 515 |
618 static const unsigned s_initialRefCount = s_refCountFlagIsStaticString; | 516 static const unsigned s_initialRefCount = s_refCountFlagIsStaticString; |
619 static const unsigned s_initialFlags = s_hashFlag8BitBuffer | BufferInte
rnal; | 517 static const unsigned s_initialFlags = s_hashFlag8BitBuffer; |
620 static const unsigned s_hashShift = s_flagCount; | 518 static const unsigned s_hashShift = s_flagCount; |
621 }; | 519 }; |
622 | 520 |
623 #ifndef NDEBUG | 521 #ifndef NDEBUG |
624 void assertHashIsCorrect() | 522 void assertHashIsCorrect() |
625 { | 523 { |
626 ASSERT(hasHash()); | 524 ASSERT(hasHash()); |
627 ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(charac
ters8(), length())); | 525 ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(charac
ters8(), length())); |
628 } | 526 } |
629 #endif | 527 #endif |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 } | 828 } |
931 | 829 |
932 using WTF::StringImpl; | 830 using WTF::StringImpl; |
933 using WTF::equal; | 831 using WTF::equal; |
934 using WTF::equalNonNull; | 832 using WTF::equalNonNull; |
935 using WTF::TextCaseSensitivity; | 833 using WTF::TextCaseSensitivity; |
936 using WTF::TextCaseSensitive; | 834 using WTF::TextCaseSensitive; |
937 using WTF::TextCaseInsensitive; | 835 using WTF::TextCaseInsensitive; |
938 | 836 |
939 #endif | 837 #endif |
OLD | NEW |