2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 
   3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 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 "Collector.h" 
  27 #include "UStringImpl.h" 
  30 #include <wtf/Assertions.h> 
  31 #include <wtf/CrossThreadRefCounted.h> 
  32 #include <wtf/OwnFastMallocPtr.h> 
  33 #include <wtf/PassRefPtr.h> 
  34 #include <wtf/PtrAndFlags.h> 
  35 #include <wtf/RefPtr.h> 
  36 #include <wtf/Vector.h> 
  37 #include <wtf/unicode/Unicode.h> 
  41     using WTF::PlacementNewAdoptType
; 
  42     using WTF::PlacementNewAdopt
; 
  53         CString(const char*, size_t); 
  54         CString(const CString
&); 
  58         static CString 
adopt(char*, size_t); // buffer should be allocated with new[]. 
  60         CString
& append(const CString
&); 
  61         CString
& operator=(const char* c
); 
  62         CString
& operator=(const CString
&); 
  63         CString
& operator+=(const CString
& c
) { return append(c
); } 
  65         size_t size() const { return m_length
; } 
  66         const char* c_str() const { return m_data
; } 
  73     bool operator==(const CString
&, const CString
&); 
  75     typedef Vector
<char, 32> CStringBuffer
; 
  81         typedef UStringImpl Rep
; 
  84         // UString constructors passed char*s assume ISO Latin-1 encoding; for UTF8 use 'createFromUTF8', below. 
  86         UString(const char*); // Constructor for null-terminated string. 
  87         UString(const char*, int length
); 
  88         UString(const UChar
*, int length
); 
  89         UString(const Vector
<UChar
>& buffer
); 
  91         UString(const UString
& s
) 
  96         // Special constructor for cases where we overwrite an object in place. 
  97         UString(PlacementNewAdoptType
) 
  98             : m_rep(PlacementNewAdopt
) 
 106         template<size_t inlineCapacity
> 
 107         static PassRefPtr
<UStringImpl
> adopt(Vector
<UChar
, inlineCapacity
>& vector
) 
 109             return Rep::adopt(vector
); 
 112         static UString 
createFromUTF8(const char*); 
 114         static UString 
from(int); 
 115         static UString 
from(long long); 
 116         static UString 
from(unsigned int); 
 117         static UString 
from(long); 
 118         static UString 
from(double); 
 122             Range(int pos
, int len
) 
 136         UString 
spliceSubstringsWithSeparators(const Range
* substringRanges
, int rangeCount
, const UString
* separators
, int separatorCount
) const; 
 138         UString 
replaceRange(int rangeStart
, int RangeEnd
, const UString
& replacement
) const; 
 140         bool getCString(CStringBuffer
&) const; 
 142         // NOTE: This method should only be used for *debugging* purposes as it 
 143         // is neither Unicode safe nor free from side effects nor thread-safe. 
 147          * Convert the string to UTF-8, assuming it is UTF-16 encoded. 
 148          * In non-strict mode, this function is tolerant of badly formed UTF-16, it 
 149          * can create UTF-8 strings that are invalid because they have characters in 
 150          * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is 
 151          * guaranteed to be otherwise valid. 
 152          * In strict mode, error is returned as null CString. 
 154         CString 
UTF8String(bool strict 
= false) const; 
 156         UString
& operator=(const char*c
); 
 158         const UChar
* data() const { return m_rep
->data(); } 
 160         bool isNull() const { return m_rep 
== &Rep::null(); } 
 161         bool isEmpty() const { return !m_rep
->size(); } 
 165         int size() const { return m_rep
->size(); } 
 167         UChar 
