| 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 // Interface for decoders decoding binary data into string data. The | 7 // Interface for decoders decoding binary data into string data. The |
| 8 // decoder keeps track of line breaks during decoding. | 8 // decoder keeps track of line breaks during decoding. |
| 9 abstract class _StringDecoder { | 9 abstract class _StringDecoder { |
| 10 // Add more binary data to be decoded. The ownership of the buffer | 10 // Add more binary data to be decoded. The ownership of the buffer |
| 11 // is transfered to the decoder and the caller most not modify it any more. | 11 // is transfered to the decoder and the caller most not modify it any more. |
| 12 int write(List<int> buffer); | 12 int write(List<int> buffer); |
| 13 | 13 |
| 14 void done(); |
| 15 |
| 14 // Returns whether any decoded data is available. | 16 // Returns whether any decoded data is available. |
| 15 bool get isEmpty; | 17 bool get isEmpty; |
| 16 | 18 |
| 17 // Returns the number of available decoded characters. | 19 // Returns the number of available decoded characters. |
| 18 int available(); | 20 int available(); |
| 19 | 21 |
| 20 // Get the number of line breaks present in the current decoded | 22 // Get the number of line breaks present in the current decoded |
| 21 // data. | 23 // data. |
| 22 int get lineBreaks; | 24 int get lineBreaks; |
| 23 | 25 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 _bufferList.add(buffer); | 83 _bufferList.add(buffer); |
| 82 // Decode as many bytes into characters as possible. | 84 // Decode as many bytes into characters as possible. |
| 83 while (_bufferList.length > 0) { | 85 while (_bufferList.length > 0) { |
| 84 if (!_processNext()) { | 86 if (!_processNext()) { |
| 85 break; | 87 break; |
| 86 } | 88 } |
| 87 } | 89 } |
| 88 return buffer.length; | 90 return buffer.length; |
| 89 } | 91 } |
| 90 | 92 |
| 93 void done() { } |
| 94 |
| 91 bool get isEmpty => _result.isEmpty; | 95 bool get isEmpty => _result.isEmpty; |
| 92 | 96 |
| 93 int get lineBreaks => _lineBreaks; | 97 int get lineBreaks => _lineBreaks; |
| 94 | 98 |
| 95 String decoded([int length]) { | 99 String decoded([int length]) { |
| 96 if (isEmpty) return null; | 100 if (isEmpty) return null; |
| 97 | 101 |
| 98 List<int> result; | 102 List<int> result; |
| 99 if (length != null && length < available()) { | 103 if (length != null && length < available()) { |
| 100 result = _result.getRange(_resultOffset, length); | 104 result = _result.getRange(_resultOffset, length); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 final int CR = 13; | 182 final int CR = 13; |
| 179 } | 183 } |
| 180 | 184 |
| 181 | 185 |
| 182 // Utility class for decoding UTF-8 from data delivered as a stream of | 186 // Utility class for decoding UTF-8 from data delivered as a stream of |
| 183 // bytes. | 187 // bytes. |
| 184 class _UTF8Decoder extends _StringDecoderBase { | 188 class _UTF8Decoder extends _StringDecoderBase { |
| 185 static const kMaxCodePoint = 0x10FFFF; | 189 static const kMaxCodePoint = 0x10FFFF; |
| 186 static const kReplacementCodePoint = 0x3f; | 190 static const kReplacementCodePoint = 0x3f; |
| 187 | 191 |
| 192 void done() { |
| 193 if (!_bufferList.isEmpty) { |
| 194 _reportError(new DecoderException("Illegal UTF-8")); |
| 195 } |
| 196 } |
| 197 |
| 188 void _reportError(error) { | 198 void _reportError(error) { |
| 189 if (onError != null) { | 199 if (onError != null) { |
| 190 onError(error); | 200 onError(error); |
| 191 return false; | 201 return false; |
| 192 } else { | 202 } else { |
| 193 throw error; | 203 throw error; |
| 194 } | 204 } |
| 195 } | 205 } |
| 196 | 206 |
| 197 // Process the next UTF-8 encoded character. | 207 // Process the next UTF-8 encoded character. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 210 } else if ((value & 0xf8) == 0xf0) { // 11110xxx | 220 } else if ((value & 0xf8) == 0xf0) { // 11110xxx |
| 211 value = value & 0x07; | 221 value = value & 0x07; |
| 212 additionalBytes = 3; | 222 additionalBytes = 3; |
| 213 } else if ((value & 0xfc) == 0xf8) { // 111110xx | 223 } else if ((value & 0xfc) == 0xf8) { // 111110xx |
| 214 value = value & 0x03; | 224 value = value & 0x03; |
| 215 additionalBytes = 4; | 225 additionalBytes = 4; |
| 216 } else if ((value & 0xfe) == 0xfc) { // 1111110x | 226 } else if ((value & 0xfe) == 0xfc) { // 1111110x |
| 217 value = value & 0x01; | 227 value = value & 0x01; |
| 218 additionalBytes = 5; | 228 additionalBytes = 5; |
| 219 } else { | 229 } else { |
| 220 _reportError(new DecoderException("Illegal UTF-8")); | 230 return _reportError(new DecoderException("Illegal UTF-8")); |
| 221 } | 231 } |
| 222 // Check if there are enough bytes to decode the character. Otherwise | 232 // Check if there are enough bytes to decode the character. Otherwise |
| 223 // return false. | 233 // return false. |
| 224 if (_bufferList.length < additionalBytes + 1) { | 234 if (_bufferList.length < additionalBytes + 1) { |
| 225 return false; | 235 return false; |
| 226 } | 236 } |
| 227 // Remove the value peeked from the buffer list. | 237 // Remove the value peeked from the buffer list. |
| 228 _bufferList.next(); | 238 _bufferList.next(); |
| 229 for (int i = 0; i < additionalBytes; i++) { | 239 for (int i = 0; i < additionalBytes; i++) { |
| 230 int byte = _bufferList.next(); | 240 int byte = _bufferList.next(); |
| 231 if ((byte & 0xc0) != 0x80) { | 241 if ((byte & 0xc0) != 0x80) { |
| 232 _reportError(new DecoderException("Illegal UTF-8")); | 242 return _reportError(new DecoderException("Illegal UTF-8")); |
| 233 } | 243 } |
| 234 value = value << 6 | (byte & 0x3F); | 244 value = value << 6 | (byte & 0x3F); |
| 235 } | 245 } |
| 236 } else { | 246 } else { |
| 237 // Remove the value peeked from the buffer list. | 247 // Remove the value peeked from the buffer list. |
| 238 _bufferList.next(); | 248 _bufferList.next(); |
| 239 } | 249 } |
| 240 if (value > kMaxCodePoint) { | 250 if (value > kMaxCodePoint) { |
| 241 addChar(kReplacementCodePoint); | 251 addChar(kReplacementCodePoint); |
| 242 } else { | 252 } else { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 } | 480 } |
| 471 if (_decoder.lineBreaks > 0 && _clientLineHandler != null) { | 481 if (_decoder.lineBreaks > 0 && _clientLineHandler != null) { |
| 472 _clientLineHandler(); | 482 _clientLineHandler(); |
| 473 } | 483 } |
| 474 _checkScheduleCallback(); | 484 _checkScheduleCallback(); |
| 475 _checkInstallDataHandler(); | 485 _checkInstallDataHandler(); |
| 476 } | 486 } |
| 477 | 487 |
| 478 void _onClosed() { | 488 void _onClosed() { |
| 479 _inputClosed = true; | 489 _inputClosed = true; |
| 490 _decoder.done(); |
| 480 if (_decoder.isEmpty && _clientCloseHandler != null) { | 491 if (_decoder.isEmpty && _clientCloseHandler != null) { |
| 481 _clientCloseHandler(); | 492 _clientCloseHandler(); |
| 482 } else { | 493 } else { |
| 483 _checkScheduleCallback(); | 494 _checkScheduleCallback(); |
| 484 } | 495 } |
| 485 } | 496 } |
| 486 | 497 |
| 487 void _readData() { | 498 void _readData() { |
| 488 List<int> data = _input.read(); | 499 List<int> data = _input.read(); |
| 489 if (data != null) { | 500 if (data != null) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 bool _inputClosed = false; // Is the underlying input stream closed? | 585 bool _inputClosed = false; // Is the underlying input stream closed? |
| 575 bool _closed = false; // Is this stream closed. | 586 bool _closed = false; // Is this stream closed. |
| 576 bool _eof = false; // Has all data been read from the decoder? | 587 bool _eof = false; // Has all data been read from the decoder? |
| 577 Timer _scheduledDataCallback; | 588 Timer _scheduledDataCallback; |
| 578 Timer _scheduledLineCallback; | 589 Timer _scheduledLineCallback; |
| 579 Timer _scheduledCloseCallback; | 590 Timer _scheduledCloseCallback; |
| 580 Function _clientDataHandler; | 591 Function _clientDataHandler; |
| 581 Function _clientLineHandler; | 592 Function _clientLineHandler; |
| 582 Function _clientCloseHandler; | 593 Function _clientCloseHandler; |
| 583 } | 594 } |
| OLD | NEW |