diff --git a/sdk/lib/io/string_stream.dart b/sdk/lib/io/string_stream.dart index 3140a3623f4..d3a698446cd 100644 --- a/sdk/lib/io/string_stream.dart +++ b/sdk/lib/io/string_stream.dart @@ -11,6 +11,8 @@ abstract class _StringDecoder { // is transfered to the decoder and the caller most not modify it any more. int write(List buffer); + void done(); + // Returns whether any decoded data is available. bool get isEmpty; @@ -88,6 +90,8 @@ abstract class _StringDecoderBase implements _StringDecoder { return buffer.length; } + void done() { } + bool get isEmpty => _result.isEmpty; int get lineBreaks => _lineBreaks; @@ -185,6 +189,12 @@ class _UTF8Decoder extends _StringDecoderBase { static const kMaxCodePoint = 0x10FFFF; static const kReplacementCodePoint = 0x3f; + void done() { + if (!_bufferList.isEmpty) { + _reportError(new DecoderException("Illegal UTF-8")); + } + } + void _reportError(error) { if (onError != null) { onError(error); @@ -217,7 +227,7 @@ class _UTF8Decoder extends _StringDecoderBase { value = value & 0x01; additionalBytes = 5; } else { - _reportError(new DecoderException("Illegal UTF-8")); + return _reportError(new DecoderException("Illegal UTF-8")); } // Check if there are enough bytes to decode the character. Otherwise // return false. @@ -229,7 +239,7 @@ class _UTF8Decoder extends _StringDecoderBase { for (int i = 0; i < additionalBytes; i++) { int byte = _bufferList.next(); if ((byte & 0xc0) != 0x80) { - _reportError(new DecoderException("Illegal UTF-8")); + return _reportError(new DecoderException("Illegal UTF-8")); } value = value << 6 | (byte & 0x3F); } @@ -477,6 +487,7 @@ class _StringInputStream implements StringInputStream { void _onClosed() { _inputClosed = true; + _decoder.done(); if (_decoder.isEmpty && _clientCloseHandler != null) { _clientCloseHandler(); } else { diff --git a/tests/standalone/io/string_decoder_test.dart b/tests/standalone/io/string_decoder_test.dart index d79bf8d7bf3..879cf8c0c57 100644 --- a/tests/standalone/io/string_decoder_test.dart +++ b/tests/standalone/io/string_decoder_test.dart @@ -1,38 +1,50 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// 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 '../../../sdk/lib/io/buffer_list.dart'; -part '../../../sdk/lib/io/input_stream.dart'; -part '../../../sdk/lib/io/string_stream.dart'; +import "dart:io"; void test() { // Code point U+10FFFF is the largest code point supported by Dart. - var decoder = _StringDecoders.decoder(Encoding.UTF_8); - decoder.write([0xf0, 0x90, 0x80, 0x80]); // U+10000 - decoder.write([0xf4, 0x8f, 0xbf, 0xbf]); // U+10FFFF - decoder.write([0xf4, 0x90, 0x80, 0x80]); // U+110000 - decoder.write([0xfa, 0x80, 0x80, 0x80, 0x80]); // U+2000000 - decoder.write([0xfd, 0x80, 0x80, 0x80, 0x80, 0x80]); // U+40000000 + //var decoder = _StringDecoders.decoder(Encoding.UTF_8); + ListInputStream lis = new ListInputStream(); + lis.write([0xf0, 0x90, 0x80, 0x80]); // U+10000 + lis.write([0xf4, 0x8f, 0xbf, 0xbf]); // U+10FFFF + lis.write([0xf4, 0x90, 0x80, 0x80]); // U+110000 + lis.write([0xfa, 0x80, 0x80, 0x80, 0x80]); // U+2000000 + lis.write([0xfd, 0x80, 0x80, 0x80, 0x80, 0x80]); // U+40000000 + lis.markEndOfStream(); - var decoded = decoder.decoded(); - Expect.equals(7, decoded.length); + var sis = new StringInputStream(lis); + sis.onData = () { + var decoded = sis.read(); + Expect.equals(7, decoded.length); - var replacementChar = '?'.charCodeAt(0); - Expect.equals(0xd800, decoded.charCodeAt(0)); - Expect.equals(0xdc00, decoded.charCodeAt(1)); - Expect.equals(0xdbff, decoded.charCodeAt(2)); - Expect.equals(0xdfff, decoded.charCodeAt(3)); - Expect.equals(replacementChar, decoded.charCodeAt(4)); - Expect.equals(replacementChar, decoded.charCodeAt(5)); - Expect.equals(replacementChar, decoded.charCodeAt(6)); + var replacementChar = '?'.charCodeAt(0); + Expect.equals(0xd800, decoded.charCodeAt(0)); + Expect.equals(0xdc00, decoded.charCodeAt(1)); + Expect.equals(0xdbff, decoded.charCodeAt(2)); + Expect.equals(0xdfff, decoded.charCodeAt(3)); + Expect.equals(replacementChar, decoded.charCodeAt(4)); + Expect.equals(replacementChar, decoded.charCodeAt(5)); + Expect.equals(replacementChar, decoded.charCodeAt(6)); + }; } void testInvalid() { - var decoder = _StringDecoders.decoder(Encoding.UTF_8); - Expect.throws(() => decoder.write([0x80])); - Expect.throws(() => decoder.write([0xff])); - Expect.throws(() => decoder.write([0xf0, 0xc0])); + void invalid(var bytes) { + ListInputStream lis = new ListInputStream(); + lis.write(bytes); + lis.markEndOfStream(); + var sis = new StringInputStream(lis); + sis.onData = () { throw "onData not expected"; }; + sis.onError = (e) { Expect.isTrue(e is DecoderException); }; + sis.onClosed = () { throw "onClosed not expected"; }; + } + + invalid([0x80]); + invalid([0xff]); + invalid([0xf0, 0xc0]); } void main() {