2013-02-21 12:08:34 +00:00
|
|
|
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
part of dart.io;
|
|
|
|
|
|
|
|
/**
|
2013-04-11 18:11:40 +00:00
|
|
|
* Helper class to wrap a [StreamConsumer<List<int>>] and provide
|
2013-03-08 10:06:28 +00:00
|
|
|
* utility functions for writing to the StreamConsumer directly. The
|
2013-04-15 07:35:45 +00:00
|
|
|
* [IOSink] buffers the input given by all [StringSink] methods and will delay
|
2014-03-18 12:30:54 +00:00
|
|
|
* an [addStream] until the buffer is flushed.
|
2013-02-21 12:08:34 +00:00
|
|
|
*
|
2013-04-15 07:35:45 +00:00
|
|
|
* When the [IOSink] is bound to a stream (through [addStream]) any call
|
2013-07-23 10:37:47 +00:00
|
|
|
* to the [IOSink] will throw a [StateError]. When the [addStream] completes,
|
2014-03-26 12:19:55 +00:00
|
|
|
* the [IOSink] will again accept all method calls.
|
2013-07-23 10:37:47 +00:00
|
|
|
*
|
|
|
|
* If data is added to the [IOSink] after the sink is closed, the data will be
|
|
|
|
* ignored. Use the [done] future to be notified when the [IOSink] is closed.
|
2013-02-21 12:08:34 +00:00
|
|
|
*/
|
2013-04-15 13:38:09 +00:00
|
|
|
abstract class IOSink implements StreamSink<List<int>>, StringSink {
|
2014-03-18 12:30:54 +00:00
|
|
|
// TODO(ajohnsen): Make _encodingMutable an argument.
|
2013-04-11 18:11:40 +00:00
|
|
|
factory IOSink(StreamConsumer<List<int>> target,
|
2013-08-26 10:37:25 +00:00
|
|
|
{Encoding encoding: UTF8})
|
2013-03-08 10:06:28 +00:00
|
|
|
=> new _IOSinkImpl(target, encoding);
|
2013-03-01 13:33:19 +00:00
|
|
|
|
|
|
|
/**
|
2013-03-08 10:06:28 +00:00
|
|
|
* The [Encoding] used when writing strings. Depending on the
|
|
|
|
* underlying consumer this property might be mutable.
|
2013-03-01 13:33:19 +00:00
|
|
|
*/
|
2013-03-08 10:06:28 +00:00
|
|
|
Encoding encoding;
|
2013-03-01 13:33:19 +00:00
|
|
|
|
|
|
|
/**
|
2014-03-18 12:30:54 +00:00
|
|
|
* Adds [data] to the target consumer, ignoring [encoding].
|
|
|
|
*
|
|
|
|
* The [encoding] does not apply to this method, and the `data` list is passed
|
|
|
|
* directly to the target consumer as a stream event.
|
|
|
|
*
|
|
|
|
* This function must not be called when a stream is currently being added
|
|
|
|
* using [addStream].
|
|
|
|
*
|
|
|
|
* This operation is non-blocking. See [flush] or [done] for how to get any
|
|
|
|
* errors generated by this call.
|
|
|
|
*
|
|
|
|
* The data list should not be modified after it has been passed to `add`.
|
2013-03-01 13:33:19 +00:00
|
|
|
*/
|
2013-04-11 12:54:19 +00:00
|
|
|
void add(List<int> data);
|
|
|
|
|
|
|
|
/**
|
2014-03-18 12:30:54 +00:00
|
|
|
* Converts [obj] to a String by invoking [Object.toString] and
|
|
|
|
* [add]s the encoding of the result to the target consumer.
|
|
|
|
*
|
|
|
|
* This operation is non-blocking. See [flush] or [done] for how to get any
|
|
|
|
* errors generated by this call.
|
|
|
|
*/
|
|
|
|
void write(Object obj);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterates over the given [objects] and [write]s them in sequence.
|
|
|
|
*
|
|
|
|
* If [separator] is provided, a `write` with the `separator` is performed
|
|
|
|
* between any two elements of `objects`.
|
|
|
|
*
|
|
|
|
* This operation is non-blocking. See [flush] or [done] for how to get any
|
|
|
|
* errors generated by this call.
|
|
|
|
*/
|
|
|
|
void writeAll(Iterable objects, [String separator = ""]);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts [obj] to a String by invoking [Object.toString] and
|
|
|
|
* writes the result to `this`, followed by a newline.
|
|
|
|
*
|
|
|
|
* This operation is non-blocking. See [flush] or [done] for how to get any
|
|
|
|
* errors generated by this call.
|
|
|
|
*/
|
|
|
|
void writeln([Object obj = ""]);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Writes the [charCode] to `this`.
|
|
|
|
*
|
|
|
|
* This method is equivalent to `write(new String.fromCharCode(charCode))`.
|
|
|
|
*
|
|
|
|
* This operation is non-blocking. See [flush] or [done] for how to get any
|
|
|
|
* errors generated by this call.
|
|
|
|
*/
|
|
|
|
void writeCharCode(int charCode);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Passes the error to the target consumer as an error event.
|
|
|
|
*
|
|
|
|
* This function must not be called when a stream is currently being added
|
|
|
|
* using [addStream].
|
|
|
|
*
|
|
|
|
* This operation is non-blocking. See [flush] or [done] for how to get any
|
|
|
|
* errors generated by this call.
|
2013-04-11 12:54:19 +00:00
|
|
|
*/
|
2013-10-29 14:30:36 +00:00
|
|
|
void addError(error, [StackTrace stackTrace]);
|
2013-03-01 13:33:19 +00:00
|
|
|
|
2013-04-05 16:22:11 +00:00
|
|
|
/**
|
|
|
|
* Adds all elements of the given [stream] to `this`.
|
|
|
|
*/
|
2013-04-15 07:35:45 +00:00
|
|
|
Future addStream(Stream<List<int>> stream);
|
2013-03-01 13:33:19 +00:00
|
|
|
|
2013-10-30 14:50:22 +00:00
|
|
|
/**
|
|
|
|
* Returns a [Future] that completes once all buffered data is accepted by the
|
|
|
|
* to underlying [StreamConsumer].
|
|
|
|
*
|
|
|
|
* It's an error to call this method, while an [addStream] is incomplete.
|
|
|
|
*
|
|
|
|
* NOTE: This is not necessarily the same as the data being flushed by the
|
|
|
|
* operating system.
|
|
|
|
*/
|
|
|
|
Future flush();
|
|
|
|
|
2013-03-01 13:33:19 +00:00
|
|
|
/**
|
2014-03-18 12:30:54 +00:00
|
|
|
* Close the target consumer.
|
2013-03-01 13:33:19 +00:00
|
|
|
*/
|
2013-04-05 16:22:11 +00:00
|
|
|
Future close();
|
2013-03-01 13:33:19 +00:00
|
|
|
|
|
|
|
/**
|
2014-03-18 12:30:54 +00:00
|
|
|
* Get a future that will complete when the consumer closes, or when an
|
|
|
|
* error occurs. This future is identical to the future returned by
|
|
|
|
* [close].
|
2013-03-01 13:33:19 +00:00
|
|
|
*/
|
2013-04-15 07:35:45 +00:00
|
|
|
Future get done;
|
2013-03-01 13:33:19 +00:00
|
|
|
}
|
|
|
|
|
2013-02-21 12:08:34 +00:00
|
|
|
|
2014-03-26 12:19:55 +00:00
|
|
|
class _IOSinkImpl extends StreamSinkAdapter<List<int>> implements IOSink {
|
2013-04-16 15:08:21 +00:00
|
|
|
Encoding _encoding;
|
|
|
|
bool _encodingMutable = true;
|
|
|
|
|
|
|
|
_IOSinkImpl(StreamConsumer<List<int>> target, this._encoding)
|
|
|
|
: super(target);
|
|
|
|
|
|
|
|
Encoding get encoding => _encoding;
|
|
|
|
|
|
|
|
void set encoding(Encoding value) {
|
|
|
|
if (!_encodingMutable) {
|
|
|
|
throw new StateError("IOSink encoding is not mutable");
|
|
|
|
}
|
|
|
|
_encoding = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void write(Object obj) {
|
|
|
|
// This comment is copied from runtime/lib/string_buffer_patch.dart.
|
|
|
|
// TODO(srdjan): The following four lines could be replaced by
|
|
|
|
// '$obj', but apparently this is too slow on the Dart VM.
|
|
|
|
String string;
|
|
|
|
if (obj is String) {
|
|
|
|
string = obj;
|
|
|
|
} else {
|
|
|
|
string = obj.toString();
|
|
|
|
if (string is! String) {
|
|
|
|
throw new ArgumentError('toString() did not return a string');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (string.isEmpty) return;
|
2014-03-04 16:23:45 +00:00
|
|
|
add(_encoding.encode(string));
|
2013-04-16 15:08:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void writeAll(Iterable objects, [String separator = ""]) {
|
|
|
|
Iterator iterator = objects.iterator;
|
|
|
|
if (!iterator.moveNext()) return;
|
|
|
|
if (separator.isEmpty) {
|
|
|
|
do {
|
|
|
|
write(iterator.current);
|
|
|
|
} while (iterator.moveNext());
|
|
|
|
} else {
|
|
|
|
write(iterator.current);
|
|
|
|
while (iterator.moveNext()) {
|
|
|
|
write(separator);
|
|
|
|
write(iterator.current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeln([Object obj = ""]) {
|
|
|
|
write(obj);
|
|
|
|
write("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeCharCode(int charCode) {
|
|
|
|
write(new String.fromCharCode(charCode));
|
|
|
|
}
|
|
|
|
}
|