Chromium Code Reviews| Index: sdk/lib/core/uri.dart |
| diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart |
| index c8277e7fc6b4b035ad7624e195049d0817a80740..f536c97936be5e08ed8513f206f225223f7a508c 100644 |
| --- a/sdk/lib/core/uri.dart |
| +++ b/sdk/lib/core/uri.dart |
| @@ -82,6 +82,16 @@ class Uri { |
| final String fragment; |
| /** |
| + * Cache the computed return value of [pathSegements]. |
| + */ |
| + List<String> _pathSegments; |
| + |
| + /** |
| + * Cache the computed return value of [queryParameters]. |
| + */ |
| + Map<String, String> _queryParameters; |
| + |
| + /** |
| * Creates a new URI object by parsing a URI string. |
| */ |
| static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri)); |
| @@ -167,10 +177,19 @@ class Uri { |
| * Returns the URI path split into its segments. Each of the |
| * segments in the returned list have been decoded. If the path is |
| * empty the empty list will be returned. |
| + * |
| + * The returned list is immutable and will throw [StateError] on any |
| + * calls that would mutate it. |
| */ |
| List<String> get pathSegments { |
| - if (path == "") return const<String>[]; |
| - return path.split("/").map(Uri.decodeComponent).toList(growable: false); |
| + if (_pathSegments == null) { |
| + _pathSegments = new _ImmutableList( |
| + path == "" ? const<String>[] |
| + : path.split("/") |
| + .map(Uri.decodeComponent) |
| + .toList(growable: false)); |
| + } |
| + return _pathSegments; |
| } |
| /* |
| @@ -178,9 +197,14 @@ class Uri { |
| * specified for FORM post in the HTML 4.01 specification. Each key |
| * and value in the returned map have been decoded. If there is no |
| * query the empty map will be returned. |
| + * |
| + * The returned map is immutable and will throw [StateError] on any |
| + * calls that would mutate it. |
| */ |
| Map<String, String> get queryParameters { |
| - return query.split("&").fold({}, (map, element) { |
| + if (_queryParameters == null) { |
| + var map; |
| + map = query.split("&").fold({}, (map, element) { |
| int index = element.indexOf("="); |
| if (index == -1) { |
| if (!element.isEmpty) map[element] = ""; |
| @@ -190,7 +214,10 @@ class Uri { |
| map[Uri.decodeQueryComponent(key)] = decodeQueryComponent(value); |
| } |
| return map; |
| - }); |
| + }); |
| + _queryParameters = new _ImmutableMap(map); |
| + } |
| + return _queryParameters; |
| } |
| static String _makeScheme(String scheme) { |
| @@ -944,3 +971,70 @@ class Uri { |
| // pqrstuvwxyz ~ |
| 0x47ff]; // 0x70 - 0x7f 1111111111100010 |
| } |
| + |
|
Lasse Reichstein Nielsen
2013/06/03 07:54:27
dart:collections has an UnmodifiableListView you c
Søren Gjesse
2013/06/03 09:18:15
Thanks - I missed that.
|
| +class _ImmutableList<E> implements List<E> { |
| + final List _list; |
| + const _ImmutableList(this._list); |
| + |
| + E operator [](int index) => _list[index]; |
| + void operator []=(int index, E value) { |
| + throw new StateError("Immutable list"); |
| + } |
| + int get length => _list.length; |
| + void set length(int newLength) => throw new StateError("Immutable list"); |
| + void add(E value) => throw new StateError("Immutable list"); |
| + void addAll(Iterable<E> iterable) => throw new StateError("Immutable list"); |
| + Iterable<E> get reversed => _list.reversed; |
| + void sort([int compare(E a, E b)]) => throw new StateError("Immutable list"); |
| + int indexOf(E element, [int start = 0]) => _list.indexOf(element, start); |
| + int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start); |
| + void clear() => throw new StateError("Immutable list"); |
| + void insert(int index, E element) => throw new StateError("Immutable list"); |
| + void insertAll(int index, Iterable<E> iterable) { |
| + throw new StateError("Immutable list"); |
| + } |
| + void setAll(int index, Iterable<E> iterable) { |
| + throw new StateError("Immutable list"); |
| + } |
| + bool remove(Object value) => throw new StateError("Immutable list"); |
| + E removeAt(int index) => throw new StateError("Immutable list"); |
| + E removeLast() => throw new StateError("Immutable list"); |
| + void removeWhere(bool test(E element)) { |
| + throw new StateError("Immutable list"); |
| + } |
| + void retainWhere(bool test(E element)) { |
| + throw new StateError("Immutable list"); |
| + } |
| + List<E> sublist(int start, [int end]) => _list.sublist(start, end); |
| + Iterable<E> getRange(int start, int end) => _list.getRange(start, end); |
| + void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { |
| + throw new StateError("Immutable list"); |
| + } |
| + void removeRange(int start, int end) => throw new StateError("Immutable list"); |
| + void fillRange(int start, int end, [E fillValue]) { |
| + throw new StateError("Immutable list"); |
| + } |
| + void replaceRange(int start, int end, Iterable<E> iterable) { |
| + throw new StateError("Immutable list"); |
| + } |
| + Map<int, E> asMap() => _list.asMap(); |
| +} |
| + |
| +class _ImmutableMap<K, V> implements Map<K, V> { |
|
Lasse Reichstein Nielsen
2013/06/03 07:54:27
No UnmodifiableMapView, sorry :(
We probably shoul
Søren Gjesse
2013/06/03 09:18:15
OK, keeping this (renaming to _UnmodifiableMap).
|
| + final Map _map; |
| + const _ImmutableMap(this._map); |
| + |
| + bool containsValue(V value) => _map.containsValue(value); |
| + bool containsKey(K key) => _map.containsKey(key); |
| + V operator [](K key) => _map[key]; |
| + void operator []=(K key, V value) => throw new StateError("Immutable map"); |
|
Lasse Reichstein Nielsen
2013/06/03 07:54:27
UnsupportedError
Søren Gjesse
2013/06/03 09:18:15
Done.
|
| + V putIfAbsent(K key, V ifAbsent()) => throw new StateError("Immutable map"); |
| + V remove(K key) => throw new StateError("Immutable map"); |
| + void clear() => throw new StateError("Immutable map"); |
| + void forEach(void f(K key, V value)) => _map.forEach(f); |
| + Iterable<K> get keys => _map.keys; |
| + Iterable<V> get values => _map.values; |
| + int get length => _map.length; |
| + bool get isEmpty => _map.isEmpty; |
| + bool get isNotEmpty => _map.isNotEmpty; |
| +} |