Commit b458c9cb authored by wangxianzhu@chromium.org's avatar wangxianzhu@chromium.org
Browse files

Basic enhancements to StringBuilder

https://bugs.webkit.org/show_bug.cgi?id=67081

Source/JavaScriptCore:

This change contains the following enhancements to StringBuilder,
for convenience, performance, testability, etc.:
- Change toStringPreserveCapacity() to const
- new public methods: capacity(), swap(), toAtomicString(), canShrink()
  and append(const StringBuilder&)
- == and != opearators to compare StringBuilders and a StringBuilder/String

Unit tests: Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp

Reviewed by Darin Adler.

* JavaScriptCore.exp:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* wtf/text/AtomicString.cpp:
(WTF::SubstringTranslator::hash):
(WTF::SubstringTranslator::equal):
(WTF::SubstringTranslator::translate):
(WTF::AtomicString::add):
(WTF::AtomicString::addSlowCase):
* wtf/text/AtomicString.h:
(WTF::AtomicString::AtomicString):
(WTF::AtomicString::add):
* wtf/text/StringBuilder.cpp:
(WTF::StringBuilder::reifyString):
(WTF::StringBuilder::resize):
(WTF::StringBuilder::canShrink):
(WTF::StringBuilder::shrinkToFit):
* wtf/text/StringBuilder.h:
(WTF::StringBuilder::append):
(WTF::StringBuilder::toString):
(WTF::StringBuilder::toStringPreserveCapacity):
(WTF::StringBuilder::toAtomicString):
(WTF::StringBuilder::isEmpty):
(WTF::StringBuilder::capacity):
(WTF::StringBuilder::is8Bit):
(WTF::StringBuilder::swap):
(WTF::equal):
(WTF::operator==):
(WTF::operator!=):
* wtf/text/StringImpl.h:

Source/WebCore:

These changes are because we explicitly disallowed StringBuilder's
copy constructor and assignment operator, and the change of return
type of StringBuilder::toString().

Reviewed by Darin Adler.

No new tests. All layout tests and unit tests should run as before.

* platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp:
(WebCore::MediaPlayerPrivateQuickTimeVisualContext::setUpCookiesForQuickTime):
* svg/SVGPathStringBuilder.h:
(WebCore::SVGPathStringBuilder::cleanup):

Source/WebKit/chromium:

This change is because we explicitly disallowed StringBuilder's
copy constructor and assignment operator.

Reviewed by Darin Adler.

No new tests. All layout tests and unit tests should run as before.

* src/WebPageSerializerImpl.cpp:
(WebKit::WebPageSerializerImpl::encodeAndFlushBuffer):

Tools:

Reviewed by Darin Adler.

* TestWebKitAPI/Tests/WTF/StringBuilder.cpp:
(TestWebKitAPI::TEST):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@105635 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 632ff8f0
2012-01-23 Xianzhu Wang <wangxianzhu@chromium.org>
Basic enhancements to StringBuilder
https://bugs.webkit.org/show_bug.cgi?id=67081
This change contains the following enhancements to StringBuilder,
for convenience, performance, testability, etc.:
- Change toStringPreserveCapacity() to const
- new public methods: capacity(), swap(), toAtomicString(), canShrink()
and append(const StringBuilder&)
- == and != opearators to compare StringBuilders and a StringBuilder/String
Unit tests: Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp
Reviewed by Darin Adler.
* JavaScriptCore.exp:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* wtf/text/AtomicString.cpp:
(WTF::SubstringTranslator::hash):
(WTF::SubstringTranslator::equal):
(WTF::SubstringTranslator::translate):
(WTF::AtomicString::add):
(WTF::AtomicString::addSlowCase):
* wtf/text/AtomicString.h:
(WTF::AtomicString::AtomicString):
(WTF::AtomicString::add):
* wtf/text/StringBuilder.cpp:
(WTF::StringBuilder::reifyString):
(WTF::StringBuilder::resize):
(WTF::StringBuilder::canShrink):
(WTF::StringBuilder::shrinkToFit):
* wtf/text/StringBuilder.h:
(WTF::StringBuilder::append):
(WTF::StringBuilder::toString):
(WTF::StringBuilder::toStringPreserveCapacity):
(WTF::StringBuilder::toAtomicString):
(WTF::StringBuilder::isEmpty):
(WTF::StringBuilder::capacity):
(WTF::StringBuilder::is8Bit):
(WTF::StringBuilder::swap):
(WTF::equal):
(WTF::operator==):
(WTF::operator!=):
* wtf/text/StringImpl.h:
2012-01-23 Carlos Garcia Campos <cgarcia@igalia.com>
 
