From 45c245645d910bb37c4fc8b2ab02370e6787269f Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 22 Mar 2023 14:50:45 +0100 Subject: [PATCH] few optimizations building string vector with arguments - avoid unneeded copying (don't gather remaining string) - don't build args byte by byte Signed-off-by: Sergey G. Brester Reviewed-by: Tino Reichardt --- CPP/Common/CommandLineParser.cpp | 64 ++++++++++++++++++++------------ CPP/Common/MyString.cpp | 10 +++++ CPP/Common/MyString.h | 1 + 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp index 51802a08..d07f0f1c 100644 --- a/CPP/Common/CommandLineParser.cpp +++ b/CPP/Common/CommandLineParser.cpp @@ -6,21 +6,23 @@ namespace NCommandLineParser { -bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) +static const wchar_t * _SplitCommandLine(const wchar_t* s, UString &dest) { unsigned qcount = 0, bcount = 0; - wchar_t c; const wchar_t *s = src.Ptr(); + wchar_t c; const wchar_t *f, *b; - dest1.Empty(); + dest.Empty(); + + // skip spaces: + while (isblank(*s)) { s++; }; + b = f = s; while ((c = *s++) != 0) { switch (c) { case L'\\': - // a backslash - firstly add it as a regular char, - // we'll delete escaped later (if followed by quote): - dest1 += c; + // a backslash - count them up to quote-char or regular char bcount++; break; case L'"': @@ -28,8 +30,8 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) if (!(bcount & 1)) { // preceded by an even number of '\', this is half that - // number of '\' (delete bcount/2 chars): - dest1.DeleteFrom(dest1.Len() - bcount/2); + // number of '\': + dest.AddFrom(f, (unsigned)(s - f - bcount/2 - 1)); f = s; // count quote chars: qcount++; } @@ -37,8 +39,8 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { // preceded by an odd number of '\', this is half that // number of '\' followed by an escaped '"': - dest1.DeleteFrom(dest1.Len() - bcount/2 - 1); - dest1 += L'"'; + dest.AddFrom(f, (unsigned)(s - f - bcount/2 - 2)); f = s; + dest += L'"'; } bcount = 0; // now count the number of consecutive quotes (inclusive @@ -48,10 +50,11 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) s++; if (++qcount == 3) { - dest1 += L'"'; - qcount = 0; + dest += L'"'; + qcount = 1; } } + f = s; if (qcount == 2) qcount = 0; break; @@ -61,37 +64,50 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) if (!qcount) { // end of argument: - bcount = 0; + dest.AddFrom(f, (unsigned)(s - f - 1)); f = s; // skip to the next one: while (isblank(*s)) { s++; }; + bcount = 0; goto done; } // no break - a space as regular char: default: - // a regular character - dest1 += c; + // a regular character, reset backslash counter bcount = 0; } } s--; // back to NTS-zero char + dest.AddFrom(f, (unsigned)(s - f)); done: - dest2 = s; - return (dest1.Len() || src[0]); + // remaining part if argument was found, otherwise NULL: + return (dest.Len() || *b) ? s : NULL; +} + +bool SplitCommandLine(const UString& src, UString& dest1, UString& dest2) +{ + const wchar_t *s = src.Ptr(); + s = _SplitCommandLine(s, dest1); + if (s) { + dest2 = s; + return true; + } else { + dest2.Empty(); + return false; + } } -void SplitCommandLine(const UString &s, UStringVector &parts) +void SplitCommandLine(const UString &src, UStringVector &parts) { - UString sTemp (s); - sTemp.Trim(); + const wchar_t *s = src.Ptr(); parts.Clear(); for (;;) { - UString s1, s2; - if (SplitCommandLine(sTemp, s1, s2)) + UString s1; + s = _SplitCommandLine(s, s1); + if (s) parts.Add(s1); - if (s2.IsEmpty()) + if (!s || !*s) break; - sTemp = s2; } } diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index bf1638eb..599550fe 100644 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp @@ -1206,6 +1206,16 @@ UString &UString::operator=(const UString &s) return *this; } +void UString::AddFrom(const wchar_t *s, unsigned len) // no check +{ + if (len) { + Grow(len); + wmemcpy(_chars + _len, s, len); + _len += len; + _chars[_len] = 0; + } +} + void UString::SetFrom(const wchar_t *s, unsigned len) // no check { if (len > _limit) diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index c777c8c3..05a25d45 100644 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -628,6 +628,7 @@ class UString UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); } UString &operator=(const wchar_t *s); UString &operator=(const UString &s); + void AddFrom(const wchar_t *s, unsigned len); // no check void SetFrom(const wchar_t *s, unsigned len); // no check void SetFromBstr(LPCOLESTR s); UString &operator=(const char *s);