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

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

Issue 12313127: Fix subscription handling in stream decoder (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added missing file 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 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 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 part of dart.utf; 5 part of dart.utf;
6 6
7 class _HelperStreamController<T> extends StreamController<T> { 7 class _HelperStreamController<T> extends StreamController<T> {
8 final Function onPauseChanged; 8 final Function onPauseChanged;
9 9
10 _HelperStreamController(this.onPauseChanged); 10 _HelperStreamController(this.onPauseChanged);
11 11
12 void onPauseStateChange() { 12 void onPauseStateChange() {
13 onPauseChanged(); 13 onPauseChanged();
14 } 14 }
15 } 15 }
16 16
17 abstract class _StringDecoder implements StreamTransformer<List<int>, String> { 17 abstract class _StringDecoder
18 _HelperStreamController<String> _controller; 18 extends StreamEventTransformer<List<int>, String> {
19 StreamSubscription<List<int>> _subscription;
20 List<int> _carry; 19 List<int> _carry;
21 List<int> _buffer; 20 List<int> _buffer;
22 int _replacementChar; 21 int _replacementChar;
23 bool _paused = false;
24 22
25 _StringDecoder(int this._replacementChar) { 23 _StringDecoder(int this._replacementChar);
26 _controller = new _HelperStreamController<String>(_onPauseChanged);
27 }
28 24
29 void _onPauseChanged() { 25 void handleData(List<int> bytes, StreamSink<String> sink) {
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>[]; 26 _buffer = <int>[];
57 List<int> carry = _carry; 27 List<int> carry = _carry;
58 _carry = null; 28 _carry = null;
59 int pos = 0; 29 int pos = 0;
60 int available = bytes.length; 30 int available = bytes.length;
61 // If we have carry-over data, start from negative index, indicating carry 31 // If we have carry-over data, start from negative index, indicating carry
62 // index. 32 // index.
63 int goodChars = 0; 33 int goodChars = 0;
64 if (carry != null) pos = -carry.length; 34 if (carry != null) pos = -carry.length;
65 while (pos < available) { 35 while (pos < available) {
(...skipping 21 matching lines...) Expand all
87 break; 57 break;
88 } else { 58 } else {
89 // Invalid byte at position pos - 1 59 // Invalid byte at position pos - 1
90 _buffer.length = goodChars; 60 _buffer.length = goodChars;
91 _addChar(-1); 61 _addChar(-1);
92 goodChars = _buffer.length; 62 goodChars = _buffer.length;
93 } 63 }
94 } 64 }
95 if (_buffer.length > 0) { 65 if (_buffer.length > 0) {
96 // Limit to 'goodChars', if lower than actual charCodes in the buffer. 66 // Limit to 'goodChars', if lower than actual charCodes in the buffer.
97 _controller.add(new String.fromCharCodes(_buffer)); 67 sink.add(new String.fromCharCodes(_buffer));
98 } 68 }
99 _buffer = null; 69 _buffer = null;
100 } 70 }
101 71
72 void handleDone(StreamSink<String> sink) {
73 if (_carry != null) {
74 sink.add(new String.fromCharCodes(
75 new List.fixedLength(_carry.length, fill: _replacementChar)));
76 }
77 sink.close();
78 }
79
102 int _processBytes(int getNext()); 80 int _processBytes(int getNext());
103 81
104 void _addChar(int char) { 82 void _addChar(int char) {
105 if (char > 0x10FFFF || char < 0) char = _replacementChar; 83 if (char > 0x10FFFF || char < 0) char = _replacementChar;
106 _buffer.add(char); 84 _buffer.add(char);
107 } 85 }
108 } 86 }
109 87
110 /** 88 /**
111 * StringTransformer that decodes a stream of UTF-8 encoded bytes. 89 * StringTransformer that decodes a stream of UTF-8 encoded bytes.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 if (value < min) value = -1; 132 if (value < min) value = -1;
155 _addChar(value); 133 _addChar(value);
156 return 1 + additionalBytes; 134 return 1 + additionalBytes;
157 } 135 }
158 _addChar(value); 136 _addChar(value);
159 return 1; 137 return 1;
160 } 138 }
161 } 139 }
162 140
163 141
164 abstract class _StringEncoder implements StreamTransformer<String, List<int>> { 142 abstract class _StringEncoder
165 _HelperStreamController<List<int>> _controller; 143 extends StreamEventTransformer<String, List<int>> {
166 StreamSubscription<String> _subscription;
167 144
168 void _onPauseChanged() { 145 void handleData(String data, StreamSink<List<int>> sink) {
169 if (_controller.isPaused) { 146 sink.add(_processString(data));
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 } 147 }
184 148
185 List<int> _processString(String string); 149 List<int> _processString(String string);
186 } 150 }
187 151
188 /** 152 /**
189 * StringTransformer that UTF-8 encodes a stream of strings. 153 * StringTransformer that UTF-8 encodes a stream of strings.
190 */ 154 */
191 class Utf8EncoderTransformer extends _StringEncoder { 155 class Utf8EncoderTransformer extends _StringEncoder {
192 List<int> _processString(String string) { 156 List<int> _processString(String string) {
(...skipping 22 matching lines...) Expand all
215 } 179 }
216 for (int i = additionalBytes; i > 0; i--) { 180 for (int i = additionalBytes; i > 0; i--) {
217 // 10xxxxxx (xxxxxx is next 6 bits from the top). 181 // 10xxxxxx (xxxxxx is next 6 bits from the top).
218 bytes.add(((charCode >> (6 * (i - 1))) & 0x3F) | 0x80); 182 bytes.add(((charCode >> (6 * (i - 1))) & 0x3F) | 0x80);
219 } 183 }
220 pos += additionalBytes + 1; 184 pos += additionalBytes + 1;
221 } 185 }
222 return bytes; 186 return bytes;
223 } 187 }
224 } 188 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698