| 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:crypto'; | 9 import 'dart:crypto'; | 
| 9 import 'dart:isolate'; | 10 import 'dart:isolate'; | 
| 10 import 'dart:uri'; | 11 import 'dart:uri'; | 
| 11 | 12 | 
| 12 /// A pair of values. | 13 /// A pair of values. | 
| 13 class Pair<E, F> { | 14 class Pair<E, F> { | 
| 14   E first; | 15   E first; | 
| 15   F last; | 16   F last; | 
| 16 | 17 | 
| 17   Pair(this.first, this.last); | 18   Pair(this.first, this.last); | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 35   while (result.length < length) { | 36   while (result.length < length) { | 
| 36     result.add(' '); | 37     result.add(' '); | 
| 37   } | 38   } | 
| 38 | 39 | 
| 39   return result.toString(); | 40   return result.toString(); | 
| 40 } | 41 } | 
| 41 | 42 | 
| 42 /// Runs [fn] after [future] completes, whether it completes successfully or | 43 /// Runs [fn] after [future] completes, whether it completes successfully or | 
| 43 /// not. Essentially an asynchronous `finally` block. | 44 /// not. Essentially an asynchronous `finally` block. | 
| 44 always(Future future, fn()) { | 45 always(Future future, fn()) { | 
| 45   var completer = new Completer(); | 46   future.catchError((_) {}).then((_) => fn()); | 
| 46   future.then((_) => fn()); |  | 
| 47   future.handleException((_) { |  | 
| 48     fn(); |  | 
| 49     return false; |  | 
| 50   }); |  | 
| 51 } | 47 } | 
| 52 | 48 | 
| 53 /// Flattens nested collections into a single list containing only non-list | 49 /// Flattens nested lists inside an iterable into a single list containing only | 
| 54 /// elements. | 50 /// non-list elements. | 
| 55 List flatten(Collection nested) { | 51 List flatten(Iterable nested) { | 
| 56   var result = []; | 52   var result = []; | 
| 57   helper(list) { | 53   helper(list) { | 
| 58     for (var element in list) { | 54     for (var element in list) { | 
| 59       if (element is List) { | 55       if (element is List) { | 
| 60         helper(element); | 56         helper(element); | 
| 61       } else { | 57       } else { | 
| 62         result.add(element); | 58         result.add(element); | 
| 63       } | 59       } | 
| 64     } | 60     } | 
| 65   } | 61   } | 
| 66   helper(nested); | 62   helper(nested); | 
| 67   return result; | 63   return result; | 
| 68 } | 64 } | 
| 69 | 65 | 
| 70 /// Asserts that [iter] contains only one element, and returns it. | 66 /// Asserts that [iter] contains only one element, and returns it. | 
| 71 only(Iterable iter) { | 67 only(Iterable iter) { | 
| 72   var iterator = iter.iterator(); | 68   var iterator = iter.iterator; | 
| 73   assert(iterator.hasNext); | 69   var currentIsValid = iterator.moveNext(); | 
| 74   var obj = iterator.next(); | 70   assert(currentIsValid); | 
| 75   assert(!iterator.hasNext); | 71   var obj = iterator.current; | 
|  | 72   assert(!iterator.moveNext()); | 
| 76   return obj; | 73   return obj; | 
| 77 } | 74 } | 
| 78 | 75 | 
| 79 /// Returns a set containing all elements in [minuend] that are not in | 76 /// Returns a set containing all elements in [minuend] that are not in | 
| 80 /// [subtrahend]. | 77 /// [subtrahend]. | 
| 81 Set setMinus(Collection minuend, Collection subtrahend) { | 78 Set setMinus(Collection minuend, Collection subtrahend) { | 
| 82   var minuendSet = new Set.from(minuend); | 79   var minuendSet = new Set.from(minuend); | 
| 83   minuendSet.removeAll(subtrahend); | 80   minuendSet.removeAll(subtrahend); | 
| 84   return minuendSet; | 81   return minuendSet; | 
| 85 } | 82 } | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 101 /// Returns whether or not [str] ends with [matcher]. | 98 /// Returns whether or not [str] ends with [matcher]. | 
| 102 bool endsWithPattern(String str, Pattern matcher) { | 99 bool endsWithPattern(String str, Pattern matcher) { | 
| 103   for (var match in matcher.allMatches(str)) { | 100   for (var match in matcher.allMatches(str)) { | 
| 104     if (match.end == str.length) return true; | 101     if (match.end == str.length) return true; | 
| 105   } | 102   } | 
| 106   return false; | 103   return false; | 
| 107 } | 104 } | 
| 108 | 105 | 
| 109 /// Returns the hex-encoded sha1 hash of [source]. | 106 /// Returns the hex-encoded sha1 hash of [source]. | 
| 110 String sha1(String source) => | 107 String sha1(String source) => | 
| 111   CryptoUtils.bytesToHex(new SHA1().update(source.charCodes).digest()); | 108   CryptoUtils.bytesToHex(new SHA1().add(source.charCodes).close()); | 
| 112 | 109 | 
| 113 /// Returns a [Future] that completes in [milliseconds]. | 110 /// Returns a [Future] that completes in [milliseconds]. | 
| 114 Future sleep(int milliseconds) { | 111 Future sleep(int milliseconds) { | 
| 115   var completer = new Completer(); | 112   var completer = new Completer(); | 
| 116   new Timer(milliseconds, completer.complete); | 113   new Timer(milliseconds, completer.complete); | 
| 117   return completer.future; | 114   return completer.future; | 
| 118 } | 115 } | 
| 119 | 116 | 
| 120 /// Configures [future] so that its result (success or exception) is passed on | 117 /// Configures [future] so that its result (success or exception) is passed on | 
| 121 /// to [completer]. | 118 /// to [completer]. | 
| 122 void chainToCompleter(Future future, Completer completer) { | 119 void chainToCompleter(Future future, Completer completer) { | 
| 123   future.handleException((e) { | 120   future | 
| 124     completer.completeException(e, future.stackTrace); | 121     .then(completer.complete) | 
| 125     return true; | 122     .catchError((e) { | 
| 126   }); | 123       completer.completeError(e.error, e.stackTrace); | 
| 127   future.then(completer.complete); | 124     }); | 
| 128 } | 125 } | 
| 129 | 126 | 
| 130 // TODO(nweiz): unify the following functions with the utility functions in | 127 // TODO(nweiz): unify the following functions with the utility functions in | 
| 131 // pkg/http. | 128 // pkg/http. | 
| 132 | 129 | 
| 133 /// Like [String.split], but only splits on the first occurrence of the pattern. | 130 /// Like [String.split], but only splits on the first occurrence of the pattern. | 
| 134 /// This will always return an array of two elements or fewer. | 131 /// This will always return an array of two elements or fewer. | 
| 135 List<String> split1(String toSplit, String pattern) { | 132 List<String> split1(String toSplit, String pattern) { | 
| 136   if (toSplit.isEmpty) return <String>[]; | 133   if (toSplit.isEmpty) return <String>[]; | 
| 137 | 134 | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 164 } | 161 } | 
| 165 | 162 | 
| 166 /// Convert a [Map] from parameter names to values to a URL query string. | 163 /// Convert a [Map] from parameter names to values to a URL query string. | 
| 167 String mapToQuery(Map<String, String> map) { | 164 String mapToQuery(Map<String, String> map) { | 
| 168   var pairs = <List<String>>[]; | 165   var pairs = <List<String>>[]; | 
| 169   map.forEach((key, value) { | 166   map.forEach((key, value) { | 
| 170     key = encodeUriComponent(key); | 167     key = encodeUriComponent(key); | 
| 171     value = (value == null || value.isEmpty) ? null : encodeUriComponent(value); | 168     value = (value == null || value.isEmpty) ? null : encodeUriComponent(value); | 
| 172     pairs.add([key, value]); | 169     pairs.add([key, value]); | 
| 173   }); | 170   }); | 
| 174   return Strings.join(pairs.map((pair) { | 171   return Strings.join(pairs.mappedBy((pair) { | 
| 175     if (pair[1] == null) return pair[0]; | 172     if (pair[1] == null) return pair[0]; | 
| 176     return "${pair[0]}=${pair[1]}"; | 173     return "${pair[0]}=${pair[1]}"; | 
| 177   }), "&"); | 174   }), "&"); | 
| 178 } | 175 } | 
| 179 | 176 | 
| 180 /// Add all key/value pairs from [source] to [destination], overwriting any | 177 /// Add all key/value pairs from [source] to [destination], overwriting any | 
| 181 /// pre-existing values. | 178 /// pre-existing values. | 
| 182 void mapAddAll(Map destination, Map source) => | 179 void mapAddAll(Map destination, Map source) => | 
| 183   source.forEach((key, value) => destination[key] = value); | 180   source.forEach((key, value) => destination[key] = value); | 
| 184 | 181 | 
| 185 /// Decodes a URL-encoded string. Unlike [decodeUriComponent], this includes | 182 /// Decodes a URL-encoded string. Unlike [decodeUriComponent], this includes | 
| 186 /// replacing `+` with ` `. | 183 /// replacing `+` with ` `. | 
| 187 String urlDecode(String encoded) => | 184 String urlDecode(String encoded) => | 
| 188   decodeUriComponent(encoded.replaceAll("+", " ")); | 185   decodeUriComponent(encoded.replaceAll("+", " ")); | 
| OLD | NEW | 
|---|