2 * Copyright (C) 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #ifndef StringBuilder_h
28 #define StringBuilder_h
30 #include <wtf/text/AtomicString.h>
31 #include <wtf/text/StringView.h>
32 #include <wtf/text/WTFString.h>
37 // Disallow copying since it's expensive and we don't want code to do it by accident.
38 WTF_MAKE_NONCOPYABLE(StringBuilder);
44 , m_bufferCharacters8(0)
48 WTF_EXPORT_PRIVATE void append(const UChar*, unsigned);
49 WTF_EXPORT_PRIVATE void append(const LChar*, unsigned);
51 ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast<const LChar*>(characters), length); }
53 void append(const String& string)
58 // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called)
59 // then just retain the string.
60 if (!m_length && !m_buffer) {
62 m_length = string.length();
63 m_is8Bit = m_string.is8Bit();
68 append(string.characters8(), string.length());
70 append(string.characters16(), string.length());
73 void append(const StringBuilder& other)
78 // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called)
79 // then just retain the string.
80 if (!m_length && !m_buffer && !other.m_string.isNull()) {
81 m_string = other.m_string;
82 m_length = other.m_length;
87 append(other.characters8(), other.m_length);
89 append(other.characters16(), other.m_length);
92 void append(StringView stringView)
94 if (stringView.is8Bit())
95 append(stringView.characters8(), stringView.length());
97 append(stringView.characters16(), stringView.length());
100 void append(const String& string, unsigned offset, unsigned length)
102 if (!string.length())
105 if ((offset + length) > string.length())
109 append(string.characters8() + offset, length);
111 append(string.characters16() + offset, length);
114 void append(const char* characters)
117 append(characters, strlen(characters));
122 if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) {
124 m_bufferCharacters16[m_length++] = c;
129 m_bufferCharacters8[m_length++] = static_cast<LChar>(c);
138 if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) {
140 m_bufferCharacters8[m_length++] = c;
142 m_bufferCharacters16[m_length++] = c;
149 append(static_cast<LChar>(c));
152 void append(UChar32 c)
155 append(static_cast<UChar>(c));
159 append(U16_TRAIL(c));
162 template<unsigned charactersCount>
163 ALWAYS_INLINE void appendLiteral(const char (&characters)[charactersCount]) { append(characters, charactersCount - 1); }
165 WTF_EXPORT_PRIVATE void appendNumber(int);
166 WTF_EXPORT_PRIVATE void appendNumber(unsigned int);
167 WTF_EXPORT_PRIVATE void appendNumber(long);
168 WTF_EXPORT_PRIVATE void appendNumber(unsigned long);
169 WTF_EXPORT_PRIVATE void appendNumber(long long);
170 WTF_EXPORT_PRIVATE void appendNumber(unsigned long long);
171 WTF_EXPORT_PRIVATE void appendNumber(double, unsigned precision = 6, TrailingZerosTruncatingPolicy = TruncateTrailingZeros);
172 WTF_EXPORT_PRIVATE void appendECMAScriptNumber(double);
173 WTF_EXPORT_PRIVATE void appendFixedWidthNumber(double, unsigned decimalPlaces);
178 if (m_string.isNull())
183 const String& toStringPreserveCapacity() const
185 if (m_string.isNull())
190 AtomicString toAtomicString() const
195 // If the buffer is sufficiently over-allocated, make a new AtomicString from a copy so its buffer is not so large.
198 return AtomicString(characters8(), length());
199 return AtomicString(characters16(), length());
202 if (!m_string.isNull())
203 return AtomicString(m_string);
206 return AtomicString(m_buffer.get(), 0, m_length);
209 unsigned length() const
214 bool isEmpty() const { return !m_length; }
216 WTF_EXPORT_PRIVATE void reserveCapacity(unsigned newCapacity);
218 unsigned capacity() const
220 return m_buffer ? m_buffer->length() : m_length;
223 WTF_EXPORT_PRIVATE void resize(unsigned newSize);
225 WTF_EXPORT_PRIVATE bool canShrink() const;
227 WTF_EXPORT_PRIVATE void shrinkToFit();
229 UChar operator[](unsigned i) const
231 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length);
233 return characters8()[i];
234 return characters16()[i];
237 const LChar* characters8() const
242 if (!m_string.isNull())
243 return m_string.characters8();
245 return m_buffer->characters8();
248 const UChar* characters16() const
253 if (!m_string.isNull())
254 return m_string.characters16();
256 return m_buffer->characters16();
259 bool is8Bit() const { return m_is8Bit; }
266 m_bufferCharacters8 = 0;
270 void swap(StringBuilder& stringBuilder)
272 std::swap(m_length, stringBuilder.m_length);
273 m_string.swap(stringBuilder.m_string);
274 m_buffer.swap(stringBuilder.m_buffer);
275 std::swap(m_is8Bit, stringBuilder.m_is8Bit);
276 std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8);
280 void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength);
281 void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
282 void allocateBufferUpConvert(const LChar* currentCharacters, unsigned requiredLength);
283 template <typename CharType>
284 void reallocateBuffer(unsigned requiredLength);
285 template <typename CharType>
286 ALWAYS_INLINE CharType* appendUninitialized(unsigned length);
287 template <typename CharType>
288 CharType* appendUninitializedSlow(unsigned length);
289 template <typename CharType>
290 ALWAYS_INLINE CharType * getBufferCharacters();
291 WTF_EXPORT_PRIVATE void reifyString() const;
294 mutable String m_string;
295 RefPtr<StringImpl> m_buffer;
298 LChar* m_bufferCharacters8;
299 UChar* m_bufferCharacters16;
304 ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters<LChar>()
307 return m_bufferCharacters8;
311 ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>()
314 return m_bufferCharacters16;
317 template <typename CharType>
318 bool equal(const StringBuilder& s, const CharType* buffer, unsigned length)
320 if (s.length() != length)
324 return equal(s.characters8(), buffer, length);
326 return equal(s.characters16(), buffer, length);
329 template <typename StringType>
330 bool equal(const StringBuilder& a, const StringType& b)
332 if (a.length() != b.length())
340 return equal(a.characters8(), b.characters8(), a.length());
341 return equal(a.characters8(), b.characters16(), a.length());
345 return equal(a.characters16(), b.characters8(), a.length());
346 return equal(a.characters16(), b.characters16(), a.length());
349 inline bool operator==(const StringBuilder& a, const StringBuilder& b) { return equal(a, b); }
350 inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { return !equal(a, b); }
351 inline bool operator==(const StringBuilder& a, const String& b) { return equal(a, b); }
352 inline bool operator!=(const StringBuilder& a, const String& b) { return !equal(a, b); }
353 inline bool operator==(const String& a, const StringBuilder& b) { return equal(b, a); }
354 inline bool operator!=(const String& a, const StringBuilder& b) { return !equal(b, a); }
358 using WTF::StringBuilder;
360 #endif // StringBuilder_h