operator[](int pos
) const; 
 169         double toDouble(bool tolerateTrailingJunk
, bool tolerateEmptyString
) const; 
 170         double toDouble(bool tolerateTrailingJunk
) const; 
 171         double toDouble() const; 
 173         uint32_t toUInt32(bool* ok 
= 0) const; 
 174         uint32_t toUInt32(bool* ok
, bool tolerateEmptyString
) const; 
 175         uint32_t toStrictUInt32(bool* ok 
= 0) const; 
 177         unsigned toArrayIndex(bool* ok 
= 0) const; 
 179         int find(const UString
& f
, int pos 
= 0) const; 
 180         int find(UChar
, int pos 
= 0) const; 
 181         int rfind(const UString
& f
, int pos
) const; 
 182         int rfind(UChar
, int pos
) const; 
 184         UString 
substr(int pos 
= 0, int len 
= -1) const; 
 186         static const UString
& null() { return *nullUString
; } 
 188         Rep
* rep() const { return m_rep
.get(); } 
 189         static Rep
* nullRep(); 
 191         UString(PassRefPtr
<Rep
> r
) 
 197         size_t cost() const { return m_rep
->cost(); } 
 203         static UString
* nullUString
; 
 205         friend void initializeUString(); 
 206         friend bool operator==(const UString
&, const UString
&); 
 209     ALWAYS_INLINE 
bool operator==(const UString
& s1
, const UString
& s2
) 
 211         int size 
= s1
.size(); 
 216             return s2
.size() == 1 && s1
.data()[0] == s2
.data()[0]; 
 220             const UChar
* d1 
= s1
.data(); 
 221             const UChar
* d2 
= s2
.data(); 
 222             return (d1
[0] == d2
[0]) & (d1
[1] == d2
[1]); 
 225             return s2
.size() == size 
&& memcmp(s1
.data(), s2
.data(), size 
* sizeof(UChar
)) == 0; 
 230     inline bool operator!=(const UString
& s1
, const UString
& s2
) 
 232         return !JSC::operator==(s1
, s2
); 
 235     bool operator<(const UString
& s1
, const UString
& s2
); 
 236     bool operator>(const UString
& s1
, const UString
& s2
); 
 238     bool operator==(const UString
& s1
, const char* s2
); 
 240     inline bool operator!=(const UString
& s1
, const char* s2
) 
 242         return !JSC::operator==(s1
, s2
); 
 245     inline bool operator==(const char *s1
, const UString
& s2
) 
 247         return operator==(s2
, s1
); 
 250     inline bool operator!=(const char *s1
, const UString
& s2
) 
 252         return !JSC::operator==(s1
, s2
); 
 255     int compare(const UString
&, const UString
&); 
 257     inline UString::UString() 
 258         : m_rep(&Rep::null()) 
 262     // Rule from ECMA 15.2 about what an array index is. 
 263     // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. 
 264     inline unsigned UString::toArrayIndex(bool* ok
) const 
 266         unsigned i 
= toStrictUInt32(ok
); 
 267         if (ok 
&& i 
>= 0xFFFFFFFFU
) 
 272     // We'd rather not do shared substring append for small strings, since 
 273     // this runs too much risk of a tiny initial string holding down a 
 275     // FIXME: this should be size_t but that would cause warnings until we 
 276     // fix UString sizes to be size_t instead of int 
 277     static const int minShareSize 
= Heap::minExtraCost 
/ sizeof(UChar
); 
 279     struct IdentifierRepHash 
