Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Unified Diff: lib/src/context.dart

Issue 1455003002: Optimize absolute() and normalize(). (Closed) Base URL: git@github.com:dart-lang/path@master
Patch Set: Code review changes Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « benchmark/benchmark.dart ('k') | pubspec.yaml » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/context.dart
diff --git a/lib/src/context.dart b/lib/src/context.dart
index db055a19b1a6ed54767ca40974d2aff6f8b93cb0..44bdde994ea46daec0052052e8aaea4bc176be2e 100644
--- a/lib/src/context.dart
+++ b/lib/src/context.dart
@@ -4,6 +4,7 @@
library path.context;
+import 'characters.dart' as chars;
import 'internal_style.dart';
import 'style.dart';
import 'parsed_path.dart';
@@ -73,6 +74,15 @@ class Context {
/// If [current] isn't absolute, this won't return an absolute path.
String absolute(String part1, [String part2, String part3, String part4,
String part5, String part6, String part7]) {
+ _validateArgList(
+ "absolute", [part1, part2, part3, part4, part5, part6, part7]);
+
+ // If there's a single absolute path, just return it. This is a lot faster
+ // for the common case of `p.absolute(path)`.
+ if (part2 == null && isAbsolute(part1) && !isRootRelative(part1)) {
+ return part1;
+ }
+
return join(current, part1, part2, part3, part4, part5, part6, part7);
}
@@ -295,11 +305,79 @@ class Context {
///
/// context.normalize('path/./to/..//file.text'); // -> 'path/file.txt'
String normalize(String path) {
+ if (!_needsNormalization(path)) return path;
+
var parsed = _parse(path);
parsed.normalize();
return parsed.toString();
}
+ /// Returns whether [path] needs to be normalized.
+ bool _needsNormalization(String path) {
+ var start = 0;
+ var codeUnits = path.codeUnits;
+ var previousPrevious;
+ var previous;
+
+ // Skip past the root before we start looking for snippets that need
+ // normalization. We want to normalize "//", but not when it's part of
+ // "http://".
+ var root = style.rootLength(path);
+ if (root != 0) {
+ start = root;
+ previous = chars.SLASH;
+
+ // On Windows, the root still needs to be normalized if it contains a
+ // forward slash.
+ if (style == Style.windows) {
+ for (var i = 0; i < root; i++) {
+ if (codeUnits[i] == chars.SLASH) return true;
+ }
+ }
+ }
+
+ for (var i = start; i < codeUnits.length; i++) {
+ var codeUnit = codeUnits[i];
+ if (style.isSeparator(codeUnit)) {
+ // Forward slashes in Windows paths are normalized to backslashes.
+ if (style == Style.windows && codeUnit == chars.SLASH) return true;
+
+ // Multiple separators are normalized to single separators.
+ if (previous != null && style.isSeparator(previous)) return true;
+
+ // Single dots and double dots are normalized to directory traversals.
+ //
+ // This can return false positives for ".../", but that's unlikely
+ // enough that it's probably not going to cause performance issues.
+ if (previous == chars.PERIOD &&
+ (previousPrevious == null ||
+ previousPrevious == chars.PERIOD ||
+ style.isSeparator(previousPrevious))) {
+ return true;
+ }
+ }
+
+ previousPrevious = previous;
+ previous = codeUnit;
+ }
+
+ // Empty paths are normalized to ".".
+ if (previous == null) return true;
+
+ // Trailing separators are removed.
+ if (style.isSeparator(previous)) return true;
+
+ // Single dots and double dots are normalized to directory traversals.
+ if (previous == chars.PERIOD &&
+ (previousPrevious == null ||
+ previousPrevious == chars.SLASH ||
+ previousPrevious == chars.PERIOD)) {
+ return true;
+ }
+
+ return false;
+ }
+
/// Attempts to convert [path] to an equivalent relative path relative to
/// [root].
///
« no previous file with comments | « benchmark/benchmark.dart ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698