OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 patch class StringBuffer { | 5 patch class StringBuffer { |
6 List<String> _buffer; | 6 /** Backing store for collected UTF-16 code units. */ |
7 int _length; | 7 Uint16List _buffer; |
8 /** Number of code units collected. */ | |
9 int _length = 0; | |
10 /** | |
11 * Collects the approximate maximal magnitude of the added code units. | |
12 * | |
13 * The value of each added code unit is or'ed with this variable, so the | |
14 * most significant bit set in any code unit is also set in this value. | |
15 * If below 256, the string is a Latin-1 string. | |
16 */ | |
17 int _code_magnitude = 0; | |
srdjan
2013/03/07 17:58:34
s/_code_magnitude/_codeMagnitude/
Lasse Reichstein Nielsen
2013/03/08 07:18:44
On 2013/03/07 17:58:34, srdjan wrote:
> s/_code_ma
Lasse Reichstein Nielsen
2013/03/08 07:18:44
_codeUnitMagnitude even.
| |
8 | 18 |
9 /// Creates the string buffer with an initial content. | 19 /// Creates the string buffer with an initial content. |
10 /* patch */ StringBuffer([Object content = ""]) { | 20 /* patch */ StringBuffer([Object content = ""]) |
11 _buffer = new List<String>(); | 21 : _buffer = new Uint16List(16) { |
12 _length = 0; | |
13 write(content); | 22 write(content); |
14 } | 23 } |
15 | 24 |
16 /* patch */ int get length => _length; | 25 /* patch */ int get length => _length; |
17 | 26 |
18 /// Adds [obj] to the buffer. | 27 /// Adds [obj] to the buffer. |
19 /* patch */ void write(Object obj) { | 28 /* patch */ void write(Object obj) { |
20 // TODO(srdjan): The following four lines could be replaced by | |
21 // '$obj', but apparently this is too slow on the Dart VM. | |
22 String str; | 29 String str; |
23 if (obj is String) { | 30 if (obj is String) { |
24 str = obj; | 31 str = obj; |
25 } else { | 32 } else { |
33 // TODO(srdjan): The following four lines could be replaced by | |
34 // '$obj', but apparently this is too slow on the Dart VM. | |
26 str = obj.toString(); | 35 str = obj.toString(); |
27 if (str is! String) { | 36 if (str is! String) { |
28 throw new ArgumentError('toString() did not return a string'); | 37 throw new ArgumentError('toString() did not return a string'); |
29 } | 38 } |
30 } | 39 } |
31 if (str.isEmpty) return; | 40 if (str.isEmpty) return; |
32 _buffer.add(str); | 41 _ensureCapacity(str.length); |
42 for (int i = 0; i < str.length; i++) { | |
43 int unit = str.codeUnitAt(i); | |
44 _buffer[_length + i] = unit; | |
45 _code_magnitude |= unit; | |
46 } | |
33 _length += str.length; | 47 _length += str.length; |
34 } | 48 } |
35 | 49 |
36 /// Clears the string buffer. | 50 /* patch */ writeCharCode(int charCode) { |
37 /* patch */ void clear() { | 51 if (charCode <= 0xFFFF) { |
38 _buffer = new List<String>(); | 52 if (charCode < 0) { |
39 _length = 0; | 53 throw new RangeError.range(charCode, 0, 0x10FFFF); |
54 } | |
55 _ensureCapacity(1); | |
56 _buffer[_length++] = charCode; | |
57 _code_magnitude |= charCode; | |
58 } else { | |
59 if (charCode > 0x10FFFF) { | |
60 throw new RangeError.range(charCode, 0, 0x10FFFF); | |
61 } | |
62 _ensureCapacity(2); | |
63 int bits = charCode - 0x10000; | |
64 _buffer[_length++] = 0xD800 | (bits >> 10); | |
65 _buffer[_length++] = 0xDC00 | (bits & 0x3FF); | |
66 _code_magnitude |= 0xFFFF; | |
67 } | |
40 } | 68 } |
41 | 69 |
42 /// Returns the contents of buffer as a concatenated string. | 70 /** Makes the buffer empty. */ |
71 /* patch */ void clear() { | |
72 _length = 0; | |
73 _code_magnitude = 0; | |
74 } | |
75 | |
76 /** Returns the contents of buffer as a string. */ | |
43 /* patch */ String toString() { | 77 /* patch */ String toString() { |
44 if (_buffer.length == 0) return ""; | 78 if (_length == 0) return ""; |
45 if (_buffer.length == 1) return _buffer[0]; | 79 return _create(_buffer, _length, _code_magnitude <= 0xFF); |
Vyacheslav Egorov (Google)
2013/03/07 13:50:52
consider:
final isLatin1 = _code_magnitude <= 0x
Lasse Reichstein Nielsen
2013/03/08 07:18:44
Done.
| |
46 String result = _StringBase.concatAll(_buffer); | |
47 _buffer.clear(); | |
48 _buffer.add(result); | |
49 // Since we track the length at each add operation, there is no | |
50 // need to update it in this function. | |
51 return result; | |
52 } | 80 } |
81 | |
82 /** Ensures that the buffer has enough capacity to contain n code units. */ | |
srdjan
2013/03/07 17:58:34
s/contain/add/
Lasse Reichstein Nielsen
2013/03/08 07:18:44
Done.
| |
83 void _ensureCapacity(int n) { | |
84 int requiredCapacity = _length + n; | |
85 if (requiredCapacity <= _buffer.length) return; | |
Vyacheslav Egorov (Google)
2013/03/07 13:50:52
consider
{
return;
}
and more vertical white s
srdjan
2013/03/07 17:58:34
I would split the rare case out:
if (requiredCapac
Lasse Reichstein Nielsen
2013/03/08 07:18:44
Done.
| |
86 int newCapacity = _buffer.length; | |
87 do { | |
88 newCapacity *= 2; | |
srdjan
2013/03/07 17:58:34
Optional: This growth may be too aggressive. Opini
Lasse Reichstein Nielsen
2013/03/08 07:18:44
I was wondering if it was too small, and consideri
| |
89 } while (newCapacity < requiredCapacity); | |
90 List<int> newBuffer = new Uint16List(newCapacity); | |
91 newBuffer.setRange(0, _length, _buffer); | |
92 _buffer = newBuffer; | |
93 } | |
94 | |
95 /** | |
96 * Create a [String] from the UFT-16 code units in buffer. | |
97 */ | |
98 static String _create(List<int> buffer, int length, bool isLatin1) | |
srdjan
2013/03/07 17:58:34
s/List<int>/Uint16List/
Lasse Reichstein Nielsen
2013/03/08 07:18:44
Done.
| |
99 native "StringBuffer_createStringFromUint16Array"; | |
53 } | 100 } |
OLD | NEW |