Commit 8ab3660a authored by Frank Winklmeier's avatar Frank Winklmeier
Browse files

cmOutputConverter: Inline some functions and avoid string re-allocations

Use std::string (with correct initial size) in cmOutputConverter::Shell__GetArgument
instead of ostringstream. This avoids several re-allocations of the
string buffer. In addition, convert some of the private static members into
inline free functions to avoid function calls.
parent ebf0a082
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <set> #include <set>
#include <sstream> #include <string.h>
#include <vector> #include <vector>
#include "cmAlgorithms.h" #include "cmAlgorithms.h"
...@@ -341,12 +341,14 @@ redirection character (for example, ^>, ^<, or ^| ). If you need to ...@@ -341,12 +341,14 @@ redirection character (for example, ^>, ^<, or ^| ). If you need to
use the caret character itself (^), use two in a row (^^). use the caret character itself (^), use two in a row (^^).
*/ */
int cmOutputConverter::Shell__CharIsWhitespace(char c) /* Some helpers to identify character classes */
namespace {
inline int Shell__CharIsWhitespace(char c)
{ {
return ((c == ' ') || (c == '\t')); return ((c == ' ') || (c == '\t'));
} }
int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c) inline int Shell__CharNeedsQuotesOnUnix(char c)
{ {
return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') || return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
(c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') || (c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
...@@ -354,12 +356,18 @@ int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c) ...@@ -354,12 +356,18 @@ int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
(c == '\\')); (c == '\\'));
} }
int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c) inline int Shell__CharNeedsQuotesOnWindows(char c)
{ {
return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') || return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
(c == '>') || (c == '|') || (c == '^')); (c == '>') || (c == '|') || (c == '^'));
} }
inline int Shell__CharIsMakeVariableName(char c)
{
return c && (c == '_' || isalpha((static_cast<int>(c))));
}
}
int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags) int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
{ {
/* On Windows the built-in command shell echo never needs quotes. */ /* On Windows the built-in command shell echo never needs quotes. */
...@@ -386,11 +394,6 @@ int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags) ...@@ -386,11 +394,6 @@ int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
return 0; return 0;
} }
int cmOutputConverter::Shell__CharIsMakeVariableName(char c)
{
return c && (c == '_' || isalpha((static_cast<int>(c))));
}
const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c) const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c)
{ {
while (*c == '$' && *(c + 1) == '(') { while (*c == '$' && *(c + 1) == '(') {
...@@ -481,7 +484,9 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags) ...@@ -481,7 +484,9 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags)
std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
{ {
std::ostringstream out; /* Output will be at least as long as input string. */
std::string out;
out.reserve(strlen(in));
/* String iterator. */ /* String iterator. */
const char* c; const char* c;
...@@ -495,11 +500,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) ...@@ -495,11 +500,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
/* Add the opening quote for this argument. */ /* Add the opening quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) { if (flags & Shell_Flag_WatcomQuote) {
if (flags & Shell_Flag_IsUnix) { if (flags & Shell_Flag_IsUnix) {
out << '"'; out += '"';
} }
out << '\''; out += '\'';
} else { } else {
out << '"'; out += '"';
} }
} }
...@@ -511,7 +516,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) ...@@ -511,7 +516,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
if (skip != c) { if (skip != c) {
/* Copy to the end of the make variable references. */ /* Copy to the end of the make variable references. */
while (c != skip) { while (c != skip) {
out << *c++; out += *c++;
} }
/* The make variable reference eliminates any escaping needed /* The make variable reference eliminates any escaping needed
...@@ -531,7 +536,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) ...@@ -531,7 +536,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
quoted argument. */ quoted argument. */
if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') { if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
/* This character needs a backslash to escape it. */ /* This character needs a backslash to escape it. */
out << '\\'; out += '\\';
} }
} else if (flags & Shell_Flag_EchoWindows) { } else if (flags & Shell_Flag_EchoWindows) {
/* On Windows the built-in command shell echo never needs escaping. */ /* On Windows the built-in command shell echo never needs escaping. */
...@@ -545,11 +550,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) ...@@ -545,11 +550,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
backslashes. */ backslashes. */
while (windows_backslashes > 0) { while (windows_backslashes > 0) {
--windows_backslashes; --windows_backslashes;
out << '\\'; out += '\\';
} }
/* Add the backslash to escape the double-quote. */ /* Add the backslash to escape the double-quote. */
out << '\\'; out += '\\';
} else { } else {
/* We encountered a normal character. This eliminates any /* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. */ escaping needed for preceding backslashes. */
...@@ -562,7 +567,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) ...@@ -562,7 +567,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
if (flags & Shell_Flag_Make) { if (flags & Shell_Flag_Make) {
/* In Makefiles a dollar is written $$. The make tool will /* In Makefiles a dollar is written $$. The make tool will
replace it with just $ before passing it to the shell. */ replace it with just $ before passing it to the shell. */
out << "$$"; out += "$$";
} else if (flags & Shell_Flag_VSIDE) { } else if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a dollar is written "$". If this is written in /* In a VS IDE a dollar is written "$". If this is written in
an un-quoted argument it starts a quoted segment, inserts an un-quoted argument it starts a quoted segment, inserts
...@@ -570,30 +575,30 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) ...@@ -570,30 +575,30 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
argument it ends quoting, inserts the $ and restarts argument it ends quoting, inserts the $ and restarts
quoting. Either way the $ is isolated from surrounding quoting. Either way the $ is isolated from surrounding
text to avoid looking like a variable reference. */ text to avoid looking like a variable reference. */
out << "\"$\""; out += "\"$\"";
} else { } else {
/* Otherwise a dollar is written just $. */ /* Otherwise a dollar is written just $. */
out << '$'; out += '$';
} }
} else if (*c == '#') { } else if (*c == '#') {
if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) { if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
/* In Watcom WMake makefiles a pound is written $#. The make /* In Watcom WMake makefiles a pound is written $#. The make
tool will replace it with just # before passing it to the tool will replace it with just # before passing it to the
shell. */ shell. */
out << "$#"; out += "$#";
} else { } else {
/* Otherwise a pound is written just #. */ /* Otherwise a pound is written just #. */
out << '#'; out += '#';
} }
} else if (*c == '%') { } else if (*c == '%') {
if ((flags & Shell_Flag_VSIDE) || if ((flags & Shell_Flag_VSIDE) ||
((flags & Shell_Flag_Make) && ((flags & Shell_Flag_Make) &&
((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) { ((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
/* In the VS IDE, NMake, or MinGW make a percent is written %%. */ /* In the VS IDE, NMake, or MinGW make a percent is written %%. */
out << "%%"; out += "%%";
} else { } else {
/* Otherwise a percent is written just %. */ /* Otherwise a percent is written just %. */
out << '%'; out += '%';
} }
} else if (*c == ';') { } else if (*c == ';') {
if (flags & Shell_Flag_VSIDE) { if (flags & Shell_Flag_VSIDE) {
...@@ -602,14 +607,14 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) ...@@ -602,14 +607,14 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
inserts the ; and ends the segment. If it is written in a inserts the ; and ends the segment. If it is written in a
quoted argument it ends quoting, inserts the ; and restarts quoted argument it ends quoting, inserts the ; and restarts
quoting. Either way the ; is isolated. */ quoting. Either way the ; is isolated. */
out << "\";\""; out += "\";\"";
} else { } else {
/* Otherwise a semicolon is written just ;. */ /* Otherwise a semicolon is written just ;. */
out << ';'; out += ';';
} }
} else { } else {
/* Store this character. */ /* Store this character. */
out << *c; out += *c;
} }
} }
...@@ -617,19 +622,19 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) ...@@ -617,19 +622,19 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
/* Add enough backslashes to escape any trailing ones. */ /* Add enough backslashes to escape any trailing ones. */
while (windows_backslashes > 0) { while (windows_backslashes > 0) {
--windows_backslashes; --windows_backslashes;
out << '\\'; out += '\\';
} }
/* Add the closing quote for this argument. */ /* Add the closing quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) { if (flags & Shell_Flag_WatcomQuote) {
out << '\''; out += '\'';
if (flags & Shell_Flag_IsUnix) { if (flags & Shell_Flag_IsUnix) {
out << '"'; out += '"';
} }
} else { } else {
out << '"'; out += '"';
} }
} }
return out.str(); return out;
} }
...@@ -117,11 +117,7 @@ public: ...@@ -117,11 +117,7 @@ public:
private: private:
cmState* GetState() const; cmState* GetState() const;
static int Shell__CharIsWhitespace(char c);
static int Shell__CharNeedsQuotesOnUnix(char c);
static int Shell__CharNeedsQuotesOnWindows(char c);
static int Shell__CharNeedsQuotes(char c, int flags); static int Shell__CharNeedsQuotes(char c, int flags);
static int Shell__CharIsMakeVariableName(char c);
static const char* Shell__SkipMakeVariables(const char* c); static const char* Shell__SkipMakeVariables(const char* c);
static int Shell__ArgumentNeedsQuotes(const char* in, int flags); static int Shell__ArgumentNeedsQuotes(const char* in, int flags);
static std::string Shell__GetArgument(const char* in, int flags); static std::string Shell__GetArgument(const char* in, int flags);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment