2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller ( mueller@kde.org )
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 #include "StringImpl.h"
28 #include "AtomicString.h"
29 #include "StringBuffer.h"
30 #include "StringHash.h"
31 #include <wtf/StdLibExtras.h>
32 #include <wtf/WTFThreadData.h>
35 using namespace Unicode
;
40 static const unsigned minLengthToShare
= 20;
42 StringImpl::~StringImpl()
47 AtomicString::remove(this);
50 wtfThreadData().currentIdentifierTable()->remove(this);
53 BufferOwnership ownership
= bufferOwnership();
54 if (ownership
!= BufferInternal
) {
55 if (ownership
== BufferOwned
) {
56 ASSERT(!m_sharedBuffer
);
58 fastFree(const_cast<UChar
*>(m_data
));
59 } else if (ownership
== BufferSubstring
) {
60 ASSERT(m_substringBuffer
);
61 m_substringBuffer
->deref();
63 ASSERT(ownership
== BufferShared
);
64 ASSERT(m_sharedBuffer
);
65 m_sharedBuffer
->deref();
70 PassRefPtr
<StringImpl
> StringImpl::createUninitialized(unsigned length
, UChar
*& data
)
77 // Allocate a single buffer large enough to contain the StringImpl
78 // struct as well as the data which it contains. This removes one
79 // heap allocation from this call.
80 if (length
> ((std::numeric_limits
<unsigned>::max() - sizeof(StringImpl
)) / sizeof(UChar
)))
82 size_t size
= sizeof(StringImpl
) + length
* sizeof(UChar
);
83 StringImpl
* string
= static_cast<StringImpl
*>(fastMalloc(size
));
85 data
= reinterpret_cast<UChar
*>(string
+ 1);
86 return adoptRef(new (string
) StringImpl(length
));
89 PassRefPtr
<StringImpl
> StringImpl::create(const UChar
* characters
, unsigned length
)
91 if (!characters
|| !length
)
95 RefPtr
<StringImpl
> string
= createUninitialized(length
, data
);
96 memcpy(data
, characters
, length
* sizeof(UChar
));
97 return string
.release();
100 PassRefPtr
<StringImpl
> StringImpl::create(const char* characters
, unsigned length
)
102 if (!characters
|| !length
)
106 RefPtr
<StringImpl
> string
= createUninitialized(length
, data
);
107 for (unsigned i
= 0; i
!= length
; ++i
) {
108 unsigned char c
= characters
[i
];
111 return string
.release();
114 PassRefPtr
<StringImpl
> StringImpl::create(const char* string
)
118 size_t length
= strlen(string
);
119 if (length
> numeric_limits
<unsigned>::max())
121 return create(string
, length
);
124 PassRefPtr
<StringImpl
> StringImpl::create(const UChar
* characters
, unsigned length
, PassRefPtr
<SharedUChar
> sharedBuffer
)
127 ASSERT(minLengthToShare
&& length
>= minLengthToShare
);
128 return adoptRef(new StringImpl(characters
, length
, sharedBuffer
));
131 SharedUChar
* StringImpl::sharedBuffer()
133 if (m_length
< minLengthToShare
)
135 // All static strings are smaller that the minimim length to share.
138 BufferOwnership ownership
= bufferOwnership();
140 if (ownership
== BufferInternal
)
142 if (ownership
== BufferSubstring
)
143 return m_substringBuffer
->sharedBuffer();
144 if (ownership
== BufferOwned
) {
145 ASSERT(!m_sharedBuffer
);
146 m_sharedBuffer
= SharedUChar::create(new SharableUChar(m_data
)).releaseRef();
147 m_refCountAndFlags
= (m_refCountAndFlags
& ~s_refCountMaskBufferOwnership
) | BufferShared
;
150 ASSERT(bufferOwnership() == BufferShared
);
151 ASSERT(m_sharedBuffer
);
152 return m_sharedBuffer
;
155 bool StringImpl::containsOnlyWhitespace()
157 // FIXME: The definition of whitespace here includes a number of characters
158 // that are not whitespace from the point of view of RenderText; I wonder if
159 // that's a problem in practice.
160 for (unsigned i
= 0; i
< m_length
; i
++)
161 if (!isASCIISpace(m_data
[i
]))
166 PassRefPtr
<StringImpl
> StringImpl::substring(unsigned start
, unsigned length
)
168 if (start
>= m_length
)
170 unsigned maxLength
= m_length
- start
;
171 if (length
>= maxLength
) {
176 return create(m_data
+ start
, length
);
179 UChar32
StringImpl::characterStartingAt(unsigned i
)
181 if (U16_IS_SINGLE(m_data
[i
]))
183 if (i
+ 1 < m_length
&& U16_IS_LEAD(m_data
[i
]) && U16_IS_TRAIL(m_data
[i
+ 1]))
184 return U16_GET_SUPPLEMENTARY(m_data
[i
], m_data
[i
+ 1]);
188 PassRefPtr
<StringImpl
> StringImpl::lower()
190 // Note: This is a hot function in the Dromaeo benchmark, specifically the
191 // no-op code path up through the first 'return' statement.
193 // First scan the string for uppercase and non-ASCII characters:
196 const UChar
*end
= m_data
+ m_length
;
197 for (const UChar
* chp
= m_data
; chp
!= end
; chp
++) {
198 if (UNLIKELY(isASCIIUpper(*chp
)))
203 // Nothing to do if the string is all ASCII with no uppercase.
204 if (noUpper
&& !(ored
& ~0x7F))
207 if (m_length
> static_cast<unsigned>(numeric_limits
<int32_t>::max()))
209 int32_t length
= m_length
;
212 RefPtr
<StringImpl
> newImpl
= createUninitialized(m_length
, data
);
214 if (!(ored
& ~0x7F)) {
215 // Do a faster loop for the case where all the characters are ASCII.
216 for (int i
= 0; i
< length
; i
++) {
218 data
[i
] = toASCIILower(c
);
223 // Do a slower implementation for cases that include non-ASCII characters.
225 int32_t realLength
= Unicode::toLower(data
, length
, m_data
, m_length
, &error
);
226 if (!error
&& realLength
== length
)
228 newImpl
= createUninitialized(realLength
, data
);
229 Unicode::toLower(data
, realLength
, m_data
, m_length
, &error
);
235 PassRefPtr
<StringImpl
> StringImpl::upper()
237 // This function could be optimized for no-op cases the way lower() is,
238 // but in empirical testing, few actual calls to upper() are no-ops, so
239 // it wouldn't be worth the extra time for pre-scanning.
241 RefPtr
<StringImpl
> newImpl
= createUninitialized(m_length
, data
);
243 if (m_length
> static_cast<unsigned>(numeric_limits
<int32_t>::max()))
245 int32_t length
= m_length
;
247 // Do a faster loop for the case where all the characters are ASCII.
249 for (int i
= 0; i
< length
; i
++) {
252 data
[i
] = toASCIIUpper(c
);
255 return newImpl
.release();
257 // Do a slower implementation for cases that include non-ASCII characters.
259 int32_t realLength
= Unicode::toUpper(data
, length
, m_data
, m_length
, &error
);
260 if (!error
&& realLength
== length
)
262 newImpl
= createUninitialized(realLength
, data
);
263 Unicode::toUpper(data
, realLength
, m_data
, m_length
, &error
);
266 return newImpl
.release();
269 PassRefPtr
<StringImpl
> StringImpl::secure(UChar character
, bool hideLastCharacter
)
272 RefPtr
<StringImpl
> newImpl
= createUninitialized(m_length
, data
);
274 const unsigned lastCharacterIndex
= m_length
- 1;
275 for (unsigned i
= 0; i
< lastCharacterIndex
; ++i
)
277 data
[lastCharacterIndex
] = hideLastCharacter
? character
: m_data
[lastCharacterIndex
];
279 return newImpl
.release();
282 PassRefPtr
<StringImpl
> StringImpl::foldCase()
285 RefPtr
<StringImpl
> newImpl
= createUninitialized(m_length
, data
);
287 if (m_length
> static_cast<unsigned>(numeric_limits
<int32_t>::max()))
289 int32_t length
= m_length
;
291 // Do a faster loop for the case where all the characters are ASCII.
293 for (int32_t i
= 0; i
< length
; i
++) {
296 data
[i
] = toASCIILower(c
);
299 return newImpl
.release();
301 // Do a slower implementation for cases that include non-ASCII characters.
303 int32_t realLength
= Unicode::foldCase(data
, length
, m_data
, m_length
, &error
);
304 if (!error
&& realLength
== length
)
305 return newImpl
.release();
306 newImpl
= createUninitialized(realLength
, data
);
307 Unicode::foldCase(data
, realLength
, m_data
, m_length
, &error
);
310 return newImpl
.release();
313 PassRefPtr
<StringImpl
> StringImpl::stripWhiteSpace()
319 unsigned end
= m_length
- 1;
321 // skip white space from start
322 while (start
<= end
&& isSpaceOrNewline(m_data
[start
]))
329 // skip white space from end
330 while (end
&& isSpaceOrNewline(m_data
[end
]))
333 if (!start
&& end
== m_length
- 1)
335 return create(m_data
+ start
, end
+ 1 - start
);
338 PassRefPtr
<StringImpl
> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch
)
340 const UChar
* from
= m_data
;
341 const UChar
* fromend
= from
+ m_length
;
343 // Assume the common case will not remove any characters
344 while (from
!= fromend
&& !findMatch(*from
))
349 StringBuffer
data(m_length
);
350 UChar
* to
= data
.characters();
351 unsigned outc
= from
- m_data
;
354 memcpy(to
, m_data
, outc
* sizeof(UChar
));
357 while (from
!= fromend
&& findMatch(*from
))
359 while (from
!= fromend
&& !findMatch(*from
))
360 to
[outc
++] = *from
++;
370 PassRefPtr
<StringImpl
> StringImpl::simplifyWhiteSpace()
372 StringBuffer
data(m_length
);
374 const UChar
* from
= m_data
;
375 const UChar
* fromend
= from
+ m_length
;
377 bool changedToSpace
= false;
379 UChar
* to
= data
.characters();
382 while (from
!= fromend
&& isSpaceOrNewline(*from
)) {
384 changedToSpace
= true;
387 while (from
!= fromend
&& !isSpaceOrNewline(*from
))
388 to
[outc
++] = *from
++;
395 if (outc
> 0 && to
[outc
- 1] == ' ')
398 if (static_cast<unsigned>(outc
) == m_length
&& !changedToSpace
)
406 int StringImpl::toIntStrict(bool* ok
, int base
)
408 return charactersToIntStrict(m_data
, m_length
, ok
, base
);
411 unsigned StringImpl::toUIntStrict(bool* ok
, int base
)
413 return charactersToUIntStrict(m_data
, m_length
, ok
, base
);
416 int64_t StringImpl::toInt64Strict(bool* ok
, int base
)
418 return charactersToInt64Strict(m_data
, m_length
, ok
, base
);
421 uint64_t StringImpl::toUInt64Strict(bool* ok
, int base
)
423 return charactersToUInt64Strict(m_data
, m_length
, ok
, base
);
426 intptr_t StringImpl::toIntPtrStrict(bool* ok
, int base
)
428 return charactersToIntPtrStrict(m_data
, m_length
, ok
, base
);
431 int StringImpl::toInt(bool* ok
)
433 return charactersToInt(m_data
, m_length
, ok
);
436 unsigned StringImpl::toUInt(bool* ok
)
438 return charactersToUInt(m_data
, m_length
, ok
);
441 int64_t StringImpl::toInt64(bool* ok
)
443 return charactersToInt64(m_data
, m_length
, ok
);
446 uint64_t StringImpl::toUInt64(bool* ok
)
448 return charactersToUInt64(m_data
, m_length
, ok
);
451 intptr_t StringImpl::toIntPtr(bool* ok
)
453 return charactersToIntPtr(m_data
, m_length
, ok
);
456 double StringImpl::toDouble(bool* ok
)
458 return charactersToDouble(m_data
, m_length
, ok
);
461 float StringImpl::toFloat(bool* ok
)
463 return charactersToFloat(m_data
, m_length
, ok
);
466 static bool equal(const UChar
* a
, const char* b
, int length
)
470 unsigned char bc
= *b
++;
477 bool equalIgnoringCase(const UChar
* a
, const char* b
, unsigned length
)
480 unsigned char bc
= *b
++;
481 if (foldCase(*a
++) != foldCase(bc
))
487 static inline bool equalIgnoringCase(const UChar
* a
, const UChar
* b
, int length
)
490 return umemcasecmp(a
, b
, length
) == 0;
493 int StringImpl::find(const char* chs
, int index
, bool caseSensitive
)
495 if (!chs
|| index
< 0)
498 size_t matchStringLength
= strlen(chs
);
499 if (matchStringLength
> static_cast<unsigned>(numeric_limits
<int>::max()))
501 int chsLength
= matchStringLength
;
502 int n
= m_length
- index
;
509 const char* chsPlusOne
= chs
+ 1;
510 int chsLengthMinusOne
= chsLength
- 1;
512 const UChar
* ptr
= m_data
+ index
- 1;
516 if (*++ptr
== c
&& equal(ptr
+ 1, chsPlusOne
, chsLengthMinusOne
))
517 return m_length
- chsLength
- n
+ 1;
520 UChar lc
= Unicode::foldCase(*chs
);
522 if (Unicode::foldCase(*++ptr
) == lc
&& equalIgnoringCase(ptr
+ 1, chsPlusOne
, chsLengthMinusOne
))
523 return m_length
- chsLength
- n
+ 1;
530 int StringImpl::find(UChar c
, int start
)
532 return WebCore::find(m_data
, m_length
, c
, start
);
535 int StringImpl::find(CharacterMatchFunctionPtr matchFunction
, int start
)
537 return WebCore::find(m_data
, m_length
, matchFunction
, start
);
540 int StringImpl::find(StringImpl
* str
, int index
, bool caseSensitive
)
543 We use a simple trick for efficiency's sake. Instead of
544 comparing strings, we compare the sum of str with that of
545 a part of this string. Only if that matches, we call memcmp
551 int lstr
= str
->m_length
;
552 int lthis
= m_length
- index
;
553 if ((unsigned)lthis
> m_length
)
555 int delta
= lthis
- lstr
;
559 const UChar
* uthis
= m_data
+ index
;
560 const UChar
* ustr
= str
->m_data
;
564 for (int i
= 0; i
< lstr
; i
++) {
570 if (hthis
== hstr
&& memcmp(uthis
+ i
, ustr
, lstr
* sizeof(UChar
)) == 0)
574 hthis
+= uthis
[i
+ lstr
];
579 for (int i
= 0; i
< lstr
; i
++ ) {
580 hthis
+= toASCIILower(uthis
[i
]);
581 hstr
+= toASCIILower(ustr
[i
]);
585 if (hthis
== hstr
&& equalIgnoringCase(uthis
+ i
, ustr
, lstr
))
589 hthis
+= toASCIILower(uthis
[i
+ lstr
]);
590 hthis
-= toASCIILower(uthis
[i
]);
596 int StringImpl::reverseFind(UChar c
, int index
)
598 return WebCore::reverseFind(m_data
, m_length
, c
, index
);
601 int StringImpl::reverseFind(StringImpl
* str
, int index
, bool caseSensitive
)
604 See StringImpl::find() for explanations.
607 int lthis
= m_length
;
611 int lstr
= str
->m_length
;
612 int delta
= lthis
- lstr
;
613 if ( index
< 0 || index
> lthis
|| delta
< 0 )
618 const UChar
*uthis
= m_data
;
619 const UChar
*ustr
= str
->m_data
;
624 for ( i
= 0; i
< lstr
; i
++ ) {
625 hthis
+= uthis
[index
+ i
];
630 if (hthis
== hstr
&& memcmp(uthis
+ i
, ustr
, lstr
* sizeof(UChar
)) == 0)
635 hthis
-= uthis
[i
+ lstr
];
639 for (i
= 0; i
< lstr
; i
++) {
640 hthis
+= toASCIILower(uthis
[index
+ i
]);
641 hstr
+= toASCIILower(ustr
[i
]);
645 if (hthis
== hstr
&& equalIgnoringCase(uthis
+ i
, ustr
, lstr
) )
650 hthis
-= toASCIILower(uthis
[i
+ lstr
]);
651 hthis
+= toASCIILower(uthis
[i
]);
655 // Should never get here.
659 bool StringImpl::endsWith(StringImpl
* m_data
, bool caseSensitive
)
662 int start
= m_length
- m_data
->m_length
;
664 return (find(m_data
, start
, caseSensitive
) == start
);
668 PassRefPtr
<StringImpl
> StringImpl::replace(UChar oldC
, UChar newC
)
673 for (i
= 0; i
!= m_length
; ++i
)
674 if (m_data
[i
] == oldC
)
680 RefPtr
<StringImpl
> newImpl
= createUninitialized(m_length
, data
);
682 for (i
= 0; i
!= m_length
; ++i
) {
683 UChar ch
= m_data
[i
];
688 return newImpl
.release();
691 PassRefPtr
<StringImpl
> StringImpl::replace(unsigned position
, unsigned lengthToReplace
, StringImpl
* str
)
693 position
= min(position
, length());
694 lengthToReplace
= min(lengthToReplace
, length() - position
);
695 unsigned lengthToInsert
= str
? str
->length() : 0;
696 if (!lengthToReplace
&& !lengthToInsert
)
700 if ((length() - lengthToReplace
) >= (numeric_limits
<unsigned>::max() - lengthToInsert
))
703 RefPtr
<StringImpl
> newImpl
=
704 createUninitialized(length() - lengthToReplace
+ lengthToInsert
, data
);
705 memcpy(data
, characters(), position
* sizeof(UChar
));
707 memcpy(data
+ position
, str
->characters(), lengthToInsert
* sizeof(UChar
));
708 memcpy(data
+ position
+ lengthToInsert
, characters() + position
+ lengthToReplace
,
709 (length() - position
- lengthToReplace
) * sizeof(UChar
));
710 return newImpl
.release();
713 PassRefPtr
<StringImpl
> StringImpl::replace(UChar pattern
, StringImpl
* replacement
)
718 int repStrLength
= replacement
->length();
719 int srcSegmentStart
= 0;
720 unsigned matchCount
= 0;
723 while ((srcSegmentStart
= find(pattern
, srcSegmentStart
)) >= 0) {
728 // If we have 0 matches, we don't have to do any more work
732 if (repStrLength
&& matchCount
> numeric_limits
<unsigned>::max() / repStrLength
)
735 unsigned replaceSize
= matchCount
* repStrLength
;
736 unsigned newSize
= m_length
- matchCount
;
737 if (newSize
>= (numeric_limits
<unsigned>::max() - replaceSize
))
740 newSize
+= replaceSize
;
743 RefPtr
<StringImpl
> newImpl
= createUninitialized(newSize
, data
);
745 // Construct the new data
747 int srcSegmentLength
;
751 while ((srcSegmentEnd
= find(pattern
, srcSegmentStart
)) >= 0) {
752 srcSegmentLength
= srcSegmentEnd
- srcSegmentStart
;
753 memcpy(data
+ dstOffset
, m_data
+ srcSegmentStart
, srcSegmentLength
* sizeof(UChar
));
754 dstOffset
+= srcSegmentLength
;
755 memcpy(data
+ dstOffset
, replacement
->m_data
, repStrLength
* sizeof(UChar
));
756 dstOffset
+= repStrLength
;
757 srcSegmentStart
= srcSegmentEnd
+ 1;
760 srcSegmentLength
= m_length
- srcSegmentStart
;
761 memcpy(data
+ dstOffset
, m_data
+ srcSegmentStart
, srcSegmentLength
* sizeof(UChar
));
763 ASSERT(dstOffset
+ srcSegmentLength
== static_cast<int>(newImpl
->length()));
765 return newImpl
.release();
768 PassRefPtr
<StringImpl
> StringImpl::replace(StringImpl
* pattern
, StringImpl
* replacement
)
770 if (!pattern
|| !replacement
)
773 int patternLength
= pattern
->length();
777 int repStrLength
= replacement
->length();
778 int srcSegmentStart
= 0;
779 unsigned matchCount
= 0;
782 while ((srcSegmentStart
= find(pattern
, srcSegmentStart
)) >= 0) {
784 srcSegmentStart
+= patternLength
;
787 // If we have 0 matches, we don't have to do any more work
791 unsigned newSize
= m_length
- matchCount
* patternLength
;
792 if (repStrLength
&& matchCount
> numeric_limits
<unsigned>::max() / repStrLength
)
795 if (newSize
> (numeric_limits
<unsigned>::max() - matchCount
* repStrLength
))
798 newSize
+= matchCount
* repStrLength
;
801 RefPtr
<StringImpl
> newImpl
= createUninitialized(newSize
, data
);
803 // Construct the new data
805 int srcSegmentLength
;
809 while ((srcSegmentEnd
= find(pattern
, srcSegmentStart
)) >= 0) {
810 srcSegmentLength
= srcSegmentEnd
- srcSegmentStart
;
811 memcpy(data
+ dstOffset
, m_data
+ srcSegmentStart
, srcSegmentLength
* sizeof(UChar
));
812 dstOffset
+= srcSegmentLength
;
813 memcpy(data
+ dstOffset
, replacement
->m_data
, repStrLength
* sizeof(UChar
));
814 dstOffset
+= repStrLength
;
815 srcSegmentStart
= srcSegmentEnd
+ patternLength
;
818 srcSegmentLength
= m_length
- srcSegmentStart
;
819 memcpy(data
+ dstOffset
, m_data
+ srcSegmentStart
, srcSegmentLength
* sizeof(UChar
));
821 ASSERT(dstOffset
+ srcSegmentLength
== static_cast<int>(newImpl
->length()));
823 return newImpl
.release();
826 bool equal(const StringImpl
* a
, const StringImpl
* b
)
828 return StringHash::equal(a
, b
);
831 bool equal(const StringImpl
* a
, const char* b
)
838 unsigned length
= a
->length();
839 const UChar
* as
= a
->characters();
840 for (unsigned i
= 0; i
!= length
; ++i
) {
841 unsigned char bc
= b
[i
];
851 bool equalIgnoringCase(StringImpl
* a
, StringImpl
* b
)
853 return CaseFoldingHash::equal(a
, b
);
856 bool equalIgnoringCase(StringImpl
* a
, const char* b
)
863 unsigned length
= a
->length();
864 const UChar
* as
= a
->characters();
866 // Do a faster loop for the case where all the characters are ASCII.
869 for (unsigned i
= 0; i
!= length
; ++i
) {
875 equal
= equal
&& (toASCIILower(ac
) == toASCIILower(bc
));
878 // Do a slower implementation for cases that include non-ASCII characters.
881 for (unsigned i
= 0; i
!= length
; ++i
) {
882 unsigned char bc
= b
[i
];
883 equal
= equal
&& (foldCase(as
[i
]) == foldCase(bc
));
887 return equal
&& !b
[length
];
890 bool equalIgnoringNullity(StringImpl
* a
, StringImpl
* b
)
892 if (StringHash::equal(a
, b
))
894 if (!a
&& b
&& !b
->length())
896 if (!b
&& a
&& !a
->length())
902 Vector
<char> StringImpl::ascii()
904 Vector
<char> buffer(m_length
+ 1);
905 for (unsigned i
= 0; i
!= m_length
; ++i
) {
907 if ((c
>= 0x20 && c
< 0x7F) || c
== 0x00)
908 buffer
[i
] = static_cast<char>(c
);
912 buffer
[m_length
] = '\0';
916 WTF::Unicode::Direction
StringImpl::defaultWritingDirection()
918 for (unsigned i
= 0; i
< m_length
; ++i
) {
919 WTF::Unicode::Direction charDirection
= WTF::Unicode::direction(m_data
[i
]);
920 if (charDirection
== WTF::Unicode::LeftToRight
)
921 return WTF::Unicode::LeftToRight
;
922 if (charDirection
== WTF::Unicode::RightToLeft
|| charDirection
== WTF::Unicode::RightToLeftArabic
)
923 return WTF::Unicode::RightToLeft
;
925 return WTF::Unicode::LeftToRight
;
928 // This is a hot function because it's used when parsing HTML.
929 PassRefPtr
<StringImpl
> StringImpl::createStrippingNullCharactersSlowCase(const UChar
* characters
, unsigned length
)
931 StringBuffer
strippedCopy(length
);
932 unsigned strippedLength
= 0;
933 for (unsigned i
= 0; i
< length
; i
++) {
934 if (int c
= characters
[i
])
935 strippedCopy
[strippedLength
++] = c
;
937 ASSERT(strippedLength
< length
); // Only take the slow case when stripping.
938 strippedCopy
.shrink(strippedLength
);
939 return adopt(strippedCopy
);
942 PassRefPtr
<StringImpl
> StringImpl::adopt(StringBuffer
& buffer
)
944 unsigned length
= buffer
.length();
947 return adoptRef(new StringImpl(buffer
.release(), length
));
950 int StringImpl::wordCount(int maxWordsToCount
)
952 unsigned wordCount
= 0;
955 for (i
= 0; i
< m_length
; i
++) {
956 if (u_isspace(m_data
[i
])) {
958 } else if (!atWord
) {
960 if (wordCount
>= (unsigned)maxWordsToCount
)
968 PassRefPtr
<StringImpl
> StringImpl::createWithTerminatingNullCharacter(const StringImpl
& string
)
970 // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer
971 // get allocated in a single memory block.
973 unsigned length
= string
.m_length
;
974 if (length
>= numeric_limits
<unsigned>::max())
976 RefPtr
<StringImpl
> terminatedString
= createUninitialized(length
+ 1, data
);
977 memcpy(data
, string
.m_data
, length
* sizeof(UChar
));
979 terminatedString
->m_length
--;
980 terminatedString
->m_hash
= string
.m_hash
;
981 terminatedString
->m_refCountAndFlags
|= s_refCountFlagHasTerminatingNullCharacter
;
982 return terminatedString
.release();
985 PassRefPtr
<StringImpl
> StringImpl::threadsafeCopy() const
987 return create(m_data
, m_length
);
990 PassRefPtr
<StringImpl
> StringImpl::crossThreadString()
992 if (SharedUChar
* sharedBuffer
= this->sharedBuffer())
993 return adoptRef(new StringImpl(m_data
, m_length
, sharedBuffer
->crossThreadCopy()));
995 // If no shared buffer is available, create a copy.
996 return threadsafeCopy();
999 } // namespace WebCore