diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2010-11-01 01:40:56 +0100 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-11-01 01:40:56 +0100 |
commit | 6cf48817436fdebf5a1995afd156d87512ed33e2 (patch) | |
tree | 88e34182930c1ac344a54048d3bd64b36572edd8 | |
parent | 278c3c7529d8440a65ff1a7c6a04b2bd27f426e9 (diff) | |
download | connman-6cf48817436fdebf5a1995afd156d87512ed33e2.tar.gz connman-6cf48817436fdebf5a1995afd156d87512ed33e2.tar.bz2 connman-6cf48817436fdebf5a1995afd156d87512ed33e2.zip |
Add really simple content token parser
-rw-r--r-- | gweb/gweb.c | 151 | ||||
-rw-r--r-- | gweb/gweb.h | 14 |
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 |