diff options
-rw-r--r-- | strutil.cc | 27 | ||||
-rw-r--r-- | strutil_test.cc | 14 |
2 files changed, 41 insertions, 0 deletions
@@ -523,6 +523,32 @@ string EchoEscape(const string str) { } void EscapeShell(string* s) { +#ifdef __SSE4_2__ + static const char ranges[] = "\0\0\n\n\"\"$$\\\\``"; + size_t prev = 0; + size_t i = SkipUntilSSE42(s->c_str(), s->size(), ranges, 12); + if (i == s->size()) + return; + + string r; + for (; i < s->size();) { + StringPiece(*s).substr(prev, i - prev).AppendToString(&r); + char c = (*s)[i]; + r += '\\'; + if (c == '$') { + if ((*s)[i+1] == '$') { + r += '$'; + i++; + } + } + r += c; + i++; + prev = i; + i += SkipUntilSSE42(s->c_str() + i, s->size() - i, ranges, 12); + } + StringPiece(*s).substr(prev).AppendToString(&r); + s->swap(r); +#else if (s->find_first_of("$`\\\"") == string::npos) return; string r; @@ -550,4 +576,5 @@ void EscapeShell(string* s) { } } s->swap(r); +#endif } diff --git a/strutil_test.cc b/strutil_test.cc index 069dc4d..ce7e012 100644 --- a/strutil_test.cc +++ b/strutil_test.cc @@ -116,6 +116,19 @@ void TestNormalizePath() { ASSERT_EQ(NormalizePath("./../../a/b"), "../../a/b"); } +string EscapeShell(string s) { + ::EscapeShell(&s); + return s; +} + +void TestEscapeShell() { + ASSERT_EQ(EscapeShell(""), ""); + ASSERT_EQ(EscapeShell("foo"), "foo"); + ASSERT_EQ(EscapeShell("foo$`\\baz\"bar"), "foo\\$\\`\\\\baz\\\"bar"); + ASSERT_EQ(EscapeShell("$$"), "\\$$"); + ASSERT_EQ(EscapeShell("$$$"), "\\$$\\$"); +} + } // namespace int main() { @@ -126,5 +139,6 @@ int main() { TestNoLineBreak(); TestHasWord(); TestNormalizePath(); + TestEscapeShell(); assert(!g_failed); } |