Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 1999-2000 Harri Porten (porten (at) 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.
      5  *
      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.
     10  *
     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.
     15  *
     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.
     20  *
     21  */
     22 
     23 #ifndef UString_h
     24 #define UString_h
     25 
     26 #include "Collector.h"
     27 #include "UStringImpl.h"
     28 #include <stdint.h>
     29 #include <string.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>
     38 
     39 namespace JSC {
     40 
     41     using WTF::PlacementNewAdoptType;
     42     using WTF::PlacementNewAdopt;
     43 
     44     class CString {
     45     public:
     46         CString()
     47             : m_length(0)
     48             , m_data(0)
     49         {
     50         }
     51 
     52         CString(const char*);
     53         CString(const char*, size_t);
     54         CString(const CString&);
     55 
     56         ~CString();
     57 
     58         static CString adopt(char*, size_t); // buffer should be allocated with new[].
     59 
     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); }
     64 
     65         size_t size() const { return m_length; }
     66         const char* c_str() const { return m_data; }
     67 
     68     private:
     69         size_t m_length;
     70         char* m_data;
     71     };
     72 
     73     bool operator==(const CString&, const CString&);
     74 
     75     typedef Vector<char, 32> CStringBuffer;
     76 
     77     class UString {
     78         friend class JIT;
     79 
     80     public:
     81         typedef UStringImpl Rep;
     82 
     83     public:
     84         UString();
     85         UString(const char*); // Constructor for null-terminated string.
     86         UString(const char*, int length);
     87         UString(const UChar*, int length);
     88         UString(const Vector<UChar>& buffer);
     89 
     90         UString(const UString& s)
     91             : m_rep(s.m_rep)
     92         {
     93         }
     94 
     95         // Special constructor for cases where we overwrite an object in place.
     96         UString(PlacementNewAdoptType)
     97             : m_rep(PlacementNewAdopt)
     98         {
     99         }
    100 
    101         ~UString()
    102         {
    103         }
    104 
    105         template<size_t inlineCapacity>
    106         static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
    107         {
    108             return Rep::adopt(vector);
    109         }
    110 
    111         static UString from(int);
    112         static UString from(long long);
    113         static UString from(unsigned int);
    114         static UString from(long);
    115         static UString from(double);
    116 
    117         bool getCString(CStringBuffer&) const;
    118 
    119         // NOTE: This method should only be used for *debugging* purposes as it
    120         // is neither Unicode safe nor free from side effects nor thread-safe.
    121         char* ascii() const;
    122 
    123         /**
    124          * Convert the string to UTF-8, assuming it is UTF-16 encoded.
    125          * In non-strict mode, this function is tolerant of badly formed UTF-16, it
    126          * can create UTF-8 strings that are invalid because they have characters in
    127          * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is
    128          * guaranteed to be otherwise valid.
    129          * In strict mode, error is returned as null CString.
    130          */
    131         CString UTF8String(bool strict = false) const;
    132 
    133         const UChar* data() const { return m_rep->data(); }
    134 
    135         bool isNull() const { return m_rep == s_nullRep; }
    136         bool isEmpty() const { return !m_rep->size(); }
    137 
    138         bool is8Bit() const;
    139 
    140         int size() const { return m_rep->size(); }
    141 
    142         UChar operator[](int pos) const;
    143 
    144         double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const;
    145         double toDouble(bool tolerateTrailingJunk) const;
    146         double toDouble() const;
    147 
    148         uint32_t toUInt32(bool* ok = 0) const;
    149         uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const;
    150         uint32_t toStrictUInt32(bool* ok = 0) const;
    151 
    152         unsigned toArrayIndex(bool* ok = 0) const;
    153 
    154         int find(const UString& f, int pos = 0) const;
    155         int find(UChar, int pos = 0) const;
    156         int rfind(const UString& f, int pos) const;
    157         int rfind(UChar, int pos) const;
    158 
    159         UString substr(int pos = 0, int len = -1) const;
    160 
    161         static const UString& null() { return *s_nullUString; }
    162 
    163         Rep* rep() const { return m_rep.get(); }
    164 
    165         UString(PassRefPtr<Rep> r)
    166             : m_rep(r)
    167         {
    168             ASSERT(m_rep);
    169         }
    170 
    171         size_t cost() const { return m_rep->cost(); }
    172 
    173     private:
    174         RefPtr<Rep> m_rep;
    175 
    176         JS_EXPORTDATA static Rep* s_nullRep;
    177         static UString* s_nullUString;
    178 
    179         friend void initializeUString();
    180         friend bool operator==(const UString&, const UString&);
    181     };
    182 
    183     ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2)
    184     {
    185         int size = s1.size();
    186         switch (size) {
    187         case 0:
    188             return !s2.size();
    189         case 1:
    190             return s2.size() == 1 && s1.data()[0] == s2.data()[0];
    191         case 2: {
    192             if (s2.size() != 2)
    193                 return false;
    194             const UChar* d1 = s1.data();
    195             const UChar* d2 = s2.data();
    196             return (d1[0] == d2[0]) & (d1[1] == d2[1]);
    197         }
    198         default:
    199             return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0;
    200         }
    201     }
    202 
    203 
    204     inline bool operator!=(const UString& s1, const UString& s2)
    205     {
    206         return !JSC::operator==(s1, s2);
    207     }
    208 
    209     bool operator<(const UString& s1, const UString& s2);
    210     bool operator>(const UString& s1, const UString& s2);
    211 
    212     bool operator==(const UString& s1, const char* s2);
    213 
    214     inline bool operator!=(const UString& s1, const char* s2)
    215     {
    216         return !JSC::operator==(s1, s2);
    217     }
    218 
    219     inline bool operator==(const char *s1, const UString& s2)
    220     {
    221         return operator==(s2, s1);
    222     }
    223 
    224     inline bool operator!=(const char *s1, const UString& s2)
    225     {
    226         return !JSC::operator==(s1, s2);
    227     }
    228 
    229     int compare(const UString&, const UString&);
    230 
    231     inline UString::UString()
    232         : m_rep(s_nullRep)
    233     {
    234     }
    235 
    236     // Rule from ECMA 15.2 about what an array index is.
    237     // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
    238     inline unsigned UString::toArrayIndex(bool* ok) const
    239     {
    240         unsigned i = toStrictUInt32(ok);
    241         if (ok && i >= 0xFFFFFFFFU)
    242             *ok = false;
    243         return i;
    244     }
    245 
    246     // We'd rather not do shared substring append for small strings, since
    247     // this runs too much risk of a tiny initial string holding down a
    248     // huge buffer.
    249     // FIXME: this should be size_t but that would cause warnings until we
    250     // fix UString sizes to be size_t instead of int
    251     static const int minShareSize = Heap::minExtraCost / sizeof(UChar);
    252 
    253     struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > {
    254         static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->existingHash(); }
    255         static unsigned hash(JSC::UString::Rep* key) { return key->existingHash(); }
    256     };
    257 
    258     void initializeUString();
    259 
    260     template<typename StringType>
    261     class StringTypeAdapter {
    262     };
    263 
    264     template<>
    265     class StringTypeAdapter<char*> {
    266     public:
    267         StringTypeAdapter<char*>(char* buffer)
    268             : m_buffer((unsigned char*)buffer)
    269             , m_length(strlen(buffer))
    270         {
    271         }
    272 
    273         unsigned length() { return m_length; }
    274 
    275         void writeTo(UChar* destination)
    276         {
    277             for (unsigned i = 0; i < m_length; ++i)
    278                 destination[i] = m_buffer[i];
    279         }
    280 
    281     private:
    282         const unsigned char* m_buffer;
    283         unsigned m_length;
    284     };
    285 
    286     template<>
    287     class StringTypeAdapter<const char*> {
    288     public:
    289         StringTypeAdapter<const char*>(const char* buffer)
    290             : m_buffer((unsigned char*)buffer)
    291             , m_length(strlen(buffer))
    292         {
    293         }
    294 
    295         unsigned length() { return m_length; }
    296 
    297         void writeTo(UChar* destination)
    298         {
    299             for (unsigned i = 0; i < m_length; ++i)
    300                 destination[i] = m_buffer[i];
    301         }
    302 
    303     private:
    304         const unsigned char* m_buffer;
    305         unsigned m_length;
    306     };
    307 
    308     template<>
    309     class StringTypeAdapter<UString> {
    310     public:
    311         StringTypeAdapter<UString>(UString& string)
    312             : m_data(string.data())
    313             , m_length(string.size())
    314         {
    315         }
    316 
    317         unsigned length() { return m_length; }
    318 
    319         void writeTo(UChar* destination)
    320         {
    321             for (unsigned i = 0; i < m_length; ++i)
    322                 destination[i] = m_data[i];
    323         }
    324 
    325     private:
    326         const UChar* m_data;
    327         unsigned m_length;
    328     };
    329 
    330     template<typename StringType1, typename StringType2>
    331     PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2)
    332     {
    333         StringTypeAdapter<StringType1> adapter1(string1);
    334         StringTypeAdapter<StringType2> adapter2(string2);
    335 
    336         UChar* buffer;
    337         unsigned length = adapter1.length() + adapter2.length();
    338         PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
    339         if (!resultImpl)
    340             return 0;
    341 
    342         UChar* result = buffer;
    343         adapter1.writeTo(result);
    344         result += adapter1.length();
    345         adapter2.writeTo(result);
    346 
    347         return resultImpl;
    348     }
    349 
    350     template<typename StringType1, typename StringType2, typename StringType3>
    351     PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
    352     {
    353         StringTypeAdapter<StringType1> adapter1(string1);
    354         StringTypeAdapter<StringType2> adapter2(string2);
    355         StringTypeAdapter<StringType3> adapter3(string3);
    356 
    357         UChar* buffer;
    358         unsigned length = adapter1.length() + adapter2.length() + adapter3.length();
    359         PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
    360         if (!resultImpl)
    361             return 0;
    362 
    363         UChar* result = buffer;
    364         adapter1.writeTo(result);
    365         result += adapter1.length();
    366         adapter2.writeTo(result);
    367         result += adapter2.length();
    368         adapter3.writeTo(result);
    369 
    370         return resultImpl;
    371     }
    372 
    373     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
    374     PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
    375     {
    376         StringTypeAdapter<StringType1> adapter1(string1);
    377         StringTypeAdapter<StringType2> adapter2(string2);
    378         StringTypeAdapter<StringType3> adapter3(string3);
    379         StringTypeAdapter<StringType4> adapter4(string4);
    380 
    381         UChar* buffer;
    382         unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length();
    383         PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
    384         if (!resultImpl)
    385             return 0;
    386 
    387         UChar* result = buffer;
    388         adapter1.writeTo(result);
    389         result += adapter1.length();
    390         adapter2.writeTo(result);
    391         result += adapter2.length();
    392         adapter3.writeTo(result);
    393         result += adapter3.length();
    394         adapter4.writeTo(result);
    395 
    396         return resultImpl;
    397     }
    398 
    399     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
    400     PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
    401     {
    402         StringTypeAdapter<StringType1> adapter1(string1);
    403         StringTypeAdapter<StringType2> adapter2(string2);
    404         StringTypeAdapter<StringType3> adapter3(string3);
    405         StringTypeAdapter<StringType4> adapter4(string4);
    406         StringTypeAdapter<StringType5> adapter5(string5);
    407 
    408         UChar* buffer;
    409         unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length();
    410         PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
    411         if (!resultImpl)
    412             return 0;
    413 
    414         UChar* result = buffer;
    415         adapter1.writeTo(result);
    416         result += adapter1.length();
    417         adapter2.writeTo(result);
    418         result += adapter2.length();
    419         adapter3.writeTo(result);
    420         result += adapter3.length();
    421         adapter4.writeTo(result);
    422         result += adapter4.length();
    423         adapter5.writeTo(result);
    424 
    425         return resultImpl;
    426     }
    427 
    428     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
    429     PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
    430     {
    431         StringTypeAdapter<StringType1> adapter1(string1);
    432         StringTypeAdapter<StringType2> adapter2(string2);
    433         StringTypeAdapter<StringType3> adapter3(string3);
    434         StringTypeAdapter<StringType4> adapter4(string4);
    435         StringTypeAdapter<StringType5> adapter5(string5);
    436         StringTypeAdapter<StringType6> adapter6(string6);
    437 
    438         UChar* buffer;
    439         unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length();
    440         PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
    441         if (!resultImpl)
    442             return 0;
    443 
    444         UChar* result = buffer;
    445         adapter1.writeTo(result);
    446         result += adapter1.length();
    447         adapter2.writeTo(result);
    448         result += adapter2.length();
    449         adapter3.writeTo(result);
    450         result += adapter3.length();
    451         adapter4.writeTo(result);
    452         result += adapter4.length();
    453         adapter5.writeTo(result);
    454         result += adapter5.length();
    455         adapter6.writeTo(result);
    456 
    457         return resultImpl;
    458     }
    459 
    460     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
    461     PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
    462     {
    463         StringTypeAdapter<StringType1> adapter1(string1);
    464         StringTypeAdapter<StringType2> adapter2(string2);
    465         StringTypeAdapter<StringType3> adapter3(string3);
    466         StringTypeAdapter<StringType4> adapter4(string4);
    467         StringTypeAdapter<StringType5> adapter5(string5);
    468         StringTypeAdapter<StringType6> adapter6(string6);
    469         StringTypeAdapter<StringType7> adapter7(string7);
    470 
    471         UChar* buffer;
    472         unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length();
    473         PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
    474         if (!resultImpl)
    475             return 0;
    476 
    477         UChar* result = buffer;
    478         adapter1.writeTo(result);
    479         result += adapter1.length();
    480         adapter2.writeTo(result);
    481         result += adapter2.length();
    482         adapter3.writeTo(result);
    483         result += adapter3.length();
    484         adapter4.writeTo(result);
    485         result += adapter4.length();
    486         adapter5.writeTo(result);
    487         result += adapter5.length();
    488         adapter6.writeTo(result);
    489         result += adapter6.length();
    490         adapter7.writeTo(result);
    491 
    492         return resultImpl;
    493     }
    494 
    495     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
    496     PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
    497     {
    498         StringTypeAdapter<StringType1> adapter1(string1);
    499         StringTypeAdapter<StringType2> adapter2(string2);
    500         StringTypeAdapter<StringType3> adapter3(string3);
    501         StringTypeAdapter<StringType4> adapter4(string4);
    502         StringTypeAdapter<StringType5> adapter5(string5);
    503         StringTypeAdapter<StringType6> adapter6(string6);
    504         StringTypeAdapter<StringType7> adapter7(string7);
    505         StringTypeAdapter<StringType8> adapter8(string8);
    506 
    507         UChar* buffer;
    508         unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length() + adapter8.length();
    509         PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
    510         if (!resultImpl)
    511             return 0;
    512 
    513         UChar* result = buffer;
    514         adapter1.writeTo(result);
    515         result += adapter1.length();
    516         adapter2.writeTo(result);
    517         result += adapter2.length();
    518         adapter3.writeTo(result);
    519         result += adapter3.length();
    520         adapter4.writeTo(result);
    521         result += adapter4.length();
    522         adapter5.writeTo(result);
    523         result += adapter5.length();
    524         adapter6.writeTo(result);
    525         result += adapter6.length();
    526         adapter7.writeTo(result);
    527         result += adapter7.length();
    528         adapter8.writeTo(result);
    529 
    530         return resultImpl;
    531     }
    532 
    533     template<typename StringType1, typename StringType2>
    534     UString makeString(StringType1 string1, StringType2 string2)
    535     {
    536         PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2);
    537         if (!resultImpl)
    538             CRASH();
    539         return resultImpl;
    540     }
    541 
    542     template<typename StringType1, typename StringType2, typename StringType3>
    543     UString makeString(StringType1 string1, StringType2 string2, StringType3 string3)
    544     {
    545         PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3);
    546         if (!resultImpl)
    547             CRASH();
    548         return resultImpl;
    549     }
    550 
    551     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
    552     UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
    553     {
    554         PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4);
    555         if (!resultImpl)
    556             CRASH();
    557         return resultImpl;
    558     }
    559 
    560     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
    561     UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
    562     {
    563         PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5);
    564         if (!resultImpl)
    565             CRASH();
    566         return resultImpl;
    567     }
    568 
    569     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
    570     UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
    571     {
    572         PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6);
    573         if (!resultImpl)
    574             CRASH();
    575         return resultImpl;
    576     }
    577 
    578     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
    579     UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
    580     {
    581         PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7);
    582         if (!resultImpl)
    583             CRASH();
    584         return resultImpl;
    585     }
    586 
    587     template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
    588     UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
    589     {
    590         PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
    591         if (!resultImpl)
    592             CRASH();
    593         return resultImpl;
    594     }
    595 
    596 } // namespace JSC
    597 
    598 namespace WTF {
    599 
    600     template<typename T> struct DefaultHash;
    601     template<typename T> struct StrHash;
    602 
    603     template<> struct StrHash<JSC::UString::Rep*> {
    604         static unsigned hash(const JSC::UString::Rep* key) { return key->hash(); }
    605         static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return JSC::equal(a, b); }
    606         static const bool safeToCompareToEmptyOrDeleted = false;
    607     };
    608 
    609     template<> struct StrHash<RefPtr<JSC::UString::Rep> > : public StrHash<JSC::UString::Rep*> {
    610         using StrHash<JSC::UString::Rep*>::hash;
    611         static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->hash(); }
    612         using StrHash<JSC::UString::Rep*>::equal;
    613         static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a.get(), b.get()); }
    614         static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a, b.get()); }
    615         static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return JSC::equal(a.get(), b); }
    616 
    617         static const bool safeToCompareToEmptyOrDeleted = false;
    618     };
    619 
    620     template<> struct DefaultHash<JSC::UString::Rep*> {
    621         typedef StrHash<JSC::UString::Rep*> Hash;
    622     };
    623 
    624     template<> struct DefaultHash<RefPtr<JSC::UString::Rep> > {
    625         typedef StrHash<RefPtr<JSC::UString::Rep> > Hash;
    626 
    627     };
    628 
    629 } // namespace WTF
    630 
    631 #endif
    632