about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/parser.c80
-rw-r--r--tests/test_parser.c66
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 = &copy[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 = &copy[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
@@ -59,6 +59,28 @@ parse_cmd_with_space_returns_null(void)
 }
 
 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)
 {
     char *inp = "/cmd arg1";
@@ -112,6 +134,45 @@ parse_cmd_three_args_with_spaces(void)
 }
 
 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)
 {
     TEST_MODULE("parser tests");
@@ -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);
 }