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