about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2012-11-18 00:07:00 +0000
committerJames Booth <boothj5@gmail.com>2012-11-18 00:07:00 +0000
commit824eaa1678043afd8e31e4de529aaf61165295d7 (patch)
tree8ac7e1ed7f9a06940606ad0dc09ff108a24652bd
parent2fe5e7bd5914c3062e8f914492e4e745ab6b9a15 (diff)
downloadprofani-tty-824eaa1678043afd8e31e4de529aaf61165295d7.tar.gz
Added parser module
-rw-r--r--Makefile.am4
-rw-r--r--src/command.c44
-rw-r--r--src/contact_list.c2
-rw-r--r--src/parser.c96
-rw-r--r--src/parser.h30
-rw-r--r--tests/test_parser.c127
-rw-r--r--tests/testsuite.c1
-rw-r--r--tests/testsuite.h1
8 files changed, 266 insertions, 39 deletions
diff --git a/Makefile.am b/Makefile.am
index 66304e99..e0e3b01b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,14 +8,14 @@ profanity_SOURCES = src/command.c src/contact.c src/history.c src/jabber.h \
 	src/main.c src/profanity.h src/prof_history.h src/chat_log.c \
 	src/chat_log.h src/tinyurl.c src/tinyurl.h src/chat_session.c \
 	src/chat_session.h src/release.c src/release.h src/room_chat.c \
-	src/room_chat.h src/stanza.c src/stanza.h
+	src/room_chat.h src/stanza.c src/stanza.h src/parser.c src/parser.h
 
 TESTS = tests/testsuite
 check_PROGRAMS = tests/testsuite
 tests_testsuite_SOURCES = tests/test_contact_list.c src/contact_list.c src/contact.c \
 	tests/test_common.c tests/test_prof_history.c src/prof_history.c src/common.c \
 	tests/test_prof_autocomplete.c src/prof_autocomplete.c tests/testsuite.c \
-	src/log.c
+	tests/test_parser.c src/parser.c
 tests_testsuite_LDADD = -lheadunit -lstdc++
 
 man_MANS = docs/profanity.1
diff --git a/src/command.c b/src/command.c
index a02c77e9..160c8091 100644
--- a/src/command.c
+++ b/src/command.c
@@ -36,6 +36,7 @@
 #include "history.h"
 #include "jabber.h"
 #include "log.h"
+#include "parser.h"
 #include "preferences.h"
 #include "prof_autocomplete.h"
 #include "tinyurl.h"
