summaryrefslogtreecommitdiffstats
path: root/src/stkutil.c
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2010-02-27 10:20:23 -0600
committerDenis Kenzior <denkenz@gmail.com>2010-02-27 10:20:23 -0600
commit172c68edf5f0cd370fd4351a61c46f67eb3a5222 (patch)
treeeb60175b8fa24cc591461679a96e3a7bca822f4f /src/stkutil.c
parent6497d29719c55cec2ffc6b36e19c51baaac4c391 (diff)
downloadofono-172c68edf5f0cd370fd4351a61c46f67eb3a5222.tar.bz2
stk: Refactor proactive command parser
Make it a bit easier to extend by using va_args
Diffstat (limited to 'src/stkutil.c')
-rw-r--r--src/stkutil.c103
1 files changed, 95 insertions, 8 deletions
diff --git a/src/stkutil.c b/src/stkutil.c
index bfe29674..0e78f543 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -34,14 +34,19 @@
#include "simutil.h"
#include "util.h"
-static gboolean parse_dataobj_text(struct stk_command *command,
- struct comprehension_tlv_iter *iter)
+enum stk_data_object_flag {
+ DATAOBJ_FLAG_MANDATORY = 1,
+ DATAOBJ_FLAG_MINIMUM = 2
+};
+
+typedef gboolean (*dataobj_handler)(struct comprehension_tlv_iter *, void *);
+
+static gboolean parse_dataobj_text(struct comprehension_tlv_iter *iter,
+ void *user)
{
+ char **text = user;
unsigned int len;
- if (comprehension_tlv_iter_next(iter) != TRUE)
- return FALSE;
-
if (comprehension_tlv_iter_get_tag(iter) !=
STK_DATA_OBJECT_TYPE_TEXT)
return FALSE;
@@ -91,9 +96,9 @@ static gboolean parse_dataobj_text(struct stk_command *command,
if (utf8 == NULL)
return FALSE;
- command->display_text.text = utf8;
+ *text = utf8;
} else
- command->display_text.text = NULL;
+ *text = NULL;
return TRUE;
}
@@ -103,10 +108,89 @@ static void destroy_display_text(struct stk_command *command)
g_free(command->display_text.text);
}
+static dataobj_handler handler_for_type(enum stk_data_object_type type)
+{
+ switch (type) {
+ case STK_DATA_OBJECT_TYPE_TEXT:
+ return parse_dataobj_text;
+ default:
+ return NULL;
+ };
+}
+
+struct dataobj_handler_entry {
+ enum stk_data_object_type type;
+ int flags;
+ void *data;
+ gboolean parsed;
+};
+
+static gboolean parse_dataobj(struct comprehension_tlv_iter *iter,
+ enum stk_data_object_type type, ...)
+{
+ GSList *entries = NULL;
+ GSList *l;
+ va_list args;
+ gboolean minimum_set = TRUE;
+
+ va_start(args, type);
+
+ while (type != STK_DATA_OBJECT_TYPE_INVALID) {
+ struct dataobj_handler_entry *entry;
+
+ entry = g_new0(struct dataobj_handler_entry, 1);
+
+ entry->type = type;
+ entry->flags = va_arg(args, int);
+ entry->data = va_arg(args, void *);
+
+ type = va_arg(args, enum stk_data_object_type);
+ entries = g_slist_prepend(entries, entry);
+ }
+
+ entries = g_slist_reverse(entries);
+
+ for (l = entries; l; l = l->next) {
+ gboolean ret;
+ dataobj_handler handler;
+ struct dataobj_handler_entry *entry = l->data;
+
+ handler = handler_for_type(entry->type);
+ if (handler == NULL)
+ continue;
+
+ ret = handler(iter, entry->data);
+ entry->parsed = ret;
+
+ if (ret && comprehension_tlv_iter_next(iter) == FALSE)
+ break;
+ }
+
+ for (l = entries; l; l = l->next) {
+ struct dataobj_handler_entry *entry = l->data;
+
+ if ((entry->flags & DATAOBJ_FLAG_MINIMUM) &&
+ entry->parsed == FALSE)
+ minimum_set = TRUE;
+ }
+
+ g_slist_foreach(entries, (GFunc)g_free, NULL);
+ g_slist_free(entries);
+
+ return minimum_set;
+}
+
static gboolean parse_display_text(struct stk_command *command,
struct comprehension_tlv_iter *iter)
{
- if (parse_dataobj_text(command, iter) == FALSE)
+ gboolean ret;
+
+ ret = parse_dataobj(iter, STK_DATA_OBJECT_TYPE_TEXT,
+ DATAOBJ_FLAG_MANDATORY | DATAOBJ_FLAG_MINIMUM,
+ &command->display_text.text,
+ STK_DATA_OBJECT_TYPE_INVALID);
+
+ if (ret == FALSE)
return FALSE;
command->destructor = destroy_display_text;
@@ -171,6 +255,9 @@ struct stk_command *stk_command_new_from_pdu(const unsigned char *pdu,
command->src = data[0];
command->dst = data[1];
+ if (comprehension_tlv_iter_next(&iter) != TRUE)
+ return FALSE;
+
switch (command->type) {
case STK_COMMAND_TYPE_DISPLAY_TEXT:
ok = parse_display_text(command, &iter);