# HG changeset patch # User William Pitcock # Date 1186665728 18000 # Node ID 740c6f8455549baa233e96dd5078553e900adbca # Parent 70789a2a5a65e5c81cfa8b6c0ffe13277408d076 revise tuple formatting engine logic diff -r 70789a2a5a65 -r 740c6f845554 src/audacious/tuple_formatter.c --- a/src/audacious/tuple_formatter.c Thu Aug 09 06:21:09 2007 -0500 +++ b/src/audacious/tuple_formatter.c Thu Aug 09 08:22:08 2007 -0500 @@ -50,7 +50,7 @@ typedef struct { Tuple *tuple; - GString str; + GString *str; } TupleFormatterContext; /* processes a construct, e.g. "${?artist:artist is defined}" would @@ -66,51 +66,74 @@ g_return_val_if_fail(string != NULL, NULL); ctx = g_new0(TupleFormatterContext, 1); + ctx->str = g_string_new(""); + /* parsers are ugly */ for (iter = string; *iter != '\0'; iter++) { /* if it's raw text, just copy the byte */ if (*iter != '$') - g_string_append_c(&ctx->str, *iter); + g_string_append_c(ctx->str, *iter); else if (*(iter + 1) == '{') { - GString expression = {}; - GString argument = {}; - GString *sel = &expression; + GString *expression = g_string_new(""); + GString *argument = g_string_new(""); + GString *sel = expression; gchar *result; + gint level = 0; for (iter += 2; *iter != '\0'; iter++) { - switch(*iter) + if (*iter == ':') + { + sel = argument; + continue; + } + + if (g_str_has_prefix(iter, "${") == TRUE) { - case '}': - break; - case ':': - sel = &argument; - break; - default: + if (sel == argument) + { + g_string_append_c(sel, *iter); + level++; + } + } + else if (*iter == '}' && (sel == argument && --level != 0)) g_string_append_c(sel, *iter); + else if (*iter == '}' && ((sel != argument) || (sel == argument && level == 0))) + { + if (sel == argument) + iter++; break; } + else + g_string_append_c(sel, *iter); } - if (expression.len == 0) + if (expression->len == 0) + { + g_string_free(expression, TRUE); + g_string_free(argument, TRUE); continue; + } - result = tuple_formatter_process_expr(tuple, expression.str, argument.len ? argument.str : NULL); + result = tuple_formatter_process_expr(tuple, expression->str, argument->len ? argument->str : NULL); if (result != NULL) { - g_string_append(&ctx->str, result); + g_string_append(ctx->str, result); g_free(result); } - g_free(expression.str); - g_free(argument.str); + g_string_free(expression, TRUE); + g_string_free(argument, TRUE); + + if (*iter == '\0') + break; } } - out = g_strdup(ctx->str.str); - g_free(ctx->str.str); + out = g_strdup(ctx->str->str); + g_string_free(ctx->str, TRUE); g_free(ctx); return out; @@ -138,7 +161,7 @@ { TupleFormatterExpression *tmp = (TupleFormatterExpression *) iter->data; - if (g_str_has_prefix(tmp->name, expression) == TRUE) + if (g_str_has_prefix(expression, tmp->name) == TRUE) { expr = tmp; expression += strlen(tmp->name); @@ -209,5 +232,5 @@ initialized = TRUE; } - return tuple_formatter_process_string(tuple, string); + return tuple_formatter_process_construct(tuple, string); } diff -r 70789a2a5a65 -r 740c6f845554 src/tests/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tests/Makefile Thu Aug 09 08:22:08 2007 -0500 @@ -0,0 +1,30 @@ +include ../../mk/rules.mk +include ../../mk/init.mk +include ../../mk/objective.mk + +OBJECTIVE_LIBS_NOINST = tuple_formatter_test + +LDFLAGS += $(AUDLDFLAGS) +LDADD = \ + $(DBUS_LIBS) \ + $(GTK_LIBS) \ + $(MOWGLI_LIBS) \ + $(LIBGLADE_LIBS) + +CFLAGS += \ + $(GTK_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(LIBGLADE_CFLAGS) \ + $(BEEP_DEFINES) \ + $(ARCH_DEFINES) \ + $(MOWGLI_CFLAGS) \ + -I.. -I../.. \ + -I../intl -I../audacious + +COMMON_OBJS = test_harness.o +TFT_OBJS = $(COMMON_OBJS) tuple_formatter_test.o ../audacious/tuple.o ../audacious/tuple_formatter.o +tuple_formatter_test: $(TFT_OBJS) + $(CC) $(LDFLAGS) $(TFT_OBJS) $(LDADD) -o $@ + @printf "%10s %-20s\n" LINK $@ + ./$@ + @printf "%10s %-20s\n" TEST-PASS $@ diff -r 70789a2a5a65 -r 740c6f845554 src/tests/test_harness.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tests/test_harness.c Thu Aug 09 08:22:08 2007 -0500 @@ -0,0 +1,38 @@ +/* + * Audacious + * Copyright (c) 2007 William Pitcock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include +#include + +extern int test_run(gint argc, const gchar *argv[]); + +int +main(gint argc, const gchar *argv[]) +{ + g_thread_init(NULL); + + mowgli_init(); + + if (!g_thread_supported()) + mowgli_log("Warning: GThread not supported. Some tests may fail."); + + return test_run(argc, argv); +} + diff -r 70789a2a5a65 -r 740c6f845554 src/tests/tuple_formatter_test.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tests/tuple_formatter_test.c Thu Aug 09 08:22:08 2007 -0500 @@ -0,0 +1,62 @@ +/* + * Audacious + * Copyright (c) 2007 William Pitcock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include +#include + +#include "tuple.h" +#include "tuple_formatter.h" + +int +test_run(int argc, const char *argv[]) +{ + Tuple *tuple; + gchar *tstr; + + tuple = tuple_new(); + tuple_associate_string(tuple, "splork", "moo"); + tuple_associate_int(tuple, "splorkerz", 42); + + tstr = tuple_formatter_process_string(tuple, "${splork} ${splorkerz}"); + if (g_ascii_strcasecmp(tstr, "moo 42")) + { + g_print("fail 1: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + + tstr = tuple_formatter_process_string(tuple, "${?fizz:${splork}} ${splorkerz}"); + if (g_ascii_strcasecmp(tstr, " 42")) + { + g_print("fail 2: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + + tstr = tuple_formatter_process_string(tuple, "${?splork:${splork}} ${splorkerz}"); + if (g_ascii_strcasecmp(tstr, "moo 42")) + { + g_print("fail 3: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + + return EXIT_SUCCESS; +}