From 1a75cf5be219468d3cc33f421b9560ac23bc0e5d Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 25 May 2011 12:24:01 +0100 Subject: [PATCH] object new from string() is now a vfunc and the inverse too ... interpolate and format need fixing still --- TODO | 12 +++- libvips/deprecated/dispatch_types.c | 4 +- libvips/include/vips/object.h | 15 +++-- libvips/iofuncs/image.c | 11 +++- libvips/iofuncs/object.c | 89 +++++++++++++++-------------- 5 files changed, 79 insertions(+), 52 deletions(-) diff --git a/TODO b/TODO index 42402d44..0f3124ca 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,13 @@ -- where exactly is vips_object_new_from_string() used? check use cases +- interpolate needs stuff for new new_from_string etc. system + + also VipsFormat ... could this replace vips_image_new_from_string()? or + could we call this from vips_image_new_from_string()? + + vipsobject should have a fall-back implementation that does something, I + don't quite know what + + - also revise the inverse operation: vips_object_to_string() ... should be a - vfunc as well since it has to match from_string() in behaviour diff --git a/libvips/deprecated/dispatch_types.c b/libvips/deprecated/dispatch_types.c index af42eaee..d00faac6 100644 --- a/libvips/deprecated/dispatch_types.c +++ b/libvips/deprecated/dispatch_types.c @@ -886,9 +886,11 @@ im_type_desc im__output_gvalue = { static int input_interpolate_init( im_object *obj, char *str ) { + VipsObjectClass *interpolate_class; VipsObject *object; - if( !(object = vips_object_new_from_string( "VipsInterpolate", str )) ) + interpolate_class = vips_class_find( "VipsInterpolate", "interpolate" ); + if( !(object = vips_object_new_from_string( interpolate_class, str )) ) return( -1 ); *obj = object; diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index 0a22948b..24435863 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -261,22 +261,28 @@ struct _VipsObjectClass { */ void (*postclose)( VipsObject * ); - /* The CLI interface. Implement these three to get CLI input and output + /* The CLI interface. Implement these four to get CLI input and output * for your object. */ /* Given a command-line arg (eg. a filename), make an instance of the - * object. + * object. Don't call this directly, see + * vips_object_new_from_string(). */ VipsObject *(*new_from_string)( const char *string ); + /* The inverse of ^^. Given an object, output what ->new_from_string() + * would have been given to make that object. + */ + void (*to_string)( VipsObject *, VipsBuf * ); + /* Does this output arg need an arg from the command line? Image * output, for example, needs a filename to write to. */ gboolean output_needs_arg; /* Write the object to the string. Return 0 for success, or -1 on - * error setting vips_error(). string is NULL if output_needs_arg() + * error, setting vips_error(). string is NULL if output_needs_arg() * was FALSE. */ int (*output_to_arg)( VipsObject *object, const char *string ); @@ -327,7 +333,8 @@ typedef void *(*VipsObjectSetArguments)( VipsObject *, void *, void * ); VipsObject *vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b ); -VipsObject *vips_object_new_from_string( const char *base, const char *str ); +VipsObject *vips_object_new_from_string( VipsObjectClass *object_class, + const char *p ); void vips_object_to_string( VipsObject *object, VipsBuf *buf ); void *vips_object_map( VipsSListMap2Fn fn, void *a, void *b ); diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index c2ed17d1..ce36ad94 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -388,14 +388,20 @@ vips_image_dispose( GObject *gobject ) G_OBJECT_CLASS( vips_image_parent_class )->dispose( gobject ); } - - static VipsObject * vips_image_new_from_file_object( const char *string ) { return( VIPS_OBJECT( vips_image_new_from_file( string ) ) ); } +static void +vips_image_to_string( VipsObject *object, VipsBuf *buf ) +{ + VipsImage *image = VIPS_IMAGE( object ); + + vips_buf_appends( buf, image->filename ); +} + static int vips_image_write_object( VipsObject *object, const char *string ) { @@ -1062,6 +1068,7 @@ vips_image_class_init( VipsImageClass *class ) gobject_class->get_property = vips_object_get_property; vobject_class->new_from_string = vips_image_new_from_file_object; + vobject_class->to_string = vips_image_to_string;; vobject_class->output_needs_arg = TRUE; vobject_class->output_to_arg = vips_image_write_object; diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index bb9d04c3..5bc513b2 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1048,11 +1048,10 @@ vips_object_set_argument_from_string( VipsObject *object, g_assert( argument_class->flags & VIPS_ARGUMENT_INPUT ); if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) && - (oclass = g_type_class_ref( otype )) && - oclass->new_from_string ) { + (oclass = g_type_class_ref( otype )) ) { VipsObject *object; - if( !(object = oclass->new_from_string( value )) ) + if( !(object = vips_object_new_from_string( oclass, value )) ) return( -1 ); g_value_init( &gvalue, G_TYPE_OBJECT ); @@ -1232,6 +1231,26 @@ vips_object_set_required( VipsObject *object, const char *value ) return( 0 ); } +VipsObject * +vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b ) +{ + VipsObject *object; + + object = VIPS_OBJECT( g_object_new( type, NULL ) ); + + if( set && set( object, a, b ) ) { + g_object_unref( object ); + return( NULL ); + } + + if( vips_object_build( object ) ) { + g_object_unref( object ); + return( NULL ); + } + + return( object ); +} + /* Set object args from a string. We've seen the '(', we need to check for the * closing ')' and make sure there's no extra stuff. */ @@ -1287,15 +1306,30 @@ vips_object_set_args( VipsObject *object, const char *p ) } VipsObject * -vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b ) +vips_object_new_from_string( VipsObjectClass *object_class, const char *p ) { + char str[PATH_MAX]; VipsObject *object; + VipsToken token; - object = VIPS_OBJECT( g_object_new( type, NULL ) ); + g_assert( object_class->new_from_string ); - if( set && set( object, a, b ) ) { - g_object_unref( object ); + /* The first string in p is the main construct arg, eg. a filename. + */ + if( !(p = vips__token_need( p, VIPS_TOKEN_STRING, str, PATH_MAX )) || + !(object = object_class->new_from_string( str )) ) return( NULL ); + + /* More tokens there? Set any other args. + */ + if( (p = vips__token_get( p, &token, str, PATH_MAX )) ) { + if( token == VIPS_TOKEN_LEFT && + vips_object_set_args( object, p ) ) { + vips_error( "VipsObject", + "%s", _( "bad object arguments" ) ); + g_object_unref( object ); + return( NULL ); + } } if( vips_object_build( object ) ) { @@ -1303,40 +1337,7 @@ vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b ) return( NULL ); } - return( object ); -} - -static void * -vips_object_new_from_string_set( VipsObject *object, void *a, void *b ) -{ - const char *p = (const char *) a; - VipsToken token; - char string[PATH_MAX]; - - if( (p = vips__token_get( p, &token, string, PATH_MAX )) ) { - if( token == VIPS_TOKEN_LEFT && - vips_object_set_args( object, p ) ) { - vips_error( "VipsObject", - "%s", _( "bad object arguments" ) ); - return( object ); - } - } - - return( NULL ); -} - -VipsObject * -vips_object_new_from_string( const char *basename, const char *p ) -{ - char string[PATH_MAX]; - GType type; - - if( !(p = vips__token_need( p, VIPS_TOKEN_STRING, string, PATH_MAX )) || - !(type = vips_type_find( basename, string )) ) - return( NULL ); - - return( vips_object_new( type, - vips_object_new_from_string_set, (void *) p, NULL ) ); + return( object ); } static void * @@ -1398,12 +1399,16 @@ vips_object_to_string_optional( VipsObject *object, void vips_object_to_string( VipsObject *object, VipsBuf *buf ) { + VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( object ); + gboolean first; + g_assert( object_class->to_string ); + /* Nicknames are not guaranteed to be unique, so use the full type * name. */ - vips_buf_appends( buf, G_OBJECT_TYPE_NAME( object ) ); + object_class->to_string( object, buf ); first = TRUE; (void) vips_argument_map( object, vips_object_to_string_required, buf, &first );