| 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 /** | 5 /// Generic utility functions. Stuff that should possibly be in core. |
| 6 * Generic utility functions. Stuff that should possibly be in core. | |
| 7 */ | |
| 8 library utils; | 6 library utils; |
| 9 | 7 |
| 10 import 'dart:crypto'; | 8 import 'dart:crypto'; |
| 11 import 'dart:isolate'; | 9 import 'dart:isolate'; |
| 12 import 'dart:uri'; | 10 import 'dart:uri'; |
| 13 | 11 |
| 14 /** A pair of values. */ | 12 /// A pair of values. |
| 15 class Pair<E, F> { | 13 class Pair<E, F> { |
| 16 E first; | 14 E first; |
| 17 F last; | 15 F last; |
| 18 | 16 |
| 19 Pair(this.first, this.last); | 17 Pair(this.first, this.last); |
| 20 | 18 |
| 21 String toString() => '($first, $last)'; | 19 String toString() => '($first, $last)'; |
| 22 | 20 |
| 23 bool operator==(other) { | 21 bool operator==(other) { |
| 24 if (other is! Pair) return false; | 22 if (other is! Pair) return false; |
| 25 return other.first == first && other.last == last; | 23 return other.first == first && other.last == last; |
| 26 } | 24 } |
| 27 | 25 |
| 28 int get hashCode => first.hashCode ^ last.hashCode; | 26 int get hashCode => first.hashCode ^ last.hashCode; |
| 29 } | 27 } |
| 30 | 28 |
| 31 // TODO(rnystrom): Move into String? | 29 // TODO(rnystrom): Move into String? |
| 32 /** Pads [source] to [length] by adding spaces at the end. */ | 30 /// Pads [source] to [length] by adding spaces at the end. |
| 33 String padRight(String source, int length) { | 31 String padRight(String source, int length) { |
| 34 final result = new StringBuffer(); | 32 final result = new StringBuffer(); |
| 35 result.add(source); | 33 result.add(source); |
| 36 | 34 |
| 37 while (result.length < length) { | 35 while (result.length < length) { |
| 38 result.add(' '); | 36 result.add(' '); |
| 39 } | 37 } |
| 40 | 38 |
| 41 return result.toString(); | 39 return result.toString(); |
| 42 } | 40 } |
| 43 | 41 |
| 44 /** | 42 /// Runs [fn] after [future] completes, whether it completes successfully or |
| 45 * Runs [fn] after [future] completes, whether it completes successfully or not. | 43 /// not. Essentially an asynchronous `finally` block. |
| 46 * Essentially an asynchronous `finally` block. | |
| 47 */ | |
| 48 always(Future future, fn()) { | 44 always(Future future, fn()) { |
| 49 var completer = new Completer(); | 45 var completer = new Completer(); |
| 50 future.then((_) => fn()); | 46 future.then((_) => fn()); |
| 51 future.handleException((_) { | 47 future.handleException((_) { |
| 52 fn(); | 48 fn(); |
| 53 return false; | 49 return false; |
| 54 }); | 50 }); |
| 55 } | 51 } |
| 56 | 52 |
| 57 /** | 53 /// Flattens nested collections into a single list containing only non-list |
| 58 * Flattens nested collections into a single list containing only non-list | 54 /// elements. |
| 59 * elements. | |
| 60 */ | |
| 61 List flatten(Collection nested) { | 55 List flatten(Collection nested) { |
| 62 var result = []; | 56 var result = []; |
| 63 helper(list) { | 57 helper(list) { |
| 64 for (var element in list) { | 58 for (var element in list) { |
| 65 if (element is List) { | 59 if (element is List) { |
| 66 helper(element); | 60 helper(element); |
| 67 } else { | 61 } else { |
| 68 result.add(element); | 62 result.add(element); |
| 69 } | 63 } |
| 70 } | 64 } |
| 71 } | 65 } |
| 72 helper(nested); | 66 helper(nested); |
| 73 return result; | 67 return result; |
| 74 } | 68 } |
| 75 | 69 |
| 76 /** | 70 /// Asserts that [iter] contains only one element, and returns it. |
| 77 * Asserts that [iter] contains only one element, and returns it. | |
| 78 */ | |
| 79 only(Iterable iter) { | 71 only(Iterable iter) { |
| 80 var iterator = iter.iterator(); | 72 var iterator = iter.iterator(); |
| 81 assert(iterator.hasNext); | 73 assert(iterator.hasNext); |
| 82 var obj = iterator.next(); | 74 var obj = iterator.next(); |
| 83 assert(!iterator.hasNext); | 75 assert(!iterator.hasNext); |
| 84 return obj; | 76 return obj; |
| 85 } | 77 } |
| 86 | 78 |
| 87 /** | 79 /// Returns a set containing all elements in [minuend] that are not in |
| 88 * Returns a set containing all elements in [minuend] that are not in | 80 /// [subtrahend]. |
| 89 * [subtrahend]. | |
| 90 */ | |
| 91 Set setMinus(Collection minuend, Collection subtrahend) { | 81 Set setMinus(Collection minuend, Collection subtrahend) { |
| 92 var minuendSet = new Set.from(minuend); | 82 var minuendSet = new Set.from(minuend); |
| 93 minuendSet.removeAll(subtrahend); | 83 minuendSet.removeAll(subtrahend); |
| 94 return minuendSet; | 84 return minuendSet; |
| 95 } | 85 } |
| 96 | 86 |
| 97 /** | 87 /// Replace each instance of [matcher] in [source] with the return value of |
| 98 * Replace each instance of [matcher] in [source] with the return value of [fn]. | 88 /// [fn]. |
| 99 */ | |
| 100 String replace(String source, Pattern matcher, String fn(Match)) { | 89 String replace(String source, Pattern matcher, String fn(Match)) { |
| 101 var buffer = new StringBuffer(); | 90 var buffer = new StringBuffer(); |
| 102 var start = 0; | 91 var start = 0; |
| 103 for (var match in matcher.allMatches(source)) { | 92 for (var match in matcher.allMatches(source)) { |
| 104 buffer.add(source.substring(start, match.start)); | 93 buffer.add(source.substring(start, match.start)); |
| 105 start = match.end; | 94 start = match.end; |
| 106 buffer.add(fn(match)); | 95 buffer.add(fn(match)); |
| 107 } | 96 } |
| 108 buffer.add(source.substring(start)); | 97 buffer.add(source.substring(start)); |
| 109 return buffer.toString(); | 98 return buffer.toString(); |
| 110 } | 99 } |
| 111 | 100 |
| 112 /** | 101 /// Returns whether or not [str] ends with [matcher]. |
| 113 * Returns whether or not [str] ends with [matcher]. | |
| 114 */ | |
| 115 bool endsWithPattern(String str, Pattern matcher) { | 102 bool endsWithPattern(String str, Pattern matcher) { |
| 116 for (var match in matcher.allMatches(str)) { | 103 for (var match in matcher.allMatches(str)) { |
| 117 if (match.end == str.length) return true; | 104 if (match.end == str.length) return true; |
| 118 } | 105 } |
| 119 return false; | 106 return false; |
| 120 } | 107 } |
| 121 | 108 |
| 122 /** | 109 /// Returns the hex-encoded sha1 hash of [source]. |
| 123 * Returns the hex-encoded sha1 hash of [source]. | |
| 124 */ | |
| 125 String sha1(String source) => | 110 String sha1(String source) => |
| 126 CryptoUtils.bytesToHex(new SHA1().update(source.charCodes).digest()); | 111 CryptoUtils.bytesToHex(new SHA1().update(source.charCodes).digest()); |
| 127 | 112 |
| 128 /** | 113 /// Returns a [Future] that completes in [milliseconds]. |
| 129 * Returns a [Future] that completes in [milliseconds]. | |
| 130 */ | |
| 131 Future sleep(int milliseconds) { | 114 Future sleep(int milliseconds) { |
| 132 var completer = new Completer(); | 115 var completer = new Completer(); |
| 133 new Timer(milliseconds, completer.complete); | 116 new Timer(milliseconds, completer.complete); |
| 134 return completer.future; | 117 return completer.future; |
| 135 } | 118 } |
| 136 | 119 |
| 137 /// Configures [future] so that its result (success or exception) is passed on | 120 /// Configures [future] so that its result (success or exception) is passed on |
| 138 /// to [completer]. | 121 /// to [completer]. |
| 139 void chainToCompleter(Future future, Completer completer) { | 122 void chainToCompleter(Future future, Completer completer) { |
| 140 future.handleException((e) { | 123 future.handleException((e) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 | 179 |
| 197 /// Add all key/value pairs from [source] to [destination], overwriting any | 180 /// Add all key/value pairs from [source] to [destination], overwriting any |
| 198 /// pre-existing values. | 181 /// pre-existing values. |
| 199 void mapAddAll(Map destination, Map source) => | 182 void mapAddAll(Map destination, Map source) => |
| 200 source.forEach((key, value) => destination[key] = value); | 183 source.forEach((key, value) => destination[key] = value); |
| 201 | 184 |
| 202 /// Decodes a URL-encoded string. Unlike [decodeUriComponent], this includes | 185 /// Decodes a URL-encoded string. Unlike [decodeUriComponent], this includes |
| 203 /// replacing `+` with ` `. | 186 /// replacing `+` with ` `. |
| 204 String urlDecode(String encoded) => | 187 String urlDecode(String encoded) => |
| 205 decodeUriComponent(encoded.replaceAll("+", " ")); | 188 decodeUriComponent(encoded.replaceAll("+", " ")); |
| OLD | NEW |