OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /// Generic utility functions. Stuff that should possibly be in core. | 5 /// Generic utility functions. Stuff that should possibly be in core. |
6 library utils; | 6 library utils; |
7 | 7 |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:crypto'; | 9 import 'dart:crypto'; |
10 import 'dart:isolate'; | 10 import 'dart:isolate'; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 | 229 |
230 /// A regular expression matching a line termination character or character | 230 /// A regular expression matching a line termination character or character |
231 /// sequence. | 231 /// sequence. |
232 final RegExp _lineRegexp = new RegExp(r"\r\n|\r|\n"); | 232 final RegExp _lineRegexp = new RegExp(r"\r\n|\r|\n"); |
233 | 233 |
234 /// Converts a stream of arbitrarily chunked strings into a line-by-line stream. | 234 /// Converts a stream of arbitrarily chunked strings into a line-by-line stream. |
235 /// The lines don't include line termination characters. A single trailing | 235 /// The lines don't include line termination characters. A single trailing |
236 /// newline is ignored. | 236 /// newline is ignored. |
237 Stream<String> streamToLines(Stream<String> stream) { | 237 Stream<String> streamToLines(Stream<String> stream) { |
238 var buffer = new StringBuffer(); | 238 var buffer = new StringBuffer(); |
239 return wrapStream(stream.transform(new StreamTransformer( | 239 return stream.transform(new StreamTransformer( |
240 handleData: (chunk, sink) { | 240 handleData: (chunk, sink) { |
241 var lines = chunk.split(_lineRegexp); | 241 var lines = chunk.split(_lineRegexp); |
242 var leftover = lines.removeLast(); | 242 var leftover = lines.removeLast(); |
243 for (var line in lines) { | 243 for (var line in lines) { |
244 if (!buffer.isEmpty) { | 244 if (!buffer.isEmpty) { |
245 buffer.add(line); | 245 buffer.add(line); |
246 line = buffer.toString(); | 246 line = buffer.toString(); |
247 buffer.clear(); | 247 buffer.clear(); |
248 } | 248 } |
249 | 249 |
250 sink.add(line); | 250 sink.add(line); |
251 } | 251 } |
252 buffer.add(leftover); | 252 buffer.add(leftover); |
253 }, | 253 }, |
254 handleDone: (sink) { | 254 handleDone: (sink) { |
255 if (!buffer.isEmpty) sink.add(buffer.toString()); | 255 if (!buffer.isEmpty) sink.add(buffer.toString()); |
256 sink.close(); | 256 sink.close(); |
257 }))); | 257 })); |
258 } | |
259 | |
260 // TODO(nweiz): remove this when issue 8310 is fixed. | |
261 /// Returns a [Stream] identical to [stream], but piped through a new | |
262 /// [StreamController]. This exists to work around issue 8310. | |
263 Stream wrapStream(Stream stream) { | |
264 var controller = stream.isBroadcast | |
265 ? new StreamController.broadcast() | |
266 : new StreamController(); | |
267 stream.listen(controller.add, | |
268 onError: (e) => controller.signalError(e), | |
269 onDone: controller.close); | |
270 return controller.stream; | |
271 } | 258 } |
272 | 259 |
273 /// Like [Iterable.where], but allows [test] to return [Future]s and uses the | 260 /// Like [Iterable.where], but allows [test] to return [Future]s and uses the |
274 /// results of those [Future]s as the test. | 261 /// results of those [Future]s as the test. |
275 Future<Iterable> futureWhere(Iterable iter, test(value)) { | 262 Future<Iterable> futureWhere(Iterable iter, test(value)) { |
276 return Future.wait(iter.map((e) { | 263 return Future.wait(iter.map((e) { |
277 var result = test(e); | 264 var result = test(e); |
278 if (result is! Future) result = new Future.immediate(result); | 265 if (result is! Future) result = new Future.immediate(result); |
279 return result.then((result) => new Pair(e, result)); | 266 return result.then((result) => new Pair(e, result)); |
280 })) | 267 })) |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 | 321 |
335 /// Add all key/value pairs from [source] to [destination], overwriting any | 322 /// Add all key/value pairs from [source] to [destination], overwriting any |
336 /// pre-existing values. | 323 /// pre-existing values. |
337 void mapAddAll(Map destination, Map source) => | 324 void mapAddAll(Map destination, Map source) => |
338 source.forEach((key, value) => destination[key] = value); | 325 source.forEach((key, value) => destination[key] = value); |
339 | 326 |
340 /// Decodes a URL-encoded string. Unlike [decodeUriComponent], this includes | 327 /// Decodes a URL-encoded string. Unlike [decodeUriComponent], this includes |
341 /// replacing `+` with ` `. | 328 /// replacing `+` with ` `. |
342 String urlDecode(String encoded) => | 329 String urlDecode(String encoded) => |
343 decodeUriComponent(encoded.replaceAll("+", " ")); | 330 decodeUriComponent(encoded.replaceAll("+", " ")); |
OLD | NEW |