Unreviewed. Fix make distcheck.
......@@ -415,7 +415,6 @@ __ZN3WTF13MetaAllocator17freeFreeSpaceNodeEPNS_12RedBlackTreeImPvE4NodeE
__ZN3WTF13MetaAllocator18debugFreeSpaceSizeEv
__ZN3WTF13MetaAllocator8allocateEm
__ZN3WTF13MetaAllocatorC2Em
__ZN3WTF13StringBuilder11reifyStringEv
__ZN3WTF13StringBuilder11shrinkToFitEv
__ZN3WTF13StringBuilder15reserveCapacityEj
__ZN3WTF13StringBuilder6appendEPKhj
......@@ -597,6 +596,8 @@ __ZNK3WTF13DecimalNumber15toStringDecimalEPtj
__ZNK3WTF13DecimalNumber19toStringExponentialEPtj
__ZNK3WTF13DecimalNumber28bufferLengthForStringDecimalEv
__ZNK3WTF13DecimalNumber32bufferLengthForStringExponentialEv
__ZNK3WTF13StringBuilder11reifyStringEv
__ZNK3WTF13StringBuilder9canShrinkEv
__ZNK3WTF6String11toIntStrictEPbi
__ZNK3WTF6String12isolatedCopyEv
__ZNK3WTF6String12toUIntStrictEPbi
......
......@@ -323,7 +323,8 @@ __ZN3WTF13StringBuilder6appendEPKtj
__ZN3WTF13StringBuilder19appendUninitializedEj
__ZN3WTF13StringBuilder14allocateBufferEPKtj
__ZN3WTF13StringBuilder11shrinkToFitEv
__ZN3WTF13StringBuilder11reifyStringEv
__ZNK3WTF13StringBuilder11reifyStringEv
__ZNK3WTF13StringBuilder9canShrinkEv
__ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
__ZN3JSC7JSArray20increaseVectorLengthEj
__ZN3WTF14tryFastReallocEPvm
......
......@@ -279,7 +279,7 @@ EXPORTS
?randomNumber@WTF@@YANXZ
?recompileAllJSFunctions@Debugger@JSC@@QAEXPAVJSGlobalData@2@@Z
?regExpFlags@JSC@@YA?AW4RegExpFlags@1@ABVUString@1@@Z
?reifyString@StringBuilder@WTF@@AAEXXZ
?reifyString@StringBuilder@WTF@@ABEXXZ
?releaseDecommitted@OSAllocator@WTF@@SAXPAXI@Z
?releaseExecutableMemory@JSGlobalData@JSC@@QAEXXZ
?reportExtraMemoryCostSlowCase@Heap@JSC@@AAEXI@Z
......
/*
* Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -250,11 +251,52 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
}
PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
struct SubstringLocation {
StringImpl* baseString;
unsigned start;
unsigned length;
};
struct SubstringTranslator {
static unsigned hash(const SubstringLocation& buffer)
{
return StringHasher::computeHash(buffer.baseString->characters() + buffer.start, buffer.length);
}
static bool equal(StringImpl* const& string, const SubstringLocation& buffer)
{
return WTF::equal(string, buffer.baseString->characters() + buffer.start, buffer.length);
}
static void translate(StringImpl*& location, const SubstringLocation& buffer, unsigned hash)
{
location = StringImpl::create(buffer.baseString, buffer.start, buffer.length).leakRef();
location->setHash(hash);
location->setIsAtomic(true);
}
};
PassRefPtr<StringImpl> AtomicString::add(StringImpl* baseString, unsigned start, unsigned length)
{
if (!r || r->isAtomic())
return r;
if (!baseString)
return 0;
if (!length || start >= baseString->length())
return StringImpl::empty();
unsigned maxLength = baseString->length() - start;
if (length >= maxLength) {
if (!start)
return add(baseString);
length = maxLength;
}
SubstringLocation buffer = { baseString, start, length };
return addToStringTable<SubstringLocation, SubstringTranslator>(buffer);
}
PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
{
if (!r->length())
return StringImpl::empty();
......
......@@ -49,6 +49,7 @@ public:
ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { }
AtomicString(AtomicStringImpl* imp) : m_string(imp) { }
ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { }
AtomicString(StringImpl* baseString, unsigned start, unsigned length) : m_string(add(baseString, start, length)) { }
// Hash table deleted values, which are only constructed and never copied or destroyed.
AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { }
......@@ -126,7 +127,8 @@ private:
ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s, unsigned length) { return add(reinterpret_cast<const char*>(s), length); };
WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash);
WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const UChar*);
ALWAYS_INLINE PassRefPtr<StringImpl> add(StringImpl* r)
static PassRefPtr<StringImpl> add(StringImpl*, unsigned offset, unsigned length);
ALWAYS_INLINE static PassRefPtr<StringImpl> add(StringImpl* r)
{
if (!r || r->isAtomic())
return r;
......
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -32,7 +33,7 @@ namespace WTF {
static const unsigned minimumCapacity = 16;
void StringBuilder::reifyString()
void StringBuilder::reifyString() const
{
// Check if the string already exists.
if (!m_string.isNull()) {
......@@ -68,6 +69,7 @@ void StringBuilder::resize(unsigned newSize)
// If there is a buffer, we only need to duplicate it if it has more than one ref.
if (m_buffer) {
m_string = String(); // Clear the string to remove the reference to m_buffer if any before checking the reference count of m_buffer.
if (!m_buffer->hasOneRef()) {
if (m_buffer->is8Bit())
allocateBuffer(m_buffer->characters8(), m_buffer->length());
......@@ -75,7 +77,6 @@ void StringBuilder::resize(unsigned newSize)
allocateBuffer(m_buffer->characters16(), m_buffer->length());
}
m_length = newSize;
m_string = String();
return;
}
......@@ -285,10 +286,15 @@ void StringBuilder::append(const LChar* characters, unsigned length)
}
}
bool StringBuilder::canShrink() const
{
// Only shrink the buffer if it's less than 80% full. Need to tune this heuristic!
return m_buffer && m_buffer->length() > (m_length + (m_length >> 2));
}
void StringBuilder::shrinkToFit()
{
// If the buffer is at least 80% full, don't bother copying. Need to tune this heuristic!
if (m_buffer && m_buffer->length() > (m_length + (m_length >> 2))) {
if (canShrink()) {
if (m_is8Bit)
reallocateBuffer<LChar>(m_length);
else
......
/*
* Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -26,12 +27,15 @@
#ifndef StringBuilder_h
#define StringBuilder_h
#include <wtf/Vector.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/WTFString.h>
namespace WTF {
class StringBuilder {
// Disallow copying since it's expensive and we don't want code to do it by accident.
WTF_MAKE_NONCOPYABLE(StringBuilder);
public:
StringBuilder()
: m_length(0)
......@@ -51,9 +55,8 @@ public:
if (!string.length())
return;
// If we're appending to an empty string, and there is not buffer
// (in case reserveCapacity has been called) then just retain the
// string.
// If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called)
// then just retain the string.
if (!m_length && !m_buffer) {
m_string = string;
m_length = string.length();
......@@ -67,6 +70,22 @@ public:
append(string.characters16(), string.length());
}
void append(const StringBuilder& other)
{
if (!other.m_length)
return;
// If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called)
// then just retain the string.
if (!m_length && !m_buffer && !other.m_string.isNull()) {
m_string = other.m_string;
m_length = other.m_length;
return;
}
append(other.characters(), other.m_length);
}
void append(const char* characters)
{
if (characters)
......@@ -94,43 +113,58 @@ public:
void append(char c)
{
if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) {
if (m_is8Bit)
m_bufferCharacters8[m_length++] = (LChar)c;
else
m_bufferCharacters16[m_length++] = (LChar)c;
}
else
append(&c, 1);
append(static_cast<LChar>(c));
}
String toString()
{
if (m_string.isNull()) {
shrinkToFit();
shrinkToFit();
if (m_string.isNull())
reifyString();
}
return m_string;
}
String toStringPreserveCapacity()
const String& toStringPreserveCapacity() const
{
if (m_string.isNull())
reifyString();
return m_string;
}
AtomicString toAtomicString() const
{
if (!m_length)
return AtomicString();
// If the buffer is sufficiently over-allocated, make a new AtomicString from a copy so its buffer is not so large.
if (canShrink())
return AtomicString(characters(), length());
if (!m_string.isNull())
return AtomicString(m_string);
ASSERT(m_buffer);
return AtomicString(m_buffer.get(), 0, m_length);
}
unsigned length() const
{
return m_length;
}
bool isEmpty() const { return !length(); }
bool isEmpty() const { return !m_length; }
WTF_EXPORT_PRIVATE void reserveCapacity(unsigned newCapacity);
unsigned capacity() const
{
return m_buffer ? m_buffer->length() : m_length;
}
WTF_EXPORT_PRIVATE void resize(unsigned newSize);
WTF_EXPORT_PRIVATE bool canShrink() const;
WTF_EXPORT_PRIVATE void shrinkToFit();
UChar operator[](unsigned i) const
......@@ -178,6 +212,8 @@ public:
return m_buffer->characters();
}
bool is8Bit() const { return m_is8Bit; }
void clear()
{
m_length = 0;
......@@ -188,6 +224,16 @@ public:
m_valid16BitShadowLength = 0;
}
void swap(StringBuilder& stringBuilder)
{
std::swap(m_length, stringBuilder.m_length);
m_string.swap(stringBuilder.m_string);
m_buffer.swap(stringBuilder.m_buffer);
std::swap(m_is8Bit, stringBuilder.m_is8Bit);
std::swap(m_valid16BitShadowLength, stringBuilder.m_valid16BitShadowLength);
std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8);
}
private:
void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength);
void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
......@@ -200,10 +246,10 @@ private:
CharType* appendUninitializedSlow(unsigned length);
template <typename CharType>
ALWAYS_INLINE CharType * getBufferCharacters();
WTF_EXPORT_PRIVATE void reifyString();
WTF_EXPORT_PRIVATE void reifyString() const;
unsigned m_length;
String m_string;
mutable String m_string;
RefPtr<StringImpl> m_buffer;
bool m_is8Bit;
mutable unsigned m_valid16BitShadowLength;
......@@ -227,6 +273,45 @@ ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>()
return m_bufferCharacters16;
}
template <typename CharType>
bool equal(const StringBuilder& s, const CharType* buffer, unsigned length)
{
if (s.length() != length)
return false;
if (s.is8Bit())
return equal(s.characters8(), buffer, length);
return equal(s.characters16(), buffer, length);
}
template <typename StringType>
bool equal(const StringBuilder& a, const StringType& b)
{
if (a.length() != b.length())
return false;
if (!a.length())
return true;
if (a.is8Bit()) {
if (b.is8Bit())
return equal(a.characters8(), b.characters8(), a.length());
return equal(a.characters8(), b.characters16(), a.length());
}
if (b.is8Bit())
return equal(a.characters16(), b.characters8(), a.length());
return equal(a.characters16(), b.characters16(), a.length());
}
inline bool operator==(const StringBuilder& a, const StringBuilder& b) { return equal(a, b); }
inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { return !equal(a, b); }
inline bool operator==(const StringBuilder& a, const String& b) { return equal(a, b); }
inline bool operator!=(const StringBuilder& a, const String& b) { return !equal(a, b); }
inline bool operator==(const String& a, const StringBuilder& b) { return equal(b, a); }
inline bool operator!=(const String& a, const StringBuilder& b) { return !equal(b, a); }
} // namespace WTF
using WTF::StringBuilder;
......
......@@ -52,6 +52,7 @@ namespace WTF {
struct CStringTranslator;
struct HashAndCharactersTranslator;
struct HashAndUTF8CharactersTranslator;
struct SubstringTranslator;
struct UCharBufferTranslator;
enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive };
......@@ -68,6 +69,7 @@ class StringImpl {
friend struct WTF::CStringTranslator;
friend struct WTF::HashAndCharactersTranslator;
friend struct WTF::HashAndUTF8CharactersTranslator;
friend struct WTF::SubstringTranslator;
friend struct WTF::UCharBufferTranslator;
friend class AtomicStringImpl;
......
2012-01-23 Xianzhu Wang <wangxianzhu@chromium.org>
Basic enhancements to StringBuilder
https://bugs.webkit.org/show_bug.cgi?id=67081
These changes are because we explicitly disallowed StringBuilder's
copy constructor and assignment operator, and the change of return
type of StringBuilder::toString().
Reviewed by Darin Adler.
No new tests. All layout tests and unit tests should run as before.
* platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp:
(WebCore::MediaPlayerPrivateQuickTimeVisualContext::setUpCookiesForQuickTime):
* svg/SVGPathStringBuilder.h:
(WebCore::SVGPathStringBuilder::cleanup):
2012-01-23 W. James MacLean <wjmaclean@chromium.org>
 
[chromium] Add WebSolidColorLayer interface to draw non-textured color layers from Aura.
......@@ -302,7 +302,8 @@ void MediaPlayerPrivateQuickTimeVisualContext::setUpCookiesForQuickTime(const St
} else
cookieURL = movieURL;
InternetSetCookieExW(cookieURL.charactersWithNullTermination(), 0, cookieBuilder.toString().charactersWithNullTermination(), 0, 0);
String string = cookieBuilder.toString();
InternetSetCookieExW(cookieURL.charactersWithNullTermination(), 0, string.charactersWithNullTermination(), 0, 0);
}
}
......
......@@ -32,7 +32,7 @@ public:
String result();
private:
virtual void cleanup() { m_stringBuilder = StringBuilder(); }
virtual void cleanup() { m_stringBuilder.clear(); }
virtual void incrementPathSegmentCount() { }
virtual bool continueConsuming() { return true; }
......
2012-01-23 Xianzhu Wang <wangxianzhu@chromium.org>
Basic enhancements to StringBuilder
https://bugs.webkit.org/show_bug.cgi?id=67081
This change is because we explicitly disallowed StringBuilder's
copy constructor and assignment operator.
Reviewed by Darin Adler.
No new tests. All layout tests and unit tests should run as before.
* src/WebPageSerializerImpl.cpp:
(WebKit::WebPageSerializerImpl::encodeAndFlushBuffer):
2012-01-23 W. James MacLean <wjmaclean@chromium.org>
 
[chromium] Add WebSolidColorLayer interface to draw non-textured color layers from Aura.
......
......@@ -283,7 +283,7 @@ void WebPageSerializerImpl::encodeAndFlushBuffer(
return;
String content = m_dataBuffer.toString();
m_dataBuffer = StringBuilder();
m_dataBuffer.clear();
// Convert the unicode content to target encoding
CString encodedContent = param->textEncoding.encode(
......
2012-01-23 Xianzhu Wang <wangxianzhu@chromium.org>
Basic enhancements to StringBuilder
https://bugs.webkit.org/show_bug.cgi?id=67081
Reviewed by Darin Adler.
* TestWebKitAPI/Tests/WTF/StringBuilder.cpp:
(TestWebKitAPI::TEST):
2012-01-23 Mario Sanchez Prada <msanchez@igalia.com>
 
[GTK] run-gtk-tests randomly fails while running the xprop comand
......@@ -75,6 +75,16 @@ TEST(StringBuilderTest, Append)
builder1.append("XYZ");
builder.append(builder1.characters(), builder1.length());
expectBuilderContent("0123456789abcdefg#0123456789abcdefg#XYZ", builder);
StringBuilder builder2;
builder2.reserveCapacity(100);
builder2.append("xyz");
const UChar* characters = builder2.characters();
builder2.append("0123456789");
ASSERT_EQ(characters, builder2.characters());
builder2.toStringPreserveCapacity(); // Test after reifyString with buffer preserved.
builder2.append("abcd");
ASSERT_EQ(characters, builder2.characters());
}
TEST(StringBuilderTest, ToString)
......@@ -114,7 +124,9 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
{
StringBuilder builder;
builder.append("0123456789");
unsigned capacity = builder.capacity();
String string = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
ASSERT_EQ(String("0123456789"), string);
ASSERT_EQ(string.impl(), builder.toStringPreserveCapacity().impl());
ASSERT_EQ(string.characters(), builder.characters());
......@@ -125,14 +137,18 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
// Changing the StringBuilder should not affect the original result of toStringPreserveCapacity() in case the capacity is not changed.
builder.reserveCapacity(200);
capacity = builder.capacity();
string = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
ASSERT_EQ(string.characters(), builder.characters());
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
builder.append("ABC");
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
// Changing the original result of toStringPreserveCapacity() should not affect the content of the StringBuilder.
capacity = builder.capacity();
String string1 = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
ASSERT_EQ(string1.characters(), builder.characters());
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
string1.append("DEF");
......@@ -140,7 +156,9 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABCDEF"), string1);
// Resizing the StringBuilder should not affect the original result of toStringPreserveCapacity().
capacity = builder.capacity();
string1 = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
ASSERT_EQ(string.characters(), builder.characters());
builder.resize(10);
builder.append("###");
......@@ -185,4 +203,75 @@ TEST(StringBuilderTest, Resize)
expectEmpty(builder);
}
TEST(StringBuilderTest, Equal)
{
StringBuilder builder1;
StringBuilder builder2;
ASSERT_TRUE(builder1 == builder2);
ASSERT_TRUE(equal(builder1, static_cast<LChar*>(0), 0));
ASSERT_TRUE(builder1 == String());
ASSERT_TRUE(String() == builder1);
ASSERT_TRUE(builder1 != String("abc"));