: PtrHash
<RefPtr
<JSC::UString::Rep
> > { 
 280         static unsigned hash(const RefPtr
<JSC::UString::Rep
>& key
) { return key
->existingHash(); } 
 281         static unsigned hash(JSC::UString::Rep
* key
) { return key
->existingHash(); } 
 284     void initializeUString(); 
 286     template<typename StringType
> 
 287     class StringTypeAdapter 
{ 
 291     class StringTypeAdapter
<char*> { 
 293         StringTypeAdapter
<char*>(char* buffer
) 
 294             : m_buffer((unsigned char*)buffer
) 
 295             , m_length(strlen(buffer
)) 
 299         unsigned length() { return m_length
; } 
 301         void writeTo(UChar
* destination
) 
 303             for (unsigned i 
= 0; i 
< m_length
; ++i
) 
 304                 destination
[i
] = m_buffer
[i
]; 
 308         const unsigned char* m_buffer
; 
 313     class StringTypeAdapter
<const char*> { 
 315         StringTypeAdapter
<const char*>(const char* buffer
) 
 316             : m_buffer((unsigned char*)buffer
) 
 317             , m_length(strlen(buffer
)) 
 321         unsigned length() { return m_length
; } 
 323         void writeTo(UChar
* destination
) 
 325             for (unsigned i 
= 0; i 
< m_length
; ++i
) 
 326                 destination
[i
] = m_buffer
[i
]; 
 330         const unsigned char* m_buffer
; 
 335     class StringTypeAdapter
<UString
> { 
 337         StringTypeAdapter
<UString
>(UString
& string
) 
 338             : m_data(string
.data()) 
 339             , m_length(string
.size()) 
 343         unsigned length() { return m_length
; } 
 345         void writeTo(UChar
* destination
) 
 347             for (unsigned i 
= 0; i 
< m_length
; ++i
) 
 348                 destination
[i
] = m_data
[i
]; 
 356     template<typename StringType1
, typename StringType2
> 
 357     UString 
makeString(StringType1 string1
, StringType2 string2
) 
 359         StringTypeAdapter
<StringType1
> adapter1(string1
); 
 360         StringTypeAdapter
<StringType2
> adapter2(string2
); 
 363         unsigned length 
= adapter1
.length() + adapter2
.length(); 
 364         PassRefPtr
<UStringImpl
> resultImpl 
= UStringImpl::tryCreateUninitialized(length
, buffer
); 
 368         UChar
* result 
= buffer
; 
 369         adapter1
.writeTo(result
); 
 370         result 
+= adapter1
.length(); 
 371         adapter2
.writeTo(result
); 
 376     template<typename StringType1
, typename StringType2
, typename StringType3
> 
 377     UString 
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
) 
 379         StringTypeAdapter
<StringType1
> adapter1(string1
); 
 380         StringTypeAdapter
<StringType2
> adapter2(string2
); 
 381         StringTypeAdapter
<StringType3
> adapter3(string3
); 
 384         unsigned length 
= adapter1
.length() + adapter2
.length() + adapter3
.length(); 
 385         PassRefPtr
<UStringImpl
> resultImpl 
= UStringImpl::tryCreateUninitialized(length
, buffer
); 
 389         UChar
* result 
= buffer
; 
 390         adapter1
.writeTo(result
); 
 391         result 
+= adapter1
.length(); 
 392         adapter2
.writeTo(result
); 
 393         result 
+= adapter2
.length(); 
 394         adapter3
.writeTo(result
); 
 399     template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
> 
 400     UString 
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
) 
 402         StringTypeAdapter
<StringType1
> adapter1(string1
); 
 403         StringTypeAdapter
<StringType2
> adapter2(string2
); 
 404         StringTypeAdapter
<StringType3
> adapter3(string3
); 
 405         StringTypeAdapter
<StringType4
> adapter4(string4
); 
 408         unsigned length 
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length(); 
 409         PassRefPtr
<UStringImpl
> resultImpl 
= UStringImpl::tryCreateUninitialized(length
, buffer
); 
 413         UChar
* result 
= buffer
; 
 414         adapter1
.writeTo(result
); 
 415         result 
+= adapter1
.length(); 
 416         adapter2
.writeTo(result
); 
 417         result 
+= adapter2
.length(); 
 418         adapter3
.writeTo(result
); 
 419         result 
+= adapter3
.length(); 
 420         adapter4
.writeTo(result
); 
 425     template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
, typename StringType5
> 
 426     UString 
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
, StringType5 string5
) 
 428         StringTypeAdapter
<StringType1
> adapter1(string1
); 
 429         StringTypeAdapter
<StringType2
> adapter2(string2
); 
 430         StringTypeAdapter
<StringType3
> adapter3(string3
); 
 431         StringTypeAdapter
<StringType4
> adapter4(string4
); 
 432         StringTypeAdapter
<StringType5
> adapter5(string5
); 
 435         unsigned length 
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length() + adapter5
.length(); 
 436         PassRefPtr
<UStringImpl
> resultImpl 
= UStringImpl::tryCreateUninitialized(length
, buffer
); 
 440         UChar
* result 
= buffer
; 
 441         adapter1
.writeTo(result
); 
 442         result 
+= adapter1
.length(); 
 443         adapter2
.writeTo(result
); 
 444         result 
+= adapter2
.length(); 
 445         adapter3
.writeTo(result
); 
 446         result 
+= adapter3
.length(); 
 447         adapter4
.writeTo(result
); 
 448         result 
+= adapter4
.length(); 
 449         adapter5
.writeTo(result
); 
 454     template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
, typename StringType5
, typename StringType6
> 
 455     UString 
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
, StringType5 string5
, StringType6 string6
) 
 457         StringTypeAdapter
<StringType1
> adapter1(string1
); 
 458         StringTypeAdapter
<StringType2
> adapter2(string2
); 
 459         StringTypeAdapter
<StringType3
> adapter3(string3
); 
 460         StringTypeAdapter
<StringType4
> adapter4(string4
); 
 461         StringTypeAdapter
<StringType5
> adapter5(string5
); 
 462         StringTypeAdapter
<StringType6
> adapter6(string6
); 
 465         unsigned length 
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length() + adapter5
.length() + adapter6
.length(); 
 466         PassRefPtr
<UStringImpl
> resultImpl 
= UStringImpl::tryCreateUninitialized(length
, buffer
); 
 470         UChar
* result 
= buffer
; 
 471         adapter1
.writeTo(result
); 
 472         result 
+= adapter1
.length(); 
 473         adapter2
.writeTo(result
); 
 474         result 
+= adapter2
.length(); 
 475         adapter3
.writeTo(result
); 
 476         result 
+= adapter3
.length(); 
 477         adapter4
.writeTo(result
); 
 478         result 
+= adapter4
.length(); 
 479         adapter5
.writeTo(result
); 
 480         result 
+= adapter5
.length(); 
 481         adapter6
.writeTo(result
); 
 486     template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
, typename StringType5
, typename StringType6
, typename StringType7
> 
 487     UString 
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
, StringType5 string5
, StringType6 string6
, StringType7 string7
) 
 489         StringTypeAdapter
