summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2014-09-13 20:37:57 +0200
committerTomas Bzatek <tbzatek@users.sourceforge.net>2014-09-13 20:37:57 +0200
commitdc32c58499caa8b1ec4e975afad75ca0d862e990 (patch)
tree91322afabcb457406ab512d20163f0dd73ce2c5a
parent302127b03d44277c829642468561ac9e518b7a21 (diff)
downloadcataract-dc32c58499caa8b1ec4e975afad75ca0d862e990.tar.xz
Introduce properties table
This is a new internal properties storage for attributes that can be defined both in the item and album scope, with the item scope taking priority. The big advantage is a better distinguishment from an undefined, default value. It also makes easier to retrieve attributes with properly defined scope priorities.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/generators.c71
-rw-r--r--src/items.c109
-rw-r--r--src/items.h50
-rw-r--r--src/properties-table.c227
-rw-r--r--src/properties-table.h62
-rw-r--r--src/setup.c56
-rw-r--r--src/xml-parser.c74
-rw-r--r--src/xml-parser.h61
9 files changed, 581 insertions, 131 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 0553245..5a4d3b2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,6 +33,8 @@ cgg_SOURCES = \
job-manager.c \
jpeg-utils.cpp \
jpeg-utils.h \
+ properties-table.c \
+ properties-table.h \
replace-table.c \
replace-table.h \
setup.c \
diff --git a/src/generators.c b/src/generators.c
index c51f24e..2483175 100644
--- a/src/generators.c
+++ b/src/generators.c
@@ -159,21 +159,11 @@ metadata_apply_overrides (ExifData *exif_data,
g_free (exif_data->override_copyright);
exif_data->override_copyright = g_strdup (setup->add_copyright);
- exif_data->timezone_shift = item->metadata_tz_shift;
- if (exif_data->timezone_shift == 0)
- exif_data->timezone_shift = items->metadata_tz_shift;
+ exif_data->timezone_shift = get_prop_int (items, item, PROP_METADATA_TZ_SHIFT, 0);
- exif_data->override_datetime = item->metadata_override_datetime;
- if (exif_data->override_datetime == (time_t) -1)
- exif_data->override_datetime = items->metadata_override_datetime;
-
- exif_data->override_aperture = item->metadata_override_aperture;
- if (exif_data->override_aperture == -1)
- exif_data->override_aperture = items->metadata_override_aperture;
-
- exif_data->override_focal_length = item->metadata_override_focal_length;
- if (exif_data->override_focal_length == -1)
- exif_data->override_focal_length = items->metadata_override_focal_length;
+ exif_data->override_datetime = get_prop_double (items, item, PROP_METADATA_OVERRIDE_DATETIME, (time_t) -1);
+ exif_data->override_aperture = get_prop_double (items, item, PROP_METADATA_OVERRIDE_APERTURE, -1);
+ exif_data->override_focal_length = get_prop_double (items, item, PROP_METADATA_OVERRIDE_FOCAL_LENGTH, -1);
g_free (exif_data->external_exif_data);
exif_data->external_exif_data = NULL;
@@ -182,9 +172,7 @@ metadata_apply_overrides (ExifData *exif_data,
exif_data->squared_thumbnail_type = setup->squared_thumbnail_type;
- exif_data->thumbnail_crop_hint = item->thumbnail_crop_hint;
- if (exif_data->thumbnail_crop_hint == CROP_HINT_UNDEFINED)
- exif_data->thumbnail_crop_hint = items->thumbnail_crop_hint;
+ exif_data->thumbnail_crop_hint = get_prop_int (items, item, PROP_THUMB_CROP_HINT, CROP_HINT_UNDEFINED);
}
@@ -206,6 +194,7 @@ generate_image (TGallerySetup *setup,
gchar *img_src;
gchar *img_dst;
unsigned long img_w, img_h;
+ unsigned long tmpw, tmph;
int quality;
GList *l;
TImageSize *image_size;
@@ -251,29 +240,37 @@ generate_image (TGallerySetup *setup,
if (img_w > 0 && img_h > 0) {
stats_images_inc ();
- /* Calculate sizes */
+ /* Only the "preview" size is affected by deprecated item and album overrides */
+ if (is_preview) {
+ tmpw = get_prop_int (items, item, PROP_WIDTH, img_w);
+ tmph = get_prop_int (items, item, PROP_HEIGHT, img_h);
+ calculate_sizes (tmpw, tmph, &img_w, &img_h);
+ }
if (is_thumbnail && setup->squared_thumbnail_type != THUMBNAIL_SQUARE_TYPE_NONE)
- img_w = img_h = image_size->square_size;
+ tmpw = tmph = image_size->square_size;
else
- if (is_preview && item->width > 0 && item->height > 0)
- calculate_sizes (item->width, item->height, &img_w, &img_h);
+ /* Calculate sizes */
if (img_w > img_h) {
- if (is_preview && items->landscape_width > 0 && items->landscape_height > 0)
- calculate_sizes (items->landscape_width, items->landscape_height, &img_w, &img_h);
- else
- calculate_sizes (image_size->landscape_width, image_size->landscape_height, &img_w, &img_h);
+ tmpw = image_size->landscape_width;
+ tmph = image_size->landscape_height;
+ if (is_preview) {
+ tmpw = get_prop_int (items, item, PROP_LANDSCAPE_W, tmpw);
+ tmph = get_prop_int (items, item, PROP_LANDSCAPE_H, tmph);
+ }
} else {
- if (is_preview && items->portrait_width > 0 && items->portrait_height > 0)
- calculate_sizes (items->portrait_width, items->portrait_height, &img_w, &img_h);
- else
- calculate_sizes (image_size->portrait_width, image_size->portrait_height, &img_w, &img_h);
+ tmpw = image_size->portrait_width;
+ tmph = image_size->portrait_height;
+ if (is_preview) {
+ tmpw = get_prop_int (items, item, PROP_PORTRAIT_W, tmpw);
+ tmph = get_prop_int (items, item, PROP_PORTRAIT_H, tmph);
+ }
}
+ calculate_sizes (tmpw, tmph, &img_w, &img_h);
/* Calculate quality */
- quality = image_size->quality;
- if (is_preview && items->quality > 0 && items->quality <= 100)
- quality = items->quality;
- if (is_preview && item->quality > 0 && item->quality <= 100)
- quality = item->quality;
+ if (is_preview)
+ quality = get_prop_int (items, item, PROP_QUALITY, image_size->quality);
+ else
+ quality = image_size->quality;
/* Perform resize and strip */
if (! resize_image (img_src, img_dst, img_w, img_h, quality, is_thumbnail, setup->autorotate, exif_data))
@@ -946,11 +943,9 @@ write_html_image (TGallerySetup *setup,
block_parser_register_function (block_parser, "has_exif_key", has_exif_key_cb, exif);
/* Border style */
- s1 = item->border_style;
- if (s1 == NULL)
- s1 = parent_items->border_style;
+ s1 = get_prop_string (parent_items, item, PROP_BORDER_STYLE, NULL);
if (s1)
- g_hash_table_replace (defines, g_strdup ("BORDER_STYLE"), g_strdup (s1));
+ g_hash_table_replace (defines, g_strdup ("BORDER_STYLE"), s1);
/* Next/Previous links */
if (next_item) {
diff --git a/src/items.c b/src/items.c
index 2434c77..d720415 100644
--- a/src/items.c
+++ b/src/items.c
@@ -131,6 +131,7 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info)
return NULL;
index = g_malloc0 (sizeof (TAlbum));
+ index->properties = properties_table_new ();
/* Retrieve gallery type */
gallery_type = xml_file_get_node_attribute (xml, "/gallery", "type");
@@ -160,36 +161,35 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info)
g_free (s);
}
- index->quality = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "quality", -1);
- index->landscape_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_w", 0);
- index->landscape_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_h", 0);
- index->portrait_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_w", 0);
- index->portrait_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_h", 0);
+ prop_xml_attr_long (index->properties, PROP_QUALITY, xml, "/gallery/general/images", "quality");
+ prop_xml_attr_long (index->properties, PROP_LANDSCAPE_W, xml, "/gallery/general/images", "landscape_w");
+ prop_xml_attr_long (index->properties, PROP_LANDSCAPE_H, xml, "/gallery/general/images", "landscape_h");
+ prop_xml_attr_long (index->properties, PROP_PORTRAIT_W, xml, "/gallery/general/images", "portrait_w");
+ prop_xml_attr_long (index->properties, PROP_PORTRAIT_H, xml, "/gallery/general/images", "portrait_h");
- index->border_style = xml_file_get_node_attribute (xml, "/gallery/general/border", "style");
+ prop_xml_attr (index->properties, PROP_BORDER_STYLE, xml, "/gallery/general/border", "style");
index->meta_author = xml_file_get_node_value (xml, "/gallery/general/meta/author/text()");
index->meta_description = xml_file_get_node_value (xml, "/gallery/general/meta/description/text()");
index->meta_keywords = xml_file_get_node_value (xml, "/gallery/general/meta/keywords/text()");
s = xml_file_get_node_attribute (xml, "/gallery/general/metadata/timezone", "shift");
if (s != NULL) {
- index->metadata_tz_shift = parse_timezone_string (s);
+ properties_table_add_int (index->properties, PROP_METADATA_TZ_SHIFT, parse_timezone_string (s));
g_free (s);
}
- index->metadata_override_datetime = (time_t) -1;
s = xml_file_get_node_attribute (xml, "/gallery/general/metadata/override", "date");
if (s != NULL) {
- index->metadata_override_datetime = parse_datetime_string (s);
+ properties_table_add_double (index->properties, PROP_METADATA_OVERRIDE_DATETIME, parse_datetime_string (s));
g_free (s);
}
- index->metadata_override_aperture = xml_file_get_node_attribute_double (xml, "/gallery/general/metadata/override", "aperture", -1);
- index->metadata_override_focal_length = xml_file_get_node_attribute_double (xml, "/gallery/general/metadata/override", "focal_length", -1);
+ prop_xml_attr_double (index->properties, PROP_METADATA_OVERRIDE_APERTURE, xml, "/gallery/general/metadata/override", "aperture");
+ prop_xml_attr_double (index->properties, PROP_METADATA_OVERRIDE_FOCAL_LENGTH, xml, "/gallery/general/metadata/override", "focal_length");
/* TODO: add support for lens name */
s = xml_file_get_node_attribute (xml, "/gallery/general/thumbnail", "crop");
if (s != NULL) {
- index->thumbnail_crop_hint = parse_thumbnail_crop_hint (s);
+ properties_table_add_int (index->properties, PROP_THUMB_CROP_HINT, parse_thumbnail_crop_hint (s));
g_free (s);
}
@@ -253,6 +253,7 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info)
continue;
item = g_malloc0 (sizeof (TIndexItem));
+ item->properties = properties_table_new ();
if (strcmp (node_name, "item") == 0) {
item->type = INDEX_ITEM_TYPE_PICTURE;
@@ -263,10 +264,10 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info)
else
item->path = xml_file_get_node_attribute (xml, s, "src");
item->preview = xml_file_get_node_attribute (xml, s, "preview");
- item->quality = xml_file_get_node_attribute_long (xml, s, "quality", -1);
- item->width = xml_file_get_node_attribute_long (xml, s, "width", 0);
- item->height = xml_file_get_node_attribute_long (xml, s, "height", 0);
- item->border_style = xml_file_get_node_attribute (xml, s, "border");
+ prop_xml_attr_long (item->properties, PROP_QUALITY, xml, s, "quality");
+ prop_xml_attr_long (item->properties, PROP_WIDTH, xml, s, "width");
+ prop_xml_attr_long (item->properties, PROP_HEIGHT, xml, s, "height");
+ prop_xml_attr (item->properties, PROP_BORDER_STYLE, xml, s, "border");
if (index->type == GALLERY_TYPE_ALBUM)
item->thumbnail = xml_file_get_node_attribute (xml, s, "thumbnail");
g_free (s);
@@ -325,19 +326,18 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info)
s2 = xml_file_get_node_attribute (xml, s, "shift");
g_free (s);
if (s2 != NULL) {
- item->metadata_tz_shift = parse_timezone_string (s2);
+ properties_table_add_int (item->properties, PROP_METADATA_TZ_SHIFT, parse_timezone_string (s2));
g_free (s2);
}
- item->metadata_override_datetime = (time_t) -1;
s = g_strdup_printf ("/gallery/items/*[%d]/metadata/override", i + 1);
s2 = xml_file_get_node_attribute (xml, s, "date");
if (s2 != NULL) {
- item->metadata_override_datetime = parse_datetime_string (s2);
+ properties_table_add_double (item->properties, PROP_METADATA_OVERRIDE_DATETIME, parse_datetime_string (s2));
g_free (s2);
}
- item->metadata_override_aperture = xml_file_get_node_attribute_double (xml, s, "aperture", -1);
- item->metadata_override_focal_length = xml_file_get_node_attribute_double (xml, s, "focal_length", -1);
+ prop_xml_attr_double (item->properties, PROP_METADATA_OVERRIDE_APERTURE, xml, s, "aperture");
+ prop_xml_attr_double (item->properties, PROP_METADATA_OVERRIDE_FOCAL_LENGTH, xml, s, "focal_length");
/* TODO: add support for lens name */
g_free (s);
@@ -345,7 +345,7 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info)
s2 = xml_file_get_node_attribute (xml, s, "crop");
g_free (s);
if (s2 != NULL) {
- item->thumbnail_crop_hint = parse_thumbnail_crop_hint (s2);
+ properties_table_add_int (item->properties, PROP_THUMB_CROP_HINT, parse_thumbnail_crop_hint (s2));
g_free (s2);
}
@@ -408,8 +408,8 @@ dup_index_item (TIndexItem *item)
i->title_description = g_strdup (item->title_description);
i->thumbnail = g_strdup (item->thumbnail);
i->preview = g_strdup (item->preview);
- i->border_style = g_strdup (item->border_style);
i->metadata_external_exif = g_strdup (item->metadata_external_exif);
+ i->properties = properties_table_dup (item->properties);
return i;
}
@@ -426,8 +426,8 @@ free_index_item (TIndexItem *item)
g_free (item->title_description);
g_free (item->thumbnail);
g_free (item->preview);
- g_free (item->border_style);
g_free (item->metadata_external_exif);
+ properties_table_free (item->properties);
g_free (item);
}
}
@@ -443,7 +443,6 @@ free_album_data (TAlbum *album)
g_free (album->title);
g_free (album->desc);
g_free (album->footnote);
- g_free (album->border_style);
g_free (album->meta_author);
g_free (album->meta_description);
g_free (album->meta_keywords);
@@ -456,6 +455,7 @@ free_album_data (TAlbum *album)
g_ptr_array_foreach (album->items, (GFunc) free_index_item, NULL);
g_ptr_array_free (album->items, TRUE);
}
+ properties_table_free (album->properties);
g_free (album);
}
}
@@ -565,3 +565,62 @@ free_path_info (TPathInfo *path_info)
g_free (path_info);
}
}
+
+
+/*
+ * get_prop_*: retrieve attribute value from properties tables, with item taking priority, using items otherwise or falling back to default if not set anywhere
+ */
+gchar *
+get_prop_string (TAlbum *items, TIndexItem *item, PropertyName name, const gchar *_default)
+{
+ const gchar *s = NULL;
+
+ if (item)
+ s = properties_table_get_string (item->properties, name);
+ if (!s && items)
+ s = properties_table_get_string (items->properties, name);
+
+ return g_strdup (s ? s : _default);
+}
+
+long int
+get_prop_int (TAlbum *items, TIndexItem *item, PropertyName name, const long int _default)
+{
+ long int i = _default;
+ gboolean res = FALSE;
+
+ if (item)
+ res = properties_table_get_int (item->properties, name, &i);
+ if (!res && items)
+ res = properties_table_get_int (items->properties, name, &i);
+
+ return i;
+}
+
+gboolean
+get_prop_bool (TAlbum *items, TIndexItem *item, PropertyName name, const gboolean _default)
+{
+ gboolean b = _default;
+ gboolean res = FALSE;
+
+ if (item)
+ res = properties_table_get_bool (item->properties, name, &b);
+ if (!res && items)
+ res = properties_table_get_bool (items->properties, name, &b);
+
+ return b;
+}
+
+double
+get_prop_double (TAlbum *items, TIndexItem *item, PropertyName name, const double _default)
+{
+ double d = _default;
+ gboolean res = FALSE;
+
+ if (item)
+ res = properties_table_get_double (item->properties, name, &d);
+ if (!res && items)
+ res = properties_table_get_double (items->properties, name, &d);
+
+ return d;
+}
diff --git a/src/items.h b/src/items.h
index 792b7f0..46b4c38 100644
--- a/src/items.h
+++ b/src/items.h
@@ -19,6 +19,7 @@
#define __CGG__ITEMS_H__
#include <glib.h>
+#include "properties-table.h"
G_BEGIN_DECLS
@@ -57,12 +58,6 @@ typedef struct {
GPtrArray *items;
void *parent_index; /* pointer to the parent TAlbum structure */
int parent_item_index; /* item index in the parent album */
- int quality;
- unsigned long landscape_width;
- unsigned long landscape_height;
- unsigned long portrait_width;
- unsigned long portrait_height;
- gchar *border_style;
gchar *meta_author;
gchar *meta_description;
gchar *meta_keywords;
@@ -73,33 +68,21 @@ typedef struct {
gchar *auth_username;
gchar *auth_passwd;
TAuthType auth_type;
- int metadata_tz_shift; /* minutes */
- time_t metadata_override_datetime;
- double metadata_override_aperture;
- double metadata_override_focal_length;
- TCropHint thumbnail_crop_hint;
+ PropertiesTable *properties;
} TAlbum;
typedef struct {
+ TIndexItemType type;
gchar *path;
gchar *title;
gchar *title_description;
gchar *thumbnail;
gchar *preview;
- int quality;
- unsigned long width;
- unsigned long height;
gboolean force_nofullsize;
gboolean force_fullsize;
- gchar *border_style;
- TIndexItemType type;
gboolean hidden;
gchar *metadata_external_exif;
- int metadata_tz_shift; /* minutes */
- time_t metadata_override_datetime;
- double metadata_override_aperture;
- double metadata_override_focal_length;
- TCropHint thumbnail_crop_hint;
+ PropertiesTable *properties;
} TIndexItem;
typedef struct {
@@ -111,6 +94,21 @@ typedef struct {
gchar *album_path; /* current path in the gallery hierarchy, starting with '/' */
} TPathInfo;
+typedef enum {
+ PROP_QUALITY,
+ PROP_WIDTH,
+ PROP_HEIGHT,
+ PROP_LANDSCAPE_W,
+ PROP_LANDSCAPE_H,
+ PROP_PORTRAIT_W,
+ PROP_PORTRAIT_H,
+ PROP_BORDER_STYLE,
+ PROP_THUMB_CROP_HINT,
+ PROP_METADATA_TZ_SHIFT, /* minutes */
+ PROP_METADATA_OVERRIDE_DATETIME,
+ PROP_METADATA_OVERRIDE_APERTURE,
+ PROP_METADATA_OVERRIDE_FOCAL_LENGTH,
+} PropertyName;
/*
* GET_ITEM_TARGET_FILENAME: get target item filename
@@ -157,6 +155,16 @@ TIndexItem *dup_index_item (TIndexItem *item);
*/
void free_index_item (TIndexItem *item);
+
+/*
+ * get_prop_*: retrieve attribute value from properties tables, with item taking priority, using items otherwise or falling back to default if not set anywhere
+ */
+gchar * get_prop_string (TAlbum *items, TIndexItem *item, PropertyName name, const gchar *_default);
+long int get_prop_int (TAlbum *items, TIndexItem *item, PropertyName name, const long int _default);
+gboolean get_prop_bool (TAlbum *items, TIndexItem *item, PropertyName name, const gboolean _default);
+double get_prop_double (TAlbum *items, TIndexItem *item, PropertyName name, const double _default);
+
+
G_END_DECLS
#endif /* __CGG__ITEMS_H__ */
diff --git a/src/properties-table.c b/src/properties-table.c
new file mode 100644
index 0000000..19d7a36
--- /dev/null
+++ b/src/properties-table.c
@@ -0,0 +1,227 @@
+/* Cataract - Static web photo gallery generator
+ * Copyright (C) 2014 Tomas Bzatek <tbzatek@users.sourceforge.net>
+ *
+ * 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; either version 2
+ * of the License, or any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include <string.h>
+
+#include <glib.h>
+
+#include "properties-table.h"
+
+
+typedef enum {
+ PROP_DATA_TYPE_STRING,
+ PROP_DATA_TYPE_INT,
+ PROP_DATA_TYPE_BOOL,
+ PROP_DATA_TYPE_DOUBLE
+} PropertyDataType;
+
+typedef struct {
+ PropertyDataType type;
+ union {
+ gchar *s;
+ long int i;
+ gboolean b;
+ double d;
+ } data;
+} PropertyData;
+
+
+static void
+free_property_data (PropertyData *data)
+{
+ if (data == NULL)
+ return;
+
+ switch (data->type) {
+ case PROP_DATA_TYPE_STRING:
+ g_free (data->data.s);
+ break;
+ default:
+ break;
+ }
+ g_free (data);
+}
+
+
+/*
+ * properties_table_new: creates new property table
+ */
+PropertiesTable *
+properties_table_new ()
+{
+ return g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) free_property_data);
+}
+
+/*
+ * properties_table_dup: creates deep copy of the table
+ */
+PropertiesTable *
+properties_table_dup (PropertiesTable *table)
+{
+ PropertiesTable *t;
+ GHashTableIter iter;
+ gpointer key, value;
+ PropertyData *data;
+
+ g_return_val_if_fail (table != NULL, NULL);
+
+ t = properties_table_new ();
+ g_hash_table_iter_init (&iter, table);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ data = (PropertyData *) value;
+ switch (data->type) {
+ case PROP_DATA_TYPE_STRING:
+ properties_table_add_string (t, GPOINTER_TO_INT (key), data->data.s);
+ break;
+ case PROP_DATA_TYPE_INT:
+ properties_table_add_int (t, GPOINTER_TO_INT (key), data->data.i);
+ break;
+ case PROP_DATA_TYPE_BOOL:
+ properties_table_add_bool (t, GPOINTER_TO_INT (key), data->data.b);
+ break;
+ case PROP_DATA_TYPE_DOUBLE:
+ properties_table_add_double (t, GPOINTER_TO_INT (key), data->data.d);
+ break;
+ }
+ }
+
+ return t;
+}
+
+/*
+ * properties_table_free: destroys properties table and frees all data
+ */
+void
+properties_table_free (PropertiesTable *table)
+{
+ g_assert (table != NULL);
+ g_hash_table_destroy (table);
+}
+
+void
+properties_table_add_string (PropertiesTable *table, int property_id, const gchar *value)
+{
+ PropertyData *data;
+
+ g_assert (table != NULL);
+
+ data = g_malloc0 (sizeof (PropertyData));
+ data->type = PROP_DATA_TYPE_STRING;
+ data->data.s = g_strdup (value);
+ g_hash_table_replace (table, GINT_TO_POINTER (property_id), data);
+}
+
+void
+properties_table_add_int (PropertiesTable *table, int property_id, long int value)
+{
+ PropertyData *data;
+
+ g_assert (table != NULL);
+
+ data = g_malloc0 (sizeof (PropertyData));
+ data->type = PROP_DATA_TYPE_INT;
+ data->data.i = value;
+ g_hash_table_replace (table, GINT_TO_POINTER (property_id), data);
+}
+
+void
+properties_table_add_bool (PropertiesTable *table, int property_id, gboolean value)
+{
+ PropertyData *data;
+
+ g_assert (table != NULL);
+
+ data = g_malloc0 (sizeof (PropertyData));
+ data->type = PROP_DATA_TYPE_BOOL;
+ data->data.b = value;
+ g_hash_table_replace (table, GINT_TO_POINTER (property_id), data);
+}
+
+void
+properties_table_add_double (PropertiesTable *table, int property_id, double value)
+{
+ PropertyData *data;
+
+ g_assert (table != NULL);
+
+ data = g_malloc0 (sizeof (PropertyData));
+ data->type = PROP_DATA_TYPE_DOUBLE;
+ data->data.d = value;
+ g_hash_table_replace (table, GINT_TO_POINTER (property_id), data);
+}
+
+
+/*
+ * properties_table_get_*: gets data for the specified id
+ */
+const gchar *
+properties_table_get_string (PropertiesTable *table, int property_id)
+{
+ PropertyData *data;
+
+ g_assert (table != NULL);
+
+ data = g_hash_table_lookup (table, GINT_TO_POINTER (property_id));
+ if (data && data->type == PROP_DATA_TYPE_STRING)
+ return data->data.s;
+ return NULL;
+}
+
+gboolean
+properties_table_get_int (PropertiesTable *table, int property_id, long int *value)
+{
+ PropertyData *data;
+
+ g_assert (table != NULL);
+
+ data = g_hash_table_lookup (table, GINT_TO_POINTER (property_id));
+ if (data && data->type == PROP_DATA_TYPE_INT) {
+ *value = data->data.i;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+gboolean
+properties_table_get_bool (PropertiesTable *table, int property_id, gboolean *value)
+{
+ PropertyData *data;
+
+ g_assert (table != NULL);
+
+ data = g_hash_table_lookup (table, GINT_TO_POINTER (property_id));
+ if (data && data->type == PROP_DATA_TYPE_BOOL) {
+ *value = data->data.b;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+gboolean
+properties_table_get_double (PropertiesTable *table, int property_id, double *value)
+{
+ PropertyData *data;
+
+ g_assert (table != NULL);
+
+ data = g_hash_table_lookup (table, GINT_TO_POINTER (property_id));
+ if (data && data->type == PROP_DATA_TYPE_DOUBLE) {
+ *value = data->data.d;
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/src/properties-table.h b/src/properties-table.h
new file mode 100644
index 0000000..4a1a9ed
--- /dev/null
+++ b/src/properties-table.h
@@ -0,0 +1,62 @@
+/* Cataract - Static web photo gallery generator
+ * Copyright (C) 2014 Tomas Bzatek <tbzatek@users.sourceforge.net>
+ *
+ * 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; either version 2
+ * of the License, or any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __CGG__PROPERTIES_TABLE_H__
+#define __CGG__PROPERTIES_TABLE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+typedef GHashTable PropertiesTable;
+
+/*
+ * properties_table_new: creates new property table
+ */
+PropertiesTable * properties_table_new ();
+
+/*
+ * properties_table_dup: creates deep copy of the table
+ */
+PropertiesTable * properties_table_dup (PropertiesTable *table);
+
+/*
+ * properties_table_add_*: adds new item in the table, duplicating data
+ */
+void properties_table_add_string (PropertiesTable *table, int property_id, const gchar *value);
+void properties_table_add_int (PropertiesTable *table, int property_id, long int value);
+void properties_table_add_bool (PropertiesTable *table, int property_id, gboolean value);
+void properties_table_add_double (PropertiesTable *table, int property_id, double value);
+
+/*
+ * properties_table_get_*: gets data for the specified id, setting *value, returning TRUE if found
+ */
+const gchar * properties_table_get_string (PropertiesTable *table, int property_id);
+gboolean properties_table_get_int (PropertiesTable *table, int property_id, long int *value);
+gboolean properties_table_get_bool (PropertiesTable *table, int property_id, gboolean *value);
+gboolean properties_table_get_double (PropertiesTable *table, int property_id, double *value);
+
+/*
+ * properties_table_free: destroys properties table and frees all data
+ */
+void properties_table_free (PropertiesTable *table);
+
+
+G_END_DECLS
+
+#endif /* __CGG__PROPERTIES_TABLE_H__ */
diff --git a/src/setup.c b/src/setup.c
index d9b5ed3..cf4ca3f 100644
--- a/src/setup.c
+++ b/src/setup.c
@@ -91,20 +91,20 @@ parse_setup_xml (const gchar *filename)
setup = g_malloc0 (sizeof (TGallerySetup));
setup->setup_xml_path = g_strdup (filename);
- setup->version = nearbyint (xml_file_get_node_attribute_double (xml, "/gallery_setup", "version", -1) * 100);
+ setup->version = nearbyint (xml_file_get_node_attribute_double_with_default (xml, "/gallery_setup", "version", -1) * 100);
/* design section */
setup->design_setup_file = xml_file_get_node_value (xml, "/gallery_setup/design/setup_file/text()");
- setup->supplemental_files_use_common_root = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/design/supplemental_files_use_common_root", "value", FALSE);
+ setup->supplemental_files_use_common_root = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/design/supplemental_files_use_common_root", "value", FALSE);
/* images section */
- setup->preload = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/preload", "value", TRUE);
- setup->use_iptc_exif = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/use_iptc_exif", "value", FALSE);
- setup->erase_exif_thumbnail = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/erase_embed_thumbnail", "value", FALSE);
- setup->strip_xmp = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/strip_xmp", "value", TRUE);
- setup->write_supplied_exif = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/write_supplied_exif", "value", FALSE);
+ setup->preload = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/preload", "value", TRUE);
+ setup->use_iptc_exif = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/use_iptc_exif", "value", FALSE);
+ setup->erase_exif_thumbnail = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/erase_embed_thumbnail", "value", FALSE);
+ setup->strip_xmp = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/strip_xmp", "value", TRUE);
+ setup->write_supplied_exif = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/write_supplied_exif", "value", FALSE);
setup->nofullsize = xml_file_get_node_present (xml, "/gallery_setup/images/nofullsize");
- setup->autorotate = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/autorotate", "value", TRUE);
+ setup->autorotate = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/autorotate", "value", TRUE);
s = xml_file_get_node_attribute (xml, "/gallery_setup/images/squared_thumbnails", "type");
if (s && g_ascii_strcasecmp (s, "simple") == 0)
@@ -118,17 +118,17 @@ parse_setup_xml (const gchar *filename)
setup->meta_author_email = xml_file_get_node_value (xml, "/gallery_setup/meta/author_email/text()");
setup->meta_description = xml_file_get_node_value (xml, "/gallery_setup/meta/description/text()");
setup->meta_keywords = xml_file_get_node_value (xml, "/gallery_setup/meta/keywords/text()");
- setup->use_title_as_meta = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/meta/use_title_as_meta", "value", TRUE);
+ setup->use_title_as_meta = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/meta/use_title_as_meta", "value", TRUE);
setup->site_title = xml_file_get_node_attribute (xml, "/gallery_setup/meta/site", "title");
setup->add_copyright = xml_file_get_node_value (xml, "/gallery_setup/meta/add_copyright/text()");
setup->favicon_file = xml_file_get_node_value (xml, "/gallery_setup/meta/favicon/text()");
setup->favicon_type = xml_file_get_node_attribute (xml, "/gallery_setup/meta/favicon", "type");
/* navigation section */
- setup->use_inpage_links = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/navigation/use_inpage_links", "value", TRUE);
+ setup->use_inpage_links = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/navigation/use_inpage_links", "value", TRUE);
/* feed section */
- setup->feed_enabled = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/feed", "enable", FALSE);
+ setup->feed_enabled = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/feed", "enable", FALSE);
setup->feed_filename = xml_file_get_node_value (xml, "/gallery_setup/feed/filename/text()");
setup->feed_title = xml_file_get_node_value (xml, "/gallery_setup/feed/title/text()");
@@ -142,7 +142,7 @@ parse_setup_xml (const gchar *filename)
/* legacy mode */
if (SETUP_IS_LEGACY (setup)) {
setup->design_setup_file = xml_file_get_node_value (xml, "/gallery_setup/templates/path/text()");
- setup->supplemental_files_use_common_root = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/templates/support_files_use_common_root", "value", FALSE);
+ setup->supplemental_files_use_common_root = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/templates/support_files_use_common_root", "value", FALSE);
setup->location_base_url = xml_file_get_node_value (xml, "/gallery_setup/feed/base_url/text()");
}
@@ -172,7 +172,7 @@ parse_design_setup_xml (const gchar *filename)
return NULL;
design = g_malloc0 (sizeof (TGalleryDesign));
- design->version = nearbyint (xml_file_get_node_attribute_double (xml, "/design_setup", "version", -1) * 100);
+ design->version = nearbyint (xml_file_get_node_attribute_double_with_default (xml, "/design_setup", "version", -1) * 100);
s2 = xml_file_get_node_value (xml, "/design_setup/supplemental_files/text()");
if (s2) {
@@ -192,21 +192,21 @@ parse_design_setup_xml (const gchar *filename)
g_free (s);
s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/landscape", i + 1);
- image_size->landscape_width = xml_file_get_node_attribute_long (xml, s, "w", 0);
- image_size->landscape_height = xml_file_get_node_attribute_long (xml, s, "h", 0);
+ image_size->landscape_width = xml_file_get_node_attribute_long_with_default (xml, s, "w", 0);
+ image_size->landscape_height = xml_file_get_node_attribute_long_with_default (xml, s, "h", 0);
g_free (s);
s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/portrait", i + 1);
- image_size->portrait_width = xml_file_get_node_attribute_long (xml, s, "w", 0);
- image_size->portrait_height = xml_file_get_node_attribute_long (xml, s, "h", 0);
+ image_size->portrait_width = xml_file_get_node_attribute_long_with_default (xml, s, "w", 0);
+ image_size->portrait_height = xml_file_get_node_attribute_long_with_default (xml, s, "h", 0);
g_free (s);
s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/square", i + 1);
- image_size->square_size = xml_file_get_node_attribute_long (xml, s, "size", 0);
+ image_size->square_size = xml_file_get_node_attribute_long_with_default (xml, s, "size", 0);
g_free (s);
s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/quality", i + 1);
- image_size->quality = xml_file_get_node_attribute_long (xml, s, "value", -1);
+ image_size->quality = xml_file_get_node_attribute_long_with_default (xml, s, "value", -1);
g_free (s);
s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/no_resize", i + 1);
@@ -222,7 +222,7 @@ parse_design_setup_xml (const gchar *filename)
design->themes = g_list_append (design->themes, theme);
s = g_strdup_printf ("/design_setup/theme[%d]", i + 1);
- theme->enabled = xml_file_get_node_attribute_boolean (xml, s, "enabled", TRUE);
+ theme->enabled = xml_file_get_node_attribute_boolean_with_default (xml, s, "enabled", TRUE);
g_free (s);
s = g_strdup_printf ("/design_setup/theme[%d]/index/template/text()", i + 1);
@@ -312,12 +312,12 @@ makeup_legacy_design (const gchar *filename)
image_size = g_malloc0 (sizeof (TImageSize));
image_size->name = g_strdup (image_sizes[i]);
s = g_strdup_printf ("/gallery_setup/images/%s", image_sizes[i]);
- image_size->landscape_width = xml_file_get_node_attribute_long (xml, s, "landscape_w", 0);
- image_size->landscape_height = xml_file_get_node_attribute_long (xml, s, "landscape_h", 0);
- image_size->portrait_width = xml_file_get_node_attribute_long (xml, s, "portrait_w", 0);
- image_size->portrait_height = xml_file_get_node_attribute_long (xml, s, "portrait_h", 0);
- image_size->square_size = xml_file_get_node_attribute_long (xml, s, "square", 0);
- image_size->quality = xml_file_get_node_attribute_long (xml, s, "quality", -1);
+ image_size->landscape_width = xml_file_get_node_attribute_long_with_default (xml, s, "landscape_w", 0);
+ image_size->landscape_height = xml_file_get_node_attribute_long_with_default (xml, s, "landscape_h", 0);
+ image_size->portrait_width = xml_file_get_node_attribute_long_with_default (xml, s, "portrait_w", 0);
+ image_size->portrait_height = xml_file_get_node_attribute_long_with_default (xml, s, "portrait_h", 0);
+ image_size->square_size = xml_file_get_node_attribute_long_with_default (xml, s, "square", 0);
+ image_size->quality = xml_file_get_node_attribute_long_with_default (xml, s, "quality", -1);
image_size->no_resize = (i == G_N_ELEMENTS (image_sizes) - 1);
g_free (s);
design->image_sizes = g_list_append (design->image_sizes, image_size);
@@ -352,9 +352,9 @@ makeup_legacy_design (const gchar *filename)
theme->picture_image_size = g_strdup (image_sizes[1]);
theme->defines = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- if (xml_file_get_node_attribute_boolean (xml, "/gallery_setup/navigation/show_go_up", "value", TRUE))
+ if (xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/navigation/show_go_up", "value", TRUE))
g_hash_table_replace (theme->defines, g_strdup ("SHOW_GO_UP"), g_strdup (""));
- if (xml_file_get_node_attribute_boolean (xml, "/gallery_setup/navigation/show_exif_table", "value", TRUE))
+ if (xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/navigation/show_exif_table", "value", TRUE))
g_hash_table_replace (theme->defines, g_strdup ("SHOW_EXIF_TABLE"), g_strdup (""));
s = xml_file_get_node_attribute (xml, "/gallery_setup/images/border", "style");
g_hash_table_replace (theme->defines, g_strdup ("BORDER_STYLE"), s ? s : g_strdup ("border_single"));
diff --git a/src/xml-parser.c b/src/xml-parser.c
index 9f95cf3..a13e502 100644
--- a/src/xml-parser.c
+++ b/src/xml-parser.c
@@ -158,13 +158,13 @@ xml_file_get_node_value_with_default (TXMLFile *file, const gchar *x_path, const
gchar *s;
s = xml_file_get_node_value (file, x_path);
-
return s ? s : g_strdup (_default);
}
/*
* xml_file_get_node_attribute: retrieve attribute value from XPath node
+ * - returns NULL if node is not present
*/
gchar *
xml_file_get_node_attribute (TXMLFile *file, const gchar *x_path, const gchar *attr)
@@ -198,35 +198,67 @@ xml_file_get_node_attribute (TXMLFile *file, const gchar *x_path, const gchar *a
return attrv;
}
-long int
-xml_file_get_node_attribute_long (TXMLFile *file, const gchar *x_path, const gchar *attr, const int _default)
+gchar *
+xml_file_get_node_attribute_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const gchar *_default)
+{
+ gchar *s = xml_file_get_node_attribute (file, x_path, attr);
+ return s != NULL ? s : g_strdup (_default);
+}
+
+/*
+ * xml_file_get_node_attribute_*: retrieve attribute value from XPath node, storing it in *value, returning TRUE if value has been set.
+ */
+gboolean
+xml_file_get_node_attribute_long (TXMLFile *file, const gchar *x_path, const gchar *attr, long int *value)
{
gchar *s;
long int i;
+ char *endptr = NULL;
s = xml_file_get_node_attribute (file, x_path, attr);
if (s == NULL)
- return _default;
+ return FALSE;
- i = atol (s);
+ i = strtol (s, &endptr, 10);
+ if (endptr != NULL && *endptr != '\0') {
+ g_free (s);
+ return FALSE;
+ }
g_free (s);
- return i;
+ *value = i;
+ return TRUE;
+}
+
+long int
+xml_file_get_node_attribute_long_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const long int _default)
+{
+ long int i;
+ return xml_file_get_node_attribute_long (file, x_path, attr, &i) ? i : _default;
}
gboolean
-xml_file_get_node_attribute_boolean (TXMLFile *file, const gchar *x_path, const gchar *attr, const gboolean _default)
+xml_file_get_node_attribute_boolean (TXMLFile *file, const gchar *x_path, const gchar *attr, gboolean *value)
{
gchar *s;
- gboolean b;
s = xml_file_get_node_attribute (file, x_path, attr);
- b = s ? (strcasecmp (s, "yes") == 0 || strcasecmp (s, "true") == 0) : _default;
+ if (s == NULL)
+ return FALSE;
+
+ *value = (strcasecmp (s, "yes") == 0 || strcasecmp (s, "true") == 0);
g_free (s);
- return b;
+ return TRUE;
}
-double
-xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const gchar *attr, const double _default)
+gboolean
+xml_file_get_node_attribute_boolean_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const gboolean _default)
+{
+ gboolean b;
+ return xml_file_get_node_attribute_boolean (file, x_path, attr, &b) ? b : _default;
+}
+
+gboolean
+xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const gchar *attr, double *value)
{
gchar *s;
double d;
@@ -234,13 +266,23 @@ xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const g
s = xml_file_get_node_attribute (file, x_path, attr);
if (s == NULL)
- return _default;
+ return FALSE;
d = strtod (s, &endptr);
- if (endptr != NULL && *endptr != '\0')
- d = _default;
+ if (endptr != NULL && *endptr != '\0') {
+ g_free (s);
+ return FALSE;
+ }
g_free (s);
- return d;
+ *value = d;
+ return TRUE;
+}
+
+double
+xml_file_get_node_attribute_double_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const double _default)
+{
+ double d;
+ return xml_file_get_node_attribute_double (file, x_path, attr, &d) ? d : _default;
}
diff --git a/src/xml-parser.h b/src/xml-parser.h
index 3ea3e90..27e8d83 100644
--- a/src/xml-parser.h
+++ b/src/xml-parser.h
@@ -23,6 +23,8 @@
#include <libxml/xmlmemory.h>
#include <libxml/xpath.h>
+#include "properties-table.h"
+
G_BEGIN_DECLS
@@ -57,11 +59,22 @@ gchar * xml_file_get_node_value_with_default (TXMLFile *file, const gchar *x_pat
/*
* xml_file_get_node_attribute: retrieve attribute value from XPath node
+ * - returns NULL if node is not present
*/
gchar * xml_file_get_node_attribute (TXMLFile *file, const gchar *x_path, const gchar *attr);
-long int xml_file_get_node_attribute_long (TXMLFile *file, const gchar *x_path, const gchar *attr, const int _default);
-gboolean xml_file_get_node_attribute_boolean (TXMLFile *file, const gchar *x_path, const gchar *attr, const gboolean _default);
-double xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const gchar *attr, const double _default);
+gchar * xml_file_get_node_attribute_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const gchar *_default);
+
+/*
+ * xml_file_get_node_attribute_*: retrieve attribute value from XPath node, storing it in *value, returning TRUE if value has been set.
+ */
+gboolean xml_file_get_node_attribute_long (TXMLFile *file, const gchar *x_path, const gchar *attr, long int *value);
+long int xml_file_get_node_attribute_long_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const long int _default);
+
+gboolean xml_file_get_node_attribute_boolean (TXMLFile *file, const gchar *x_path, const gchar *attr, gboolean *value);
+gboolean xml_file_get_node_attribute_boolean_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const gboolean _default);
+
+gboolean xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const gchar *attr, double *value);
+double xml_file_get_node_attribute_double_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const double _default);
/*
* xml_file_get_node_present: existency test of the XPath node
@@ -74,6 +87,48 @@ gboolean xml_file_get_node_present (TXMLFile *file, const gchar *x_path);
int xml_file_node_get_children_count (TXMLFile *file, const gchar *x_path);
+/*
+ * prop_xml_attr_*: retrieve data from the XML file and set the property if suceeded
+ * prop_xml_attr_*def: retrieve data from the XML file and set the property or default value on failure
+ */
+#define prop_xml_attr(t, n, xml, x_path, attr) { \
+ gchar *xxxs = xml_file_get_node_attribute (xml, x_path, attr); \
+ if (xxxs != NULL) \
+ properties_table_add_string (t, n, xxxs); \
+ g_free (xxxs); \
+ }
+#define prop_xml_attr_def(t, n, xml, x_path, attr, _default) { \
+ gchar *xxxs = xml_file_get_node_attribute_with_default (xml, x_path, attr, _default); \
+ properties_table_add_string (t, n, xxxs); \
+ g_free (xxxs); \
+ }
+
+#define prop_xml_attr_long(t, n, xml, x_path, attr) { \
+ long int xxxi; \
+ if (xml_file_get_node_attribute_long (xml, x_path, attr, &xxxi)) \
+ properties_table_add_int (t, n, xxxi); \
+ }
+#define prop_xml_attr_long_def(t, n, xml, x_path, attr, _default) \
+ properties_table_add_int (t, n, xml_file_get_node_attribute_long_with_default (xml, x_path, attr, _default))
+
+#define prop_xml_attr_bool(t, n, xml, x_path, attr) { \
+ gboolean xxxb; \
+ if (xml_file_get_node_attribute_boolean (xml, x_path, attr, &xxxb)) \
+ properties_table_add_bool (t, n, xxxb); \
+ }
+#define prop_xml_attr_bool_def(t, n, xml, x_path, attr, _default) \
+ properties_table_add_bool (t, n, xml_file_get_node_attribute_boolean_with_default (xml, x_path, attr, _default))
+
+#define prop_xml_attr_double(t, n, xml, x_path, attr) { \
+ double xxxd; \
+ if (xml_file_get_node_attribute_double (xml, x_path, attr, &xxxd)) \
+ properties_table_add_double (t, n, xxxd); \
+ }
+#define prop_xml_attr_double_def(t, n, xml, x_path, attr, _default) \
+ properties_table_add_double (t, n, xml_file_get_node_attribute_double_with_default (xml, x_path, attr, _default))
+
+
+
G_END_DECLS
#endif /* __CGG__XML_PARSER_H__ */