summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2012-05-03 23:13:40 (GMT)
committerNico Weber <thakis@chromium.org>2012-05-04 01:12:21 (GMT)
commit8be4ffbaac5e88bf4da8e537ffdbecccbb916170 (patch)
treee49eebaa873602e046272b9209f1a8d7d83b492b
parent3253f66fd14fce3278f71b29a22d61bf1b4aa9f5 (diff)
downloadNinja-8be4ffbaac5e88bf4da8e537ffdbecccbb916170.zip
Ninja-8be4ffbaac5e88bf4da8e537ffdbecccbb916170.tar.gz
Ninja-8be4ffbaac5e88bf4da8e537ffdbecccbb916170.tar.bz2
Speed up CanonicalizePath() 6.8% (322ms -> 300ms for chrome empty build).
-rw-r--r--src/util.cc17
-rw-r--r--src/util_test.cc26
2 files changed, 35 insertions, 8 deletions
diff --git a/src/util.cc b/src/util.cc
index 73f13f8..6bafc91 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -113,29 +113,30 @@ bool CanonicalizePath(char* path, int* len, string* err) {
}
while (src < end) {
- const char* sep = (const char*)memchr(src, '/', end - src);
- if (sep == NULL)
- sep = end;
-
if (*src == '.') {
- if (sep - src == 1) {
+ if (src[1] == '/' || src + 1 == end) {
// '.' component; eliminate.
src += 2;
continue;
- } else if (sep - src == 2 && src[1] == '.') {
+ } else if (src[1] == '.' && (src[2] == '/' || src + 2 == end)) {
// '..' component. Back up if possible.
if (component_count > 0) {
dst = components[component_count - 1];
src += 3;
--component_count;
} else {
- while (src <= sep)
- *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
}
continue;
}
}
+ const char* sep = (const char*)memchr(src, '/', end - src);
+ if (sep == NULL)
+ sep = end;
+
if (sep > src) {
if (component_count == kMaxPathComponents)
Fatal("path has too many components");
diff --git a/src/util_test.cc b/src/util_test.cc
index f7ccf00..23d4b83 100644
--- a/src/util_test.cc
+++ b/src/util_test.cc
@@ -58,6 +58,14 @@ TEST(CanonicalizePath, PathSamples) {
path = "foo/./.";
EXPECT_TRUE(CanonicalizePath(&path, &err));
EXPECT_EQ("foo", path);
+
+ path = "foo/bar/..";
+ EXPECT_TRUE(CanonicalizePath(&path, &err));
+ EXPECT_EQ("foo", path);
+
+ path = "foo/.hidden_bar";
+ EXPECT_TRUE(CanonicalizePath(&path, &err));
+ EXPECT_EQ("foo/.hidden_bar", path);
}
TEST(CanonicalizePath, EmptyResult) {
@@ -94,6 +102,24 @@ TEST(CanonicalizePath, AbsolutePath) {
EXPECT_EQ("/usr/include/stdio.h", path);
}
+TEST(CanonicalizePath, NotNullTerminated) {
+ string path;
+ string err;
+ int len;
+
+ path = "foo/. bar/.";
+ len = strlen("foo/."); // Canonicalize only the part before the space.
+ EXPECT_TRUE(CanonicalizePath(&path[0], &len, &err));
+ EXPECT_EQ(strlen("foo"), static_cast<size_t>(len));
+ EXPECT_EQ("foo/. bar/.", string(path));
+
+ path = "foo/../file bar/.";
+ len = strlen("foo/../file");
+ EXPECT_TRUE(CanonicalizePath(&path[0], &len, &err));
+ EXPECT_EQ(strlen("file"), static_cast<size_t>(len));
+ EXPECT_EQ("file ./file bar/.", string(path));
+}
+
TEST(StripAnsiEscapeCodes, EscapeAtEnd) {
string stripped = StripAnsiEscapeCodes("foo\33");
EXPECT_EQ("foo", stripped);