@@ -835,7 +836,7 @@ _cmd_connect(const char * const inp, struct cmd_help_t help)
 {
     gboolean result = FALSE;
     int num_args = 0;
-    gchar **args = _cmd_parse_args(inp, 1, 1, &num_args);
+    gchar **args = parse_args(inp, 1, 1, &num_args);
 
     if (args == NULL) {
         cons_show("Usage: %s", help.usage);
@@ -882,7 +883,7 @@ _cmd_sub(const char * const inp, struct cmd_help_t help)
 {
     gboolean result = FALSE;
     int num_args = 0;
-    gchar **args = _cmd_parse_args(inp, 1, 2, &num_args);
+    gchar **args = parse_args(inp, 1, 2, &num_args);
 
     if (args == NULL) {
         cons_show("Usage: %s", help.usage);
@@ -1220,7 +1221,7 @@ _cmd_info(const char * const inp, struct cmd_help_t help)
 {
     gboolean result = FALSE;
     int num_args = 0;
-    gchar **args = _cmd_parse_args(inp, 1, 1, &num_args);
+    gchar **args = parse_args(inp, 1, 1, &num_args);
 
     if (args == NULL) {
         cons_show("Usage: %s", help.usage);
@@ -1252,7 +1253,7 @@ _cmd_join(const char * const inp, struct cmd_help_t help)
 {
     gboolean result = FALSE;
     int num_args = 0;
-    gchar **args = _cmd_parse_args(inp, 1, 2, &num_args);
+    gchar **args = parse_args(inp, 1, 2, &num_args);
 
     if (args == NULL) {
         cons_show("Usage: %s", help.usage);
@@ -1296,7 +1297,7 @@ _cmd_tiny(const char * const inp, struct cmd_help_t help)
 {
     gboolean result = FALSE;
     int num_args = 0;
-    gchar **args = _cmd_parse_args(inp, 1, 1, &num_args);
+    gchar **args = parse_args(inp, 1, 1, &num_args);
 
     if (args == NULL) {
         cons_show("Usage: %s", help.usage);
@@ -1401,7 +1402,7 @@ _cmd_set_notify(const char * const inp, struct cmd_help_t help)
 {
     gboolean result = FALSE;
     int num_args = 0;
-    gchar **args = _cmd_parse_args(inp, 2, 2, &num_args);
+    gchar **args = parse_args(inp, 2, 2, &num_args);
 
     if (args == NULL) {
         cons_show("Usage: %s", help.usage);
@@ -1463,7 +1464,7 @@ _cmd_set_log(const char * const inp, struct cmd_help_t help)
 {
     gboolean result = FALSE;
     int num_args = 0;
-    gchar **args = _cmd_parse_args(inp, 2, 2, &num_args);
+    gchar **args = parse_args(inp, 2, 2, &num_args);
 
     if (args == NULL) {
         cons_show("Usage: %s", help.usage);
@@ -1496,7 +1497,7 @@ _cmd_set_priority(const char * const inp, struct cmd_help_t help)
 {
     gboolean result = FALSE;
     int num_args = 0;
-    gchar **args = _cmd_parse_args(inp, 1, 1, &num_args);
+    gchar **args = parse_args(inp, 1, 1, &num_args);
 
     if (args == NULL) {
         cons_show("Usage: %s", help.usage);
@@ -1805,30 +1806,3 @@ _strtoi(char *str, int *saveptr, int min, int max)
 
     return 0;
 }
-
-gchar **
-_cmd_parse_args(const char * const inp, int min, int max, int *num)
-{
-    char *copy = strdup(inp);
-    gchar **args = NULL;
-    g_strstrip(copy);
-    gchar **split = g_strsplit(copy, " ", 0);
-    *num = g_strv_length(split) - 1;
-
-    if ((*num < min) || (*num > max)) {
-        g_strfreev(split);
-        free(copy);
-        return NULL;
-    } else {
-        args = malloc((*num + 1) * sizeof(*args));
-        int i;
-        for (i = 0; i < *num; i++) {
-            args[i] = strdup(split[i+1]);
-        }
-        args[i] = NULL;
-        g_strfreev(split);
-        free(copy);
-
-        return args;
-    }
-}
diff --git a/src/contact_list.c b/src/contact_list.c
index d05d7412..714750dd 100644
--- a/src/contact_list.c
+++ b/src/contact_list.c
@@ -25,7 +25,6 @@
 #include <glib.h>
 
 #include "contact.h"
-#include "log.h"
 #include "prof_autocomplete.h"
 
 static PAutocomplete ac;
@@ -80,7 +79,6 @@ contact_list_update_contact(const char * const jid, const char * const presence,
     PContact contact = g_hash_table_lookup(contacts, jid);
 
     if (contact == NULL) {
-        log_warning("Contact not in list: %s", jid);
         return FALSE;
     }
 
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 00000000..5034c215
--- /dev/null
+++ b/src/parser.c
@@ -0,0 +1,96 @@
+/*
+ * parser.c
+ *
+ * Copyright (C) 2012 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+gchar **
+parse_args(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;
+    char *token_start = &copy[0];
+    int token_size = 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;
+                token_start = &copy[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;
+            } else {
+                token_size++;
+            }
+        }
+    }
+    
+    *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;
+    }
+}
diff --git a/src/parser.h b/src/parser.h
new file mode 100644
index 00000000..a0442f33
--- /dev/null
+++ b/src/parser.h
@@ -0,0 +1,30 @@
+/*
+ * parser.h
+ *
+ * Copyright (C) 2012 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <glib.h>
+
+gchar** parse_args(const char * const inp, int min, int max, int *num);
+
+#endif
diff --git a/tests/test_parser.c b/tests/test_parser.c
new file mode 100644
index 00000000..40d4fc28
--- /dev/null
+++ b/tests/test_parser.c
@@ -0,0 +1,127 @@
+#include <stdlib.h>
+#include <string.h>
+#include <head-unit.h>
+#include "parser.h"
+
+void
+parse_null_returns_null(void)
+{
+    char *inp = NULL;
+    int num = 0;
+    gchar **result = parse_args(inp, 1, 2, &num);
+
+    assert_is_null(result);
+    g_strfreev(result);
+}
+
+void
+parse_empty_returns_null(void)
+{
+    char *inp = "";
+    int num = 0;
+    gchar **result = parse_args(inp, 1, 2, &num);
+
+    assert_is_null(result);
+    g_strfreev(result);
+}
+
+void
+parse_space_returns_null(void)
+{
+    char *inp = "   ";
+    int num = 0;
+    gchar **result = parse_args(inp, 1, 2, &num);
+
+    assert_is_null(result);
+    g_strfreev(result);
+}
+
+void
+parse_cmd_no_args_returns_null(void)
+{
+    char *inp = "/cmd";
+    int num = 0;
+    gchar **result = parse_args(inp, 1, 2, &num);
+
+    assert_is_null(result);
+    g_strfreev(result);
+}
+
+void
+parse_cmd_with_space_returns_null(void)
+{
+    char *inp = "/cmd   ";
+    int num = 0;
+    gchar **result = parse_args(inp, 1, 2, &num);
+
+    assert_is_null(result);
+    g_strfreev(result);
+}
+
+void
+parse_cmd_one_arg(void)
+{
+    char *inp = "/cmd arg1";
+    int num = 0;
+    gchar **result = parse_args(inp, 1, 2, &num);
+
+    assert_int_equals(1, num);
+    assert_string_equals("arg1", result[0]);
+    g_strfreev(result);
+}
+
+void
+parse_cmd_two_args(void)
+{
+    char *inp = "/cmd arg1 arg2";
+    int num = 0;
+    gchar **result = parse_args(inp, 1, 2, &num);
+
+    assert_int_equals(2, num);
+    assert_string_equals("arg1", result[0]);
+    assert_string_equals("arg2", result[1]);
+    g_strfreev(result);
+}
+
+void
+parse_cmd_three_args(void)
+{
+    char *inp = "/cmd arg1 arg2 arg3";
+    int num = 0;
+    gchar **result = parse_args(inp, 3, 3, &num);
+
+    assert_int_equals(3, num);
+    assert_string_equals("arg1", result[0]);
+    assert_string_equals("arg2", result[1]);
+    assert_string_equals("arg3", result[2]);
+    g_strfreev(result);
+}
+
+void
+parse_cmd_three_args_with_spaces(void)
+{
+    char *inp = "  /cmd    arg1  arg2     arg3 ";
+    int num = 0;
+    gchar **result = parse_args(inp, 3, 3, &num);
+
+    assert_int_equals(3, num);
+    assert_string_equals("arg1", result[0]);
+    assert_string_equals("arg2", result[1]);
+    assert_string_equals("arg3", result[2]);
+    g_strfreev(result);
+}
+
+void
+register_parser_tests(void)
+{
+    TEST_MODULE("parser tests");
+    TEST(parse_null_returns_null);
+    TEST(parse_empty_returns_null);
+    TEST(parse_space_returns_null);
+    TEST(parse_cmd_no_args_returns_null);
+    TEST(parse_cmd_with_space_returns_null);
+    TEST(parse_cmd_one_arg);
+    TEST(parse_cmd_two_args);
+    TEST(parse_cmd_three_args);
+    TEST(parse_cmd_three_args_with_spaces);
+}
diff --git a/tests/testsuite.c b/tests/testsuite.c
index e7a23005..7c1b81dc 100644
--- a/tests/testsuite.c
+++ b/tests/testsuite.c
@@ -7,6 +7,7 @@ int main(void)
     register_contact_list_tests();
     register_common_tests();
     register_prof_autocomplete_tests();
+    register_parser_tests();
     run_suite();
     return 0;
 }
diff --git a/tests/testsuite.h b/tests/testsuite.h
index 45145c9b..029cd48c 100644
--- a/tests/testsuite.h
+++ b/tests/testsuite.h
@@ -5,5 +5,6 @@ void register_prof_history_tests(void);
 void register_contact_list_tests(void);
 void register_common_tests(void);
 void register_prof_autocomplete_tests(void);
+void register_parser_tests(void);
 
 #endif