Chromium Code Reviews| 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; |
| } |