<StringType1
> adapter1(string1
); 
 490         StringTypeAdapter
<StringType2
> adapter2(string2
); 
 491         StringTypeAdapter
<StringType3
> adapter3(string3
); 
 492         StringTypeAdapter
<StringType4
> adapter4(string4
); 
 493         StringTypeAdapter
<StringType5
> adapter5(string5
); 
 494         StringTypeAdapter
<StringType6
> adapter6(string6
); 
 495         StringTypeAdapter
<StringType7
> adapter7(string7
); 
 498         unsigned length 
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length() + adapter5
.length() + adapter6
.length() + adapter7
.length(); 
 499         PassRefPtr
<UStringImpl
> resultImpl 
= UStringImpl::tryCreateUninitialized(length
, buffer
); 
 503         UChar
* result 
= buffer
; 
 504         adapter1
.writeTo(result
); 
 505         result 
+= adapter1
.length(); 
 506         adapter2
.writeTo(result
); 
 507         result 
+= adapter2
.length(); 
 508         adapter3
.writeTo(result
); 
 509         result 
+= adapter3
.length(); 
 510         adapter4
.writeTo(result
); 
 511         result 
+= adapter4
.length(); 
 512         adapter5
.writeTo(result
); 
 513         result 
+= adapter5
.length(); 
 514         adapter6
