История изменений
Исправление wandrien, (текущая версия) :
Подниму тред. Свежих баек у меня снова нет, поэтому поделюсь еще парой кусков кода, которые я сегодня наговнокодил.
Первая - аналог PHP-шной escapeshellarg()
на крестах:
std::string escapeshellarg(const std::string &str)
{
std::string result;
if (str.size() == 0) {
result = "\'\'";
return result;
}
int estimated_size = 0;
for(const char& c : str) {
if (c == '\'')
estimated_size += 4;
else
estimated_size += 1;
}
result.reserve(estimated_size);
bool inside_quotes = false;
for(const char& c : str) {
if (c == '\'') {
if (inside_quotes) {
result += '\'';
inside_quotes = false;
}
result += "\\\'";
} else {
if (!inside_quotes) {
result += '\'';
inside_quotes = true;
}
result += c;
}
}
if (inside_quotes) {
result += '\'';
inside_quotes = false;
}
return result;
}
#ifdef INSIDE_CATCH
struct TestStringPair {
const char * str;
const char * result;
};
TEST_CASE( "escapeshellarg") {
auto testData = GENERATE(
TestStringPair {"", "\'\'"},
TestStringPair {"\'", "\\\'"},
TestStringPair {" ", "\' \'"},
TestStringPair {"\"\"", "\'\"\"\'"},
TestStringPair {"\'a", "\\\'\'a\'"},
TestStringPair {"a\'", "\'a\'\\\'"},
TestStringPair {"a b c \'\'\' 1 2 3", "\'a b c \'\\\'\\\'\\\'\' 1 2 3\'"},
TestStringPair {"/abc/d/", "\'/abc/d/\'"}
);
REQUIRE(escapeshellarg(testData.str) == std::string(testData.result));
}
#endif
Не нашел готовой стандартной функции на это. Может плохо искал.
А вторая – ради чего была написана первая. Поставляет в указанную строку указанные переменные.
std::string substitute_prefixed_variables(const std::string &str, const std::map<char, std::string> &variables, char prefix, bool escape_for_shell)
{
std::string result;
result.reserve(str.size() * 2);
bool in_prefix = false;
for(const char& c : str) {
if (in_prefix) {
if (c == prefix) {
result += c;
} else {
auto search = variables.find(c);
if (search != variables.end()) {
if (escape_for_shell) {
result += escapeshellarg(search->second);
} else {
result += search->second;
}
}
}
in_prefix = false;
} else {
if (c == prefix) {
in_prefix = true;
} else {
result += c;
}
}
}
return result;
}
#ifdef INSIDE_CATCH
struct TestData {
const char * str;
bool escape_for_shell;
const char * result;
};
TEST_CASE( "substitute_prefixed_variables") {
auto testData = GENERATE(
TestData {"/abc/d%% %1 %2 %3", false, "/abc/d% file file \' "},
TestData {"/abc/d%% %1 %2 %3", true, "/abc/d% \'file\' \'file \'\\\' \'\'"},
TestData {"", true, ""},
TestData {"%1", true, "\'file\'"},
TestData {"%%", true, "%"}
);
std::map<char, std::string> variables{
{ '1', "file"},
{ '2', "file \'"},
{ '3', ""},
};
REQUIRE(
substitute_prefixed_variables(testData.str, variables, '%', testData.escape_for_shell)
==
std::string(testData.result)
);
}
#endif
Критикуйте. =)
Исправление wandrien, :
Подниму тред. Свежих баек у меня снова нет, поэтому поделюсь еще парой кусков кода, которы я сегодня наговнокодил.
Первая - аналог PHP-шной escapeshellarg()
на крестах:
std::string escapeshellarg(const std::string &str)
{
std::string result;
if (str.size() == 0) {
result = "\'\'";
return result;
}
int estimated_size = 0;
for(const char& c : str) {
if (c == '\'')
estimated_size += 4;
else
estimated_size += 1;
}
result.reserve(estimated_size);
bool inside_quotes = false;
for(const char& c : str) {
if (c == '\'') {
if (inside_quotes) {
result += '\'';
inside_quotes = false;
}
result += "\\\'";
} else {
if (!inside_quotes) {
result += '\'';
inside_quotes = true;
}
result += c;
}
}
if (inside_quotes) {
result += '\'';
inside_quotes = false;
}
return result;
}
#ifdef INSIDE_CATCH
struct TestStringPair {
const char * str;
const char * result;
};
TEST_CASE( "escapeshellarg") {
auto testData = GENERATE(
TestStringPair {"", "\'\'"},
TestStringPair {"\'", "\\\'"},
TestStringPair {" ", "\' \'"},
TestStringPair {"\"\"", "\'\"\"\'"},
TestStringPair {"\'a", "\\\'\'a\'"},
TestStringPair {"a\'", "\'a\'\\\'"},
TestStringPair {"a b c \'\'\' 1 2 3", "\'a b c \'\\\'\\\'\\\'\' 1 2 3\'"},
TestStringPair {"/abc/d/", "\'/abc/d/\'"}
);
REQUIRE(escapeshellarg(testData.str) == std::string(testData.result));
}
#endif
Не нашел готовой стандартной функции на это. Может плохо искал.
А вторая – ради чего была написана первая. Поставляет в указанную строку указанные переменные.
std::string substitute_prefixed_variables(const std::string &str, const std::map<char, std::string> &variables, char prefix, bool escape_for_shell)
{
std::string result;
result.reserve(str.size() * 2);
bool in_prefix = false;
for(const char& c : str) {
if (in_prefix) {
if (c == prefix) {
result += c;
} else {
auto search = variables.find(c);
if (search != variables.end()) {
if (escape_for_shell) {
result += escapeshellarg(search->second);
} else {
result += search->second;
}
}
}
in_prefix = false;
} else {
if (c == prefix) {
in_prefix = true;
} else {
result += c;
}
}
}
return result;
}
#ifdef INSIDE_CATCH
struct TestData {
const char * str;
bool escape_for_shell;
const char * result;
};
TEST_CASE( "substitute_prefixed_variables") {
auto testData = GENERATE(
TestData {"/abc/d%% %1 %2 %3", false, "/abc/d% file file \' "},
TestData {"/abc/d%% %1 %2 %3", true, "/abc/d% \'file\' \'file \'\\\' \'\'"},
TestData {"", true, ""},
TestData {"%1", true, "\'file\'"},
TestData {"%%", true, "%"}
);
std::map<char, std::string> variables{
{ '1', "file"},
{ '2', "file \'"},
{ '3', ""},
};
REQUIRE(
substitute_prefixed_variables(testData.str, variables, '%', testData.escape_for_shell)
==
std::string(testData.result)
);
}
#endif
Критикуйте. =)
Исходная версия wandrien, :
Подниму тред. Свежих баек у меня снова нет, поэтому моделюсь еще парой кусков кода, которы я сегодня наговнокодил.
Первая - аналог PHP-шной escapeshellarg()
на крестах:
std::string escapeshellarg(const std::string &str)
{
std::string result;
if (str.size() == 0) {
result = "\'\'";
return result;
}
int estimated_size = 0;
for(const char& c : str) {
if (c == '\'')
estimated_size += 4;
else
estimated_size += 1;
}
result.reserve(estimated_size);
bool inside_quotes = false;
for(const char& c : str) {
if (c == '\'') {
if (inside_quotes) {
result += '\'';
inside_quotes = false;
}
result += "\\\'";
} else {
if (!inside_quotes) {
result += '\'';
inside_quotes = true;
}
result += c;
}
}
if (inside_quotes) {
result += '\'';
inside_quotes = false;
}
return result;
}
#ifdef INSIDE_CATCH
struct TestStringPair {
const char * str;
const char * result;
};
TEST_CASE( "escapeshellarg") {
auto testData = GENERATE(
TestStringPair {"", "\'\'"},
TestStringPair {"\'", "\\\'"},
TestStringPair {" ", "\' \'"},
TestStringPair {"\"\"", "\'\"\"\'"},
TestStringPair {"\'a", "\\\'\'a\'"},
TestStringPair {"a\'", "\'a\'\\\'"},
TestStringPair {"a b c \'\'\' 1 2 3", "\'a b c \'\\\'\\\'\\\'\' 1 2 3\'"},
TestStringPair {"/abc/d/", "\'/abc/d/\'"}
);
REQUIRE(escapeshellarg(testData.str) == std::string(testData.result));
}
#endif
Не нашел готовой стандартной функции на это. Может плохо искал.
А вторая – ради чего была написана первая. Поставляет в указанную строку указанные переменные.
std::string substitute_prefixed_variables(const std::string &str, const std::map<char, std::string> &variables, char prefix, bool escape_for_shell)
{
std::string result;
result.reserve(str.size() * 2);
bool in_prefix = false;
for(const char& c : str) {
if (in_prefix) {
if (c == prefix) {
result += c;
} else {
auto search = variables.find(c);
if (search != variables.end()) {
if (escape_for_shell) {
result += escapeshellarg(search->second);
} else {
result += search->second;
}
}
}
in_prefix = false;
} else {
if (c == prefix) {
in_prefix = true;
} else {
result += c;
}
}
}
return result;
}
#ifdef INSIDE_CATCH
struct TestData {
const char * str;
bool escape_for_shell;
const char * result;
};
TEST_CASE( "substitute_prefixed_variables") {
auto testData = GENERATE(
TestData {"/abc/d%% %1 %2 %3", false, "/abc/d% file file \' "},
TestData {"/abc/d%% %1 %2 %3", true, "/abc/d% \'file\' \'file \'\\\' \'\'"},
TestData {"", true, ""},
TestData {"%1", true, "\'file\'"},
TestData {"%%", true, "%"}
);
std::map<char, std::string> variables{
{ '1', "file"},
{ '2', "file \'"},
{ '3', ""},
};
REQUIRE(
substitute_prefixed_variables(testData.str, variables, '%', testData.escape_for_shell)
==
std::string(testData.result)
);
}
#endif
Критикуйте. =)