From 6cf48817436fdebf5a1995afd156d87512ed33e2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 1 Nov 2010 01:40:56 +0100 Subject: [PATCH] Add really simple content token parser --- gweb/gweb.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gweb/gweb.h | 14 ++++++ 2 files changed, 165 insertions(+) diff --git a/gweb/gweb.c b/gweb/gweb.c index 177e9bd..94da3d1 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 24c84a0..cc2324c 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 -- 2.7.4