Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: sdk/lib/utf/utf_stream.dart

Issue 12328037: Add missing files from previous commit (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/io/string_transformer.dart ('k') | tests/standalone/io/delete_symlink_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
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.
4
5 part of dart.utf;
6
7 class _HelperStreamController<T> extends StreamController<T> {
8 final Function onPauseChanged;
9
10 _HelperStreamController(this.onPauseChanged);
11
12 void onPauseStateChange() {
13 onPauseChanged();
14 }
15 }
16
17 abstract class _StringDecoder implements StreamTransformer<List<int>, String> {
18 _HelperStreamController<String> _controller;
19 StreamSubscription<List<int>> _subscription;
20 List<int> _carry;
21 List<int> _buffer;
22 int _replacementChar;
23 bool _paused = false;
24
25 _StringDecoder(int this._replacementChar) {
26 _controller = new _HelperStreamController<String>(_onPauseChanged);
27 }
28
29 void _onPauseChanged() {
30 _paused = _controller.isPaused;
31 if (_subscription == null) return;
32 if (_paused) {
33 _subscription.pause();
34 } else {
35 _subscription.resume();
36 }
37 }
38
39 Stream<String> bind(Stream<List<int>> stream) {
40 _subscription = stream.listen(
41 _onData,
42 onError: _controller.signalError,
43 onDone: () {
44 if (_carry != null) {
45 _controller.add(new String.fromCharCodes(
46 new List.fixedLength(_carry.length, fill: _replacementChar)));
47 }
48 _controller.close();
49 },
50 unsubscribeOnError: false);
51 if (_paused) _subscription.pause();
52 return _controller.stream;
53 }
54
55 void _onData(List<int> bytes) {
56 _buffer = <int>[];
57 List<int> carry = _carry;
58 _carry = null;
59 int pos = 0;
60 int available = bytes.length;
61 // If we have carry-over data, start from negative index, indicating carry
62 // index.
63 int goodChars = 0;
64 if (carry != null) pos = -carry.length;
65 while (pos < available) {
66 int currentPos = pos;
67 int getNext() {
68 if (pos < 0) {
69 return carry[pos++ + carry.length];
70 } else if (pos < available) {
71 return bytes[pos++];
72 }
73 return null;
74 }
75 int consumed = _processBytes(getNext);
76 if (consumed > 0) {
77 goodChars = _buffer.length;
78 } else if (consumed == 0) {
79 _buffer.length = goodChars;
80 if (currentPos < 0) {
81 _carry = [];
82 _carry.addAll(carry);
83 _carry.addAll(bytes);
84 } else {
85 _carry = bytes.getRange(currentPos, bytes.length - currentPos);
86 }
87 break;
88 } else {
89 // Invalid byte at position pos - 1
90 _buffer.length = goodChars;
91 _addChar(-1);
92 goodChars = _buffer.length;
93 }
94 }
95 if (_buffer.length > 0) {
96 // Limit to 'goodChars', if lower than actual charCodes in the buffer.
97 _controller.add(new String.fromCharCodes(_buffer));
98 }
99 _buffer = null;
100 }
101
102 int _processBytes(int getNext());
103
104 void _addChar(int char) {
105 if (char > 0x10FFFF || char < 0) char = _replacementChar;
106 _buffer.add(char);
107 }
108 }
109
110 /**
111 * StringTransformer that decodes a stream of UTF-8 encoded bytes.
112 */
113 class Utf8DecoderTransformer extends _StringDecoder {
114 Utf8DecoderTransformer(
115 [int replacementChar = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT])
116 : super(replacementChar);
117
118 int _processBytes(int getNext()) {
119 int value = getNext();
120 if ((value & 0xFF) != value) return -1; // Not a byte.
121 if ((value & 0x80) == 0x80) {
122 int additionalBytes;
123 int min;
124 if ((value & 0xe0) == 0xc0) { // 110xxxxx
125 value = value & 0x1F;
126 additionalBytes = 1;
127 min = 0x80;
128 } else if ((value & 0xf0) == 0xe0) { // 1110xxxx
129 value = value & 0x0F;
130 additionalBytes = 2;
131 min = 0x800;
132 } else if ((value & 0xf8) == 0xf0) { // 11110xxx
133 value = value & 0x07;
134 additionalBytes = 3;
135 min = 0x10000;
136 } else if ((value & 0xfc) == 0xf8) { // 111110xx
137 value = value & 0x03;
138 additionalBytes = 4;
139 min = 0x200000;
140 } else if ((value & 0xfe) == 0xfc) { // 1111110x
141 value = value & 0x01;
142 additionalBytes = 5;
143 min = 0x4000000;
144 } else {
145 return -1;
146 }
147 for (int i = 0; i < additionalBytes; i++) {
148 int next = getNext();
149 if (next == null) return 0; // Not enough chars, reset.
150 if ((next & 0xc0) != 0x80 || (next & 0xff) != next) return -1;
151 value = value << 6 | (next & 0x3f);
152 }
153 // Invalid charCode if less then minimum expected.
154 if (value < min) value = -1;
155 _addChar(value);
156 return 1 + additionalBytes;
157 }
158 _addChar(value);
159 return 1;
160 }
161 }
162
163
164 abstract class _StringEncoder implements StreamTransformer<String, List<int>> {
165 _HelperStreamController<List<int>> _controller;
166 StreamSubscription<String> _subscription;
167
168 void _onPauseChanged() {
169 if (_controller.isPaused) {
170 _subscription.pause();
171 } else {
172 _subscription.resume();
173 }
174 }
175 Stream<List<int>> bind(Stream<String> stream) {
176 _controller = new _HelperStreamController(_onPauseChanged);
177 _subscription = stream.listen(
178 (string) => _controller.add(_processString(string)),
179 onError: _controller.signalError,
180 onDone: _controller.close,
181 unsubscribeOnError: false);
182 return _controller.stream;
183 }
184
185 List<int> _processString(String string);
186 }
187
188 /**
189 * StringTransformer that UTF-8 encodes a stream of strings.
190 */
191 class Utf8EncoderTransformer extends _StringEncoder {
192 List<int> _processString(String string) {
193 var bytes = [];
194 int pos = 0;
195 List<int> codepoints = _utf16CodeUnitsToCodepoints(string.charCodes);
196 int length = codepoints.length;
197 for (int i = 0; i < length; i++) {
198 int additionalBytes;
199 int charCode = codepoints[i];
200 if (charCode <= 0x007F) {
201 additionalBytes = 0;
202 bytes.add(charCode);
203 } else if (charCode <= 0x07FF) {
204 // 110xxxxx (xxxxx is top 5 bits).
205 bytes.add(((charCode >> 6) & 0x1F) | 0xC0);
206 additionalBytes = 1;
207 } else if (charCode <= 0xFFFF) {
208 // 1110xxxx (xxxx is top 4 bits)
209 bytes.add(((charCode >> 12) & 0x0F)| 0xE0);
210 additionalBytes = 2;
211 } else {
212 // 11110xxx (xxx is top 3 bits)
213 bytes.add(((charCode >> 18) & 0x07) | 0xF0);
214 additionalBytes = 3;
215 }
216 for (int i = additionalBytes; i > 0; i--) {
217 // 10xxxxxx (xxxxxx is next 6 bits from the top).
218 bytes.add(((charCode >> (6 * (i - 1))) & 0x3F) | 0x80);
219 }
220 pos += additionalBytes + 1;
221 }
222 return bytes;
223 }
224 }
OLDNEW
« no previous file with comments | « sdk/lib/io/string_transformer.dart ('k') | tests/standalone/io/delete_symlink_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698