From 8be4ffbaac5e88bf4da8e537ffdbecccbb916170 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 3 May 2012 16:13:40 -0700 Subject: Speed up CanonicalizePath() 6.8% (322ms -> 300ms for chrome empty build). --- src/util.cc | 17 +++++++++-------- src/util_test.cc | 26 ++++++++++++++++++++++++++ 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(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(len)); + EXPECT_EQ("file ./file bar/.", string(path)); +} + TEST(StripAnsiEscapeCodes, EscapeAtEnd) { string stripped = StripAnsiEscapeCodes("foo\33"); EXPECT_EQ("foo", stripped); -- cgit v0.12