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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |