From 3c852ea244a4d774a89be7234eada00f4f1a26c7 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Sat, 4 Apr 2009 22:37:11 +0200 Subject: Speed up replace table by using token parser --- src/replace-table.c | 143 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 104 insertions(+), 39 deletions(-) (limited to 'src/replace-table.c') diff --git a/src/replace-table.c b/src/replace-table.c index d3503c4..1f674a3 100644 --- a/src/replace-table.c +++ b/src/replace-table.c @@ -87,39 +87,6 @@ replace_table_add_key_printf (ReplaceTable *table, const gchar *tag, const gchar } - -static void -replace_table_process_value (gpointer key, gpointer value, gpointer user_data) -{ - gchar **buffer = user_data; - gchar *tag; - gchar *tag_value; - - g_return_if_fail (key != NULL); - g_return_if_fail (value != NULL); - g_return_if_fail (user_data != NULL); - - /* replace tags */ - tag = g_strdup_printf ("", (gchar *) key); - tag_value = g_strdup ((gchar *) value); - adjust_tags_normal (&tag_value); - while (strstr (*buffer, tag)) { - str_replace (buffer, tag, tag_value); - } - g_free (tag_value); - g_free (tag); - - /* replace $(xxx) tags */ - tag = g_strdup_printf ("$(%s)", (gchar *) key); - tag_value = g_strdup ((gchar *) value); - adjust_tags_parameter (&tag_value); - while (strstr (*buffer, tag)) { - str_replace (buffer, tag, tag_value); - } - g_free (tag_value); - g_free (tag); -} - /* * replace_table_process: process buffer and replace all tags filled in the replace table * @@ -129,14 +96,51 @@ replace_table_process_value (gpointer key, gpointer value, gpointer user_data) void replace_table_process (gchar **buffer, ReplaceTable *table) { - g_return_if_fail (table != NULL); + char *token; + char *start, *end; + char *b; + char *replace_value; + GString *dst; + gboolean tag_parameter; + gboolean handled; - g_hash_table_foreach (table, replace_table_process_value, buffer); + g_return_if_fail (table != NULL); + g_return_if_fail (buffer != NULL); + if (*buffer == NULL || strlen (*buffer) < 1) + return; + + + dst = g_string_new (NULL); + b = *buffer; + while ((token = get_next_token (b, &start, &end, &tag_parameter))) { + handled = FALSE; + + /* push the string before the token */ + g_string_append_len (dst, b, start - b); + + replace_value = g_strdup (g_hash_table_lookup (table, token)); + if (replace_value) { + if (! tag_parameter) + adjust_tags_normal (&replace_value); + else + adjust_tags_parameter (&replace_value); + g_string_append (dst, replace_value); + g_free (replace_value); + handled = TRUE; + } + + /* push the tag if not matched above */ + if (! handled) + g_string_append_len (dst, start, end - start + 1); + + g_free (token); + b = end + 1; + } + /* push rest of the buffer till the end of the line */ + g_string_append (dst, b); -/* - gchar *val = g_hash_table_lookup (table, "TAG"); - g_print ("replace_table_process: val = '%s'\n", val); -*/ + g_free (*buffer); + *buffer = g_string_free (dst, FALSE); } @@ -161,3 +165,64 @@ adjust_tags_parameter (char **str) str_replace (str, "\"", """); /* " */ str_replace (str, "'", "'"); /* ' */ } + + +/* -------------------------------------------------------------------------------------------------------- */ + + +/* + * get_next_token: retrieves first token ( or $(TOKEN)) in the string + * - returns newly allocated token name, caller is responsible for freeing + * - start and end are positions of token in the source string 's' + * - tag_parameter indicates where the token stands - as a tag itself ( ) + * or as a parameter value of some tag ( $(TOKEN) ) + * + */ +char * +get_next_token (const char *s, char **start, char **end, gboolean *tag_parameter) +{ + char *dollar; + char *end_brace; + char *b; + + *start = NULL; + *end = NULL; + if (tag_parameter) + *tag_parameter = TRUE; + + dollar = strstr (s, "$("); + if (dollar == NULL) + return NULL; + end_brace = strchr (dollar + 2, ')'); + if (end_brace == NULL) + return NULL; + + /* Go back and try to find placeholder beginning */ + for (b = dollar - 1; b >= s + 3; b--) { + if (*b == '-' && *(b-1) == '-' && *(b-2) == '!' && *(b-3) == '<') { + *start = b - 3; + if (tag_parameter) + *tag_parameter = FALSE; + break; + } + if (*b != ' ') + break; + } + if (*start == NULL) + *start = dollar; + + /* Go forth and try to find placeholder end */ + for (b = end_brace + 1; b <= end_brace + strlen (end_brace) - 3; b++) { + if (*b == '-' && *(b+1) == '-' && *(b+2) == '>') { + *end = b + 2; + break; + } + if (*b != ' ') + break; + } + if (*end == NULL) + *end = end_brace; + + return g_strndup (dollar + 2, end_brace - dollar - 2); +} + -- cgit v1.2.3