Change the serialization format of form control state to make the code simple
[WebKit-https.git] / Source / WTF / wtf / text / StringBuilder.h
1 /*
2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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. 
25  */
26
27 #ifndef StringBuilder_h
28 #define StringBuilder_h
29
30 #include <wtf/text/AtomicString.h>
31 #include <wtf/text/WTFString.h>
32
33 namespace WTF {
34
35 class StringBuilder {
36     // Disallow copying since it's expensive and we don't want code to do it by accident.
37     WTF_MAKE_NONCOPYABLE(StringBuilder);
38
39 public:
40     StringBuilder()
41         : m_length(0)
42         , m_is8Bit(true)
43         , m_valid16BitShadowLength(0)
44         , m_bufferCharacters8(0)
45     {
46     }
47
48     WTF_EXPORT_PRIVATE void append(const UChar*, unsigned);
49     WTF_EXPORT_PRIVATE void append(const LChar*, unsigned);
50
51     ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast<const LChar*>(characters), length); }
52
53     void append(const String& string)
54     {
55         if (!string.length())
56             return;
57
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) {
61             m_string = string;
62             m_length = string.length();
63             m_is8Bit = m_string.is8Bit();
64             return;
65         }
66
67         if (string.is8Bit())
68             append(string.characters8(), string.length());
69         else
70             append(string.characters16(), string.length());
71     }
72
73     void append(const StringBuilder& other)
74     {
75         if (!other.m_length)
76             return;
77
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;
83             return;
84         }
85
86         append(other.characters(), other.m_length);
87     }
88
89     void append(const String& string, unsigned offset, unsigned length)
90     {
91         if (!string.length())
92             return;
93
94         if ((offset + length) > string.length())
95             return;
96
97         if (string.is8Bit())
98             append(string.characters8() + offset, length);
99         else
100             append(string.characters16() + offset, length);
101     }
102
103     void append(const char* characters)
104     {
105         if (characters)
106             append(characters, strlen(characters));
107     }
108
109     void append(UChar c)
110     {
111         if (m_buffer && !m_is8Bit && m_length < m_buffer->length() && m_string.isNull())
112             m_bufferCharacters16[m_length++] = c;
113         else
114             append(&c, 1);
115     }
116
117     void append(LChar c)
118     {
119         if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) {
120             if (m_is8Bit)
121                 m_bufferCharacters8[m_length++] = c;
122             else
123                 m_bufferCharacters16[m_length++] = c;
124         } else
125             append(&c, 1);
126     }
127     
128     void append(char c)
129     {
130         append(static_cast<LChar>(c));
131     }
132
133     void appendEscaped(const String& string, UChar escape, UChar special)
134     {
135         if (string.isEmpty())
136             return;
137         unsigned requiredSize = length() + string.length();
138         if (capacity() < requiredSize)
139             reserveCapacity(requiredSize);
140         for (unsigned i = 0; i < string.length(); ++i) {
141             UChar ch = string[i];
142             if (ch == escape || ch == special)
143                 append(escape);
144             append(ch);
145         }
146     }
147
148     String toString()
149     {
150         shrinkToFit();
151         if (m_string.isNull())
152             reifyString();
153         return m_string;
154     }
155
156     const String& toStringPreserveCapacity() const
157     {
158         if (m_string.isNull())
159             reifyString();
160         return m_string;
161     }
162
163     AtomicString toAtomicString() const
164     {
165         if (!m_length)
166             return AtomicString();
167
168         // If the buffer is sufficiently over-allocated, make a new AtomicString from a copy so its buffer is not so large.
169         if (canShrink())
170             return AtomicString(characters(), length());
171
172         if (!m_string.isNull())
173             return AtomicString(m_string);
174
175         ASSERT(m_buffer);
176         return AtomicString(m_buffer.get(), 0, m_length);
177     }
178
179     unsigned length() const
180     {
181         return m_length;
182     }
183
184     bool isEmpty() const { return !m_length; }
185
186     WTF_EXPORT_PRIVATE void reserveCapacity(unsigned newCapacity);
187
188     unsigned capacity() const
189     {
190         return m_buffer ? m_buffer->length() : m_length;
191     }
192
193     WTF_EXPORT_PRIVATE void resize(unsigned newSize);
194
195     WTF_EXPORT_PRIVATE bool canShrink() const;
196
197     WTF_EXPORT_PRIVATE void shrinkToFit();
198
199     UChar operator[](unsigned i) const
200     {
201         ASSERT(i < m_length);
202         if (m_is8Bit)
203             return characters8()[i];
204         return characters16()[i];
205     }
206
207     const LChar* characters8() const
208     {
209         ASSERT(m_is8Bit);
210         if (!m_length)
211             return 0;
212         if (!m_string.isNull())
213             return m_string.characters8();
214         ASSERT(m_buffer);
215         return m_buffer->characters8();
216     }
217
218     const UChar* characters16() const
219     {
220         ASSERT(!m_is8Bit);
221         if (!m_length)
222             return 0;
223         if (!m_string.isNull())
224             return m_string.characters16();
225         ASSERT(m_buffer);
226         return m_buffer->characters16();
227     }
228     
229     const UChar* characters() const
230     {
231         if (!m_length)
232             return 0;
233         if (!m_string.isNull())
234             return m_string.characters();
235         ASSERT(m_buffer);
236         if (m_buffer->has16BitShadow() && m_valid16BitShadowLength < m_length)
237             m_buffer->upconvertCharacters(m_valid16BitShadowLength, m_length);
238
239         m_valid16BitShadowLength = m_length;
240
241         return m_buffer->characters();
242     }
243     
244     bool is8Bit() const { return m_is8Bit; }
245
246     void clear()
247     {
248         m_length = 0;
249         m_string = String();
250         m_buffer = 0;
251         m_bufferCharacters8 = 0;
252         m_is8Bit = true;
253         m_valid16BitShadowLength = 0;
254     }
255
256     void swap(StringBuilder& stringBuilder)
257     {
258         std::swap(m_length, stringBuilder.m_length);
259         m_string.swap(stringBuilder.m_string);
260         m_buffer.swap(stringBuilder.m_buffer);
261         std::swap(m_is8Bit, stringBuilder.m_is8Bit);
262         std::swap(m_valid16BitShadowLength, stringBuilder.m_valid16BitShadowLength);
263         std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8);
264     }
265
266 private:
267     void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength);
268     void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
269     void allocateBufferUpConvert(const LChar* currentCharacters, unsigned requiredLength);
270     template <typename CharType>
271     void reallocateBuffer(unsigned requiredLength);
272     template <typename CharType>
273     ALWAYS_INLINE CharType* appendUninitialized(unsigned length);
274     template <typename CharType>
275     CharType* appendUninitializedSlow(unsigned length);
276     template <typename CharType>
277     ALWAYS_INLINE CharType * getBufferCharacters();
278     WTF_EXPORT_PRIVATE void reifyString() const;
279
280     unsigned m_length;
281     mutable String m_string;
282     RefPtr<StringImpl> m_buffer;
283     bool m_is8Bit;
284     mutable unsigned m_valid16BitShadowLength;
285     union {
286         LChar* m_bufferCharacters8;
287         UChar* m_bufferCharacters16;
288     };
289 };
290
291 template <>
292 ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters<LChar>()
293 {
294     ASSERT(m_is8Bit);
295     return m_bufferCharacters8;
296 }
297
298 template <>
299 ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>()
300 {
301     ASSERT(!m_is8Bit);
302     return m_bufferCharacters16;
303 }    
304
305 template <typename CharType>
306 bool equal(const StringBuilder& s, const CharType* buffer, unsigned length)
307 {
308     if (s.length() != length)
309         return false;
310
311     if (s.is8Bit())
312         return equal(s.characters8(), buffer, length);
313
314     return equal(s.characters16(), buffer, length);
315 }
316
317 template <typename StringType>
318 bool equal(const StringBuilder& a, const StringType& b)
319 {
320     if (a.length() != b.length())
321         return false;
322
323     if (!a.length())
324         return true;
325
326     if (a.is8Bit()) {
327         if (b.is8Bit())
328             return equal(a.characters8(), b.characters8(), a.length());
329         return equal(a.characters8(), b.characters16(), a.length());
330     }
331
332     if (b.is8Bit())
333         return equal(a.characters16(), b.characters8(), a.length());
334     return equal(a.characters16(), b.characters16(), a.length());
335 }
336
337 inline bool operator==(const StringBuilder& a, const StringBuilder& b) { return equal(a, b); }
338 inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { return !equal(a, b); }
339 inline bool operator==(const StringBuilder& a, const String& b) { return equal(a, b); }
340 inline bool operator!=(const StringBuilder& a, const String& b) { return !equal(a, b); }
341 inline bool operator==(const String& a, const StringBuilder& b) { return equal(b, a); }
342 inline bool operator!=(const String& a, const StringBuilder& b) { return !equal(b, a); }
343
344 } // namespace WTF
345
346 using WTF::StringBuilder;
347
348 #endif // StringBuilder_h