.writeTo(result
); 
 515         result 
+= adapter6
.length(); 
 516         adapter7
.writeTo(result
); 
 521     template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
, typename StringType5
, typename StringType6
, typename StringType7
, typename StringType8
> 
 522     UString 
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
, StringType5 string5
, StringType6 string6
, StringType7 string7
, StringType8 string8
) 
 524         StringTypeAdapter
<StringType1
> adapter1(string1
); 
 525         StringTypeAdapter
<StringType2
> adapter2(string2
); 
 526         StringTypeAdapter
<StringType3
> adapter3(string3
); 
 527         StringTypeAdapter
<StringType4
> adapter4(string4
); 
 528         StringTypeAdapter
<StringType5
> adapter5(string5
); 
 529         StringTypeAdapter
<StringType6
> adapter6(string6
); 
 530         StringTypeAdapter
<StringType7
> adapter7(string7
); 
 531         StringTypeAdapter
<StringType8
> adapter8(string8
); 
 534         unsigned length 
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length() + adapter5
.length() + adapter6
.length() + adapter7
.length() + adapter8
.length(); 
 535         PassRefPtr
<UStringImpl
> resultImpl 
= UStringImpl::tryCreateUninitialized(length
, buffer
); 
 539         UChar
* result 
= buffer
; 
 540         adapter1
.writeTo(result
); 
 541         result 
+= adapter1
.length(); 
 542         adapter2
.writeTo(result
); 
 543         result 
+= adapter2
.length(); 
 544         adapter3
.writeTo(result
); 
 545         result 
+= adapter3
.length(); 
 546         adapter4
.writeTo(result
); 
 547         result 
+= adapter4
.length(); 
 548         adapter5
.writeTo(result
); 
 549         result 
+= adapter5
.length(); 
 550         adapter6
.writeTo(result
); 
 551         result 
+= adapter6
.length(); 
 552         adapter7
.writeTo(result
); 
 553         result 
+= adapter7
.length(); 
 554         adapter8
.writeTo(result
); 
 563     template<typename T
> struct DefaultHash
; 
 564     template<typename T
> struct StrHash
; 
 566     template<> struct StrHash
<JSC::UString::Rep
*> { 
 567         static unsigned hash(const JSC::UString::Rep
* key
) { return key
->hash(); } 
 568         static bool equal(const JSC::UString::Rep
* a
, const JSC::UString::Rep
* b
) { return JSC::equal(a
, b
); } 
 569         static const bool safeToCompareToEmptyOrDeleted 
= false; 
 572     template<> struct StrHash
<RefPtr
<JSC::UString::Rep
> > : public StrHash
<JSC::UString::Rep
*> { 
 573         using StrHash
<JSC::UString::Rep
*>::hash
; 
 574         static unsigned hash(const RefPtr
<JSC::UString::Rep
>& key
) { return key
->hash(); } 
 575         using StrHash
<JSC::UString::Rep
*>::equal
; 
 576         static bool equal(const RefPtr
<JSC::UString::Rep
>& a
, const RefPtr
<JSC::UString::Rep
>& b
) { return JSC::equal(a
.get(), b
.get()); } 
 577         static bool equal(const JSC::UString::Rep
* a
, const RefPtr
<JSC::UString::Rep
>& b
) { return JSC::equal(a
, b
.get()); } 
 578         static bool equal(const RefPtr
<JSC::UString::Rep
>& a
, const JSC::UString::Rep
* b
) { return JSC::equal(a
.get(), b
); } 
 580         static const bool safeToCompareToEmptyOrDeleted 
= false; 
 583     template<> struct DefaultHash
<JSC::UString::Rep
*> { 
 584         typedef StrHash
<JSC::UString::Rep
*> Hash
; 
 587     template<> struct DefaultHash
<RefPtr
<JSC::UString::Rep
> > { 
 588         typedef StrHash
<RefPtr
<JSC::UString::Rep
> > Hash
;