summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2011-06-04 17:30:12 +0200
committerTomas Bzatek <tbzatek@users.sourceforge.net>2011-06-04 17:30:12 +0200
commitfb5a52884dd17d17bab47de7f53c17c05ced6e1b (patch)
treefdb3873d295b615bfb1689c54fb76e3abb4e273f /src
parent960c477148cf832f79e89a4cdf9f3ce3389c7b06 (diff)
downloadcataract-fb5a52884dd17d17bab47de7f53c17c05ced6e1b.tar.xz
Introduce conditional system
This is very basic scripting support - simple value retrieval and block conditionals. Defines could be either static from theme setup or programatically added during page generation.
Diffstat (limited to 'src')
-rw-r--r--src/block-parser.c133
-rw-r--r--src/block-parser.h6
-rw-r--r--src/gallery-utils.c19
-rw-r--r--src/gallery-utils.h5
-rw-r--r--src/generators.c14
-rw-r--r--src/replace-table.c46
-rw-r--r--src/replace-table.h6
-rw-r--r--src/setup.c19
-rw-r--r--src/setup.h1
9 files changed, 218 insertions, 31 deletions
diff --git a/src/block-parser.c b/src/block-parser.c
index d4fcccb..cfe9047 100644
--- a/src/block-parser.c
+++ b/src/block-parser.c
@@ -23,7 +23,6 @@
#include <unistd.h>
#include <glib.h>
-#include <glib/gprintf.h>
#include "block-parser.h"
#include "gallery-utils.h"
@@ -38,6 +37,8 @@ struct BlockParser {
GHashTable *table;
GQueue *active_tree;
gchar *current_line;
+ GHashTable *conditionals;
+ guint ignore_level;
};
typedef struct {
@@ -45,6 +46,10 @@ typedef struct {
gchar *data;
gboolean used;
gboolean finished;
+
+ gboolean is_conditional;
+ gchar *conditional_key;
+ gboolean should_ignore;
} BlockData;
@@ -59,6 +64,7 @@ block_parser_destroy_notify (gpointer data)
g_free (d->replace_key);
g_free (d->data);
+ g_free (d->conditional_key);
g_free (d);
}
@@ -84,6 +90,17 @@ block_parser_free (BlockParser *parser)
g_free (parser);
}
+/*
+ * block_parser_set_conditionals: set a hash table to be used for conditionals lookup
+ *
+ */
+void
+block_parser_set_conditionals (BlockParser *parser, GHashTable *conditionals)
+{
+ g_return_if_fail (parser != NULL);
+
+ parser->conditionals = conditionals;
+}
/*
* block_parser_register_key: tell parser to expect the key to catch
@@ -103,10 +120,10 @@ block_parser_register_key (BlockParser *parser, const gchar *key, const gchar *r
if (replace_key)
data->replace_key = g_strdup_printf ("<!-- $(%s) -->", replace_key);
data->used = TRUE; /* buffer is empty, mask it for block_parser_has_unused_data() */
+ data->is_conditional = FALSE;
g_hash_table_replace (parser->table, g_strdup (key), data);
}
-
/*
* block_parser_get_data: return retrieved data or NULL if none read yet
* returns newly allocated string, caller is responsible for freeing
@@ -174,8 +191,18 @@ push_string (BlockParser *parser, const gchar *piece)
{
BlockData *data;
gchar *s;
+ guint i;
- data = g_queue_peek_head (parser->active_tree);
+ /* Test if the data should be ignored */
+ if (parser->ignore_level > 0)
+ return;
+
+ /* Not ignoring, find first non-conditional record */
+ for (i = 0; (data = g_queue_peek_nth (parser->active_tree, i)) != NULL; i++)
+ if (! data->is_conditional)
+ break;
+
+ /* Actually push the string */
if (data) {
if (data->data)
s = g_strdup_printf ("%s%s", data->data, piece);
@@ -192,6 +219,25 @@ push_string (BlockParser *parser, const gchar *piece)
}
}
+static gchar *
+extract_arg (const gchar *str)
+{
+ const gchar *start;
+ const gchar *end;
+
+ start = strstr (str, "(");
+ if (start == NULL)
+ return NULL;
+ start++;
+
+ end = strstr (str, ")");
+ if (end == NULL)
+ return NULL;
+ end++;
+
+ return g_strndup (start, end - start - 1);
+}
+
/*
* block_parser_read_and_parse: reads input from the file and returns parsed line
* - if there's a multiline block, string before the opening placeholder and
@@ -210,8 +256,8 @@ block_parser_read_and_parse (BlockParser *parser, FILE *stream)
gchar *token;
gchar *start, *end;
gchar *s;
- GList *keys;
- GList *l;
+ GHashTableIter iter;
+ gchar *key;
BlockData *data;
gboolean handled;
@@ -224,8 +270,6 @@ block_parser_read_and_parse (BlockParser *parser, FILE *stream)
}
parser->current_line = g_strdup ("");
- keys = g_hash_table_get_keys (parser->table);
-
/* find tokens */
b = buffer;
while ((token = get_next_token (b, &start, &end, NULL))) {
@@ -236,25 +280,77 @@ block_parser_read_and_parse (BlockParser *parser, FILE *stream)
push_string (parser, s);
g_free (s);
+ /* match conditionals */
+ if (parser->conditionals && (g_str_has_prefix (token, "ifdef(") || g_str_has_prefix (token, "ifndef("))) {
+ data = g_new0 (BlockData, 1);
+ data->is_conditional = TRUE;
+ data->conditional_key = extract_arg (token);
+ data->should_ignore = ((g_str_has_prefix (token, "ifdef(") && g_hash_table_lookup (parser->conditionals, data->conditional_key) == NULL) ||
+ (g_str_has_prefix (token, "ifndef(") && g_hash_table_lookup (parser->conditionals, data->conditional_key) != NULL));
+ if (data->should_ignore && parser->ignore_level == 0)
+ parser->ignore_level = 1;
+ else
+ if (parser->ignore_level > 0)
+ parser->ignore_level++;
+ g_queue_push_head (parser->active_tree, data);
+ handled = TRUE;
+ }
+
+ if (parser->conditionals && g_str_has_prefix (token, "endif(")) {
+ s = extract_arg (token);
+ data = g_queue_peek_head (parser->active_tree);
+ if (data == NULL || !data->is_conditional || strcmp (data->conditional_key, s) != 0) {
+ log_error ("block_parser_read_and_parse: something is wrong with the parser table: expected '%s' but got '%s'\n", s, data->conditional_key);
+ }
+ else {
+ g_queue_pop_head (parser->active_tree);
+ if (parser->ignore_level > 0)
+ parser->ignore_level--;
+ block_parser_destroy_notify (data);
+ handled = TRUE;
+ }
+ g_free (s);
+ }
+
+ if (parser->conditionals && g_str_has_prefix (token, "else(")) {
+ s = extract_arg (token);
+ data = g_queue_peek_head (parser->active_tree);
+ if (data == NULL || !data->is_conditional || strcmp (data->conditional_key, s) != 0) {
+ log_error ("block_parser_read_and_parse: something is wrong with the parser table: expected '%s' but got '%s'\n", s, data->conditional_key);
+ }
+ else {
+ data->should_ignore = ! data->should_ignore;
+ /* if we're not ignoring, level is zero, let's start ignoring by setting to one */
+ if (data->should_ignore && parser->ignore_level == 0)
+ parser->ignore_level = 1;
+ else
+ /* if we're ignoring but should not, let's go down to zero */
+ if (! data->should_ignore && parser->ignore_level == 1)
+ parser->ignore_level = 0;
+ /* in all other cases (level > 1) we're ignoring already and we're not the topmost block, so let's keep being ignored */
+ handled = TRUE;
+ }
+ g_free (s);
+ }
+
/* match known tags */
- for (l = keys; l != NULL; l = l->next) {
+ g_hash_table_iter_init (&iter, parser->table);
+ while (!handled && g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &data)) {
/* test BEGIN_ tokens */
- s = g_strdup_printf ("BEGIN_%s", (gchar *) l->data);
- if (strcmp (s, token) == 0) {
- data = g_hash_table_lookup (parser->table, (gchar *) l->data);
- if (data) {
- g_queue_push_head (parser->active_tree, data);
- handled = TRUE;
- }
+ s = g_strdup_printf ("BEGIN_%s", key);
+ if (strcmp (s, token) == 0 && data) {
+ g_queue_push_head (parser->active_tree, data);
+ handled = TRUE;
}
g_free (s);
+ if (handled)
+ break;
/* test END_ tokens */
- s = g_strdup_printf ("END_%s", (gchar *) l->data);
+ s = g_strdup_printf ("END_%s", key);
if (strcmp (s, token) == 0) {
- data = g_hash_table_lookup (parser->table, (gchar *) l->data);
if (data == NULL || data != g_queue_peek_head (parser->active_tree)) {
- log_error ("block_parser_read_and_parse: something is wrong with the parser table: expected '%s'\n", (gchar *) l->data);
+ log_error ("block_parser_read_and_parse: something is wrong with the parser table: expected '%s'\n", key);
}
else {
g_queue_pop_head (parser->active_tree);
@@ -282,7 +378,6 @@ block_parser_read_and_parse (BlockParser *parser, FILE *stream)
/* push rest of the buffer till the end of the line */
push_string (parser, b);
- g_list_free (keys);
g_free (buffer);
return parser->current_line;
}
diff --git a/src/block-parser.h b/src/block-parser.h
index 21d0cfb..96c7fb8 100644
--- a/src/block-parser.h
+++ b/src/block-parser.h
@@ -31,7 +31,11 @@ BlockParser * block_parser_new ();
void block_parser_free (BlockParser *parser);
-
+/*
+ * block_parser_set_conditionals: set a hash table to be used for conditionals lookup
+ *
+ */
+void block_parser_set_conditionals (BlockParser *parser, GHashTable *conditionals);
/*
* block_parser_register_key: tell parser to expect the key to catch
diff --git a/src/gallery-utils.c b/src/gallery-utils.c
index 494900c..3caff02 100644
--- a/src/gallery-utils.c
+++ b/src/gallery-utils.c
@@ -365,3 +365,22 @@ needs_update (const gchar *source, const gchar *dest)
return (src_stat.st_mtime > dst_stat.st_mtime);
}
+
+/*
+ * clone_string_hash_table: clones data from existing string hash table and returns newly-allocated copy
+ */
+GHashTable *
+clone_string_hash_table (GHashTable *hash_table)
+{
+ GHashTable *dest;
+ GHashTableIter iter;
+ gchar *key, *value;
+
+ dest = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ g_hash_table_iter_init (&iter, hash_table);
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
+ g_hash_table_insert (dest, g_strdup (key), g_strdup (value));
+
+ return dest;
+}
diff --git a/src/gallery-utils.h b/src/gallery-utils.h
index 29c7d8f..4559fa4 100644
--- a/src/gallery-utils.h
+++ b/src/gallery-utils.h
@@ -78,6 +78,11 @@ void log_error (const gchar *format, ...) G_GNUC_PRINTF (1, 2);
*/
gboolean needs_update (const gchar *source, const gchar *dest);
+/*
+ * clone_string_hash_table: clones data from existing string hash table and returns newly-allocated copy
+ */
+GHashTable * clone_string_hash_table (GHashTable *hash_table);
+
G_END_DECLS
diff --git a/src/generators.c b/src/generators.c
index 051ee28..4f0963d 100644
--- a/src/generators.c
+++ b/src/generators.c
@@ -280,6 +280,7 @@ write_html_album (TGallerySetup *setup,
ReplaceTable *local_replace_table;
BlockParser *block_parser;
TImageSize *image_size, *thumb_image_size;
+ GHashTable *defines;
fin = fopen (template_src, "r");
@@ -296,8 +297,10 @@ write_html_album (TGallerySetup *setup,
res = TRUE;
- global_replace_table = replace_table_new ();
+ global_replace_table = replace_table_new_from_defines (theme->defines);
block_parser = block_parser_new ();
+ defines = clone_string_hash_table (theme->defines);
+ block_parser_set_conditionals (block_parser, defines);
/* Get number of real pictures in the list */
real_total_items = 0;
@@ -460,7 +463,7 @@ write_html_album (TGallerySetup *setup,
}
/* Generate images (preview, original, thumbnail) */
- local_replace_table = replace_table_new ();
+ local_replace_table = replace_table_new_from_defines (defines);
s1 = NULL;
switch (item->type) {
@@ -546,6 +549,7 @@ write_html_album (TGallerySetup *setup,
fclose (fout);
fclose (fin);
+ g_hash_table_destroy (defines);
replace_table_free (global_replace_table);
block_parser_free (block_parser);
return res;
@@ -600,6 +604,7 @@ write_html_image (TGallerySetup *setup,
ReplaceTable *replace_table;
BlockParser *block_parser;
TImageSize *image_size;
+ GHashTable *defines;
fin = fopen (template_src, "r");
@@ -620,8 +625,10 @@ write_html_image (TGallerySetup *setup,
preload_imgname = NULL;
res = TRUE;
- replace_table = replace_table_new ();
+ replace_table = replace_table_new_from_defines (theme->defines);
block_parser = block_parser_new ();
+ defines = clone_string_hash_table (theme->defines);
+ block_parser_set_conditionals (block_parser, defines);
/* Get our index in the album */
item_index = 0;
@@ -927,6 +934,7 @@ write_html_image (TGallerySetup *setup,
g_free (img_orig_dst_page);
g_free (imgname);
g_free (preload_imgname);
+ g_hash_table_destroy (defines);
free_exif_data (exif);
replace_table_free (replace_table);
block_parser_free (block_parser);
diff --git a/src/replace-table.c b/src/replace-table.c
index 95d5e30..9cd02ea 100644
--- a/src/replace-table.c
+++ b/src/replace-table.c
@@ -37,6 +37,26 @@ replace_table_new ()
return (ReplaceTable *) g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
+/*
+ * replace_table_new_from_defines: creates new replace table object and fills it with defines from the hash table
+ *
+ */
+ReplaceTable *
+replace_table_new_from_defines (GHashTable *defines)
+{
+ GHashTable *table;
+ GHashTableIter iter;
+ gchar *key, *value;
+
+ table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ g_hash_table_iter_init (&iter, defines);
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
+ g_hash_table_insert (table, g_strdup_printf ("value(%s)", key), g_strdup (value));
+
+ return table;
+}
+
void
replace_table_free (ReplaceTable *table)
{
@@ -182,8 +202,9 @@ gchar *
get_next_token (const gchar *s, gchar **start, gchar **end, gboolean *tag_parameter)
{
gchar *dollar;
- gchar *end_brace;
+ gchar *end_paren;
gchar *b;
+ int num_paren;
*start = NULL;
*end = NULL;
@@ -193,10 +214,23 @@ get_next_token (const gchar *s, gchar **start, gchar **end, gboolean *tag_parame
dollar = strstr (s, "$(");
if (dollar == NULL)
return NULL;
- end_brace = strchr (dollar + 2, ')');
- if (end_brace == NULL)
+ end_paren = strchr (dollar + 2, ')');
+ if (end_paren == NULL)
return NULL;
+ /* Count opening parentheses and include nested parentheses in the token */
+ num_paren = 0;
+ for (b = dollar; b < end_paren; b++)
+ if (*b == '(')
+ num_paren++;
+ while (num_paren > 1) {
+ end_paren = strchr (end_paren + 1, ')');
+ if (end_paren == NULL)
+ return NULL;
+ num_paren--;
+ }
+ g_assert (num_paren <= 1); /* something really bad happened */
+
/* Go back and try to find placeholder beginning */
for (b = dollar - 1; b >= s + 3; b--) {
if (*b == '-' && *(b-1) == '-' && *(b-2) == '!' && *(b-3) == '<') {
@@ -212,7 +246,7 @@ get_next_token (const gchar *s, gchar **start, gchar **end, gboolean *tag_parame
*start = dollar;
/* Go forth and try to find placeholder end */
- for (b = end_brace + 1; b <= end_brace + strlen (end_brace) - 3; b++) {
+ for (b = end_paren + 1; b <= end_paren + strlen (end_paren) - 3; b++) {
if (*b == '-' && *(b+1) == '-' && *(b+2) == '>') {
*end = b + 2;
break;
@@ -221,8 +255,8 @@ get_next_token (const gchar *s, gchar **start, gchar **end, gboolean *tag_parame
break;
}
if (*end == NULL)
- *end = end_brace;
+ *end = end_paren;
- return g_strndup (dollar + 2, end_brace - dollar - 2);
+ return g_strndup (dollar + 2, end_paren - dollar - 2);
}
diff --git a/src/replace-table.h b/src/replace-table.h
index 916af2b..799956d 100644
--- a/src/replace-table.h
+++ b/src/replace-table.h
@@ -28,6 +28,12 @@ typedef GHashTable ReplaceTable;
ReplaceTable * replace_table_new ();
+/*
+ * replace_table_new_from_defines: creates new replace table object and fills it with defines from the hash table
+ *
+ */
+ReplaceTable * replace_table_new_from_defines (GHashTable *defines);
+
void replace_table_free (ReplaceTable *table);
diff --git a/src/setup.c b/src/setup.c
index 83c5504..3a2a66d 100644
--- a/src/setup.c
+++ b/src/setup.c
@@ -143,11 +143,12 @@ parse_design_setup_xml (const gchar *filename)
TXMLFile *xml;
gchar *s;
gchar *s2;
+ gchar *s3;
TGalleryDesign *design;
TImageSize *image_size;
TGalleryDesignTheme *theme;
- int count;
- int i;
+ int count, c;
+ int i, j;
xml = xml_parser_load (filename);
if (xml == NULL)
@@ -240,6 +241,19 @@ parse_design_setup_xml (const gchar *filename)
g_free (s2);
}
g_free (s);
+
+ theme->defines = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ s = g_strdup_printf ("/design_setup/theme[%d]/define", i + 1);
+ c = xml_file_node_get_children_count (xml, s);
+ g_free (s);
+ for (j = 0; j < c; j++) {
+ s = g_strdup_printf ("/design_setup/theme[%d]/define[%d]", i + 1, j + 1);
+ s2 = xml_file_get_node_attribute (xml, s, "name");
+ s3 = xml_file_get_node_attribute (xml, s, "value");
+ if (s2)
+ g_hash_table_replace (theme->defines, s2, s3 ? s3 : g_strdup (""));
+ g_free (s);
+ }
}
xml_parser_free (xml);
@@ -397,6 +411,7 @@ free_design_theme_data (TGalleryDesignTheme *theme)
g_free (theme->picture_filename);
g_free (theme->picture_image_size);
g_strfreev (theme->supplemental_files);
+ g_hash_table_destroy (theme->defines);
g_free (theme);
}
}
diff --git a/src/setup.h b/src/setup.h
index 69e92b6..a96a73f 100644
--- a/src/setup.h
+++ b/src/setup.h
@@ -109,6 +109,7 @@ typedef struct {
gchar *picture_filename;
gchar *picture_image_size;
gchar **supplemental_files;
+ GHashTable *defines;
} TGalleryDesignTheme;
struct TGalleryDesign {