Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(301)

Unified Diff: sdk/lib/core/uri.dart

Issue 16108003: Avoid parsing path and query string more than once (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/corelib/uri_path_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
+}
« no previous file with comments | « no previous file | tests/corelib/uri_path_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698