Index: third_party/WebKit/Source/wtf/text/StringBuilder.h |
diff --git a/third_party/WebKit/Source/wtf/text/StringBuilder.h b/third_party/WebKit/Source/wtf/text/StringBuilder.h |
index c967fa6082696ec2c0f232172ddd0837ee13a327..783fdbaf8c8b4254a99af444239f488fd9c7ac13 100644 |
--- a/third_party/WebKit/Source/wtf/text/StringBuilder.h |
+++ b/third_party/WebKit/Source/wtf/text/StringBuilder.h |
@@ -35,19 +35,17 @@ |
namespace WTF { |
class WTF_EXPORT 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_bufferCharacters8(0) |
+ : m_buffer(nullptr) |
, m_length(0) |
- , m_is8Bit(true) |
- { |
- } |
+ , m_is8Bit(true) {} |
- void append(const UChar*, unsigned); |
- void append(const LChar*, unsigned); |
+ ~StringBuilder() { clear(); } |
+ |
+ void append(const UChar*, unsigned length); |
+ void append(const LChar*, unsigned length); |
ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast<const LChar*>(characters), length); } |
@@ -56,11 +54,10 @@ public: |
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()) { |
+ if (!m_length && !hasBuffer() && !other.m_string.isNull()) { |
m_string = other.m_string; |
- m_length = other.m_length; |
+ m_length = other.m_string.length(); |
+ m_is8Bit = other.m_string.is8Bit(); |
return; |
} |
@@ -99,7 +96,7 @@ public: |
// inside the parser in the common case when flushing buffered text to |
// a Text node. |
StringImpl* impl = string.sharedImpl(); |
- if (!m_length && !m_buffer && impl) { |
+ if (!m_length && !hasBuffer() && impl) { |
m_string = impl; |
m_length = impl->length(); |
m_is8Bit = impl->is8Bit(); |
@@ -114,30 +111,26 @@ public: |
void append(UChar c) |
{ |
- if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) { |
- if (!m_is8Bit) { |
- m_bufferCharacters16[m_length++] = c; |
- return; |
- } |
- |
- if (!(c & ~0xff)) { |
- m_bufferCharacters8[m_length++] = static_cast<LChar>(c); |
- return; |
- } |
+ if (m_is8Bit && c <= 0xFF) { |
+ append(static_cast<LChar>(c)); |
+ return; |
} |
- append(&c, 1); |
+ ensureBuffer16(); |
+ m_string = String(); |
+ m_buffer16->append(c); |
+ ++m_length; |
} |
void append(LChar c) |
{ |
- if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) { |
- if (m_is8Bit) |
- m_bufferCharacters8[m_length++] = c; |
- else |
- m_bufferCharacters16[m_length++] = c; |
- } else { |
- append(&c, 1); |
+ if (!m_is8Bit) { |
+ append(static_cast<UChar>(c)); |
+ return; |
} |
+ ensureBuffer8(); |
+ m_string = String(); |
+ m_buffer8->append(c); |
+ ++m_length; |
} |
void append(char c) |
@@ -163,62 +156,19 @@ public: |
void appendNumber(unsigned long long); |
void appendNumber(double, unsigned precision = 6, TrailingZerosTruncatingPolicy = TruncateTrailingZeros); |
- String toString() |
- { |
- shrinkToFit(); |
- if (m_string.isNull()) |
- reifyString(); |
- return m_string; |
- } |
- |
- String substring(unsigned position, unsigned length) const |
- { |
- if (!m_length) |
- return emptyString(); |
- if (!m_string.isNull()) |
- return m_string.substring(position, length); |
- return reifySubstring(position, length); |
- } |
- |
- AtomicString toAtomicString() const |
- { |
- if (!m_length) |
- return emptyAtom; |
- |
- // If the buffer is sufficiently over-allocated, make a new AtomicString from a copy so its buffer is not so large. |
- if (canShrink()) { |
- if (is8Bit()) |
- return AtomicString(characters8(), length()); |
- return AtomicString(characters16(), length()); |
- } |
- |
- if (!m_string.isNull()) |
- return AtomicString(m_string); |
- |
- DCHECK(m_buffer); |
- return AtomicString(m_buffer.get(), 0, m_length); |
- } |
- |
- unsigned length() const |
- { |
- return m_length; |
- } |
+ String toString(); |
+ AtomicString toAtomicString(); |
+ String substring(unsigned start, unsigned length) const; |
+ unsigned length() const { return m_length; } |
bool isEmpty() const { return !m_length; } |
+ unsigned capacity() const; |
void reserveCapacity(unsigned newCapacity); |
- unsigned capacity() const |
- { |
- return m_buffer ? m_buffer->length() : m_length; |
- } |
- |
+ // TODO(esprehn): Rename to shrink(). |
void resize(unsigned newSize); |
- bool canShrink() const; |
- |
- void shrinkToFit(); |
- |
UChar operator[](unsigned i) const |
{ |
ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); |
@@ -230,84 +180,62 @@ public: |
const LChar* characters8() const |
{ |
DCHECK(m_is8Bit); |
- if (!m_length) |
- return 0; |
+ if (!length()) |
+ return nullptr; |
if (!m_string.isNull()) |
return m_string.characters8(); |
- DCHECK(m_buffer); |
- return m_buffer->characters8(); |
+ DCHECK(m_buffer8); |
+ return m_buffer8->data(); |
} |
const UChar* characters16() const |
{ |
DCHECK(!m_is8Bit); |
- if (!m_length) |
- return 0; |
+ if (!length()) |
+ return nullptr; |
if (!m_string.isNull()) |
return m_string.characters16(); |
- DCHECK(m_buffer); |
- return m_buffer->characters16(); |
+ DCHECK(m_buffer16); |
+ return m_buffer16->data(); |
} |
bool is8Bit() const { return m_is8Bit; } |
- void clear() |
+ void clear(); |
+ void swap(StringBuilder&); |
+ |
+private: |
+ typedef Vector<LChar, 16> Buffer8; |
+ typedef Vector<UChar, 16> Buffer16; |
haraken
2016/06/27 06:36:01
I don't mind specifying a larger inline capacity f
esprehn
2016/06/27 23:36:40
Yeah we can do that, there's a bunch of StringBuil
|
+ |
+ void ensureBuffer8() |
{ |
- m_length = 0; |
- m_string = String(); |
- m_buffer = nullptr; |
- m_bufferCharacters8 = 0; |
- m_is8Bit = true; |
+ DCHECK(m_is8Bit); |
+ if (!hasBuffer()) |
+ createBuffer8(); |
} |
- void swap(StringBuilder& stringBuilder) |
+ void ensureBuffer16() |
{ |
- 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_bufferCharacters8, stringBuilder.m_bufferCharacters8); |
+ if (m_is8Bit || !hasBuffer()) |
haraken
2016/06/27 06:36:01
Shouldn't this be:
DCHECK(!m_is8Bit);
if (!ha
esprehn
2016/06/27 23:36:40
No, this is called whenever we need a 16 bit buffe
|
+ createBuffer16(); |
} |
-private: |
- void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength); |
- void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength); |
- void allocateBufferUpConvert(const LChar* currentCharacters, unsigned requiredLength); |
- template <typename CharType> |
- void reallocateBuffer(unsigned requiredLength); |
- template <typename CharType> |
- ALWAYS_INLINE CharType* appendUninitialized(unsigned length); |
- template <typename CharType> |
- CharType* appendUninitializedSlow(unsigned length); |
- template <typename CharType> |
- ALWAYS_INLINE CharType * getBufferCharacters(); |
- void reifyString(); |
- String reifySubstring(unsigned position, unsigned length) const; |
- |
- String m_string; // Pointers first: crbug.com/232031 |
- RefPtr<StringImpl> m_buffer; |
+ void createBuffer8(); |
+ void createBuffer16(); |
+ |
+ bool hasBuffer() const { return m_buffer; } |
+ |
+ String m_string; |
union { |
- LChar* m_bufferCharacters8; |
- UChar* m_bufferCharacters16; |
+ Buffer8* m_buffer8; |
+ Buffer16* m_buffer16; |
+ void* m_buffer; |
hajimehoshi
2016/06/27 06:13:20
Where is |m_buffer| used now?
esprehn
2016/06/27 06:15:15
hasBuffer() uses it since it doesn't care about th
|
}; |
unsigned m_length; |
bool m_is8Bit; |
}; |
-template <> |
-ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters<LChar>() |
-{ |
- DCHECK(m_is8Bit); |
- return m_bufferCharacters8; |
-} |
- |
-template <> |
-ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>() |
-{ |
- DCHECK(!m_is8Bit); |
- return m_bufferCharacters16; |
-} |
- |
template <typename CharType> |
bool equal(const StringBuilder& s, const CharType* buffer, unsigned length) |
{ |