Chromium Code Reviews| 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 | |
| 162 StreamSubscription<String> _subscription; | |
| 163 StreamController<String> _controller; | |
| 164 String _carry; | 161 String _carry; |
| 165 | 162 |
| 166 Stream<String> bind(Stream<String> stream) { | 163 void handle(String data, StreamSink<String> sink, bool isClosing) { |
|
floitsch
2013/02/26 14:47:26
make it private.
Søren Gjesse
2013/02/26 15:23:33
Done.
| |
| 167 _controller = new StreamController<String>( | 164 if (_carry != null) { |
| 168 onPauseStateChange: _pauseChanged, | 165 data = _carry.concat(data); |
| 169 onSubscriptionStateChange: _subscriptionChanged); | 166 _carry = null; |
| 170 | 167 } |
| 171 void handle(String data, bool isClosing) { | 168 int startPos = 0; |
| 172 if (_carry != null) { | 169 int pos = 0; |
| 173 data = _carry.concat(data); | 170 while (pos < data.length) { |
| 174 _carry = null; | 171 int skip = 0; |
| 175 } | 172 int char = data.codeUnitAt(pos); |
| 176 int startPos = 0; | 173 if (char == _LF) { |
| 177 int pos = 0; | 174 skip = 1; |
| 178 while (pos < data.length) { | 175 } else if (char == _CR) { |
| 179 int skip = 0; | 176 skip = 1; |
| 180 int char = data.codeUnitAt(pos); | 177 if (pos + 1 < data.length) { |
| 181 if (char == _LF) { | 178 if (data.codeUnitAt(pos + 1) == _LF) { |
| 182 skip = 1; | 179 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 } | 180 } |
| 193 } | 181 } else if (!isClosing) { |
| 194 if (skip > 0) { | 182 _carry = data.substring(startPos); |
| 195 _buffer.add(data.substring(startPos, pos)); | 183 return; |
| 196 _controller.add(_buffer.toString()); | |
| 197 _buffer.clear(); | |
| 198 startPos = pos = pos + skip; | |
| 199 } else { | |
| 200 pos++; | |
| 201 } | 184 } |
| 202 } | 185 } |
| 203 if (pos != startPos) { | 186 if (skip > 0) { |
| 204 // Add remaining | |
| 205 _buffer.add(data.substring(startPos, pos)); | 187 _buffer.add(data.substring(startPos, pos)); |
| 206 } | 188 sink.add(_buffer.toString()); |
| 207 if (isClosing && !_buffer.isEmpty) { | |
| 208 _controller.add(_buffer.toString()); | |
| 209 _buffer.clear(); | 189 _buffer.clear(); |
| 190 startPos = pos = pos + skip; | |
| 191 } else { | |
| 192 pos++; | |
| 210 } | 193 } |
| 211 } | 194 } |
| 212 | 195 if (pos != startPos) { |
| 213 _subscription = stream.listen( | 196 // Add remaining |
| 214 (data) => handle(data, false), | 197 _buffer.add(data.substring(startPos, pos)); |
| 215 onDone: () { | 198 } |
| 216 // Handle remaining data (mainly _carry). | 199 if (isClosing && !_buffer.isEmpty) { |
| 217 handle("", true); | 200 sink.add(_buffer.toString()); |
| 218 _controller.close(); | 201 _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 } | 202 } |
| 230 } | 203 } |
| 231 | 204 |
| 232 void _subscriptionChanged() { | 205 void handleData(String data, StreamSink<String> sink) { |
| 233 if (!_controller.hasSubscribers) { | 206 handle(data, sink, false); |
| 234 _subscription.cancel(); | 207 } |
| 235 } | 208 |
| 209 void handleDone(StreamSink<String> sink) { | |
| 210 handle("", sink, true); | |
|
floitsch
2013/02/26 14:47:26
sink.close()
Søren Gjesse
2013/02/26 15:23:33
Thanks.
| |
| 236 } | 211 } |
| 237 } | 212 } |
| 238 | 213 |
| 239 | 214 |
| 240 class _SingleByteDecoder implements StreamTransformer<List<int>, String> { | 215 class _SingleByteDecoder extends StreamEventTransformer<List<int>, String> { |
| 241 StreamSubscription<List<int>> _subscription; | |
| 242 StreamController<String> _controller; | |
| 243 final int _replacementChar; | 216 final int _replacementChar; |
| 244 | 217 |
| 245 _SingleByteDecoder(this._replacementChar); | 218 _SingleByteDecoder(this._replacementChar); |
| 246 | 219 |
| 247 Stream<String> bind(Stream<List<int>> stream) { | 220 void handleData(List<int> data, StreamSink<String> sink) { |
| 248 _controller = new StreamController<String>( | 221 var buffer = new List<int>.fixedLength(data.length); |
| 249 onPauseStateChange: _pauseChanged, | 222 for (int i = 0; i < data.length; i++) { |
| 250 onSubscriptionStateChange: _subscriptionChanged); | 223 int char = _decodeByte(data[i]); |
| 251 _subscription = stream.listen( | 224 if (char < 0) char = _replacementChar; |
| 252 (data) { | 225 buffer[i] = char; |
| 253 var buffer = new List<int>.fixedLength(data.length); | 226 } |
| 254 for (int i = 0; i < data.length; i++) { | 227 sink.add(new String.fromCharCodes(buffer)); |
| 255 int char = _decodeByte(data[i]); | |
| 256 if (char < 0) char = _replacementChar; | |
| 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 } | 228 } |
| 265 | 229 |
| 266 int _decodeByte(int byte); | 230 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 } | 231 } |
| 282 | 232 |
| 283 | 233 |
| 284 // Utility class for decoding ascii data delivered as a stream of | 234 // Utility class for decoding ascii data delivered as a stream of |
| 285 // bytes. | 235 // bytes. |
| 286 class _AsciiDecoder extends _SingleByteDecoder { | 236 class _AsciiDecoder extends _SingleByteDecoder { |
| 287 _AsciiDecoder(int replacementChar) : super(replacementChar); | 237 _AsciiDecoder(int replacementChar) : super(replacementChar); |
| 288 | 238 |
| 289 int _decodeByte(int byte) => ((byte & 0x7f) == byte) ? byte : -1; | 239 int _decodeByte(int byte) => ((byte & 0x7f) == byte) ? byte : -1; |
| 290 } | 240 } |
| 291 | 241 |
| 292 | 242 |
| 293 // Utility class for decoding Latin-1 data delivered as a stream of | 243 // Utility class for decoding Latin-1 data delivered as a stream of |
| 294 // bytes. | 244 // bytes. |
| 295 class _Latin1Decoder extends _SingleByteDecoder { | 245 class _Latin1Decoder extends _SingleByteDecoder { |
| 296 _Latin1Decoder(int replacementChar) : super(replacementChar); | 246 _Latin1Decoder(int replacementChar) : super(replacementChar); |
| 297 | 247 |
| 298 int _decodeByte(int byte) => ((byte & 0xFF) == byte) ? byte : -1; | 248 int _decodeByte(int byte) => ((byte & 0xFF) == byte) ? byte : -1; |
| 299 } | 249 } |
| 300 | 250 |
| 301 | 251 |
| 302 class _SingleByteEncoder implements StreamTransformer<String, List<int>> { | 252 class _SingleByteEncoder extends StreamEventTransformer<String, List<int>> { |
| 303 StreamSubscription<String> _subscription; | 253 void handleData(String data, StreamSink<List<int>> sink) { |
| 304 StreamController<List<int>> _controller; | 254 var bytes = _encode(data); |
| 305 | 255 if (bytes == null) { |
| 306 Stream<List<int>> bind(Stream<String> stream) { | 256 throw new FormatException("Invalid character for encoding"); |
| 307 _controller = new StreamController<List<int>>( | 257 sink.close(); |
| 308 onPauseStateChange: _pauseChanged, | 258 } else { |
| 309 onSubscriptionStateChange: _subscriptionChanged); | 259 sink.add(bytes); |
| 310 _subscription = stream.listen( | 260 } |
| 311 (string) { | |
| 312 var bytes = _encode(string); | |
| 313 if (bytes == null) { | |
| 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 } | 261 } |
| 326 | 262 |
| 327 List<int> _encode(String string); | 263 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 } | 264 } |
| 343 | 265 |
| 344 | 266 |
| 345 // Utility class for encoding a string into an ASCII byte stream. | 267 // Utility class for encoding a string into an ASCII byte stream. |
| 346 class _AsciiEncoder extends _SingleByteEncoder { | 268 class _AsciiEncoder extends _SingleByteEncoder { |
| 347 List<int> _encode(String string) { | 269 List<int> _encode(String string) { |
| 348 var bytes = string.codeUnits; | 270 var bytes = string.codeUnits; |
| 349 for (var byte in bytes) { | 271 for (var byte in bytes) { |
| 350 if (byte > 127) return null; | 272 if (byte > 127) return null; |
| 351 } | 273 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 372 // single byte encoder, to avoid copying boilerplate. | 294 // single byte encoder, to avoid copying boilerplate. |
| 373 class _WindowsCodePageEncoder extends _SingleByteEncoder { | 295 class _WindowsCodePageEncoder extends _SingleByteEncoder { |
| 374 List<int> _encode(String string) => _encodeString(string); | 296 List<int> _encode(String string) => _encodeString(string); |
| 375 | 297 |
| 376 external static List<int> _encodeString(String string); | 298 external static List<int> _encodeString(String string); |
| 377 } | 299 } |
| 378 | 300 |
| 379 | 301 |
| 380 // Utility class for decoding Windows current code page data delivered | 302 // Utility class for decoding Windows current code page data delivered |
| 381 // as a stream of bytes. | 303 // as a stream of bytes. |
| 382 class _WindowsCodePageDecoder implements StreamTransformer<List<int>, String> { | 304 class _WindowsCodePageDecoder extends StreamEventTransformer<List<int>, String> { |
| 383 StreamSubscription<List<int>> _subscription; | 305 void handleData(List<int> data, StreamSink<String> sink) { |
| 384 StreamController<String> _controller; | 306 sink.add(_decodeBytes(data)); |
| 385 | |
| 386 Stream<String> bind(Stream<List<int>> stream) { | |
| 387 _controller = new StreamController<String>( | |
| 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 } | 307 } |
| 398 | 308 |
| 399 external static String _decodeBytes(List<int> bytes); | 309 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 } | 310 } |
| OLD | NEW |