From 180e5efe6fd592e49069f30bfa22ee016eb66490 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 16 Jul 2015 14:46:20 +0100 Subject: [PATCH] store all string metadata as refstr various things break if you attach a G_TYPE_STRING as metadata, so make sure it's always VIPS_TYPE_REF_STRING also, type convert on read --- libvips/iofuncs/header.c | 19 +++++++++++++++++-- libvips/iofuncs/type.c | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index 436151ff..105b5cef 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -20,6 +20,8 @@ * 22/3/11 * - rename fields for vips8 * - move to vips_ prefix + * 16/7/15 + * - auto wrap GString as RefString */ /* @@ -284,8 +286,21 @@ meta_new( VipsImage *image, const char *field, GValue *value ) memset( &meta->value, 0, sizeof( GValue ) ); meta->field = g_strdup( field ); - g_value_init( &meta->value, G_VALUE_TYPE( value ) ); - g_value_copy( value, &meta->value ); + /* Special case: we don't want to have G_STRING on meta. They will be + * copied down pipelines, plus some of our API (like + * vips_image_get_string()) assumes that the GValue is a refstring and + * that read-only pointers can be handed out. + * + * Turn G_TYPE_STRING into VIPS_TYPE_REF_STRING. + */ + if( G_VALUE_TYPE( value ) == G_TYPE_STRING ) + g_value_init( &meta->value, VIPS_TYPE_REF_STRING ); + else + g_value_init( &meta->value, G_VALUE_TYPE( value ) ); + + /* We don't do any conversions that can fail. + */ + (void) g_value_transform( value, &meta->value ); image->meta_traverse = g_slist_append( image->meta_traverse, meta ); g_hash_table_replace( image->meta, meta->field, meta ); diff --git a/libvips/iofuncs/type.c b/libvips/iofuncs/type.c index c40797c5..751b448f 100644 --- a/libvips/iofuncs/type.c +++ b/libvips/iofuncs/type.c @@ -1339,6 +1339,7 @@ vips_value_set_ref_string( GValue *value, const char *str ) VipsRefString *ref_str; g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_REF_STRING ); + ref_str = vips_ref_string_new( str ); g_value_set_boxed( value, ref_str ); vips_area_unref( VIPS_AREA( ref_str ) );