From bae9bde484ac97f44ad1b3e0b0cbe391b0e16b49 Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 14 Jan 2013 23:18:50 +0000 Subject: [PATCH] Command parser handles quotes arguments --- src/parser.c | 57 ++++++++++++++++++----- tests/test_parser.c | 107 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 12 deletions(-) diff --git a/src/parser.c b/src/parser.c index c0ee70a7..af01ddcc 100644 --- a/src/parser.c +++ b/src/parser.c @@ -60,6 +60,7 @@ parse_args(const char * const inp, int min, int max) int inp_size = strlen(copy); gboolean in_token = FALSE; + gboolean in_quotes = FALSE; char *token_start = ©[0]; int token_size = 0; GSList *tokens = NULL; @@ -72,17 +73,33 @@ parse_args(const char * const inp, int min, int max) continue; } else { in_token = TRUE; + if (copy[i] == '"') { + in_quotes = TRUE; + i++; + } token_start = ©[i]; token_size++; } } else { - if (copy[i] == ' ' || copy[i] == '\0') { - tokens = g_slist_append(tokens, g_strndup(token_start, - token_size)); - token_size = 0; - in_token = FALSE; + if (in_quotes) { + if ((copy[i] == '\0') || (copy[i] == '"')) { + tokens = g_slist_append(tokens, g_strndup(token_start, + token_size)); + token_size = 0; + in_token = FALSE; + in_quotes = FALSE; + } else { + token_size++; + } } else { - token_size++; + if (copy[i] == ' ' || copy[i] == '\0') { + tokens = g_slist_append(tokens, g_strndup(token_start, + token_size)); + token_size = 0; + in_token = FALSE; + } else { + token_size++; + } } } } @@ -163,6 +180,7 @@ parse_args_with_freetext(const char * const inp, int min, int max) int inp_size = strlen(copy); gboolean in_token = FALSE; gboolean in_freetext = FALSE; + gboolean in_quotes = FALSE; char *token_start = ©[0]; int token_size = 0; int num_tokens = 0; @@ -179,18 +197,33 @@ parse_args_with_freetext(const char * const inp, int min, int max) num_tokens++; if (num_tokens == max + 1) { in_freetext = TRUE; + } else if (copy[i] == '"') { + in_quotes = TRUE; + i++; } token_start = ©[i]; token_size++; } } else { - if ((!in_freetext && copy[i] == ' ') || copy[i] == '\0') { - tokens = g_slist_append(tokens, g_strndup(token_start, - token_size)); - token_size = 0; - in_token = FALSE; + if (in_quotes) { + if ((copy[i] == '\0') || (copy[i] == '"')) { + tokens = g_slist_append(tokens, g_strndup(token_start, + token_size)); + token_size = 0; + in_token = FALSE; + in_quotes = FALSE; + } else { + token_size++; + } } else { - token_size++; + if ((!in_freetext && copy[i] == ' ') || copy[i] == '\0') { + tokens = g_slist_append(tokens, g_strndup(token_start, + token_size)); + token_size = 0; + in_token = FALSE; + } else { + token_size++; + } } } } diff --git a/tests/test_parser.c b/tests/test_parser.c index a829f37e..88e03c71 100644 --- a/tests/test_parser.c +++ b/tests/test_parser.c @@ -180,6 +180,105 @@ parse_cmd_min_zero_with_freetext(void) g_strfreev(result); } +void +parse_cmd_with_quoted(void) +{ + char *inp = "/cmd \"arg1\" arg2"; + gchar **result = parse_args(inp, 2, 2); + + assert_int_equals(2, g_strv_length(result)); + assert_string_equals("arg1", result[0]); + assert_string_equals("arg2", result[1]); + g_strfreev(result); +} + +void +parse_cmd_with_quoted_and_space(void) +{ + char *inp = "/cmd \"the arg1\" arg2"; + gchar **result = parse_args(inp, 2, 2); + + assert_int_equals(2, g_strv_length(result)); + assert_string_equals("the arg1", result[0]); + assert_string_equals("arg2", result[1]); + g_strfreev(result); +} + +void +parse_cmd_with_quoted_and_many_spaces(void) +{ + char *inp = "/cmd \"the arg1 is here\" arg2"; + gchar **result = parse_args(inp, 2, 2); + + assert_int_equals(2, g_strv_length(result)); + assert_string_equals("the arg1 is here", result[0]); + assert_string_equals("arg2", result[1]); + g_strfreev(result); +} + +void +parse_cmd_with_many_quoted_and_many_spaces(void) +{ + char *inp = "/cmd \"the arg1 is here\" \"and arg2 is right here\""; + gchar **result = parse_args(inp, 2, 2); + + assert_int_equals(2, g_strv_length(result)); + assert_string_equals("the arg1 is here", result[0]); + assert_string_equals("and arg2 is right here", result[1]); + g_strfreev(result); +} + +void +parse_cmd_freetext_with_quoted(void) +{ + char *inp = "/cmd \"arg1\" arg2 hello there whats up"; + gchar **result = parse_args_with_freetext(inp, 3, 3); + + assert_int_equals(3, g_strv_length(result)); + assert_string_equals("arg1", result[0]); + assert_string_equals("arg2", result[1]); + assert_string_equals("hello there whats up", result[2]); + g_strfreev(result); +} + +void +parse_cmd_freetext_with_quoted_and_space(void) +{ + char *inp = "/cmd \"the arg1\" arg2 another bit of freetext"; + gchar **result = parse_args_with_freetext(inp, 3, 3); + + assert_int_equals(3, g_strv_length(result)); + assert_string_equals("the arg1", result[0]); + assert_string_equals("arg2", result[1]); + assert_string_equals("another bit of freetext", result[2]); + g_strfreev(result); +} + +void +parse_cmd_freetext_with_quoted_and_many_spaces(void) +{ + char *inp = "/cmd \"the arg1 is here\" arg2 some more freetext"; + gchar **result = parse_args_with_freetext(inp, 3, 3); + + assert_int_equals(3, g_strv_length(result)); + assert_string_equals("the arg1 is here", result[0]); + assert_string_equals("arg2", result[1]); + assert_string_equals("some more freetext", result[2]); + g_strfreev(result); +} + +void +parse_cmd_freetext_with_many_quoted_and_many_spaces(void) +{ + char *inp = "/cmd \"the arg1 is here\" \"and arg2 is right here\" and heres the free text"; + gchar **result = parse_args_with_freetext(inp, 3, 3); + + assert_int_equals(3, g_strv_length(result)); + assert_string_equals("the arg1 is here", result[0]); + assert_string_equals("and arg2 is right here", result[1]); + assert_string_equals("and heres the free text", result[2]); + g_strfreev(result); +} void register_parser_tests(void) { @@ -200,4 +299,12 @@ register_parser_tests(void) TEST(parse_cmd_with_too_many_returns_null); TEST(parse_cmd_min_zero); TEST(parse_cmd_min_zero_with_freetext); + TEST(parse_cmd_with_quoted); + TEST(parse_cmd_with_quoted_and_space); + TEST(parse_cmd_with_quoted_and_many_spaces); + TEST(parse_cmd_with_many_quoted_and_many_spaces); + TEST(parse_cmd_freetext_with_quoted); + TEST(parse_cmd_freetext_with_quoted_and_space); + TEST(parse_cmd_freetext_with_quoted_and_many_spaces); + TEST(parse_cmd_freetext_with_many_quoted_and_many_spaces); }