Skip to content

Commit f0b3f0c

Browse files
committed
better cli arg parsing
1 parent cc75872 commit f0b3f0c

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

inc/mkn/kul/src/cli/asArgs.ipp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,48 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030
*/
3131
// IWYU pragma: private, include "mkn/kul/cli.hpp"
3232

33+
namespace {
34+
//
35+
std::size_t sub_string_to_next_occurrence(std::string const& cmd, std::size_t const s,
36+
std::string const& needle) {
37+
std::string const rest = cmd.substr(s);
38+
auto const pos = rest.find(needle);
39+
if (pos == std::string::npos)
40+
KEXCEPT(mkn::kul::Exception, "Error: CLI Arg parsing unclosed quotes!");
41+
return pos;
42+
}
43+
44+
} // namespace
45+
3346
void mkn::kul::cli::asArgs(std::string const& cmd, std::vector<std::string>& args) {
3447
std::string arg;
3548
bool openQuotesS = false, openQuotesD = false, backSlashed = false;
36-
for (char const c : cmd) {
49+
50+
for (std::size_t i = 0; i < cmd.size(); ++i) {
51+
auto const c = cmd[i];
52+
3753
if (backSlashed) {
3854
backSlashed = false;
3955
arg += c;
4056
continue;
57+
58+
} else if (openQuotesD) {
59+
auto const pos = sub_string_to_next_occurrence(cmd, i, "\"");
60+
arg = cmd.substr(i, pos);
61+
if (arg.size() > 0) args.push_back(arg);
62+
i += arg.size();
63+
arg.clear();
64+
openQuotesD = false;
65+
continue;
4166
}
67+
4268
switch (c) {
4369
case ' ':
44-
if (!openQuotesD && !openQuotesS) { // ||||| ||||| ||||| ||||| |||||
45-
if (arg.size() > 0) args.push_back(arg); // || || || || || || ||
46-
arg.clear(); // ||||| ||||| ||||| || |||||
47-
continue; // || || || || || ||
48-
} // ||||| || || || ||||| |||||
70+
if (!openQuotesD && !openQuotesS) {
71+
if (arg.size() > 0) args.push_back(arg);
72+
arg.clear();
73+
continue;
74+
}
4975
break;
5076
case '"':
5177
if (openQuotesD && !openQuotesS) {

tst/test/cli.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
TEST(CLI_Test, ParseCommandLineArguments) {
88
std::vector<std::string> v;
9-
mkn::kul::cli::asArgs("/path/to \"words in quotes\" words\\ not\\ in\\ quotes end", v);
10-
EXPECT_EQ((size_t)4, v.size());
9+
mkn::kul::cli::asArgs("/path/to \"words 'in' quotes\" words\\ not\\ in\\ quotes end", v);
10+
ASSERT_EQ(4ull, v.size());
1111
EXPECT_EQ("/path/to", v[0]);
1212
EXPECT_EQ("words in quotes", v[1]);
1313
EXPECT_EQ("words not in quotes", v[2]);

0 commit comments

Comments
 (0)