Index: pkg/path/lib/src/style/windows.dart |
diff --git a/pkg/path/lib/src/style/windows.dart b/pkg/path/lib/src/style/windows.dart |
index be9f45fdfabc8ed88f0f5eea7ccd9eab686f7555..21b4cf3ec395ccb5fa1618774dea471d26f01fd3 100644 |
--- a/pkg/path/lib/src/style/windows.dart |
+++ b/pkg/path/lib/src/style/windows.dart |
@@ -4,8 +4,9 @@ |
library path.style.windows; |
-import '../parsed_path.dart'; |
import '../internal_style.dart'; |
+import '../parsed_path.dart'; |
+import '../utils.dart'; |
/// The style for Windows paths. |
class WindowsStyle extends InternalStyle { |
@@ -13,11 +14,32 @@ class WindowsStyle extends InternalStyle { |
final name = 'windows'; |
final separator = '\\'; |
+ final separators = const ['/', '\\']; |
+ |
+ // Deprecated properties. |
+ |
final separatorPattern = new RegExp(r'[/\\]'); |
final needsSeparatorPattern = new RegExp(r'[^/\\]$'); |
final rootPattern = new RegExp(r'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])'); |
final relativeRootPattern = new RegExp(r"^[/\\](?![/\\])"); |
+ bool needsSeparator(String path) { |
+ if (path.isEmpty) return false; |
+ return !_isSeparator(path.codeUnitAt(path.length - 1)); |
+ } |
+ |
+ String getRoot(String path) { |
+ var root = _getRoot(path); |
+ return root == null ? getRelativeRoot(path) : root; |
+ } |
+ |
+ String getRelativeRoot(String path) { |
+ if (path.isEmpty) return null; |
+ if (!_isSeparator(path.codeUnitAt(0))) return null; |
+ if (path.length > 1 && _isSeparator(path.codeUnitAt(1))) return null; |
+ return path[0]; |
+ } |
+ |
String pathFromUri(Uri uri) { |
if (uri.scheme != '' && uri.scheme != 'file') { |
throw new ArgumentError("Uri $uri must have scheme 'file:'."); |
@@ -66,9 +88,48 @@ class WindowsStyle extends InternalStyle { |
// Get rid of the trailing "\" in "C:\" because the URI constructor will |
// add a separator on its own. |
- parsed.parts.insert(0, parsed.root.replaceAll(separatorPattern, "")); |
+ parsed.parts.insert(0, |
+ parsed.root.replaceAll("/", "").replaceAll("\\", "")); |
return new Uri(scheme: 'file', pathSegments: parsed.parts); |
} |
} |
+ |
+ // A helper method for [getRoot] that doesn't handle relative roots. |
+ String _getRoot(String path) { |
+ if (path.length < 3) return null; |
+ |
+ // We aren't using a RegExp for this because they're slow (issue 19090). If |
+ // we could, we'd match against r"r'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])'". |
+ |
+ // Try roots like "C:\". |
+ if (isAlphabetic(path.codeUnitAt(0))) { |
+ if (path.codeUnitAt(1) != 0x3a) return null; // ":" |
Bob Nystrom
2014/06/02 22:43:05
":".
Or, better, make a little class with constan
nweiz
2014/06/02 23:13:25
Done.
|
+ if (!_isSeparator(path.codeUnitAt(2))) return null; |
+ return path.substring(0, 3); |
+ } |
+ |
+ // Try roots like "\\server\share". |
+ if (!path.startsWith('\\\\')) return null; |
+ |
+ var start = 2; |
+ // The server is one or more non-"\" characters. |
+ while (start < path.length && path.codeUnitAt(start) != 0x5c) { |
+ start++; |
+ } |
+ if (start == 2 || start == path.length) return null; |
+ |
+ // The share is one or more non-"\" characters. |
+ start += 1; |
+ if (path.codeUnitAt(start) == 0x5c) return null; |
+ start += 1; |
+ while (start < path.length && path.codeUnitAt(start) != 0x5c) { |
+ start++; |
+ } |
+ |
+ return path.substring(0, start); |
+ } |
+ |
+ /// Returns whether [char] is a separator ("/" or "\\"). |
+ bool _isSeparator(int char) => char == 0x2f || char == 0x5c; |
} |