| 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..2965f1eee9230ae930e02acd11f42f36b2f82b02 100644
|
| --- a/pkg/path/lib/src/style/windows.dart
|
| +++ b/pkg/path/lib/src/style/windows.dart
|
| @@ -4,8 +4,10 @@
|
|
|
| library path.style.windows;
|
|
|
| -import '../parsed_path.dart';
|
| +import '../characters.dart' as chars;
|
| import '../internal_style.dart';
|
| +import '../parsed_path.dart';
|
| +import '../utils.dart';
|
|
|
| /// The style for Windows paths.
|
| class WindowsStyle extends InternalStyle {
|
| @@ -13,11 +15,37 @@ 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 containsSeparator(String path) => path.contains('/');
|
| +
|
| + bool isSeparator(int codeUnit) =>
|
| + codeUnit == chars.SLASH || codeUnit == chars.BACKSLASH;
|
| +
|
| + 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 +94,45 @@ 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'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])'.
|
| +
|
| + // Try roots like "C:\".
|
| + if (isAlphabetic(path.codeUnitAt(0))) {
|
| + if (path.codeUnitAt(1) != chars.COLON) return null;
|
| + 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) != chars.BACKSLASH) {
|
| + start++;
|
| + }
|
| + if (start == 2 || start == path.length) return null;
|
| +
|
| + // The share is one or more non-"\" characters.
|
| + start += 1;
|
| + if (path.codeUnitAt(start) == chars.BACKSLASH) return null;
|
| + start += 1;
|
| + while (start < path.length && path.codeUnitAt(start) != chars.BACKSLASH) {
|
| + start++;
|
| + }
|
| +
|
| + return path.substring(0, start);
|
| + }
|
| }
|
|
|