summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2010-11-01 01:40:56 +0100
committerMarcel Holtmann <marcel@holtmann.org>2010-11-01 01:40:56 +0100
commit6cf48817436fdebf5a1995afd156d87512ed33e2 (patch)
tree88e34182930c1ac344a54048d3bd64b36572edd8
parent278c3c7529d8440a65ff1a7c6a04b2bd27f426e9 (diff)
downloadconnman-6cf48817436fdebf5a1995afd156d87512ed33e2.tar.gz
connman-6cf48817436fdebf5a1995afd156d87512ed33e2.tar.bz2
connman-6cf48817436fdebf5a1995afd156d87512ed33e2.zip
Add really simple content token parser
-rw-r--r--gweb/gweb.c151
-rw-r--r--gweb/gweb.h14
2 files changed, 165 insertions, 0 deletions
diff --git a/gweb/gweb.c b/gweb/gweb.c
index 177e9bd7..94da3d1a 100644
--- a/gweb/gweb.c
+++ b/gweb/gweb.c
@@ -650,3 +650,154 @@ gboolean g_web_result_get_chunk(GWebResult *result,
return TRUE;
}
+
+struct _GWebParser {
+ gint ref_count;
+ char *begin_token;
+ char *end_token;
+ const char *token_str;
+ size_t token_len;
+ size_t token_pos;
+ gboolean intoken;
+ GString *content;
+ GWebParserFunc func;
+ gpointer user_data;
+};
+
+GWebParser *g_web_parser_new(const char *begin, const char *end,
+ GWebParserFunc func, gpointer user_data)
+{
+ GWebParser *parser;
+
+ parser = g_try_new0(GWebParser, 1);
+ if (parser == NULL)
+ return NULL;
+
+ parser->ref_count = 1;
+
+ parser->begin_token = g_strdup(begin);
+ parser->end_token = g_strdup(end);
+
+ if (parser->begin_token == NULL) {
+ g_free(parser);
+ return NULL;
+ }
+
+ parser->func = func;
+ parser->user_data = user_data;
+
+ parser->token_str = parser->begin_token;
+ parser->token_len = strlen(parser->token_str);
+ parser->token_pos = 0;
+
+ parser->intoken = FALSE;
+ parser->content = g_string_sized_new(0);
+
+ return parser;
+}
+
+GWebParser *g_web_parser_ref(GWebParser *parser)
+{
+ if (parser == NULL)
+ return NULL;
+
+ g_atomic_int_inc(&parser->ref_count);
+
+ return parser;
+}
+
+void g_web_parser_unref(GWebParser *parser)
+{
+ if (parser == NULL)
+ return;
+
+ if (g_atomic_int_dec_and_test(&parser->ref_count) == FALSE)
+ return;
+
+ g_string_free(parser->content, TRUE);
+
+ g_free(parser->begin_token);
+ g_free(parser->end_token);
+ g_free(parser);
+}
+
+void g_web_parser_feed_data(GWebParser *parser,
+ const guint8 *data, gsize length)
+{
+ const guint8 *ptr = data;
+
+ if (parser == NULL)
+ return;
+
+ while (length > 0) {
+ guint8 chr = parser->token_str[parser->token_pos];
+
+ if (parser->token_pos == 0) {
+ guint8 *pos;
+
+ pos = memchr(ptr, chr, length);
+ if (pos == NULL) {
+ if (parser->intoken == TRUE)
+ g_string_append_len(parser->content,
+ (gchar *) ptr, length);
+ break;
+ }
+
+ if (parser->intoken == TRUE)
+ g_string_append_len(parser->content,
+ (gchar *) ptr, (pos - ptr) + 1);
+
+ length -= (pos - ptr) + 1;
+ ptr = pos + 1;
+
+ parser->token_pos++;
+ continue;
+ }
+
+ if (parser->intoken == TRUE)
+ g_string_append_c(parser->content, ptr[0]);
+
+ if (ptr[0] != chr) {
+ length--;
+ ptr++;
+
+ parser->token_pos = 0;
+ continue;
+ }
+
+ length--;
+ ptr++;
+
+ parser->token_pos++;
+
+ if (parser->token_pos == parser->token_len) {
+ if (parser->intoken == FALSE) {
+ g_string_append(parser->content,
+ parser->token_str);
+
+ parser->intoken = TRUE;
+ parser->token_str = parser->end_token;
+ parser->token_len = strlen(parser->end_token);
+ parser->token_pos = 0;
+ } else {
+ char *str;
+ str = g_string_free(parser->content, FALSE);
+ parser->content = g_string_sized_new(0);
+ if (parser->func)
+ parser->func(str, parser->user_data);
+ g_free(str);
+
+ parser->intoken = FALSE;
+ parser->token_str = parser->begin_token;
+ parser->token_len = strlen(parser->begin_token);
+ parser->token_pos = 0;
+ }
+ }
+ }
+}
+
+void g_web_parser_end_data(GWebParser *parser)
+{
+ if (parser == NULL)
+ return;
+}
diff --git a/gweb/gweb.h b/gweb/gweb.h
index 24c84a03..cc2324c9 100644
--- a/gweb/gweb.h
+++ b/gweb/gweb.h
@@ -32,9 +32,11 @@ extern "C" {
struct _GWeb;
struct _GWebResult;
+struct _GWebParser;
typedef struct _GWeb GWeb;
typedef struct _GWebResult GWebResult;
+typedef struct _GWebParser GWebParser;
typedef enum {
G_WEB_METHOD_GET,
@@ -72,6 +74,18 @@ guint16 g_web_result_get_status(GWebResult *result);
gboolean g_web_result_get_chunk(GWebResult *result,
const guint8 **chunk, gsize *length);
+typedef void (*GWebParserFunc)(const char *str, gpointer user_data);
+
+GWebParser *g_web_parser_new(const char *begin, const char *end,
+ GWebParserFunc func, gpointer user_data);
+
+GWebParser *g_web_parser_ref(GWebParser *parser);
+void g_web_parser_unref(GWebParser *parser);
+
+void g_web_parser_feed_data(GWebParser *parser,
+ const guint8 *data, gsize length);
+void g_web_parser_end_data(GWebParser *parser);
+
#ifdef __cplusplus
}
#endif