| 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 * String encodings. | 8 * String encodings. |
| 9 */ | 9 */ |
| 10 class Encoding { | 10 class Encoding { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 controller.stream | 146 controller.stream |
| 147 .transform(new StringEncoder(encoding)) | 147 .transform(new StringEncoder(encoding)) |
| 148 .listen((data) => bytes = data); | 148 .listen((data) => bytes = data); |
| 149 controller.add(string); | 149 controller.add(string); |
| 150 controller.close(); | 150 controller.close(); |
| 151 assert(bytes != null); | 151 assert(bytes != null); |
| 152 return bytes; | 152 return bytes; |
| 153 } | 153 } |
| 154 | 154 |
| 155 | 155 |
| 156 class LineTransformer implements StreamTransformer<String, String> { | 156 class LineTransformer extends StreamEventTransformer<String, String> { |
| 157 const int _LF = 10; | 157 const int _LF = 10; |
| 158 const int _CR = 13; | 158 const int _CR = 13; |
| 159 | 159 |
| 160 final StringBuffer _buffer = new StringBuffer(); | 160 final StringBuffer _buffer = new StringBuffer(); |
| 161 | 161 |
| 162 StreamSubscription<String> _subscription; | 162 StreamSubscription<String> _subscription; |
| 163 StreamController<String> _controller; | |
| 164 String _carry; | 163 String _carry; |
| 165 | 164 |
| 166 Stream<String> bind(Stream<String> stream) { | 165 void _handle(String data, StreamSink<String> sink, bool isClosing) { |
| 167 _controller = new StreamController<String>( | 166 if (_carry != null) { |
| 168 onPauseStateChange: _pauseChanged, | 167 data = _carry.concat(data); |
| 169 onSubscriptionStateChange: _subscriptionChanged); | 168 _carry = null; |
| 170 | 169 } |
| 171 void handle(String data, bool isClosing) { | 170 int startPos = 0; |
| 172 if (_carry != null) { | 171 int pos = 0; |
| 173 data = _carry.concat(data); | 172 while (pos < data.length) { |
| 174 _carry = null; | 173 int skip = 0; |
| 175 } | 174 int char = data.codeUnitAt(pos); |
| 176 int startPos = 0; | 175 if (char == _LF) { |
| 177 int pos = 0; | 176 skip = 1; |
| 178 while (pos < data.length) { | 177 } else if (char == _CR) { |
| 179 int skip = 0; | 178 skip = 1; |
| 180 int char = data.codeUnitAt(pos); | 179 if (pos + 1 < data.length) { |
| 181 if (char == _LF) { | 180 if (data.codeUnitAt(pos + 1) == _LF) { |
| 182 skip = 1; | 181 skip = 2; |
| 183 } else if (char == _CR) { | |
| 184 skip = 1; | |
| 185 if (pos + 1 < data.length) { | |
| 186 if (data.codeUnitAt(pos + 1) == _LF) { | |
| 187 skip = 2; | |
| 188 } | |
| 189 } else if (!isClosing) { | |
| 190 _carry = data.substring(startPos); | |
| 191 return; | |
| 192 } | 182 } |
| 193 } | 183 } else if (!isClosing) { |
| 194 if (skip > 0) { | 184 _carry = data.substring(startPos); |
| 195 _buffer.add(data.substring(startPos, pos)); | 185 return; |
| 196 _controller.add(_buffer.toString()); | |
| 197 _buffer.clear(); | |
| 198 startPos = pos = pos + skip; | |
| 199 } else { | |
| 200 pos++; | |
| 201 } | 186 } |
| 202 } | 187 } |
| 203 if (pos != startPos) { | 188 if (skip > 0) { |
| 204 // Add remaining | |
| 205 _buffer.add(data.substring(startPos, pos)); | 189 _buffer.add(data.substring(startPos, pos)); |
| 206 } | 190 sink.add(_buffer.toString()); |
| 207 if (isClosing && !_buffer.isEmpty) { | |
| 208 _controller.add(_buffer.toString()); | |
| 209 _buffer.clear(); | 191 _buffer.clear(); |
| 192 startPos = pos = pos + skip; |
| 193 } else { |
| 194 pos++; |
| 210 } | 195 } |
| 211 } | 196 } |
| 212 | 197 if (pos != startPos) { |
| 213 _subscription = stream.listen( | 198 // Add remaining |
| 214 (data) => handle(data, false), | 199 _buffer.add(data.substring(startPos, pos)); |
| 215 onDone: () { | 200 } |
| 216 // Handle remaining data (mainly _carry). | 201 if (isClosing && !_buffer.isEmpty) { |
| 217 handle("", true); | 202 sink.add(_buffer.toString()); |
| 218 _controller.close(); | 203 _buffer.clear(); |
| 219 }, | |
| 220 onError: _controller.signalError); | |
| 221 return _controller.stream; | |
| 222 } | |
| 223 | |
| 224 void _pauseChanged() { | |
| 225 if (_controller.isPaused) { | |
| 226 _subscription.pause(); | |
| 227 } else { | |
| 228 _subscription.resume(); | |
| 229 } | 204 } |
| 230 } | 205 } |
| 231 | 206 |
| 232 void _subscriptionChanged() { | 207 handleData(String data, StreamSink<String> sink) { |
| 233 if (!_controller.hasSubscribers) { | 208 _handle(data, sink, false); |
| 234 _subscription.cancel(); | 209 } |
| 235 } | 210 |
| 211 handleDone(StreamSink<String> sink) { |
| 212 _handle("", sink, true); |
| 213 sink.close(); |
| 236 } | 214 } |
| 237 } | 215 } |
| 238 | 216 |
| 239 | 217 |
| 240 class _SingleByteDecoder implements StreamTransformer<List<int>, String> { | 218 abstract class _SingleByteDecoder |
| 241 StreamSubscription<List<int>> _subscription; | 219 implements StreamTransformer<List<int>, String> { |
| 242 StreamController<String> _controller; | 220 |
| 243 final int _replacementChar; | 221 final int _replacementChar; |
| 244 | 222 |
| 245 _SingleByteDecoder(this._replacementChar); | 223 _SingleByteDecoder(this._replacementChar); |
| 246 | 224 |
| 247 Stream<String> bind(Stream<List<int>> stream) { | 225 Stream<String> bind(Stream<List<int>> stream) { |
| 248 _controller = new StreamController<String>( | 226 return stream.map((List<int> data) { |
| 249 onPauseStateChange: _pauseChanged, | 227 var buffer = new List<int>.fixedLength(data.length); |
| 250 onSubscriptionStateChange: _subscriptionChanged); | 228 for (int i = 0; i < data.length; i++) { |
| 251 _subscription = stream.listen( | 229 int char = _decodeByte(data[i]); |
| 252 (data) { | 230 if (char < 0) char = _replacementChar; |
| 253 var buffer = new List<int>.fixedLength(data.length); | 231 buffer[i] = char; |
| 254 for (int i = 0; i < data.length; i++) { | 232 } |
| 255 int char = _decodeByte(data[i]); | 233 return new String.fromCharCodes(buffer); |
| 256 if (char < 0) char = _replacementChar; | 234 }); |
| 257 buffer[i] = char; | |
| 258 } | |
| 259 _controller.add(new String.fromCharCodes(buffer)); | |
| 260 }, | |
| 261 onDone: _controller.close, | |
| 262 onError: _controller.signalError); | |
| 263 return _controller.stream; | |
| 264 } | 235 } |
| 265 | 236 |
| 266 int _decodeByte(int byte); | 237 int _decodeByte(int byte); |
| 267 | |
| 268 void _pauseChanged() { | |
| 269 if (_controller.isPaused) { | |
| 270 _subscription.pause(); | |
| 271 } else { | |
| 272 _subscription.resume(); | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 void _subscriptionChanged() { | |
| 277 if (!_controller.hasSubscribers) { | |
| 278 _subscription.cancel(); | |
| 279 } | |
| 280 } | |
| 281 } | 238 } |
| 282 | 239 |
| 283 | 240 |
| 284 // Utility class for decoding ascii data delivered as a stream of | 241 // Utility class for decoding ascii data delivered as a stream of |
| 285 // bytes. | 242 // bytes. |
| 286 class _AsciiDecoder extends _SingleByteDecoder { | 243 class _AsciiDecoder extends _SingleByteDecoder { |
| 287 _AsciiDecoder(int replacementChar) : super(replacementChar); | 244 _AsciiDecoder(int replacementChar) : super(replacementChar); |
| 288 | 245 |
| 289 int _decodeByte(int byte) => ((byte & 0x7f) == byte) ? byte : -1; | 246 int _decodeByte(int byte) => ((byte & 0x7f) == byte) ? byte : -1; |
| 290 } | 247 } |
| 291 | 248 |
| 292 | 249 |
| 293 // Utility class for decoding Latin-1 data delivered as a stream of | 250 // Utility class for decoding Latin-1 data delivered as a stream of |
| 294 // bytes. | 251 // bytes. |
| 295 class _Latin1Decoder extends _SingleByteDecoder { | 252 class _Latin1Decoder extends _SingleByteDecoder { |
| 296 _Latin1Decoder(int replacementChar) : super(replacementChar); | 253 _Latin1Decoder(int replacementChar) : super(replacementChar); |
| 297 | 254 |
| 298 int _decodeByte(int byte) => ((byte & 0xFF) == byte) ? byte : -1; | 255 int _decodeByte(int byte) => ((byte & 0xFF) == byte) ? byte : -1; |
| 299 } | 256 } |
| 300 | 257 |
| 301 | 258 |
| 302 class _SingleByteEncoder implements StreamTransformer<String, List<int>> { | 259 abstract class _SingleByteEncoder implements StreamTransformer<String, List<int>
> { |
| 303 StreamSubscription<String> _subscription; | |
| 304 StreamController<List<int>> _controller; | |
| 305 | |
| 306 Stream<List<int>> bind(Stream<String> stream) { | 260 Stream<List<int>> bind(Stream<String> stream) { |
| 307 _controller = new StreamController<List<int>>( | 261 return stream.map((String string) { |
| 308 onPauseStateChange: _pauseChanged, | 262 var bytes = _encode(string); |
| 309 onSubscriptionStateChange: _subscriptionChanged); | 263 if (bytes == null) { |
| 310 _subscription = stream.listen( | 264 throw new FormatException("Invalid character for encoding"); |
| 311 (string) { | 265 } |
| 312 var bytes = _encode(string); | 266 return bytes; |
| 313 if (bytes == null) { | 267 }); |
| 314 _controller.signalError(new FormatException( | |
| 315 "Invalid character for encoding")); | |
| 316 _controller.close(); | |
| 317 _subscription.cancel(); | |
| 318 } else { | |
| 319 _controller.add(bytes); | |
| 320 } | |
| 321 }, | |
| 322 onDone: _controller.close, | |
| 323 onError: _controller.signalError); | |
| 324 return _controller.stream; | |
| 325 } | 268 } |
| 326 | 269 |
| 327 List<int> _encode(String string); | 270 List<int> _encode(String string); |
| 328 | |
| 329 void _pauseChanged() { | |
| 330 if (_controller.isPaused) { | |
| 331 _subscription.pause(); | |
| 332 } else { | |
| 333 _subscription.resume(); | |
| 334 } | |
| 335 } | |
| 336 | |
| 337 void _subscriptionChanged() { | |
| 338 if (!_controller.hasSubscribers) { | |
| 339 _subscription.cancel(); | |
| 340 } | |
| 341 } | |
| 342 } | 271 } |
| 343 | 272 |
| 344 | 273 |
| 345 // Utility class for encoding a string into an ASCII byte stream. | 274 // Utility class for encoding a string into an ASCII byte stream. |
| 346 class _AsciiEncoder extends _SingleByteEncoder { | 275 class _AsciiEncoder extends _SingleByteEncoder { |
| 347 List<int> _encode(String string) { | 276 List<int> _encode(String string) { |
| 348 var bytes = string.codeUnits; | 277 var bytes = string.codeUnits; |
| 349 for (var byte in bytes) { | 278 for (var byte in bytes) { |
| 350 if (byte > 127) return null; | 279 if (byte > 127) return null; |
| 351 } | 280 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 373 class _WindowsCodePageEncoder extends _SingleByteEncoder { | 302 class _WindowsCodePageEncoder extends _SingleByteEncoder { |
| 374 List<int> _encode(String string) => _encodeString(string); | 303 List<int> _encode(String string) => _encodeString(string); |
| 375 | 304 |
| 376 external static List<int> _encodeString(String string); | 305 external static List<int> _encodeString(String string); |
| 377 } | 306 } |
| 378 | 307 |
| 379 | 308 |
| 380 // Utility class for decoding Windows current code page data delivered | 309 // Utility class for decoding Windows current code page data delivered |
| 381 // as a stream of bytes. | 310 // as a stream of bytes. |
| 382 class _WindowsCodePageDecoder implements StreamTransformer<List<int>, String> { | 311 class _WindowsCodePageDecoder implements StreamTransformer<List<int>, String> { |
| 383 StreamSubscription<List<int>> _subscription; | |
| 384 StreamController<String> _controller; | |
| 385 | |
| 386 Stream<String> bind(Stream<List<int>> stream) { | 312 Stream<String> bind(Stream<List<int>> stream) { |
| 387 _controller = new StreamController<String>( | 313 return stream.map(_decodeBytes); |
| 388 onPauseStateChange: _pauseChanged, | |
| 389 onSubscriptionStateChange: _subscriptionChanged); | |
| 390 _subscription = stream.listen( | |
| 391 (data) { | |
| 392 _controller.add(_decodeBytes(data)); | |
| 393 }, | |
| 394 onDone: _controller.close, | |
| 395 onError: _controller.signalError); | |
| 396 return _controller.stream; | |
| 397 } | 314 } |
| 398 | 315 |
| 399 external static String _decodeBytes(List<int> bytes); | 316 external static String _decodeBytes(List<int> bytes); |
| 400 | |
| 401 void _pauseChanged() { | |
| 402 if (_controller.isPaused) { | |
| 403 _subscription.pause(); | |
| 404 } else { | |
| 405 _subscription.resume(); | |
| 406 } | |
| 407 } | |
| 408 | |
| 409 void _subscriptionChanged() { | |
| 410 if (!_controller.hasSubscribers) { | |
| 411 _subscription.cancel(); | |
| 412 } | |
| 413 } | |
| 414 } | 317 } |
| OLD | NEW |