From 191ab83c9b888ebd5f60afc256833c8062629e05 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 18 Nov 2012 00:25:08 +0000 Subject: [PATCH] Added command parser for commands accepting free text e.g. /msg user@host here is a message --- src/parser.c | 80 +++++++++++++++++++++++++++++++++++++++++++-- tests/test_parser.c | 66 +++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 2 deletions(-) diff --git a/src/parser.c b/src/parser.c index 5034c215..447e1b4a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -56,7 +56,7 @@ parse_args(const char * const inp, int min, int max, int *num) } } else { if (copy[i] == ' ' || copy[i] == '\0') { - tokens = g_slist_append(tokens, g_strndup(token_start, + tokens = g_slist_append(tokens, g_strndup(token_start, token_size)); token_size = 0; in_token = FALSE; @@ -65,7 +65,83 @@ parse_args(const char * const inp, int min, int max, int *num) } } } - + + *num = g_slist_length(tokens) - 1; + + // if num args not valid return NULL + if ((*num < min) || (*num > max)) { + g_slist_free_full(tokens, free); + free(copy); + *num = 0; + return NULL; + + // otherwise return args array + } else { + gchar **args = malloc((*num + 1) * sizeof(*args)); + GSList *token = tokens; + token = g_slist_next(token); + int arg_count = 0; + + while (token != NULL) { + args[arg_count++] = strdup(token->data); + token = g_slist_next(token); + } + + args[arg_count] = NULL; + g_slist_free_full(tokens, free); + free(copy); + + return args; + } +} + +gchar ** +parse_args_with_freetext(const char * const inp, int min, int max, int *num) +{ + if (inp == NULL) { + *num = 0; + return NULL; + } + + // copy and strip input of leading/trailing whitepsace + char *copy = strdup(inp); + g_strstrip(copy); + + int inp_size = strlen(copy); + gboolean in_token = FALSE; + gboolean in_freetext = FALSE; + char *token_start = ©[0]; + int token_size = 0; + int num_tokens = 0; + GSList *tokens = NULL; + + // add tokens to GSList + int i; + for (i = 0; i <= inp_size; i++) { + if (!in_token) { + if (copy[i] == ' ') { + continue; + } else { + in_token = TRUE; + num_tokens++; + if (num_tokens == max + 1) { + in_freetext = TRUE; + } + 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; + } else { + token_size++; + } + } + } + *num = g_slist_length(tokens) - 1; // if num args not valid return NULL diff --git a/tests/test_parser.c b/tests/test_parser.c index 40d4fc28..a3e31ed6 100644 --- a/tests/test_parser.c +++ b/tests/test_parser.c @@ -58,6 +58,28 @@ parse_cmd_with_space_returns_null(void) g_strfreev(result); } +void +parse_cmd_with_too_few_returns_null(void) +{ + char *inp = "/cmd arg1"; + int num = 0; + gchar **result = parse_args(inp, 2, 3, &num); + + assert_is_null(result); + g_strfreev(result); +} + +void +parse_cmd_with_too_many_returns_null(void) +{ + char *inp = "/cmd arg1 arg2 arg3 arg4"; + int num = 0; + gchar **result = parse_args(inp, 1, 3, &num); + + assert_is_null(result); + g_strfreev(result); +} + void parse_cmd_one_arg(void) { @@ -111,6 +133,45 @@ parse_cmd_three_args_with_spaces(void) g_strfreev(result); } +void +parse_cmd_with_freetext(void) +{ + char *inp = "/cmd this is some free text"; + int num = 0; + gchar **result = parse_args_with_freetext(inp, 1, 1, &num); + + assert_int_equals(1, num); + assert_string_equals("this is some free text", result[0]); + g_strfreev(result); +} + +void +parse_cmd_one_arg_with_freetext(void) +{ + char *inp = "/cmd arg1 this is some free text"; + int num = 0; + gchar **result = parse_args_with_freetext(inp, 1, 2, &num); + + assert_int_equals(2, num); + assert_string_equals("arg1", result[0]); + assert_string_equals("this is some free text", result[1]); + g_strfreev(result); +} + +void +parse_cmd_two_args_with_freetext(void) +{ + char *inp = "/cmd arg1 arg2 this is some free text"; + int num = 0; + gchar **result = parse_args_with_freetext(inp, 1, 3, &num); + + assert_int_equals(3, num); + assert_string_equals("arg1", result[0]); + assert_string_equals("arg2", result[1]); + assert_string_equals("this is some free text", result[2]); + g_strfreev(result); +} + void register_parser_tests(void) { @@ -124,4 +185,9 @@ register_parser_tests(void) TEST(parse_cmd_two_args); TEST(parse_cmd_three_args); TEST(parse_cmd_three_args_with_spaces); + TEST(parse_cmd_with_freetext); + TEST(parse_cmd_one_arg_with_freetext); + TEST(parse_cmd_two_args_with_freetext); + TEST(parse_cmd_with_too_few_returns_null); + TEST(parse_cmd_with_too_many_returns_null); }