• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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.
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:
CString()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 
size()65         size_t size() const { return m_length; }
c_str()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 
UString(const UString & s)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.
UString(PlacementNewAdoptType)96         UString(PlacementNewAdoptType)
97             : m_rep(PlacementNewAdopt)
98         {
99         }
100 
~UString()101         ~UString()
102         {
103         }
104 
105         template<size_t inlineCapacity>
adopt(Vector<UChar,inlineCapacity> & vector)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 
data()133         const UChar* data() const { return m_rep->data(); }
134 
isNull()135         bool isNull() const { return m_rep == s_nullRep; }
isEmpty()136         bool isEmpty() const { return !m_rep->size(); }
137 
138         bool is8Bit() const;
139 
size()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 
null()161         static const UString& null() { return *s_nullUString; }
162 
rep()163         Rep* rep() const { return m_rep.get(); }
164 
UString(PassRefPtr<Rep> r)165         UString(PassRefPtr<Rep> r)
166             : m_rep(r)
167         {
168             ASSERT(m_rep);
169         }
170 
cost()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 
UString()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.
toArrayIndex(bool * ok)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> > {
hashIdentifierRepHash254         static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->existingHash(); }
hashIdentifierRepHash255         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 
length()273         unsigned length() { return m_length; }
274 
writeTo(UChar * destination)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 
length()295         unsigned length() { return m_length; }
296 
writeTo(UChar * destination)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 
length()317         unsigned length() { return m_length; }
318 
writeTo(UChar * destination)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>
tryMakeString(StringType1 string1,StringType2 string2)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>
tryMakeString(StringType1 string1,StringType2 string2,StringType3 string3)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>
tryMakeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4)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>
tryMakeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4,StringType5 string5)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>
tryMakeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4,StringType5 string5,StringType6 string6)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>
tryMakeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4,StringType5 string5,StringType6 string6,StringType7 string7)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>
tryMakeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4,StringType5 string5,StringType6 string6,StringType7 string7,StringType8 string8)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>
makeString(StringType1 string1,StringType2 string2)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>
makeString(StringType1 string1,StringType2 string2,StringType3 string3)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>
makeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4)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>
makeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4,StringType5 string5)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>
makeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4,StringType5 string5,StringType6 string6)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>
makeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4,StringType5 string5,StringType6 string6,StringType7 string7)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>
makeString(StringType1 string1,StringType2 string2,StringType3 string3,StringType4 string4,StringType5 string5,StringType6 string6,StringType7 string7,StringType8 string8)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