| OLD | NEW |
| 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.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Helper class to wrap a [StreamConsumer<List<int>>] and provide | 8 * Helper class to wrap a [StreamConsumer<List<int>>] and provide |
| 9 * utility functions for writing to the StreamConsumer directly. The | 9 * utility functions for writing to the StreamConsumer directly. The |
| 10 * [IOSink] buffers the input given by all [StringSink] methods and will delay | 10 * [IOSink] buffers the input given by all [StringSink] methods and will delay |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 */ | 45 */ |
| 46 Future close(); | 46 Future close(); |
| 47 | 47 |
| 48 /** | 48 /** |
| 49 * Get a future that will complete when all synchronous have completed, or an | 49 * Get a future that will complete when all synchronous have completed, or an |
| 50 * error happened. This future is identical to the future returned from close. | 50 * error happened. This future is identical to the future returned from close. |
| 51 */ | 51 */ |
| 52 Future get done; | 52 Future get done; |
| 53 } | 53 } |
| 54 | 54 |
| 55 | 55 class _StreamSinkImpl<T> implements StreamSink<T> { |
| 56 class _IOSinkImpl implements IOSink { | 56 final StreamConsumer<T> _target; |
| 57 final StreamConsumer<List<int>> _target; | |
| 58 Completer _doneCompleter = new Completer(); | 57 Completer _doneCompleter = new Completer(); |
| 59 Future _doneFuture; | 58 Future _doneFuture; |
| 60 StreamController<List<int>> _controllerInstance; | 59 StreamController<T> _controllerInstance; |
| 61 Completer _controllerCompleter; | 60 Completer _controllerCompleter; |
| 62 Encoding _encoding; | |
| 63 bool _isClosed = false; | 61 bool _isClosed = false; |
| 64 bool _isBound = false; | 62 bool _isBound = false; |
| 65 bool _encodingMutable = true; | |
| 66 | 63 |
| 67 _IOSinkImpl(StreamConsumer<List<int>> this._target, this._encoding) { | 64 _StreamSinkImpl(StreamConsumer<T> this._target) { |
| 68 _doneFuture = _doneCompleter.future; | 65 _doneFuture = _doneCompleter.future; |
| 69 } | 66 } |
| 70 | 67 |
| 71 Encoding get encoding => _encoding; | 68 void add(T data) { |
| 72 | |
| 73 void set encoding(Encoding value) { | |
| 74 if (!_encodingMutable) { | |
| 75 throw new StateError("IOSink encoding is not mutable"); | |
| 76 } | |
| 77 _encoding = value; | |
| 78 } | |
| 79 | |
| 80 void write(Object obj) { | |
| 81 // This comment is copied from runtime/lib/string_buffer_patch.dart. | |
| 82 // TODO(srdjan): The following four lines could be replaced by | |
| 83 // '$obj', but apparently this is too slow on the Dart VM. | |
| 84 String string; | |
| 85 if (obj is String) { | |
| 86 string = obj; | |
| 87 } else { | |
| 88 string = obj.toString(); | |
| 89 if (string is! String) { | |
| 90 throw new ArgumentError('toString() did not return a string'); | |
| 91 } | |
| 92 } | |
| 93 if (string.isEmpty) return; | |
| 94 add(_encodeString(string, _encoding)); | |
| 95 } | |
| 96 | |
| 97 void writeAll(Iterable objects, [String separator = ""]) { | |
| 98 Iterator iterator = objects.iterator; | |
| 99 if (!iterator.moveNext()) return; | |
| 100 if (separator.isEmpty) { | |
| 101 do { | |
| 102 write(iterator.current); | |
| 103 } while (iterator.moveNext()); | |
| 104 } else { | |
| 105 write(iterator.current); | |
| 106 while (iterator.moveNext()) { | |
| 107 write(separator); | |
| 108 write(iterator.current); | |
| 109 } | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 void writeln([Object obj = ""]) { | |
| 114 write(obj); | |
| 115 write("\n"); | |
| 116 } | |
| 117 | |
| 118 void writeCharCode(int charCode) { | |
| 119 write(new String.fromCharCode(charCode)); | |
| 120 } | |
| 121 | |
| 122 void add(List<int> data) { | |
| 123 _controller.add(data); | 69 _controller.add(data); |
| 124 } | 70 } |
| 125 | 71 |
| 126 void addError(error) { | 72 void addError(error) { |
| 127 _controller.addError(error); | 73 _controller.addError(error); |
| 128 } | 74 } |
| 129 | 75 |
| 130 Future addStream(Stream<List<int>> stream) { | 76 Future addStream(Stream<T> stream) { |
| 131 if (_isBound) { | 77 if (_isBound) { |
| 132 throw new StateError("IOSink is already bound to a stream"); | 78 throw new StateError("StreamSink is already bound to a stream"); |
| 133 } | 79 } |
| 134 _isBound = true; | 80 _isBound = true; |
| 135 // Wait for any sync operations to complete. | 81 // Wait for any sync operations to complete. |
| 136 Future targetAddStream() { | 82 Future targetAddStream() { |
| 137 return _target.addStream(stream) | 83 return _target.addStream(stream) |
| 138 .whenComplete(() { | 84 .whenComplete(() { |
| 139 _isBound = false; | 85 _isBound = false; |
| 140 }); | 86 }); |
| 141 } | 87 } |
| 142 if (_controllerInstance == null) return targetAddStream(); | 88 if (_controllerInstance == null) return targetAddStream(); |
| 143 var future = _controllerCompleter.future; | 89 var future = _controllerCompleter.future; |
| 144 _controllerInstance.close(); | 90 _controllerInstance.close(); |
| 145 return future.then((_) => targetAddStream()); | 91 return future.then((_) => targetAddStream()); |
| 146 } | 92 } |
| 147 | 93 |
| 148 Future close() { | 94 Future close() { |
| 149 if (_isBound) { | 95 if (_isBound) { |
| 150 throw new StateError("IOSink is bound to a stream"); | 96 throw new StateError("StreamSink is bound to a stream"); |
| 151 } | 97 } |
| 152 if (!_isClosed) { | 98 if (!_isClosed) { |
| 153 _isClosed = true; | 99 _isClosed = true; |
| 154 if (_controllerInstance != null) { | 100 if (_controllerInstance != null) { |
| 155 _controllerInstance.close(); | 101 _controllerInstance.close(); |
| 156 } else { | 102 } else { |
| 157 _closeTarget(); | 103 _closeTarget(); |
| 158 } | 104 } |
| 159 } | 105 } |
| 160 return done; | 106 return done; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 172 if (_doneCompleter == null) return; | 118 if (_doneCompleter == null) return; |
| 173 var tmp = _doneCompleter; | 119 var tmp = _doneCompleter; |
| 174 _doneCompleter = null; | 120 _doneCompleter = null; |
| 175 if (error == null) { | 121 if (error == null) { |
| 176 tmp.complete(value); | 122 tmp.complete(value); |
| 177 } else { | 123 } else { |
| 178 tmp.completeError(error); | 124 tmp.completeError(error); |
| 179 } | 125 } |
| 180 } | 126 } |
| 181 | 127 |
| 182 StreamController<List<int>> get _controller { | 128 StreamController<T> get _controller { |
| 183 if (_isBound) { | 129 if (_isBound) { |
| 184 throw new StateError("IOSink is bound to a stream"); | 130 throw new StateError("StreamSink is bound to a stream"); |
| 185 } | 131 } |
| 186 if (_isClosed) { | 132 if (_isClosed) { |
| 187 throw new StateError("IOSink is closed"); | 133 throw new StateError("StreamSink is closed"); |
| 188 } | 134 } |
| 189 if (_controllerInstance == null) { | 135 if (_controllerInstance == null) { |
| 190 _controllerInstance = new StreamController<List<int>>(); | 136 _controllerInstance = new StreamController<T>(); |
| 191 _controllerCompleter = new Completer(); | 137 _controllerCompleter = new Completer(); |
| 192 _target.addStream(_controller.stream) | 138 _target.addStream(_controller.stream) |
| 193 .then( | 139 .then( |
| 194 (_) { | 140 (_) { |
| 195 if (_isBound) { | 141 if (_isBound) { |
| 196 // A new stream takes over - forward values to that stream. | 142 // A new stream takes over - forward values to that stream. |
| 197 var completer = _controllerCompleter; | 143 var completer = _controllerCompleter; |
| 198 _controllerCompleter = null; | 144 _controllerCompleter = null; |
| 199 _controllerInstance = null; | 145 _controllerInstance = null; |
| 200 completer.complete(); | 146 completer.complete(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 213 } else { | 159 } else { |
| 214 // No new stream. No need to close target, as it have already | 160 // No new stream. No need to close target, as it have already |
| 215 // failed. | 161 // failed. |
| 216 _completeDone(error: error); | 162 _completeDone(error: error); |
| 217 } | 163 } |
| 218 }); | 164 }); |
| 219 } | 165 } |
| 220 return _controllerInstance; | 166 return _controllerInstance; |
| 221 } | 167 } |
| 222 } | 168 } |
| 169 |
| 170 |
| 171 class _IOSinkImpl extends _StreamSinkImpl<List<int>> implements IOSink { |
| 172 Encoding _encoding; |
| 173 bool _encodingMutable = true; |
| 174 |
| 175 _IOSinkImpl(StreamConsumer<List<int>> target, this._encoding) |
| 176 : super(target); |
| 177 |
| 178 Encoding get encoding => _encoding; |
| 179 |
| 180 void set encoding(Encoding value) { |
| 181 if (!_encodingMutable) { |
| 182 throw new StateError("IOSink encoding is not mutable"); |
| 183 } |
| 184 _encoding = value; |
| 185 } |
| 186 |
| 187 void write(Object obj) { |
| 188 // This comment is copied from runtime/lib/string_buffer_patch.dart. |
| 189 // TODO(srdjan): The following four lines could be replaced by |
| 190 // '$obj', but apparently this is too slow on the Dart VM. |
| 191 String string; |
| 192 if (obj is String) { |
| 193 string = obj; |
| 194 } else { |
| 195 string = obj.toString(); |
| 196 if (string is! String) { |
| 197 throw new ArgumentError('toString() did not return a string'); |
| 198 } |
| 199 } |
| 200 if (string.isEmpty) return; |
| 201 add(_encodeString(string, _encoding)); |
| 202 } |
| 203 |
| 204 void writeAll(Iterable objects, [String separator = ""]) { |
| 205 Iterator iterator = objects.iterator; |
| 206 if (!iterator.moveNext()) return; |
| 207 if (separator.isEmpty) { |
| 208 do { |
| 209 write(iterator.current); |
| 210 } while (iterator.moveNext()); |
| 211 } else { |
| 212 write(iterator.current); |
| 213 while (iterator.moveNext()) { |
| 214 write(separator); |
| 215 write(iterator.current); |
| 216 } |
| 217 } |
| 218 } |
| 219 |
| 220 void writeln([Object obj = ""]) { |
| 221 write(obj); |
| 222 write("\n"); |
| 223 } |
| 224 |
| 225 void writeCharCode(int charCode) { |
| 226 write(new String.fromCharCode(charCode)); |
| 227 } |
| 228 } |
| OLD | NEW |