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"
29 #include <wtf/Assertions.h>
30 #include <wtf/CrossThreadRefCounted.h>
31 #include <wtf/OwnFastMallocPtr.h>
32 #include <wtf/PassRefPtr.h>
33 #include <wtf/PtrAndFlags.h>
34 #include <wtf/RefPtr.h>
35 #include <wtf/Vector.h>
36 #include <wtf/unicode/Unicode.h>
40 using WTF::PlacementNewAdoptType
;
41 using WTF::PlacementNewAdopt
;
43 class IdentifierTable
;
54 CString(const char*, size_t);
55 CString(const CString
&);
59 static CString
adopt(char*, size_t); // buffer should be allocated with new[].
61 CString
& append(const CString
&);
62 CString
& operator=(const char* c
);
63 CString
& operator=(const CString
&);
64 CString
& operator+=(const CString
& c
) { return append(c
); }
66 size_t size() const { return m_length
; }
67 const char* c_str() const { return m_data
; }
74 typedef Vector
<char, 32> CStringBuffer
;
80 typedef CrossThreadRefCounted
<OwnFastMallocPtr
<UChar
> > SharedUChar
;
82 struct Rep
: Noncopyable
{
85 static PassRefPtr
<Rep
> create(UChar
* buffer
, int length
)
87 return adoptRef(new BaseString(buffer
, length
));
90 static PassRefPtr
<Rep
> createEmptyBuffer(size_t size
)
92 // Guard against integer overflow
93 if (size
< (std::numeric_limits
<size_t>::max() / sizeof(UChar
))) {
95 if (tryFastMalloc(size
* sizeof(UChar
)).getValue(buf
))
96 return adoptRef(new BaseString(static_cast<UChar
*>(buf
), 0, size
));
98 return adoptRef(new BaseString(0, 0, 0));
101 static PassRefPtr
<Rep
> createCopying(const UChar
*, int);
102 static PassRefPtr
<Rep
> create(PassRefPtr
<Rep
> base
, int offset
, int length
);
104 // Constructs a string from a UTF-8 string, using strict conversion (see comments in UTF8.h).
105 // Returns UString::Rep::null for null input or conversion failure.
106 static PassRefPtr
<Rep
> createFromUTF8(const char*);
108 // Uses SharedUChar to have joint ownership over the UChar*.
109 static PassRefPtr
<Rep
> create(UChar
*, int, PassRefPtr
<SharedUChar
>);
111 SharedUChar
* sharedBuffer();
114 bool baseIsSelf() const { return m_identifierTableAndFlags
.isFlagSet(BaseStringFlag
); }
116 int size() const { return len
; }
118 unsigned hash() const { if (_hash
== 0) _hash
= computeHash(data(), len
); return _hash
; }
119 unsigned computedHash() const { ASSERT(_hash
); return _hash
; } // fast path for Identifiers
121 static unsigned computeHash(const UChar
*, int length
);
122 static unsigned computeHash(const char*, int length
);
123 static unsigned computeHash(const char* s
) { return computeHash(s
, strlen(s
)); }
125 IdentifierTable
* identifierTable() const { return m_identifierTableAndFlags
.get(); }
126 void setIdentifierTable(IdentifierTable
* table
) { ASSERT(!isStatic()); m_identifierTableAndFlags
.set(table
); }
128 bool isStatic() const { return m_identifierTableAndFlags
.isFlagSet(StaticFlag
); }
129 void setStatic(bool);
130 void setBaseString(PassRefPtr
<BaseString
>);
131 BaseString
* baseString();
132 const BaseString
* baseString() const;
134 Rep
* ref() { ++rc
; return this; }
135 ALWAYS_INLINE
void deref() { if (--rc
== 0) destroy(); }
137 void checkConsistency() const;
146 int rc
; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted.
147 mutable unsigned _hash
;
148 PtrAndFlags
<IdentifierTable
, UStringFlags
> m_identifierTableAndFlags
;
150 static BaseString
& null() { return *nullBaseString
; }
151 static BaseString
& empty() { return *emptyBaseString
; }
153 bool reserveCapacity(int capacity
);
156 // Constructor for use by BaseString subclass; they use the union with m_baseString for another purpose.
166 Rep(PassRefPtr
<BaseString
> base
, int offsetInBase
, int length
)
167 : offset(offsetInBase
)
171 , m_baseString(base
.releaseRef())
178 BaseString
* m_baseString
;
180 SharedUChar
* m_sharedBuffer
;
184 // For SmallStringStorage which allocates an array and does initialization manually.
187 friend class SmallStringsStorage
;
188 friend void initializeUString();
189 JS_EXPORTDATA
static BaseString
* nullBaseString
;
190 JS_EXPORTDATA
static BaseString
* emptyBaseString
;
194 struct BaseString
: public Rep
{
195 bool isShared() { return rc
!= 1 || isBufferReadOnly(); }
196 void setSharedBuffer(PassRefPtr
<SharedUChar
>);
198 bool isBufferReadOnly()
202 return slowIsBufferReadOnly();
205 // potentially shared data.
215 BaseString(UChar
* buffer
, int length
, int additionalCapacity
= 0)
220 , capacity(length
+ additionalCapacity
)
221 , usedCapacity(length
)
224 m_identifierTableAndFlags
.setFlag(BaseStringFlag
);
228 SharedUChar
* sharedBuffer();
229 bool slowIsBufferReadOnly();
232 friend class SmallStringsStorage
;
233 friend void initializeUString();
238 // Constructor for null-terminated ASCII string.
239 UString(const char*);
240 // Constructor for non-null-terminated ASCII string.
241 UString(const char*, int length
);
242 UString(const UChar
*, int length
);
243 UString(UChar
*, int length
, bool copy
);
245 UString(const UString
& s
)
250 UString(const Vector
<UChar
>& buffer
);
256 // Special constructor for cases where we overwrite an object in place.
257 UString(PlacementNewAdoptType
)
258 : m_rep(PlacementNewAdopt
)
262 static UString
from(int);
263 static UString
from(long long);
264 static UString
from(unsigned int);
265 static UString
from(long);
266 static UString
from(double);
270 Range(int pos
, int len
)
284 UString
spliceSubstringsWithSeparators(const Range
* substringRanges
, int rangeCount
, const UString
* separators
, int separatorCount
) const;
286 UString
replaceRange(int rangeStart
, int RangeEnd
, const UString
& replacement
) const;
288 UString
& append(const UString
&);
289 UString
& append(const char*);
290 UString
& append(UChar
);
291 UString
& append(char c
) { return append(static_cast<UChar
>(static_cast<unsigned char>(c
))); }
292 UString
& append(const UChar
*, int size
);
294 bool getCString(CStringBuffer
&) const;
296 // NOTE: This method should only be used for *debugging* purposes as it
297 // is neither Unicode safe nor free from side effects nor thread-safe.
301 * Convert the string to UTF-8, assuming it is UTF-16 encoded.
302 * In non-strict mode, this function is tolerant of badly formed UTF-16, it
303 * can create UTF-8 strings that are invalid because they have characters in
304 * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is
305 * guaranteed to be otherwise valid.
306 * In strict mode, error is returned as null CString.
308 CString
UTF8String(bool strict
= false) const;
310 UString
& operator=(const char*c
);
312 UString
& operator+=(const UString
& s
) { return append(s
); }
313 UString
& operator+=(const char* s
) { return append(s
); }
315 const UChar
* data() const { return m_rep
->data(); }
317 bool isNull() const { return (m_rep
== &Rep::null()); }
318 bool isEmpty() const { return (!m_rep
->len
); }
322 int size() const { return m_rep
->size(); }
324 UChar
operator[](int pos
) const;
326 double toDouble(bool tolerateTrailingJunk
, bool tolerateEmptyString
) const;
327 double toDouble(bool tolerateTrailingJunk
) const;
328 double toDouble() const;
330 uint32_t toUInt32(bool* ok
= 0) const;
331 uint32_t toUInt32(bool* ok
, bool tolerateEmptyString
) const;
332 uint32_t toStrictUInt32(bool* ok
= 0) const;
334 unsigned toArrayIndex(bool* ok
= 0) const;
336 int find(const UString
& f
, int pos
= 0) const;
337 int find(UChar
, int pos
= 0) const;
338 int rfind(const UString
& f
, int pos
) const;
339 int rfind(UChar
, int pos
) const;
341 UString
substr(int pos
= 0, int len
= -1) const;
343 static const UString
& null() { return *nullUString
; }
345 Rep
* rep() const { return m_rep
.get(); }
346 static Rep
* nullRep();
348 UString(PassRefPtr
<Rep
> r
)
356 // Attempt to grow this string such that it can grow to a total length of 'capacity'
357 // without reallocation. This may fail a number of reasons - if the BasicString is
358 // shared and another string is using part of the capacity beyond our end point, if
359 // the realloc fails, or if this string is empty and has no storage.
361 // This method returns a boolean indicating success.
362 bool reserveCapacity(int capacity
)
364 return m_rep
->reserveCapacity(capacity
);
368 void expandCapacity(int requiredLength
);
369 void expandPreCapacity(int requiredPreCap
);
373 static UString
* nullUString
;
375 friend void initializeUString();
376 friend bool operator==(const UString
&, const UString
&);
377 friend PassRefPtr
<Rep
> concatenate(Rep
*, Rep
*); // returns 0 if out of memory
379 PassRefPtr
<UString::Rep
> concatenate(UString::Rep
*, UString::Rep
*);
380 PassRefPtr
<UString::Rep
> concatenate(UString::Rep
*, int);
381 PassRefPtr
<UString::Rep
> concatenate(UString::Rep
*, double);
383 inline bool operator==(const UString
& s1
, const UString
& s2
)
385 int size
= s1
.size();
390 return s2
.size() == 1 && s1
.data()[0] == s2
.data()[0];
394 const UChar
* d1
= s1
.data();
395 const UChar
* d2
= s2
.data();
396 return (d1
[0] == d2
[0]) & (d1
[1] == d2
[1]);
399 return s2
.size() == size
&& memcmp(s1
.data(), s2
.data(), size
* sizeof(UChar
)) == 0;
404 inline bool operator!=(const UString
& s1
, const UString
& s2
)
406 return !JSC::operator==(s1
, s2
);
409 bool operator<(const UString
& s1
, const UString
& s2
);
410 bool operator>(const UString
& s1
, const UString
& s2
);
412 bool operator==(const UString
& s1
, const char* s2
);
414 inline bool operator!=(const UString
& s1
, const char* s2
)
416 return !JSC::operator==(s1
, s2
);
419 inline bool operator==(const char *s1
, const UString
& s2
)
421 return operator==(s2
, s1
);
424 inline bool operator!=(const char *s1
, const UString
& s2
)
426 return !JSC::operator==(s1
, s2
);
429 bool operator==(const CString
&, const CString
&);
431 inline UString
operator+(const UString
& s1
, const UString
& s2
)
433 RefPtr
<UString::Rep
> result
= concatenate(s1
.rep(), s2
.rep());
434 return UString(result
? result
.release() : UString::nullRep());
437 int compare(const UString
&, const UString
&);
439 bool equal(const UString::Rep
*, const UString::Rep
*);
441 inline PassRefPtr
<UString::Rep
> UString::Rep::create(PassRefPtr
<UString::Rep
> rep
, int offset
, int length
)
444 rep
->checkConsistency();
446 int repOffset
= rep
->offset
;
448 PassRefPtr
<BaseString
> base
= rep
->baseString();
450 ASSERT(-(offset
+ repOffset
) <= base
->usedPreCapacity
);
451 ASSERT(offset
+ repOffset
+ length
<= base
->usedCapacity
);
453 // Steal the single reference this Rep was created with.
454 return adoptRef(new Rep(base
, repOffset
+ offset
, length
));
457 inline UChar
* UString::Rep::data() const
459 const BaseString
* base
= baseString();
460 return base
->buf
+ base
->preCapacity
+ offset
;
463 inline void UString::Rep::setStatic(bool v
)
465 ASSERT(!identifierTable());
467 m_identifierTableAndFlags
.setFlag(StaticFlag
);
469 m_identifierTableAndFlags
.clearFlag(StaticFlag
);
472 inline void UString::Rep::setBaseString(PassRefPtr
<BaseString
> base
)
474 ASSERT(base
!= this);
475 ASSERT(!baseIsSelf());
476 m_baseString
= base
.releaseRef();
479 inline UString::BaseString
* UString::Rep::baseString()
481 return !baseIsSelf() ? m_baseString
: reinterpret_cast<BaseString
*>(this) ;
484 inline const UString::BaseString
* UString::Rep::baseString() const
486 return const_cast<Rep
*>(this)->baseString();
490 inline void UString::Rep::checkConsistency() const
495 inline UString::UString()
496 : m_rep(&Rep::null())
500 // Rule from ECMA 15.2 about what an array index is.
501 // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
502 inline unsigned UString::toArrayIndex(bool* ok
) const
504 unsigned i
= toStrictUInt32(ok
);
505 if (ok
&& i
>= 0xFFFFFFFFU
)
510 // We'd rather not do shared substring append for small strings, since
511 // this runs too much risk of a tiny initial string holding down a
513 // FIXME: this should be size_t but that would cause warnings until we
514 // fix UString sizes to be size_t instead of int
515 static const int minShareSize
= Heap::minExtraCost
/ sizeof(UChar
);
517 inline size_t UString::cost() const
519 BaseString
* base
= m_rep
->baseString();
520 size_t capacity
= (base
->capacity
+ base
->preCapacity
) * sizeof(UChar
);
521 size_t reportedCost
= base
->reportedCost
;
522 ASSERT(capacity
>= reportedCost
);
524 size_t capacityDelta
= capacity
- reportedCost
;
526 if (capacityDelta
< static_cast<size_t>(minShareSize
))
529 base
->reportedCost
= capacity
;
531 return capacityDelta
;
534 struct IdentifierRepHash
: PtrHash
<RefPtr
<JSC::UString::Rep
> > {
535 static unsigned hash(const RefPtr
<JSC::UString::Rep
>& key
) { return key
->computedHash(); }
536 static unsigned hash(JSC::UString::Rep
* key
) { return key
->computedHash(); }
539 void initializeUString();
541 template<typename StringType
>
542 class StringTypeAdapter
{
546 class StringTypeAdapter
<char*> {
548 StringTypeAdapter
<char*>(char* buffer
)
549 : m_buffer((unsigned char*)buffer
)
550 , m_length(strlen(buffer
))
554 unsigned length() { return m_length
; }
556 void writeTo(UChar
* destination
)
558 for (unsigned i
= 0; i
< m_length
; ++i
)
559 destination
[i
] = m_buffer
[i
];
563 const unsigned char* m_buffer
;
568 class StringTypeAdapter
<const char*> {
570 StringTypeAdapter
<const char*>(const char* buffer
)
571 : m_buffer((unsigned char*)buffer
)
572 , m_length(strlen(buffer
))
576 unsigned length() { return m_length
; }
578 void writeTo(UChar
* destination
)
580 for (unsigned i
= 0; i
< m_length
; ++i
)
581 destination
[i
] = m_buffer
[i
];
585 const unsigned char* m_buffer
;
590 class StringTypeAdapter
<UString
> {
592 StringTypeAdapter
<UString
>(UString
& string
)
593 : m_data(string
.data())
594 , m_length(string
.size())
598 unsigned length() { return m_length
; }
600 void writeTo(UChar
* destination
)
602 for (unsigned i
= 0; i
< m_length
; ++i
)
603 destination
[i
] = m_data
[i
];
611 template<typename StringType1
, typename StringType2
>
612 UString
makeString(StringType1 string1
, StringType2 string2
)
614 StringTypeAdapter
<StringType1
> adapter1(string1
);
615 StringTypeAdapter
<StringType2
> adapter2(string2
);
618 unsigned length
= adapter1
.length() + adapter2
.length();
619 if (!tryFastMalloc(length
* sizeof(UChar
)).getValue(buffer
))
622 UChar
* result
= buffer
;
623 adapter1
.writeTo(result
);
624 result
+= adapter1
.length();
625 adapter2
.writeTo(result
);
627 return UString(buffer
, length
, false);
630 template<typename StringType1
, typename StringType2
, typename StringType3
>
631 UString
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
)
633 StringTypeAdapter
<StringType1
> adapter1(string1
);
634 StringTypeAdapter
<StringType2
> adapter2(string2
);
635 StringTypeAdapter
<StringType3
> adapter3(string3
);
638 unsigned length
= adapter1
.length() + adapter2
.length() + adapter3
.length();
639 if (!tryFastMalloc(length
* sizeof(UChar
)).getValue(buffer
))
642 UChar
* result
= buffer
;
643 adapter1
.writeTo(result
);
644 result
+= adapter1
.length();
645 adapter2
.writeTo(result
);
646 result
+= adapter2
.length();
647 adapter3
.writeTo(result
);
649 return UString(buffer
, length
, false);
652 template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
>
653 UString
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
)
655 StringTypeAdapter
<StringType1
> adapter1(string1
);
656 StringTypeAdapter
<StringType2
> adapter2(string2
);
657 StringTypeAdapter
<StringType3
> adapter3(string3
);
658 StringTypeAdapter
<StringType4
> adapter4(string4
);
661 unsigned length
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length();
662 if (!tryFastMalloc(length
* sizeof(UChar
)).getValue(buffer
))
665 UChar
* result
= buffer
;
666 adapter1
.writeTo(result
);
667 result
+= adapter1
.length();
668 adapter2
.writeTo(result
);
669 result
+= adapter2
.length();
670 adapter3
.writeTo(result
);
671 result
+= adapter3
.length();
672 adapter4
.writeTo(result
);
674 return UString(buffer
, length
, false);
677 template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
, typename StringType5
>
678 UString
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
, StringType5 string5
)
680 StringTypeAdapter
<StringType1
> adapter1(string1
);
681 StringTypeAdapter
<StringType2
> adapter2(string2
);
682 StringTypeAdapter
<StringType3
> adapter3(string3
);
683 StringTypeAdapter
<StringType4
> adapter4(string4
);
684 StringTypeAdapter
<StringType5
> adapter5(string5
);
687 unsigned length
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length() + adapter5
.length();
688 if (!tryFastMalloc(length
* sizeof(UChar
)).getValue(buffer
))
691 UChar
* result
= buffer
;
692 adapter1
.writeTo(result
);
693 result
+= adapter1
.length();
694 adapter2
.writeTo(result
);
695 result
+= adapter2
.length();
696 adapter3
.writeTo(result
);
697 result
+= adapter3
.length();
698 adapter4
.writeTo(result
);
699 result
+= adapter4
.length();
700 adapter5
.writeTo(result
);
702 return UString(buffer
, length
, false);
705 template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
, typename StringType5
, typename StringType6
>
706 UString
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
, StringType5 string5
, StringType6 string6
)
708 StringTypeAdapter
<StringType1
> adapter1(string1
);
709 StringTypeAdapter
<StringType2
> adapter2(string2
);
710 StringTypeAdapter
<StringType3
> adapter3(string3
);
711 StringTypeAdapter
<StringType4
> adapter4(string4
);
712 StringTypeAdapter
<StringType5
> adapter5(string5
);
713 StringTypeAdapter
<StringType6
> adapter6(string6
);
716 unsigned length
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length() + adapter5
.length() + adapter6
.length();
717 if (!tryFastMalloc(length
* sizeof(UChar
)).getValue(buffer
))
720 UChar
* result
= buffer
;
721 adapter1
.writeTo(result
);
722 result
+= adapter1
.length();
723 adapter2
.writeTo(result
);
724 result
+= adapter2
.length();
725 adapter3
.writeTo(result
);
726 result
+= adapter3
.length();
727 adapter4
.writeTo(result
);
728 result
+= adapter4
.length();
729 adapter5
.writeTo(result
);
730 result
+= adapter5
.length();
731 adapter6
.writeTo(result
);
733 return UString(buffer
, length
, false);
736 template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
, typename StringType5
, typename StringType6
, typename StringType7
>
737 UString
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
, StringType5 string5
, StringType6 string6
, StringType7 string7
)
739 StringTypeAdapter
<StringType1
> adapter1(string1
);
740 StringTypeAdapter
<StringType2
> adapter2(string2
);
741 StringTypeAdapter
<StringType3
> adapter3(string3
);
742 StringTypeAdapter
<StringType4
> adapter4(string4
);
743 StringTypeAdapter
<StringType5
> adapter5(string5
);
744 StringTypeAdapter
<StringType6
> adapter6(string6
);
745 StringTypeAdapter
<StringType7
> adapter7(string7
);
748 unsigned length
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length() + adapter5
.length() + adapter6
.length() + adapter7
.length();
749 if (!tryFastMalloc(length
* sizeof(UChar
)).getValue(buffer
))
752 UChar
* result
= buffer
;
753 adapter1
.writeTo(result
);
754 result
+= adapter1
.length();
755 adapter2
.writeTo(result
);
756 result
+= adapter2
.length();
757 adapter3
.writeTo(result
);
758 result
+= adapter3
.length();
759 adapter4
.writeTo(result
);
760 result
+= adapter4
.length();
761 adapter5
.writeTo(result
);
762 result
+= adapter5
.length();
763 adapter6
.writeTo(result
);
764 result
+= adapter6
.length();
765 adapter7
.writeTo(result
);
767 return UString(buffer
, length
, false);
770 template<typename StringType1
, typename StringType2
, typename StringType3
, typename StringType4
, typename StringType5
, typename StringType6
, typename StringType7
, typename StringType8
>
771 UString
makeString(StringType1 string1
, StringType2 string2
, StringType3 string3
, StringType4 string4
, StringType5 string5
, StringType6 string6
, StringType7 string7
, StringType8 string8
)
773 StringTypeAdapter
<StringType1
> adapter1(string1
);
774 StringTypeAdapter
<StringType2
> adapter2(string2
);
775 StringTypeAdapter
<StringType3
> adapter3(string3
);
776 StringTypeAdapter
<StringType4
> adapter4(string4
);
777 StringTypeAdapter
<StringType5
> adapter5(string5
);
778 StringTypeAdapter
<StringType6
> adapter6(string6
);
779 StringTypeAdapter
<StringType7
> adapter7(string7
);
780 StringTypeAdapter
<StringType8
> adapter8(string8
);
783 unsigned length
= adapter1
.length() + adapter2
.length() + adapter3
.length() + adapter4
.length() + adapter5
.length() + adapter6
.length() + adapter7
.length() + adapter8
.length();
784 if (!tryFastMalloc(length
* sizeof(UChar
)).getValue(buffer
))
787 UChar
* result
= buffer
;
788 adapter1
.writeTo(result
);
789 result
+= adapter1
.length();
790 adapter2
.writeTo(result
);
791 result
+= adapter2
.length();
792 adapter3
.writeTo(result
);
793 result
+= adapter3
.length();
794 adapter4
.writeTo(result
);
795 result
+= adapter4
.length();
796 adapter5
.writeTo(result
);
797 result
+= adapter5
.length();
798 adapter6
.writeTo(result
);
799 result
+= adapter6
.length();
800 adapter7
.writeTo(result
);
801 result
+= adapter7
.length();
802 adapter8
.writeTo(result
);
804 return UString(buffer
, length
, false);
811 template<typename T
> struct DefaultHash
;
812 template<typename T
> struct StrHash
;
814 template<> struct StrHash
<JSC::UString::Rep
*> {
815 static unsigned hash(const JSC::UString::Rep
* key
) { return key
->hash(); }
816 static bool equal(const JSC::UString::Rep
* a
, const JSC::UString::Rep
* b
) { return JSC::equal(a
, b
); }
817 static const bool safeToCompareToEmptyOrDeleted
= false;
820 template<> struct StrHash
<RefPtr
<JSC::UString::Rep
> > : public StrHash
<JSC::UString::Rep
*> {
821 using StrHash
<JSC::UString::Rep
*>::hash
;
822 static unsigned hash(const RefPtr
<JSC::UString::Rep
>& key
) { return key
->hash(); }
823 using StrHash
<JSC::UString::Rep
*>::equal
;
824 static bool equal(const RefPtr
<JSC::UString::Rep
>& a
, const RefPtr
<JSC::UString::Rep
>& b
) { return JSC::equal(a
.get(), b
.get()); }
825 static bool equal(const JSC::UString::Rep
* a
, const RefPtr
<JSC::UString::Rep
>& b
) { return JSC::equal(a
, b
.get()); }
826 static bool equal(const RefPtr
<JSC::UString::Rep
>& a
, const JSC::UString::Rep
* b
) { return JSC::equal(a
.get(), b
); }
828 static const bool safeToCompareToEmptyOrDeleted
= false;
831 template<> struct DefaultHash
<JSC::UString::Rep
*> {
832 typedef StrHash
<JSC::UString::Rep
*> Hash
;
835 template<> struct DefaultHash
<RefPtr
<JSC::UString::Rep
> > {
836 typedef StrHash
<RefPtr
<JSC::UString::Rep
> > Hash
;