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

Unified Diff: sdk/lib/io/string_stream.dart

Issue 12316036: Merge IO v2 branch to bleeding edge (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased to r18818 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/io/stream_util.dart ('k') | sdk/lib/io/websocket.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/io/string_stream.dart
diff --git a/sdk/lib/io/string_stream.dart b/sdk/lib/io/string_stream.dart
index cd38e2cb3c14c15102c070c5ea9a7c002a8b23d7..52f2d64230c43b2dd91c8cc5c97e8deef1267b72 100644
--- a/sdk/lib/io/string_stream.dart
+++ b/sdk/lib/io/string_stream.dart
@@ -3,592 +3,3 @@
// BSD-style license that can be found in the LICENSE file.
part of dart.io;
-
-// Interface for decoders decoding binary data into string data. The
-// decoder keeps track of line breaks during decoding.
-abstract class _StringDecoder {
- // Add more binary data to be decoded. The ownership of the buffer
- // is transfered to the decoder and the caller most not modify it any more.
- int write(List<int> buffer);
-
- void done();
-
- // Returns whether any decoded data is available.
- bool get isEmpty;
-
- // Returns the number of available decoded characters.
- int available();
-
- // Get the number of line breaks present in the current decoded
- // data.
- int get lineBreaks;
-
- // Get up to [len] characters of string data decoded since the last
- // call to [decode] or [decodeLine]. Returns null if no decoded data
- // is available. If [len] is not specified all decoded characters
- // are returned.
- String decoded([int len]);
-
- // Get the string data decoded since the last call to [decode] or
- // [decodeLine] up to the next line break present. Returns null if
- // no line break is present. The line break character sequence is
- // discarded.
- String get decodedLine;
-
- // Set the handler that will be called if an error ocurs while decoding.
- void set onError(Function callback);
-}
-
-
-class _StringDecoders {
- static _StringDecoder decoder(Encoding encoding) {
- if (encoding == Encoding.UTF_8) {
- return new _UTF8Decoder();
- } else if (encoding == Encoding.ISO_8859_1) {
- return new _Latin1Decoder();
- } else if (encoding == Encoding.ASCII) {
- return new _AsciiDecoder();
- } else if (encoding == Encoding.SYSTEM) {
- if (Platform.operatingSystem == 'windows') {
- return new _WindowsCodePageDecoder();
- }
- return new _UTF8Decoder();
- } else {
- if (encoding is Encoding) {
- throw new StreamException("Unsupported encoding ${encoding.name}");
- } else {
- throw new StreamException("Unsupported encoding ${encoding}");
- }
- }
- }
-}
-
-
-class DecoderException implements Exception {
- const DecoderException([String this.message]);
- String toString() => "DecoderException: $message";
- final String message;
-}
-
-
-// Utility class for decoding UTF-8 from data delivered as a stream of
-// bytes.
-abstract class _StringDecoderBase implements _StringDecoder {
- _StringDecoderBase()
- : _bufferList = new _BufferList(),
- _result = new List<int>(),
- _lineBreakEnds = new Queue<int>();
-
- int write(List<int> buffer) {
- _bufferList.add(buffer);
- // Decode as many bytes into characters as possible.
- while (_bufferList.length > 0) {
- if (!_processNext()) {
- break;
- }
- }
- return buffer.length;
- }
-
- void done() { }
-
- bool get isEmpty => _result.isEmpty;
-
- int get lineBreaks => _lineBreaks;
-
- String decoded([int length]) {
- if (isEmpty) return null;
-
- List<int> result;
- if (length != null && length < available()) {
- result = _result.getRange(_resultOffset, length);
- } else if (_resultOffset == 0) {
- result = _result;
- } else {
- result = _result.getRange(_resultOffset, _result.length - _resultOffset);
- }
-
- _resultOffset += result.length;
- while (!_lineBreakEnds.isEmpty &&
- _lineBreakEnds.first < _charOffset + _resultOffset) {
- _lineBreakEnds.removeFirst();
- _lineBreaks--;
- }
- if (_result.length == _resultOffset) _resetResult();
- return new String.fromCharCodes(result);
- }
-
- String get decodedLine {
- if (_lineBreakEnds.isEmpty) return null;
- int lineEnd = _lineBreakEnds.removeFirst();
- int terminationSequenceLength = 1;
- if (_result[lineEnd - _charOffset] == LF &&
- lineEnd > _charOffset &&
- _resultOffset < lineEnd &&
- _result[lineEnd - _charOffset - 1] == CR) {
- terminationSequenceLength = 2;
- }
- var lineLength =
- lineEnd - _charOffset - _resultOffset - terminationSequenceLength + 1;
- String result =
- new String.fromCharCodes(_result.getRange(_resultOffset, lineLength));
- _lineBreaks--;
- _resultOffset += (lineLength + terminationSequenceLength);
- if (_result.length == _resultOffset) _resetResult();
- return result;
- }
-
- // Add another decoded character.
- void addChar(int charCode) {
- _result.add(charCode);
- _charCount++;
- // Check for line ends (\r, \n and \r\n).
- if (charCode == LF) {
- _recordLineBreakEnd(_charCount - 1);
- } else if (_lastCharCode == CR) {
- _recordLineBreakEnd(_charCount - 2);
- }
- _lastCharCode = charCode;
- }
-
- int available() => _result.length - _resultOffset;
-
- void _recordLineBreakEnd(int charPos) {
- _lineBreakEnds.add(charPos);
- _lineBreaks++;
- }
-
- void _resetResult() {
- _charOffset += _result.length;
- _result = new List<int>();
- _resultOffset = 0;
- }
-
- bool _processNext();
-
- _BufferList _bufferList;
- int _resultOffset = 0;
- List<int> _result;
- int _lineBreaks = 0; // Number of line breaks in the current list.
- // The positions of the line breaks are tracked in terms of absolute
- // character positions from the begining of the decoded data.
- Queue<int> _lineBreakEnds; // Character position of known line breaks.
- int _charOffset = 0; // Character number of the first character in the list.
- int _charCount = 0; // Total number of characters decoded.
- int _lastCharCode = -1;
- Function onError;
-
- final int LF = 10;
- final int CR = 13;
-}
-
-
-// Utility class for decoding UTF-8 from data delivered as a stream of
-// bytes.
-class _UTF8Decoder extends _StringDecoderBase {
- static const kMaxCodePoint = 0x10FFFF;
- static const kReplacementCodePoint = 0x3f;
-
- void done() {
- if (!_bufferList.isEmpty) {
- _reportError(new DecoderException("Illegal UTF-8"));
- }
- }
-
- bool _reportError(error) {
- if (onError != null) {
- onError(error);
- return false;
- } else {
- throw error;
- }
- }
-
- // Process the next UTF-8 encoded character.
- bool _processNext() {
- // Peek the next byte to calculate the number of bytes required for
- // the next character.
- int value = _bufferList.peek() & 0xFF;
- if ((value & 0x80) == 0x80) {
- int additionalBytes;
- if ((value & 0xe0) == 0xc0) { // 110xxxxx
- value = value & 0x1F;
- additionalBytes = 1;
- } else if ((value & 0xf0) == 0xe0) { // 1110xxxx
- value = value & 0x0F;
- additionalBytes = 2;
- } else if ((value & 0xf8) == 0xf0) { // 11110xxx
- value = value & 0x07;
- additionalBytes = 3;
- } else if ((value & 0xfc) == 0xf8) { // 111110xx
- value = value & 0x03;
- additionalBytes = 4;
- } else if ((value & 0xfe) == 0xfc) { // 1111110x
- value = value & 0x01;
- additionalBytes = 5;
- } else {
- return _reportError(new DecoderException("Illegal UTF-8"));
- }
- // Check if there are enough bytes to decode the character. Otherwise
- // return false.
- if (_bufferList.length < additionalBytes + 1) {
- return false;
- }
- // Remove the value peeked from the buffer list.
- _bufferList.next();
- for (int i = 0; i < additionalBytes; i++) {
- int byte = _bufferList.next();
- if ((byte & 0xc0) != 0x80) {
- return _reportError(new DecoderException("Illegal UTF-8"));
- }
- value = value << 6 | (byte & 0x3F);
- }
- } else {
- // Remove the value peeked from the buffer list.
- _bufferList.next();
- }
- if (value > kMaxCodePoint) {
- addChar(kReplacementCodePoint);
- } else {
- addChar(value);
- }
- return true;
- }
-}
-
-
-// Utility class for decoding ascii data delivered as a stream of
-// bytes.
-class _AsciiDecoder extends _StringDecoderBase {
- // Process the next ascii encoded character.
- bool _processNext() {
- while (_bufferList.length > 0) {
- int byte = _bufferList.next();
- if (byte > 127) {
- var error = new DecoderException("Illegal ASCII character $byte");
- if (onError != null) {
- onError(error);
- return false;
- } else {
- throw error;
- }
- }
- addChar(byte);
- }
- return true;
- }
-}
-
-
-// Utility class for decoding Latin-1 data delivered as a stream of
-// bytes.
-class _Latin1Decoder extends _StringDecoderBase {
- // Process the next Latin-1 encoded character.
- bool _processNext() {
- while (_bufferList.length > 0) {
- int byte = _bufferList.next();
- addChar(byte);
- }
- return true;
- }
-}
-
-
-// Utility class for decoding Windows current code page data delivered
-// as a stream of bytes.
-class _WindowsCodePageDecoder extends _StringDecoderBase {
- // Process the next chunk of data.
- bool _processNext() {
- List<int> bytes = _bufferList.readBytes(_bufferList.length);
- for (var charCode in _decodeBytes(bytes).charCodes) {
- addChar(charCode);
- }
- return true;
- }
-
- external static String _decodeBytes(List<int> bytes);
-}
-
-
-// Interface for encoders encoding string data into binary data.
-abstract class _StringEncoder {
- List<int> encodeString(String string);
-}
-
-
-// Utility class for encoding a string into UTF-8 byte stream.
-class _UTF8Encoder implements _StringEncoder {
- List<int> encodeString(String string) {
- int size = _encodingSize(string);
- List<int> result = new Uint8List(size);
- _encodeString(string, result);
- return result;
- }
-
- static int _encodingSize(String string) => _encodeString(string, null);
-
- static int _encodeString(String string, List<int> buffer) {
- List<int> utf8CodeUnits = encodeUtf8(string);
- if (buffer != null) {
- for (int i = 0; i < utf8CodeUnits.length; i++) {
- buffer[i] = utf8CodeUnits[i];
- }
- }
- return utf8CodeUnits.length;
- }
-}
-
-
-// Utility class for encoding a string into a Latin1 byte stream.
-class _Latin1Encoder implements _StringEncoder {
- List<int> encodeString(String string) {
- List<int> result = new Uint8List(string.length);
- for (int i = 0; i < string.length; i++) {
- int charCode = string.charCodeAt(i);
- if (charCode > 255) {
- throw new EncoderException(
- "No ISO_8859_1 encoding for code point $charCode");
- }
- result[i] = charCode;
- }
- return result;
- }
-}
-
-
-// Utility class for encoding a string into an ASCII byte stream.
-class _AsciiEncoder implements _StringEncoder {
- List<int> encodeString(String string) {
- List<int> result = new Uint8List(string.length);
- for (int i = 0; i < string.length; i++) {
- int charCode = string.charCodeAt(i);
- if (charCode > 127) {
- throw new EncoderException(
- "No ASCII encoding for code point $charCode");
- }
- result[i] = charCode;
- }
- return result;
- }
-}
-
-
-// Utility class for encoding a string into a current windows
-// code page byte list.
-class _WindowsCodePageEncoder implements _StringEncoder {
- List<int> encodeString(String string) {
- return _encodeString(string);
- }
-
- external static List<int> _encodeString(String string);
-}
-
-
-class _StringEncoders {
- static _StringEncoder encoder(Encoding encoding) {
- if (encoding == Encoding.UTF_8) {
- return new _UTF8Encoder();
- } else if (encoding == Encoding.ISO_8859_1) {
- return new _Latin1Encoder();
- } else if (encoding == Encoding.ASCII) {
- return new _AsciiEncoder();
- } else if (encoding == Encoding.SYSTEM) {
- if (Platform.operatingSystem == 'windows') {
- return new _WindowsCodePageEncoder();
- }
- return new _UTF8Encoder();
- } else {
- throw new StreamException("Unsupported encoding ${encoding.name}");
- }
- }
-}
-
-
-class EncoderException implements Exception {
- const EncoderException([String this.message]);
- String toString() => "EncoderException: $message";
- final String message;
-}
-
-
-class _StringInputStream implements StringInputStream {
- _StringInputStream(InputStream this._input, Encoding this._encoding) {
- _decoder = _StringDecoders.decoder(encoding);
- _input.onData = _onData;
- _input.onClosed = _onClosed;
- }
-
- String read([int len]) {
- String result = _decoder.decoded(len);
- _checkInstallDataHandler();
- return result;
- }
-
- String readLine() {
- String decodedLine = _decoder.decodedLine;
- if (decodedLine == null) {
- if (_inputClosed) {
- // Last line might not have a line separator.
- decodedLine = _decoder.decoded();
- if (decodedLine != null &&
- decodedLine[decodedLine.length - 1] == '\r') {
- decodedLine = decodedLine.substring(0, decodedLine.length - 1);
- }
- }
- }
- _checkInstallDataHandler();
- return decodedLine;
- }
-
- int available() => _decoder.available();
-
- Encoding get encoding => _encoding;
-
- bool get closed => _inputClosed && _decoder.isEmpty;
-
- void set onData(void callback()) {
- _clientDataHandler = callback;
- _clientLineHandler = null;
- _checkInstallDataHandler();
- _checkScheduleCallback();
- }
-
- void set onLine(void callback()) {
- _clientLineHandler = callback;
- _clientDataHandler = null;
- _checkInstallDataHandler();
- _checkScheduleCallback();
- }
-
- void set onClosed(void callback()) {
- _clientCloseHandler = callback;
- }
-
- void set onError(void callback(e)) {
- _input.onError = callback;
- _decoder.onError = (e) {
- _clientCloseHandler = null;
- _input.close();
- callback(e);
- };
- }
-
- void _onData() {
- _readData();
- if (!_decoder.isEmpty && _clientDataHandler != null) {
- _clientDataHandler();
- }
- if (_decoder.lineBreaks > 0 && _clientLineHandler != null) {
- _clientLineHandler();
- }
- _checkScheduleCallback();
- _checkInstallDataHandler();
- }
-
- void _onClosed() {
- _inputClosed = true;
- _decoder.done();
- if (_decoder.isEmpty && _clientCloseHandler != null) {
- _clientCloseHandler();
- } else {
- _checkScheduleCallback();
- }
- }
-
- void _readData() {
- List<int> data = _input.read();
- if (data != null) {
- _decoder.write(data);
- }
- }
-
- void _checkInstallDataHandler() {
- if (_inputClosed ||
- (_clientDataHandler == null && _clientLineHandler == null)) {
- _input.onData = null;
- } else if (_clientDataHandler != null) {
- if (_decoder.isEmpty) {
- _input.onData = _onData;
- } else {
- _input.onData = null;
- }
- } else {
- assert(_clientLineHandler != null);
- if (_decoder.lineBreaks == 0) {
- _input.onData = _onData;
- } else {
- _input.onData = null;
- }
- }
- }
-
- // TODO(sgjesse): Find a better way of scheduling callbacks from
- // the event loop.
- void _checkScheduleCallback() {
- void issueDataCallback() {
- _scheduledDataCallback = null;
- if (_clientDataHandler != null) {
- _clientDataHandler();
- _checkScheduleCallback();
- }
- }
-
- void issueLineCallback() {
- _scheduledLineCallback = null;
- if (_clientLineHandler != null) {
- _clientLineHandler();
- _checkScheduleCallback();
- }
- }
-
- void issueCloseCallback() {
- _scheduledCloseCallback = null;
- if (!_closed) {
- if (_clientCloseHandler != null) _clientCloseHandler();
- _closed = true;
- }
- }
-
- if (!_closed) {
- // Schedule data callback if string data available.
- if (_clientDataHandler != null &&
- !_decoder.isEmpty &&
- _scheduledDataCallback == null) {
- if (_scheduledLineCallback != null) {
- _scheduledLineCallback.cancel();
- }
- _scheduledDataCallback = Timer.run(issueDataCallback);
- }
-
- // Schedule line callback if a line is available.
- if (_clientLineHandler != null &&
- (_decoder.lineBreaks > 0 || (!_decoder.isEmpty && _inputClosed)) &&
- _scheduledLineCallback == null) {
- if (_scheduledDataCallback != null) {
- _scheduledDataCallback.cancel();
- }
- _scheduledLineCallback = Timer.run(issueLineCallback);
- }
-
- // Schedule close callback if no more data and input is closed.
- if (_decoder.isEmpty &&
- _inputClosed &&
- _scheduledCloseCallback == null) {
- _scheduledCloseCallback = Timer.run(issueCloseCallback);
- }
- }
- }
-
- InputStream _input;
- Encoding _encoding;
- _StringDecoder _decoder;
- bool _inputClosed = false; // Is the underlying input stream closed?
- bool _closed = false; // Is this stream closed.
- bool _eof = false; // Has all data been read from the decoder?
- Timer _scheduledDataCallback;
- Timer _scheduledLineCallback;
- Timer _scheduledCloseCallback;
- Function _clientDataHandler;
- Function _clientLineHandler;
- Function _clientCloseHandler;
-}
« no previous file with comments | « sdk/lib/io/stream_util.dart ('k') | sdk/lib/io/websocket.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698