Basic enhancements to StringBuilder
authorwangxianzhu@chromium.org <wangxianzhu@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 23 Jan 2012 20:42:05 +0000 (20:42 +0000)
committerwangxianzhu@chromium.org <wangxianzhu@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 23 Jan 2012 20:42:05 +0000 (20:42 +0000)
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

16 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.exp
Source/JavaScriptCore/JavaScriptCore.order
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
Source/JavaScriptCore/wtf/text/AtomicString.cpp
Source/JavaScriptCore/wtf/text/AtomicString.h
Source/JavaScriptCore/wtf/text/StringBuilder.cpp
Source/JavaScriptCore/wtf/text/StringBuilder.h
Source/JavaScriptCore/wtf/text/StringImpl.h
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
Source/WebCore/svg/SVGPathStringBuilder.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/WebPageSerializerImpl.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp

index 59d9f46..16bacea 100644 (file)
@@ -1,3 +1,49 @@
+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.
index 7862e07..f726757 100644 (file)
@@ -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
index 3ceda65..d8513d0 100644 (file)
@@ -323,7 +323,8 @@ __ZN3WTF13StringBuilder6appendEPKtj
 __ZN3WTF13StringBuilder19appendUninitializedEj
 __ZN3WTF13StringBuilder14allocateBufferEPKtj
 __ZN3WTF13StringBuilder11shrinkToFitEv
-__ZN3WTF13StringBuilder11reifyStringEv
+__ZNK3WTF13StringBuilder11reifyStringEv
+__ZNK3WTF13StringBuilder9canShrinkEv
 __ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
 __ZN3JSC7JSArray20increaseVectorLengthEj
 __ZN3WTF14tryFastReallocEPvm
index 7cc41cd..4ef8ed3 100644 (file)
@@ -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
index 9668798..d775e7b 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * 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();
 
index 4c44f3d..6c26069 100644 (file)
@@ -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;
index 6d3c310..4eac756 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * 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
index bf7aed4..6475d54 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * 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
 #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;
index a2fe53d..1c743cb 100644 (file)
@@ -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;
 
index 0b28d38..418d2ad 100644 (file)
@@ -1,3 +1,21 @@
+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.
index e2e0c10..f800d57 100644 (file)
@@ -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);
     }
 }
 
index 6a7e980..f91adad 100644 (file)
@@ -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; }
 
index 1aad2b3..529faa2 100644 (file)
@@ -1,3 +1,18 @@
+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.
index fd2690a..37489c6 100644 (file)
@@ -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(
index 1951c2d..a27f3c6 100644 (file)
@@ -1,3 +1,13 @@
+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
index 35b1244..9d540ed 100644 (file)
@@ -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"));
+
+    builder1.append("123");
+    builder1.reserveCapacity(32);
+    builder2.append("123");
+    builder1.reserveCapacity(64);
+    ASSERT_TRUE(builder1 == builder2);
+    ASSERT_TRUE(builder1 == String("123"));
+    ASSERT_TRUE(String("123") == builder1);
+
+    builder2.append("456");
+    ASSERT_TRUE(builder1 != builder2);
+    ASSERT_TRUE(builder2 != builder1);
+    ASSERT_TRUE(String("123") != builder2);
+    ASSERT_TRUE(builder2 != String("123"));
+    builder2.toString(); // Test after reifyString().
+    ASSERT_TRUE(builder1 != builder2);
+
+    builder2.resize(3);
+    ASSERT_TRUE(builder1 == builder2);
+
+    builder1.toString(); // Test after reifyString().
+    ASSERT_TRUE(builder1 == builder2);
+}
+
+TEST(StringBuilderTest, CanShrink)
+{
+    StringBuilder builder;
+    builder.reserveCapacity(256);
+    ASSERT_TRUE(builder.canShrink());
+    for (int i = 0; i < 256; i++)
+        builder.append('x');
+    ASSERT_EQ(builder.length(), builder.capacity());
+    ASSERT_FALSE(builder.canShrink());
+}
+
+TEST(StringBuilderTest, ToAtomicString)
+{
+    StringBuilder builder;
+    builder.append("123");
+    AtomicString atomicString = builder.toAtomicString();
+    ASSERT_EQ(String("123"), atomicString);
+
+    builder.reserveCapacity(256);
+    ASSERT_TRUE(builder.canShrink());
+    for (int i = builder.length(); i < 128; i++)
+        builder.append('x');
+    AtomicString atomicString1 = builder.toAtomicString();
+    ASSERT_EQ(128, atomicString1.length());
+    ASSERT_EQ('x', atomicString1[127]);
+
+    // Later change of builder should not affect the atomic string.
+    for (int i = builder.length(); i < 256; i++)
+        builder.append('x');
+    ASSERT_EQ(128, atomicString1.length());
+
+    ASSERT_FALSE(builder.canShrink());
+    String string = builder.toString();
+    AtomicString atomicString2 = builder.toAtomicString();
+    // They should share the same StringImpl.
+    ASSERT_EQ(atomicString2.impl(), string.impl());
+}
+
 } // namespace