| 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 * A combined byte and text output. | 8 * A combined byte and text output. |
| 9 * | 9 * |
| 10 * An [IOSink] combines a [StreamSink] of bytes with a [StringSink], | 10 * An [IOSink] combines a [StreamSink] of bytes with a [StringSink], |
| 11 * and allows easy output of both bytes and text. | 11 * and allows easy output of both bytes and text. |
| 12 * | 12 * |
| 13 * Writing text ([write]) and adding bytes ([add]) may be interleaved freely. | 13 * Writing text ([write]) and adding bytes ([add]) may be interleaved freely. |
| 14 * | 14 * |
| 15 * While a stream is being added using [addStream], any further attempts | 15 * While a stream is being added using [addStream], any further attempts |
| 16 * to add or write to the [IOSink] will fail until the [addStream] completes. | 16 * to add or write to the [IOSink] will fail until the [addStream] completes. |
| 17 * | 17 * |
| 18 * If data is added to the [IOSink] after the sink is closed, the data will be | 18 * If data is added to the [IOSink] after the sink is closed, the data will be |
| 19 * ignored. Use the [done] future to be notified when the [IOSink] is closed. | 19 * ignored. Use the [done] future to be notified when the [IOSink] is closed. |
| 20 */ | 20 */ |
| 21 abstract class IOSink implements StreamSink<List<int>>, StringSink { | 21 abstract class IOSink implements StreamSink<List<int>>, StringSink { |
| 22 | |
| 23 /** | 22 /** |
| 24 * Create an [IOSink] that outputs to a [target] [StreamConsumer] of bytes. | 23 * Create an [IOSink] that outputs to a [target] [StreamConsumer] of bytes. |
| 25 * | 24 * |
| 26 * Text written to [StreamSink] methods is encoded to bytes using [encoding] | 25 * Text written to [StreamSink] methods is encoded to bytes using [encoding] |
| 27 * before being output on [target]. | 26 * before being output on [target]. |
| 28 */ | 27 */ |
| 29 factory IOSink(StreamConsumer<List<int>> target, | 28 factory IOSink(StreamConsumer<List<int>> target, {Encoding encoding: UTF8}) => |
| 30 {Encoding encoding: UTF8}) | 29 new _IOSinkImpl(target, encoding); |
| 31 => new _IOSinkImpl(target, encoding); | |
| 32 | 30 |
| 33 /** | 31 /** |
| 34 * The [Encoding] used when writing strings. Depending on the | 32 * The [Encoding] used when writing strings. Depending on the |
| 35 * underlying consumer this property might be mutable. | 33 * underlying consumer this property might be mutable. |
| 36 */ | 34 */ |
| 37 Encoding encoding; | 35 Encoding encoding; |
| 38 | 36 |
| 39 /** | 37 /** |
| 40 * Adds byte [data] to the target consumer, ignoring [encoding]. | 38 * Adds byte [data] to the target consumer, ignoring [encoding]. |
| 41 * | 39 * |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 } | 157 } |
| 160 | 158 |
| 161 Future addStream(Stream<T> stream) { | 159 Future addStream(Stream<T> stream) { |
| 162 if (_isBound) { | 160 if (_isBound) { |
| 163 throw new StateError("StreamSink is already bound to a stream"); | 161 throw new StateError("StreamSink is already bound to a stream"); |
| 164 } | 162 } |
| 165 _isBound = true; | 163 _isBound = true; |
| 166 if (_hasError) return done; | 164 if (_hasError) return done; |
| 167 // Wait for any sync operations to complete. | 165 // Wait for any sync operations to complete. |
| 168 Future targetAddStream() { | 166 Future targetAddStream() { |
| 169 return _target.addStream(stream) | 167 return _target.addStream(stream).whenComplete(() { |
| 170 .whenComplete(() { | 168 _isBound = false; |
| 171 _isBound = false; | 169 }); |
| 172 }); | |
| 173 } | 170 } |
| 171 |
| 174 if (_controllerInstance == null) return targetAddStream(); | 172 if (_controllerInstance == null) return targetAddStream(); |
| 175 var future = _controllerCompleter.future; | 173 var future = _controllerCompleter.future; |
| 176 _controllerInstance.close(); | 174 _controllerInstance.close(); |
| 177 return future.then((_) => targetAddStream()); | 175 return future.then((_) => targetAddStream()); |
| 178 } | 176 } |
| 179 | 177 |
| 180 Future flush() { | 178 Future flush() { |
| 181 if (_isBound) { | 179 if (_isBound) { |
| 182 throw new StateError("StreamSink is bound to a stream"); | 180 throw new StateError("StreamSink is bound to a stream"); |
| 183 } | 181 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 // A new stream takes over - forward errors to that stream. | 249 // A new stream takes over - forward errors to that stream. |
| 252 _controllerCompleter.completeError(error, stackTrace); | 250 _controllerCompleter.completeError(error, stackTrace); |
| 253 _controllerCompleter = null; | 251 _controllerCompleter = null; |
| 254 _controllerInstance = null; | 252 _controllerInstance = null; |
| 255 } else { | 253 } else { |
| 256 // No new stream. No need to close target, as it has already | 254 // No new stream. No need to close target, as it has already |
| 257 // failed. | 255 // failed. |
| 258 _completeDoneError(error, stackTrace); | 256 _completeDoneError(error, stackTrace); |
| 259 } | 257 } |
| 260 }); | 258 }); |
| 261 } | 259 } |
| 262 return _controllerInstance; | 260 return _controllerInstance; |
| 263 } | 261 } |
| 264 } | 262 } |
| 265 | 263 |
| 266 | |
| 267 class _IOSinkImpl extends _StreamSinkImpl<List<int>> implements IOSink { | 264 class _IOSinkImpl extends _StreamSinkImpl<List<int>> implements IOSink { |
| 268 Encoding _encoding; | 265 Encoding _encoding; |
| 269 bool _encodingMutable = true; | 266 bool _encodingMutable = true; |
| 270 | 267 |
| 271 _IOSinkImpl(StreamConsumer<List<int>> target, this._encoding) | 268 _IOSinkImpl(StreamConsumer<List<int>> target, this._encoding) : super(target); |
| 272 : super(target); | |
| 273 | 269 |
| 274 Encoding get encoding => _encoding; | 270 Encoding get encoding => _encoding; |
| 275 | 271 |
| 276 void set encoding(Encoding value) { | 272 void set encoding(Encoding value) { |
| 277 if (!_encodingMutable) { | 273 if (!_encodingMutable) { |
| 278 throw new StateError("IOSink encoding is not mutable"); | 274 throw new StateError("IOSink encoding is not mutable"); |
| 279 } | 275 } |
| 280 _encoding = value; | 276 _encoding = value; |
| 281 } | 277 } |
| 282 | 278 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 304 | 300 |
| 305 void writeln([Object object = ""]) { | 301 void writeln([Object object = ""]) { |
| 306 write(object); | 302 write(object); |
| 307 write("\n"); | 303 write("\n"); |
| 308 } | 304 } |
| 309 | 305 |
| 310 void writeCharCode(int charCode) { | 306 void writeCharCode(int charCode) { |
| 311 write(new String.fromCharCode(charCode)); | 307 write(new String.fromCharCode(charCode)); |
| 312 } | 308 } |
| 313 } | 309 } |
| OLD | NEW |