| Index: packages/path/lib/src/style/windows.dart
|
| diff --git a/packages/path/lib/src/style/windows.dart b/packages/path/lib/src/style/windows.dart
|
| index f38efa52537ddecd65c6c92db1a3f47a179c1581..31114dbb54cc372f7d9621a465ac8258909e8d7c 100644
|
| --- a/packages/path/lib/src/style/windows.dart
|
| +++ b/packages/path/lib/src/style/windows.dart
|
| @@ -2,13 +2,15 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| -library path.style.windows;
|
| -
|
| import '../characters.dart' as chars;
|
| import '../internal_style.dart';
|
| import '../parsed_path.dart';
|
| import '../utils.dart';
|
|
|
| +// `0b100000` can be bitwise-ORed with uppercase ASCII letters to get their
|
| +// lowercase equivalents.
|
| +const _asciiCaseBit = 0x20;
|
| +
|
| /// The style for Windows paths.
|
| class WindowsStyle extends InternalStyle {
|
| WindowsStyle();
|
| @@ -34,7 +36,7 @@ class WindowsStyle extends InternalStyle {
|
| return !isSeparator(path.codeUnitAt(path.length - 1));
|
| }
|
|
|
| - int rootLength(String path) {
|
| + int rootLength(String path, {bool withDrive: false}) {
|
| if (path.isEmpty) return 0;
|
| if (path.codeUnitAt(0) == chars.SLASH) return 1;
|
| if (path.codeUnitAt(0) == chars.BACKSLASH) {
|
| @@ -76,8 +78,13 @@ class WindowsStyle extends InternalStyle {
|
| var path = uri.path;
|
| if (uri.host == '') {
|
| // Drive-letter paths look like "file:///C:/path/to/file". The
|
| - // replaceFirst removes the extra initial slash.
|
| - if (path.startsWith('/')) path = path.replaceFirst("/", "");
|
| + // replaceFirst removes the extra initial slash. Otherwise, leave the
|
| + // slash to match IE's interpretation of "/foo" as a root-relative path.
|
| + if (path.length >= 3 &&
|
| + path.startsWith('/') &&
|
| + isDriveLetter(path, 1)) {
|
| + path = path.replaceFirst("/", "");
|
| + }
|
| } else {
|
| // Network paths look like "file://hostname/path/to/file".
|
| path = '\\\\${uri.host}$path';
|
| @@ -122,4 +129,40 @@ class WindowsStyle extends InternalStyle {
|
| return new Uri(scheme: 'file', pathSegments: parsed.parts);
|
| }
|
| }
|
| +
|
| + bool codeUnitsEqual(int codeUnit1, int codeUnit2) {
|
| + if (codeUnit1 == codeUnit2) return true;
|
| +
|
| + /// Forward slashes and backslashes are equivalent on Windows.
|
| + if (codeUnit1 == chars.SLASH) return codeUnit2 == chars.BACKSLASH;
|
| + if (codeUnit1 == chars.BACKSLASH) return codeUnit2 == chars.SLASH;
|
| +
|
| + // If this check fails, the code units are definitely different. If it
|
| + // succeeds *and* either codeUnit is an ASCII letter, they're equivalent.
|
| + if (codeUnit1 ^ codeUnit2 != _asciiCaseBit) return false;
|
| +
|
| + // Now we just need to verify that one of the code units is an ASCII letter.
|
| + var upperCase1 = codeUnit1 | _asciiCaseBit;
|
| + return upperCase1 >= chars.LOWER_A && upperCase1 <= chars.LOWER_Z;
|
| + }
|
| +
|
| + bool pathsEqual(String path1, String path2) {
|
| + if (identical(path1, path2)) return true;
|
| + if (path1.length != path2.length) return false;
|
| + for (var i = 0; i < path1.length; i++) {
|
| + if (!codeUnitsEqual(path1.codeUnitAt(i), path2.codeUnitAt(i))) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + int canonicalizeCodeUnit(int codeUnit) {
|
| + if (codeUnit == chars.SLASH) return chars.BACKSLASH;
|
| + if (codeUnit < chars.UPPER_A) return codeUnit;
|
| + if (codeUnit > chars.UPPER_Z) return codeUnit;
|
| + return codeUnit | _asciiCaseBit;
|
| + }
|
| +
|
| + String canonicalizePart(String part) => part.toLowerCase();
|
| }
|
|
|