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

Side by Side 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, 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/corelib/uri_path_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 part of dart.core; 5 part of dart.core;
6 6
7 /** 7 /**
8 * A parsed URI, as specified by RFC-3986, http://tools.ietf.org/html/rfc3986. 8 * A parsed URI, as specified by RFC-3986, http://tools.ietf.org/html/rfc3986.
9 */ 9 */
10 class Uri { 10 class Uri {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 75
76 /** 76 /**
77 * Returns the fragment identifier component. 77 * Returns the fragment identifier component.
78 * 78 *
79 * Returns the empty string if there is no fragment identifier 79 * Returns the empty string if there is no fragment identifier
80 * component. 80 * component.
81 */ 81 */
82 final String fragment; 82 final String fragment;
83 83
84 /** 84 /**
85 * Cache the computed return value of [pathSegements].
86 */
87 List<String> _pathSegments;
88
89 /**
90 * Cache the computed return value of [queryParameters].
91 */
92 Map<String, String> _queryParameters;
93
94 /**
85 * Creates a new URI object by parsing a URI string. 95 * Creates a new URI object by parsing a URI string.
86 */ 96 */
87 static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri)); 97 static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri));
88 98
89 Uri._fromMatch(Match m) : 99 Uri._fromMatch(Match m) :
90 this(scheme: _emptyIfNull(m[_COMPONENT_SCHEME]), 100 this(scheme: _emptyIfNull(m[_COMPONENT_SCHEME]),
91 userInfo: _emptyIfNull(m[_COMPONENT_USER_INFO]), 101 userInfo: _emptyIfNull(m[_COMPONENT_USER_INFO]),
92 host: _eitherOf( 102 host: _eitherOf(
93 m[_COMPONENT_HOST], m[_COMPONENT_HOST_IPV6]), 103 m[_COMPONENT_HOST], m[_COMPONENT_HOST_IPV6]),
94 port: _parseIntOrZero(m[_COMPONENT_PORT]), 104 port: _parseIntOrZero(m[_COMPONENT_PORT]),
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 _port = 0; 170 _port = 0;
161 } else { 171 } else {
162 _port = port; 172 _port = port;
163 } 173 }
164 } 174 }
165 175
166 /* 176 /*
167 * Returns the URI path split into its segments. Each of the 177 * Returns the URI path split into its segments. Each of the
168 * segments in the returned list have been decoded. If the path is 178 * segments in the returned list have been decoded. If the path is
169 * empty the empty list will be returned. 179 * empty the empty list will be returned.
180 *
181 * The returned list is immutable and will throw [StateError] on any
182 * calls that would mutate it.
170 */ 183 */
171 List<String> get pathSegments { 184 List<String> get pathSegments {
172 if (path == "") return const<String>[]; 185 if (_pathSegments == null) {
173 return path.split("/").map(Uri.decodeComponent).toList(growable: false); 186 _pathSegments = new _ImmutableList(
187 path == "" ? const<String>[]
188 : path.split("/")
189 .map(Uri.decodeComponent)
190 .toList(growable: false));
191 }
192 return _pathSegments;
174 } 193 }
175 194
176 /* 195 /*
177 * Returns the URI query split into a map according to the rules 196 * Returns the URI query split into a map according to the rules
178 * specified for FORM post in the HTML 4.01 specification. Each key 197 * specified for FORM post in the HTML 4.01 specification. Each key
179 * and value in the returned map have been decoded. If there is no 198 * and value in the returned map have been decoded. If there is no
180 * query the empty map will be returned. 199 * query the empty map will be returned.
200 *
201 * The returned map is immutable and will throw [StateError] on any
202 * calls that would mutate it.
181 */ 203 */
182 Map<String, String> get queryParameters { 204 Map<String, String> get queryParameters {
183 return query.split("&").fold({}, (map, element) { 205 if (_queryParameters == null) {
206 var map;
207 map = query.split("&").fold({}, (map, element) {
184 int index = element.indexOf("="); 208 int index = element.indexOf("=");
185 if (index == -1) { 209 if (index == -1) {
186 if (!element.isEmpty) map[element] = ""; 210 if (!element.isEmpty) map[element] = "";
187 } else if (index != 0) { 211 } else if (index != 0) {
188 var key = element.substring(0, index); 212 var key = element.substring(0, index);
189 var value = element.substring(index + 1); 213 var value = element.substring(index + 1);
190 map[Uri.decodeQueryComponent(key)] = decodeQueryComponent(value); 214 map[Uri.decodeQueryComponent(key)] = decodeQueryComponent(value);
191 } 215 }
192 return map; 216 return map;
193 }); 217 });
218 _queryParameters = new _ImmutableMap(map);
219 }
220 return _queryParameters;
194 } 221 }
195 222
196 static String _makeScheme(String scheme) { 223 static String _makeScheme(String scheme) {
197 bool isSchemeLowerCharacter(int ch) { 224 bool isSchemeLowerCharacter(int ch) {
198 return ch < 128 && 225 return ch < 128 &&
199 ((_schemeLowerTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); 226 ((_schemeLowerTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
200 } 227 }
201 228
202 bool isSchemeCharacter(int ch) { 229 bool isSchemeCharacter(int ch) {
203 return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); 230 return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 0xafff, // 0x30 - 0x3f 1111111111110101 964 0xafff, // 0x30 - 0x3f 1111111111110101
938 // @ABCDEFGHIJKLMNO 965 // @ABCDEFGHIJKLMNO
939 0xffff, // 0x40 - 0x4f 1111111111111111 966 0xffff, // 0x40 - 0x4f 1111111111111111
940 // PQRSTUVWXYZ _ 967 // PQRSTUVWXYZ _
941 0x87ff, // 0x50 - 0x5f 1111111111100001 968 0x87ff, // 0x50 - 0x5f 1111111111100001
942 // abcdefghijklmno 969 // abcdefghijklmno
943 0xfffe, // 0x60 - 0x6f 0111111111111111 970 0xfffe, // 0x60 - 0x6f 0111111111111111
944 // pqrstuvwxyz ~ 971 // pqrstuvwxyz ~
945 0x47ff]; // 0x70 - 0x7f 1111111111100010 972 0x47ff]; // 0x70 - 0x7f 1111111111100010
946 } 973 }
974
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.
975 class _ImmutableList<E> implements List<E> {
976 final List _list;
977 const _ImmutableList(this._list);
978
979 E operator [](int index) => _list[index];
980 void operator []=(int index, E value) {
981 throw new StateError("Immutable list");
982 }
983 int get length => _list.length;
984 void set length(int newLength) => throw new StateError("Immutable list");
985 void add(E value) => throw new StateError("Immutable list");
986 void addAll(Iterable<E> iterable) => throw new StateError("Immutable list");
987 Iterable<E> get reversed => _list.reversed;
988 void sort([int compare(E a, E b)]) => throw new StateError("Immutable list");
989 int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
990 int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
991 void clear() => throw new StateError("Immutable list");
992 void insert(int index, E element) => throw new StateError("Immutable list");
993 void insertAll(int index, Iterable<E> iterable) {
994 throw new StateError("Immutable list");
995 }
996 void setAll(int index, Iterable<E> iterable) {
997 throw new StateError("Immutable list");
998 }
999 bool remove(Object value) => throw new StateError("Immutable list");
1000 E removeAt(int index) => throw new StateError("Immutable list");
1001 E removeLast() => throw new StateError("Immutable list");
1002 void removeWhere(bool test(E element)) {
1003 throw new StateError("Immutable list");
1004 }
1005 void retainWhere(bool test(E element)) {
1006 throw new StateError("Immutable list");
1007 }
1008 List<E> sublist(int start, [int end]) => _list.sublist(start, end);
1009 Iterable<E> getRange(int start, int end) => _list.getRange(start, end);
1010 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
1011 throw new StateError("Immutable list");
1012 }
1013 void removeRange(int start, int end) => throw new StateError("Immutable list") ;
1014 void fillRange(int start, int end, [E fillValue]) {
1015 throw new StateError("Immutable list");
1016 }
1017 void replaceRange(int start, int end, Iterable<E> iterable) {
1018 throw new StateError("Immutable list");
1019 }
1020 Map<int, E> asMap() => _list.asMap();
1021 }
1022
1023 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).
1024 final Map _map;
1025 const _ImmutableMap(this._map);
1026
1027 bool containsValue(V value) => _map.containsValue(value);
1028 bool containsKey(K key) => _map.containsKey(key);
1029 V operator [](K key) => _map[key];
1030 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.
1031 V putIfAbsent(K key, V ifAbsent()) => throw new StateError("Immutable map");
1032 V remove(K key) => throw new StateError("Immutable map");
1033 void clear() => throw new StateError("Immutable map");
1034 void forEach(void f(K key, V value)) => _map.forEach(f);
1035 Iterable<K> get keys => _map.keys;
1036 Iterable<V> get values => _map.values;
1037 int get length => _map.length;
1038 bool get isEmpty => _map.isEmpty;
1039 bool get isNotEmpty => _map.isNotEmpty;
1040 }
OLDNEW
« 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