OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 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 #include "wtf/text/StringBuilder.h" | |
28 | |
29 #include "wtf/dtoa.h" | |
30 #include "wtf/text/IntegerToStringConversion.h" | |
31 #include "wtf/text/WTFString.h" | |
32 #include <algorithm> | |
33 | |
34 namespace WTF { | |
35 | |
36 String StringBuilder::toString() { | |
37 if (!m_length) | |
38 return emptyString; | |
39 if (m_string.isNull()) { | |
40 if (m_is8Bit) | |
41 m_string = String(characters8(), m_length); | |
42 else | |
43 m_string = String(characters16(), m_length); | |
44 clearBuffer(); | |
45 } | |
46 return m_string; | |
47 } | |
48 | |
49 AtomicString StringBuilder::toAtomicString() { | |
50 if (!m_length) | |
51 return emptyAtom; | |
52 if (m_string.isNull()) { | |
53 if (m_is8Bit) | |
54 m_string = AtomicString(characters8(), m_length); | |
55 else | |
56 m_string = AtomicString(characters16(), m_length); | |
57 clearBuffer(); | |
58 } | |
59 return AtomicString(m_string); | |
60 } | |
61 | |
62 String StringBuilder::substring(unsigned start, unsigned length) const { | |
63 if (start >= m_length) | |
64 return emptyString; | |
65 if (!m_string.isNull()) | |
66 return m_string.substring(start, length); | |
67 length = std::min(length, m_length - start); | |
68 if (m_is8Bit) | |
69 return String(characters8() + start, length); | |
70 return String(characters16() + start, length); | |
71 } | |
72 | |
73 void StringBuilder::swap(StringBuilder& builder) { | |
74 std::swap(m_string, builder.m_string); | |
75 std::swap(m_buffer, builder.m_buffer); | |
76 std::swap(m_length, builder.m_length); | |
77 std::swap(m_is8Bit, builder.m_is8Bit); | |
78 } | |
79 | |
80 void StringBuilder::clearBuffer() { | |
81 if (m_is8Bit) | |
82 delete m_buffer8; | |
83 else | |
84 delete m_buffer16; | |
85 m_buffer = nullptr; | |
86 } | |
87 | |
88 void StringBuilder::clear() { | |
89 clearBuffer(); | |
90 m_string = String(); | |
91 m_length = 0; | |
92 m_is8Bit = true; | |
93 } | |
94 | |
95 unsigned StringBuilder::capacity() const { | |
96 if (!hasBuffer()) | |
97 return 0; | |
98 if (m_is8Bit) | |
99 return m_buffer8->capacity(); | |
100 return m_buffer16->capacity(); | |
101 } | |
102 | |
103 void StringBuilder::reserveCapacity(unsigned newCapacity) { | |
104 if (m_is8Bit) | |
105 ensureBuffer8(newCapacity); | |
106 else | |
107 ensureBuffer16(newCapacity); | |
108 } | |
109 | |
110 void StringBuilder::resize(unsigned newSize) { | |
111 DCHECK_LE(newSize, m_length); | |
112 m_string = m_string.left(newSize); | |
113 m_length = newSize; | |
114 if (hasBuffer()) { | |
115 if (m_is8Bit) | |
116 m_buffer8->resize(newSize); | |
117 else | |
118 m_buffer16->resize(newSize); | |
119 } | |
120 } | |
121 | |
122 void StringBuilder::createBuffer8(unsigned addedSize) { | |
123 DCHECK(!hasBuffer()); | |
124 DCHECK(m_is8Bit); | |
125 m_buffer8 = new Buffer8; | |
126 // createBuffer is called right before appending addedSize more bytes. We | |
127 // want to ensure we have enough space to fit m_string plus the added | |
128 // size. | |
129 // | |
130 // We also ensure that we have at least the initialBufferSize of extra space | |
131 // for appending new bytes to avoid future mallocs for appending short | |
132 // strings or single characters. This is a no-op if m_length == 0 since | |
133 // initialBufferSize() is the same as the inline capacity of the vector. | |
134 // This allows doing append(string); append('\0') without extra mallocs. | |
135 m_buffer8->reserveInitialCapacity(m_length + | |
136 std::max(addedSize, initialBufferSize())); | |
137 m_length = 0; | |
138 append(m_string); | |
139 m_string = String(); | |
140 } | |
141 | |
142 void StringBuilder::createBuffer16(unsigned addedSize) { | |
143 DCHECK(m_is8Bit || !hasBuffer()); | |
144 Buffer8 buffer8; | |
145 unsigned length = m_length; | |
146 if (m_buffer8) { | |
147 m_buffer8->swap(buffer8); | |
148 delete m_buffer8; | |
149 } | |
150 m_buffer16 = new Buffer16; | |
151 // See createBuffer8's call to reserveInitialCapacity for why we do this. | |
152 m_buffer16->reserveInitialCapacity(m_length + | |
153 std::max(addedSize, initialBufferSize())); | |
154 m_is8Bit = false; | |
155 m_length = 0; | |
156 if (!buffer8.isEmpty()) { | |
157 append(buffer8.data(), length); | |
158 return; | |
159 } | |
160 append(m_string); | |
161 m_string = String(); | |
162 } | |
163 | |
164 void StringBuilder::append(const UChar* characters, unsigned length) { | |
165 if (!length) | |
166 return; | |
167 DCHECK(characters); | |
168 | |
169 // If there's only one char we use append(UChar) instead since it will | |
170 // check for latin1 and avoid converting to 16bit if possible. | |
171 if (length == 1) { | |
172 append(*characters); | |
173 return; | |
174 } | |
175 | |
176 ensureBuffer16(length); | |
177 m_buffer16->append(characters, length); | |
178 m_length += length; | |
179 } | |
180 | |
181 void StringBuilder::append(const LChar* characters, unsigned length) { | |
182 if (!length) | |
183 return; | |
184 DCHECK(characters); | |
185 | |
186 if (m_is8Bit) { | |
187 ensureBuffer8(length); | |
188 m_buffer8->append(characters, length); | |
189 m_length += length; | |
190 return; | |
191 } | |
192 | |
193 ensureBuffer16(length); | |
194 m_buffer16->append(characters, length); | |
195 m_length += length; | |
196 } | |
197 | |
198 template <typename IntegerType> | |
199 static void appendIntegerInternal(StringBuilder& builder, IntegerType input) { | |
200 IntegerToStringConverter<IntegerType> converter(input); | |
201 builder.append(converter.characters8(), converter.length()); | |
202 } | |
203 | |
204 void StringBuilder::appendNumber(int number) { | |
205 appendIntegerInternal(*this, number); | |
206 } | |
207 | |
208 void StringBuilder::appendNumber(unsigned number) { | |
209 appendIntegerInternal(*this, number); | |
210 } | |
211 | |
212 void StringBuilder::appendNumber(long number) { | |
213 appendIntegerInternal(*this, number); | |
214 } | |
215 | |
216 void StringBuilder::appendNumber(unsigned long number) { | |
217 appendIntegerInternal(*this, number); | |
218 } | |
219 | |
220 void StringBuilder::appendNumber(long long number) { | |
221 appendIntegerInternal(*this, number); | |
222 } | |
223 | |
224 void StringBuilder::appendNumber(unsigned long long number) { | |
225 appendIntegerInternal(*this, number); | |
226 } | |
227 | |
228 void StringBuilder::appendNumber(double number, unsigned precision) { | |
229 NumberToStringBuffer buffer; | |
230 append(numberToFixedPrecisionString(number, precision, buffer)); | |
231 } | |
232 | |
233 } // namespace WTF | |
OLD | NEW |