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 |