2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
4 * Copyright (C) 2009 Google Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include "wtf/ASCIICType.h"
27 #include "wtf/Forward.h"
28 #include "wtf/HashMap.h"
29 #include "wtf/StringHasher.h"
30 #include "wtf/Vector.h"
31 #include "wtf/WTFExport.h"
32 #include "wtf/text/Unicode.h"
36 typedef const struct __CFString
* CFStringRef
;
46 struct CStringTranslator
;
47 template<typename CharacterType
> struct HashAndCharactersTranslator
;
48 struct HashAndUTF8CharactersTranslator
;
49 struct LCharBufferTranslator
;
50 struct CharBufferFromLiteralDataTranslator
;
51 struct SubstringTranslator
;
52 struct UCharBufferTranslator
;
53 template<typename
> class RetainPtr
;
55 enum TextCaseSensitivity
{ TextCaseSensitive
, TextCaseInsensitive
};
57 enum StripBehavior
{ StripExtraWhiteSpace
, DoNotStripWhiteSpace
};
59 typedef bool (*CharacterMatchFunctionPtr
)(UChar
);
60 typedef bool (*IsWhiteSpaceFunctionPtr
)(UChar
);
61 typedef HashMap
<unsigned, StringImpl
*, AlreadyHashed
> StaticStringsTable
;
63 // Define STRING_STATS to turn on run time statistics of string sizes and memory usage
68 inline void add8BitString(unsigned length
)
70 ++m_totalNumberStrings
;
71 ++m_number8BitStrings
;
72 m_total8BitData
+= length
;
75 inline void add16BitString(unsigned length
)
77 ++m_totalNumberStrings
;
78 ++m_number16BitStrings
;
79 m_total16BitData
+= length
;
82 void removeString(StringImpl
*);
85 static const unsigned s_printStringStatsFrequency
= 5000;
86 static unsigned s_stringRemovesTillPrintStats
;
88 unsigned m_totalNumberStrings
;
89 unsigned m_number8BitStrings
;
90 unsigned m_number16BitStrings
;
91 unsigned long long m_total8BitData
;
92 unsigned long long m_total16BitData
;
95 void addStringForStats(StringImpl
*);
96 void removeStringForStats(StringImpl
*);
98 #define STRING_STATS_ADD_8BIT_STRING(length) StringImpl::stringStats().add8BitString(length); addStringForStats(this)
99 #define STRING_STATS_ADD_16BIT_STRING(length) StringImpl::stringStats().add16BitString(length); addStringForStats(this)
100 #define STRING_STATS_REMOVE_STRING(string) StringImpl::stringStats().removeString(string); removeStringForStats(this)
102 #define STRING_STATS_ADD_8BIT_STRING(length) ((void)0)
103 #define STRING_STATS_ADD_16BIT_STRING(length) ((void)0)
104 #define STRING_STATS_REMOVE_STRING(string) ((void)0)
107 // You can find documentation about this class in this doc:
108 // https://docs.google.com/document/d/1kOCUlJdh2WJMJGDf-WoEQhmnjKLaOYRbiHz5TiGJl14/edit?usp=sharing
109 class WTF_EXPORT StringImpl
{
110 WTF_MAKE_NONCOPYABLE(StringImpl
);
111 friend struct WTF::CStringTranslator
;
112 template<typename CharacterType
> friend struct WTF::HashAndCharactersTranslator
;
113 friend struct WTF::HashAndUTF8CharactersTranslator
;
114 friend struct WTF::CharBufferFromLiteralDataTranslator
;
115 friend struct WTF::LCharBufferTranslator
;
116 friend struct WTF::SubstringTranslator
;
117 friend struct WTF::UCharBufferTranslator
;
120 // StringImpls are allocated out of the WTF buffer partition.
121 void* operator new(size_t);
122 void* operator new(size_t, void* ptr
) { return ptr
; }
123 void operator delete(void*);
125 // Used to construct static strings, which have an special refCount that can never hit zero.
126 // This means that the static string will never be destroyed, which is important because
127 // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
128 enum ConstructEmptyStringTag
{ ConstructEmptyString
};
129 explicit StringImpl(ConstructEmptyStringTag
)
137 // Ensure that the hash is computed so that AtomicStringHash can call existingHash()
138 // with impunity. The empty string is special because it is never entered into
139 // AtomicString's HashKey, but still needs to compare correctly.
140 STRING_STATS_ADD_8BIT_STRING(m_length
);
144 enum ConstructEmptyString16BitTag
{ ConstructEmptyString16Bit
};
145 explicit StringImpl(ConstructEmptyString16BitTag
)
153 STRING_STATS_ADD_16BIT_STRING(m_length
);
157 // FIXME: there has to be a less hacky way to do this.
158 enum Force8Bit
{ Force8BitConstructor
};
159 StringImpl(unsigned length
, Force8Bit
)
168 STRING_STATS_ADD_8BIT_STRING(m_length
);
171 StringImpl(unsigned length
)
180 STRING_STATS_ADD_16BIT_STRING(m_length
);
183 enum StaticStringTag
{ StaticString
};
184 StringImpl(unsigned length
, unsigned hash
, StaticStringTag
)
197 static StringImpl
* createStatic(const char* string
, unsigned length
, unsigned hash
);
198 static void freezeStaticStrings();
199 static const StaticStringsTable
& allStaticStrings();
200 static unsigned highestStaticStringLength() { return m_highestStaticStringLength
; }
202 static PassRefPtr
<StringImpl
> create(const UChar
*, unsigned length
);
203 static PassRefPtr
<StringImpl
> create(const LChar
*, unsigned length
);
204 static PassRefPtr
<StringImpl
> create8BitIfPossible(const UChar
*, unsigned length
);
205 template<size_t inlineCapacity
>
206 static PassRefPtr
<StringImpl
> create8BitIfPossible(const Vector
<UChar
, inlineCapacity
>& vector
)
208 return create8BitIfPossible(vector
.data(), vector
.size());
211 ALWAYS_INLINE
static PassRefPtr
<StringImpl
> create(const char* s
, unsigned length
) { return create(reinterpret_cast<const LChar
*>(s
), length
); }
212 static PassRefPtr
<StringImpl
> create(const LChar
*);
213 ALWAYS_INLINE
static PassRefPtr
<StringImpl
> create(const char* s
) { return create(reinterpret_cast<const LChar
*>(s
)); }
215 static PassRefPtr
<StringImpl
> createUninitialized(unsigned length
, LChar
*& data
);
216 static PassRefPtr
<StringImpl
> createUninitialized(unsigned length
, UChar
*& data
);
218 // Reallocate the StringImpl. The originalString must be only owned by the PassRefPtr.
219 // Just like the input pointer of realloc(), the originalString can't be used after this function.
220 static PassRefPtr
<StringImpl
> reallocate(PassRefPtr
<StringImpl
> originalString
, unsigned length
);
222 // If this StringImpl has only one reference, we can truncate the string by updating
223 // its m_length property without actually re-allocating its buffer.
224 void truncateAssumingIsolated(unsigned length
)
227 ASSERT(length
<= m_length
);
231 unsigned length() const { return m_length
; }
232 bool is8Bit() const { return m_is8Bit
; }
234 ALWAYS_INLINE
const LChar
* characters8() const { ASSERT(is8Bit()); return reinterpret_cast<const LChar
*>(this + 1); }
235 ALWAYS_INLINE
const UChar
* characters16() const { ASSERT(!is8Bit()); return reinterpret_cast<const UChar
*>(this + 1); }
237 template <typename CharType
>
238 ALWAYS_INLINE
const CharType
* getCharacters() const;
240 size_t sizeInBytes() const;
242 bool isAtomic() const { return m_isAtomic
; }
243 void setIsAtomic(bool isAtomic
) { m_isAtomic
= isAtomic
; }
245 bool isStatic() const { return m_isStatic
; }
248 // The high bits of 'hash' are always empty, but we prefer to store our flags
249 // in the low bits because it makes them slightly more efficient to access.
250 // So, we shift left and right when setting and getting our hash code.
251 void setHash(unsigned hash
) const
254 // Multiple clients assume that StringHasher is the canonical string hash function.
255 ASSERT(hash
== (is8Bit() ? StringHasher::computeHashAndMaskTop8Bits(characters8(), m_length
) : StringHasher::computeHashAndMaskTop8Bits(characters16(), m_length
)));
257 ASSERT(hash
); // Verify that 0 is a valid sentinel hash value.
260 unsigned rawHash() const
265 void destroyIfNotStatic();
270 return rawHash() != 0;
273 unsigned existingHash() const
279 unsigned hash() const
282 return existingHash();
283 return hashSlowCase();
286 ALWAYS_INLINE
bool hasOneRef() const
288 return m_refCount
== 1;
291 ALWAYS_INLINE
void ref()
296 ALWAYS_INLINE
void deref()
299 destroyIfNotStatic();
306 static StringImpl
* empty();
307 static StringImpl
* empty16Bit();
309 // FIXME: Does this really belong in StringImpl?
310 template <typename T
> static void copyChars(T
* destination
, const T
* source
, unsigned numCharacters
)
312 memcpy(destination
, source
, numCharacters
* sizeof(T
));
315 ALWAYS_INLINE
static void copyChars(UChar
* destination
, const LChar
* source
, unsigned numCharacters
)
317 for (unsigned i
= 0; i
< numCharacters
; ++i
)
318 destination
[i
] = source
[i
];
321 // Some string features, like refcounting and the atomicity flag, are not
322 // thread-safe. We achieve thread safety by isolation, giving each thread
323 // its own copy of the string.
324 PassRefPtr
<StringImpl
> isolatedCopy() const;
326 PassRefPtr
<StringImpl
> substring(unsigned pos
, unsigned len
= UINT_MAX
);
328 UChar
operator[](unsigned i
) const
330 ASSERT_WITH_SECURITY_IMPLICATION(i
< m_length
);
332 return characters8()[i
];
333 return characters16()[i
];
335 UChar32
characterStartingAt(unsigned);
337 bool containsOnlyWhitespace();
339 int toIntStrict(bool* ok
= 0, int base
= 10);
340 unsigned toUIntStrict(bool* ok
= 0, int base
= 10);
341 int64_t toInt64Strict(bool* ok
= 0, int base
= 10);
342 uint64_t toUInt64Strict(bool* ok
= 0, int base
= 10);
344 int toInt(bool* ok
= 0); // ignores trailing garbage
345 unsigned toUInt(bool* ok
= 0); // ignores trailing garbage
346 int64_t toInt64(bool* ok
= 0); // ignores trailing garbage
347 uint64_t toUInt64(bool* ok
= 0); // ignores trailing garbage
349 // FIXME: Like the strict functions above, these give false for "ok" when there is trailing garbage.
350 // Like the non-strict functions above, these return the value when there is trailing garbage.
351 // It would be better if these were more consistent with the above functions instead.
352 double toDouble(bool* ok
= 0);
353 float toFloat(bool* ok
= 0);
355 PassRefPtr
<StringImpl
> lower();
356 PassRefPtr
<StringImpl
> upper();
357 PassRefPtr
<StringImpl
> lower(const AtomicString
& localeIdentifier
);
358 PassRefPtr
<StringImpl
> upper(const AtomicString
& localeIdentifier
);
360 PassRefPtr
<StringImpl
> fill(UChar
);
361 // FIXME: Do we need fill(char) or can we just do the right thing if UChar is ASCII?
362 PassRefPtr
<StringImpl
> foldCase();
364 PassRefPtr
<StringImpl
> stripWhiteSpace();
365 PassRefPtr
<StringImpl
> stripWhiteSpace(IsWhiteSpaceFunctionPtr
);
366 PassRefPtr
<StringImpl
> simplifyWhiteSpace(StripBehavior stripBehavior
= StripExtraWhiteSpace
);
367 PassRefPtr
<StringImpl
> simplifyWhiteSpace(IsWhiteSpaceFunctionPtr
, StripBehavior stripBehavior
= StripExtraWhiteSpace
);
369 PassRefPtr
<StringImpl
> removeCharacters(CharacterMatchFunctionPtr
);
370 template <typename CharType
>
371 ALWAYS_INLINE PassRefPtr
<StringImpl
> removeCharacters(const CharType
* characters
, CharacterMatchFunctionPtr
);
373 size_t find(LChar character
, unsigned start
= 0);
374 size_t find(char character
, unsigned start
= 0);
375 size_t find(UChar character
, unsigned start
= 0);
376 size_t find(CharacterMatchFunctionPtr
, unsigned index
= 0);
377 size_t find(const LChar
*, unsigned index
= 0);
378 ALWAYS_INLINE
size_t find(const char* s
, unsigned index
= 0) { return find(reinterpret_cast<const LChar
*>(s
), index
); }
379 size_t find(StringImpl
*);
380 size_t find(StringImpl
*, unsigned index
);
381 size_t findIgnoringCase(const LChar
*, unsigned index
= 0);
382 ALWAYS_INLINE
size_t findIgnoringCase(const char* s
, unsigned index
= 0) { return findIgnoringCase(reinterpret_cast<const LChar
*>(s
), index
); }
383 size_t findIgnoringCase(StringImpl
*, unsigned index
= 0);
385 size_t findNextLineStart(unsigned index
= UINT_MAX
);
387 size_t reverseFind(UChar
, unsigned index
= UINT_MAX
);
388 size_t reverseFind(StringImpl
*, unsigned index
= UINT_MAX
);
389 size_t reverseFindIgnoringCase(StringImpl
*, unsigned index
= UINT_MAX
);
391 size_t count(LChar
) const;
393 bool startsWith(StringImpl
* str
, TextCaseSensitivity caseSensitivity
= TextCaseSensitive
) { return ((caseSensitivity
== TextCaseSensitive
) ? reverseFind(str
, 0) : reverseFindIgnoringCase(str
, 0)) == 0; }
394 bool startsWith(UChar
) const;
395 bool startsWith(const char*, unsigned matchLength
, TextCaseSensitivity
) const;
396 template<unsigned matchLength
>
397 bool startsWith(const char (&prefix
)[matchLength
], TextCaseSensitivity caseSensitivity
= TextCaseSensitive
) const { return startsWith(prefix
, matchLength
- 1, caseSensitivity
); }
399 bool endsWith(StringImpl
*, TextCaseSensitivity
= TextCaseSensitive
);
400 bool endsWith(UChar
) const;
401 bool endsWith(const char*, unsigned matchLength
, TextCaseSensitivity
) const;
402 template<unsigned matchLength
>
403 bool endsWith(const char (&prefix
)[matchLength
], TextCaseSensitivity caseSensitivity
= TextCaseSensitive
) const { return endsWith(prefix
, matchLength
- 1, caseSensitivity
); }
405 PassRefPtr
<StringImpl
> replace(UChar
, UChar
);
406 PassRefPtr
<StringImpl
> replace(UChar
, StringImpl
*);
407 ALWAYS_INLINE PassRefPtr
<StringImpl
> replace(UChar pattern
, const char* replacement
, unsigned replacementLength
) { return replace(pattern
, reinterpret_cast<const LChar
*>(replacement
), replacementLength
); }
408 PassRefPtr
<StringImpl
> replace(UChar
, const LChar
*, unsigned replacementLength
);
409 PassRefPtr
<StringImpl
> replace(UChar
, const UChar
*, unsigned replacementLength
);
410 PassRefPtr
<StringImpl
> replace(StringImpl
*, StringImpl
*);
411 PassRefPtr
<StringImpl
> replace(unsigned index
, unsigned len
, StringImpl
*);
412 PassRefPtr
<StringImpl
> upconvertedString();
415 RetainPtr
<CFStringRef
> createCFString();
418 operator NSString
*();
422 ALWAYS_INLINE
static StringStats
& stringStats() { return m_stringStats
; }
424 static const UChar latin1CaseFoldTable
[256];
427 template<typename CharType
> static size_t allocationSize(unsigned length
)
429 RELEASE_ASSERT(length
<= ((std::numeric_limits
<unsigned>::max() - sizeof(StringImpl
)) / sizeof(CharType
)));
430 return sizeof(StringImpl
) + length
* sizeof(CharType
);
433 template <class UCharPredicate
> PassRefPtr
<StringImpl
> stripMatchedCharacters(UCharPredicate
);
434 template <typename CharType
, class UCharPredicate
> PassRefPtr
<StringImpl
> simplifyMatchedCharactersToSpace(UCharPredicate
, StripBehavior
);
435 NEVER_INLINE
unsigned hashSlowCase() const;
438 static StringStats m_stringStats
;
441 static unsigned m_highestStaticStringLength
;
444 void assertHashIsCorrect()
447 ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(characters8(), length()));
454 mutable unsigned m_hash
: 24;
455 unsigned m_isAtomic
: 1;
456 unsigned m_is8Bit
: 1;
457 unsigned m_isStatic
: 1;
461 ALWAYS_INLINE
const LChar
* StringImpl::getCharacters
<LChar
>() const { return characters8(); }
464 ALWAYS_INLINE
const UChar
* StringImpl::getCharacters
<UChar
>() const { return characters16(); }
466 WTF_EXPORT
bool equal(const StringImpl
*, const StringImpl
*);
467 WTF_EXPORT
bool equal(const StringImpl
*, const LChar
*);
468 inline bool equal(const StringImpl
* a
, const char* b
) { return equal(a
, reinterpret_cast<const LChar
*>(b
)); }
469 WTF_EXPORT
bool equal(const StringImpl
*, const LChar
*, unsigned);
470 WTF_EXPORT
bool equal(const StringImpl
*, const UChar
*, unsigned);
471 inline bool equal(const StringImpl
* a
, const char* b
, unsigned length
) { return equal(a
, reinterpret_cast<const LChar
*>(b
), length
); }
472 inline bool equal(const LChar
* a
, StringImpl
* b
) { return equal(b
, a
); }
473 inline bool equal(const char* a
, StringImpl
* b
) { return equal(b
, reinterpret_cast<const LChar
*>(a
)); }
474 WTF_EXPORT
bool equalNonNull(const StringImpl
* a
, const StringImpl
* b
);
476 template<typename CharType
>
477 ALWAYS_INLINE
bool equal(const CharType
* a
, const CharType
* b
, unsigned length
) { return !memcmp(a
, b
, length
* sizeof(CharType
)); }
479 ALWAYS_INLINE
bool equal(const LChar
* a
, const UChar
* b
, unsigned length
)
481 for (unsigned i
= 0; i
< length
; ++i
) {
488 ALWAYS_INLINE
bool equal(const UChar
* a
, const LChar
* b
, unsigned length
) { return equal(b
, a
, length
); }
490 WTF_EXPORT
bool equalIgnoringCase(const StringImpl
*, const StringImpl
*);
491 WTF_EXPORT
bool equalIgnoringCase(const StringImpl
*, const LChar
*);
492 inline bool equalIgnoringCase(const LChar
* a
, const StringImpl
* b
) { return equalIgnoringCase(b
, a
); }
493 WTF_EXPORT
bool equalIgnoringCase(const LChar
*, const LChar
*, unsigned);
494 WTF_EXPORT
bool equalIgnoringCase(const UChar
*, const LChar
*, unsigned);
495 inline bool equalIgnoringCase(const UChar
* a
, const char* b
, unsigned length
) { return equalIgnoringCase(a
, reinterpret_cast<const LChar
*>(b
), length
); }
496 inline bool equalIgnoringCase(const LChar
* a
, const UChar
* b
, unsigned length
) { return equalIgnoringCase(b
, a
, length
); }
497 inline bool equalIgnoringCase(const char* a
, const UChar
* b
, unsigned length
) { return equalIgnoringCase(b
, reinterpret_cast<const LChar
*>(a
), length
); }
498 inline bool equalIgnoringCase(const char* a
, const LChar
* b
, unsigned length
) { return equalIgnoringCase(b
, reinterpret_cast<const LChar
*>(a
), length
); }
499 inline bool equalIgnoringCase(const UChar
* a
, const UChar
* b
, int length
)
502 return !Unicode::umemcasecmp(a
, b
, length
);
504 WTF_EXPORT
bool equalIgnoringCaseNonNull(const StringImpl
*, const StringImpl
*);
506 WTF_EXPORT
bool equalIgnoringNullity(StringImpl
*, StringImpl
*);
508 template<typename CharacterTypeA
, typename CharacterTypeB
>
509 inline bool equalIgnoringASCIICase(const CharacterTypeA
* a
, const CharacterTypeB
* b
, unsigned length
)
511 for (unsigned i
= 0; i
< length
; ++i
) {
512 if (toASCIILower(a
[i
]) != toASCIILower(b
[i
]))
518 template<typename CharacterTypeA
, typename CharacterTypeB
>
519 bool startsWithIgnoringASCIICase(const CharacterTypeA
& reference
, const CharacterTypeB
& prefix
)
521 unsigned prefixLength
= prefix
.length();
522 if (prefixLength
> reference
.length())
525 if (reference
.is8Bit()) {
527 return equalIgnoringASCIICase(reference
.characters8(), prefix
.characters8(), prefixLength
);
528 return equalIgnoringASCIICase(reference
.characters8(), prefix
.characters16(), prefixLength
);
531 return equalIgnoringASCIICase(reference
.characters16(), prefix
.characters8(), prefixLength
);
532 return equalIgnoringASCIICase(reference
.characters16(), prefix
.characters16(), prefixLength
);
535 template<typename CharacterType
>
536 inline size_t find(const CharacterType
* characters
, unsigned length
, CharacterType matchCharacter
, unsigned index
= 0)
538 while (index
< length
) {
539 if (characters
[index
] == matchCharacter
)
546 ALWAYS_INLINE
size_t find(const UChar
* characters
, unsigned length
, LChar matchCharacter
, unsigned index
= 0)
548 return find(characters
, length
, static_cast<UChar
>(matchCharacter
), index
);
551 inline size_t find(const LChar
* characters
, unsigned length
, UChar matchCharacter
, unsigned index
= 0)
553 if (matchCharacter
& ~0xFF)
555 return find(characters
, length
, static_cast<LChar
>(matchCharacter
), index
);
558 inline size_t find(const LChar
* characters
, unsigned length
, CharacterMatchFunctionPtr matchFunction
, unsigned index
= 0)
560 while (index
< length
) {
561 if (matchFunction(characters
[index
]))
568 inline size_t find(const UChar
* characters
, unsigned length
, CharacterMatchFunctionPtr matchFunction
, unsigned index
= 0)
570 while (index
< length
) {
571 if (matchFunction(characters
[index
]))
578 template<typename CharacterType
>
579 inline size_t findNextLineStart(const CharacterType
* characters
, unsigned length
, unsigned index
= 0)
581 while (index
< length
) {
582 CharacterType c
= characters
[index
++];
583 if ((c
!= '\n') && (c
!= '\r'))
586 // There can only be a start of a new line if there are more characters
587 // beyond the current character.
588 if (index
< length
) {
589 // The 3 common types of line terminators are 1. \r\n (Windows),
590 // 2. \r (old MacOS) and 3. \n (Unix'es).
593 return index
; // Case 3: just \n.
595 CharacterType c2
= characters
[index
];
597 return index
; // Case 2: just \r.
600 // But, there's only a start of a new line if there are more
601 // characters beyond the \r\n.
602 if (++index
< length
)
609 template<typename CharacterType
>
610 inline size_t reverseFindLineTerminator(const CharacterType
* characters
, unsigned length
, unsigned index
= UINT_MAX
)
616 CharacterType c
= characters
[index
];
617 while ((c
!= '\n') && (c
!= '\r')) {
620 c
= characters
[index
];
625 template<typename CharacterType
>
626 inline size_t reverseFind(const CharacterType
* characters
, unsigned length
, CharacterType matchCharacter
, unsigned index
= UINT_MAX
)
632 while (characters
[index
] != matchCharacter
) {
639 ALWAYS_INLINE
size_t reverseFind(const UChar
* characters
, unsigned length
, LChar matchCharacter
, unsigned index
= UINT_MAX
)
641 return reverseFind(characters
, length
, static_cast<UChar
>(matchCharacter
), index
);
644 inline size_t reverseFind(const LChar
* characters
, unsigned length
, UChar matchCharacter
, unsigned index
= UINT_MAX
)
646 if (matchCharacter
& ~0xFF)
648 return reverseFind(characters
, length
, static_cast<LChar
>(matchCharacter
), index
);
651 inline size_t StringImpl::find(LChar character
, unsigned start
)
654 return WTF::find(characters8(), m_length
, character
, start
);
655 return WTF::find(characters16(), m_length
, character
, start
);
658 ALWAYS_INLINE
size_t StringImpl::find(char character
, unsigned start
)
660 return find(static_cast<LChar
>(character
), start
);
663 inline size_t StringImpl::find(UChar character
, unsigned start
)
666 return WTF::find(characters8(), m_length
, character
, start
);
667 return WTF::find(characters16(), m_length
, character
, start
);
670 inline unsigned lengthOfNullTerminatedString(const UChar
* string
)
673 while (string
[length
] != UChar(0))
675 RELEASE_ASSERT(length
<= std::numeric_limits
<unsigned>::max());
676 return static_cast<unsigned>(length
);
679 template<size_t inlineCapacity
>
680 bool equalIgnoringNullity(const Vector
<UChar
, inlineCapacity
>& a
, StringImpl
* b
)
684 if (a
.size() != b
->length())
687 return equal(a
.data(), b
->characters8(), b
->length());
688 return equal(a
.data(), b
->characters16(), b
->length());
691 template<typename CharacterType1
, typename CharacterType2
>
692 static inline int codePointCompare(unsigned l1
, unsigned l2
, const CharacterType1
* c1
, const CharacterType2
* c2
)
694 const unsigned lmin
= l1
< l2
? l1
: l2
;
696 while (pos
< lmin
&& *c1
== *c2
) {
703 return (c1
[0] > c2
[0]) ? 1 : -1;
708 return (l1
> l2
) ? 1 : -1;
711 static inline int codePointCompare8(const StringImpl
* string1
, const StringImpl
* string2
)
713 return codePointCompare(string1
->length(), string2
->length(), string1
->characters8(), string2
->characters8());
716 static inline int codePointCompare16(const StringImpl
* string1
, const StringImpl
* string2
)
718 return codePointCompare(string1
->length(), string2
->length(), string1
->characters16(), string2
->characters16());
721 static inline int codePointCompare8To16(const StringImpl
* string1
, const StringImpl
* string2
)
723 return codePointCompare(string1
->length(), string2
->length(), string1
->characters8(), string2
->characters16());
726 static inline int codePointCompare(const StringImpl
* string1
, const StringImpl
* string2
)
729 return (string2
&& string2
->length()) ? -1 : 0;
732 return string1
->length() ? 1 : 0;
734 bool string1Is8Bit
= string1
->is8Bit();
735 bool string2Is8Bit
= string2
->is8Bit();
738 return codePointCompare8(string1
, string2
);
739 return codePointCompare8To16(string1
, string2
);
742 return -codePointCompare8To16(string2
, string1
);
743 return codePointCompare16(string1
, string2
);
746 static inline bool isSpaceOrNewline(UChar c
)
748 // Use isASCIISpace() for basic Latin-1.
749 // This will include newlines, which aren't included in Unicode DirWS.
750 return c
<= 0x7F ? WTF::isASCIISpace(c
) : WTF::Unicode::direction(c
) == WTF::Unicode::WhiteSpaceNeutral
;
753 inline PassRefPtr
<StringImpl
> StringImpl::isolatedCopy() const
756 return create(characters8(), m_length
);
757 return create(characters16(), m_length
);
760 // TODO(rob.buis) possibly find a better place for this method.
761 // Turns a UChar32 to uppercase based on localeIdentifier.
762 WTF_EXPORT UChar32
toUpper(UChar32
, const AtomicString
& localeIdentifier
);
766 // StringHash is the default hash for StringImpl* and RefPtr<StringImpl>
767 template<typename T
> struct DefaultHash
;
768 template<> struct DefaultHash
<StringImpl
*> {
769 typedef StringHash Hash
;
771 template<> struct DefaultHash
<RefPtr
<StringImpl
>> {
772 typedef StringHash Hash
;
777 using WTF::StringImpl
;
779 using WTF::equalNonNull
;
780 using WTF::TextCaseSensitivity
;
781 using WTF::TextCaseSensitive
;
782 using WTF::TextCaseInsensitive
;