Skip to content

Commit

Permalink
Enable the use of embedded quotes
Browse files Browse the repository at this point in the history
Issue: ECFLOW-1883
  • Loading branch information
marcosbento committed Jul 10, 2023
1 parent a9c96e1 commit 671cf13
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 12 deletions.
30 changes: 26 additions & 4 deletions ACore/src/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,17 @@ class custom_unix_style_separator {
}
}

std::vector<char> selected_quote_ = {};

bool in_quote() { return !selected_quote_.empty(); }

public:
void reset() { last_ = false; }

template <typename InputIterator, typename Token>
bool operator()(InputIterator& next, InputIterator end, Token& tok) {
// Reset collected Token
tok = Token();
tok = Token();
bool valid = false;

// Consume pre-separators, and handle the case where we reach the end of the iterable
Expand All @@ -93,12 +97,12 @@ class custom_unix_style_separator {

// Otherwise, collect the token
last_ = false;
for (bool in_quote = false; next != end; ++next) {
for (; next != end; ++next) {
if (is_escape(*next)) {
do_escape(next, end, tok);
}
else if (is_separator(*next)) {
if (!in_quote) {
if (!in_quote()) {
// If we are not in quote, then we are done
++next;
// The last character was a c, that means there is
Expand All @@ -122,7 +126,19 @@ class custom_unix_style_separator {
}
}
else if (is_quote(*next)) {
in_quote = !in_quote;

if (!in_quote()) {
// Entering quoted sequence...
selected_quote_.push_back(*next);
}
else if (selected_quote_.back() == *next) {
// Matching quotation marks detected... Ending the quoted sequence!
selected_quote_.pop_back();
}
else {
// Unmatched quotation marks detected... Keep collecting the quoted sequence!
tok += *next;
}
}
else {
valid = true;
Expand All @@ -136,9 +152,15 @@ class custom_unix_style_separator {
last_ = false;
return true;
}
if (in_quote()) {
throw std::runtime_error("Unmatched quotation marks detected");
}
return valid;
}

if (in_quote()) {
throw std::runtime_error("Unmatched quotation marks detected");
}
return true;
}
};
Expand Down
40 changes: 32 additions & 8 deletions ACore/test/TestCommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,32 @@ BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_command_line_with_even_
BOOST_REQUIRE_EQUAL(cl.tokens()[5], "/path/to/task");
}

BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_command_line_with_uneven_quotes) {
CommandLine cl{R"(ecflow_client --alter=change variable VARIABLE 'some long value string" "/path/to/task')"};
BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_command_line_with_incorrect_quotes) {
BOOST_REQUIRE_THROW(
CommandLine{R"(ecflow_client --alter=change variable name "some incorrectly ' quoted value" "/some/path)"},
std::runtime_error);
}

BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_command_line_with_unmatched_quotes) {
BOOST_REQUIRE_THROW(CommandLine{R"(ecflow_client --alter=change variable name "some unclosed value /some/path)"},
std::runtime_error);
}

BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_command_line_with_matched_quotes) {
CommandLine cl{R"(ecflow_client --alter=change variable name "some correctly 'inner' quotes value" '/some/path')"};

BOOST_REQUIRE_EQUAL(cl.tokens().size(), 6ul);
BOOST_REQUIRE_EQUAL(cl.size(), 6ul);
BOOST_REQUIRE_EQUAL(cl.tokens()[0], "ecflow_client");
BOOST_REQUIRE_EQUAL(cl.tokens()[4], "some long value string");
BOOST_REQUIRE_EQUAL(cl.tokens()[5], "/path/to/task");
BOOST_REQUIRE_EQUAL(cl.tokens()[4], "some correctly 'inner' quotes value");
BOOST_REQUIRE_EQUAL(cl.tokens()[5], "/some/path");
}

BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_single_option) {
CommandLine cl{R"(executable --option)"};

BOOST_REQUIRE_EQUAL(cl.tokens().size(), 2ul);
BOOST_REQUIRE_EQUAL(cl.tokens()[0], "executable");
BOOST_REQUIRE_EQUAL(cl.tokens()[1], "--option");
BOOST_CHECK_EQUAL(cl.tokens().size(), 2ul);
BOOST_CHECK_EQUAL(cl.tokens()[0], "executable");
BOOST_CHECK_EQUAL(cl.tokens()[1], "--option");
}

BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_empty_value_parameters) {
Expand All @@ -102,4 +113,17 @@ BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_empty_value_parameters)
BOOST_REQUIRE_EQUAL(cl.tokens()[9], "/some/path");
}

BOOST_AUTO_TEST_CASE(test_command_line_is_able_to_handle_single_quotes_in_double_quotes) {
CommandLine cl{R"(ecflow_client --alter change variable name "'value'" /some/path )"};

BOOST_REQUIRE_EQUAL(cl.tokens().size(), 7ul);
BOOST_REQUIRE_EQUAL(cl.tokens()[0], "ecflow_client");
BOOST_REQUIRE_EQUAL(cl.tokens()[1], "--alter");
BOOST_REQUIRE_EQUAL(cl.tokens()[2], "change");
BOOST_REQUIRE_EQUAL(cl.tokens()[3], "variable");
BOOST_REQUIRE_EQUAL(cl.tokens()[4], "name");
BOOST_REQUIRE_EQUAL(cl.tokens()[5], "'value'");
BOOST_REQUIRE_EQUAL(cl.tokens()[6], "/some/path");
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 671cf13

Please sign in to comment.