object new from string() is now a vfunc

and the inverse too ... interpolate and format need fixing still
This commit is contained in:
John Cupitt 2011-05-25 12:24:01 +01:00
parent 5492e0dbda
commit 1a75cf5be2
5 changed files with 79 additions and 52 deletions
TODO
libvips
deprecated
include/vips
iofuncs

12
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

@ -886,9 +886,11 @@ im_type_desc im__output_gvalue = {
static int static int
input_interpolate_init( im_object *obj, char *str ) input_interpolate_init( im_object *obj, char *str )
{ {
VipsObjectClass *interpolate_class;
VipsObject *object; 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 ); return( -1 );
*obj = object; *obj = object;

@ -261,22 +261,28 @@ struct _VipsObjectClass {
*/ */
void (*postclose)( VipsObject * ); 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. * for your object.
*/ */
/* Given a command-line arg (eg. a filename), make an instance of the /* 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 ); 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 /* Does this output arg need an arg from the command line? Image
* output, for example, needs a filename to write to. * output, for example, needs a filename to write to.
*/ */
gboolean output_needs_arg; gboolean output_needs_arg;
/* Write the object to the string. Return 0 for success, or -1 on /* 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. * was FALSE.
*/ */
int (*output_to_arg)( VipsObject *object, const char *string ); 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, VipsObject *vips_object_new( GType type,
VipsObjectSetArguments set, void *a, void *b ); 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_to_string( VipsObject *object, VipsBuf *buf );
void *vips_object_map( VipsSListMap2Fn fn, void *a, void *b ); void *vips_object_map( VipsSListMap2Fn fn, void *a, void *b );

@ -388,14 +388,20 @@ vips_image_dispose( GObject *gobject )
G_OBJECT_CLASS( vips_image_parent_class )->dispose( gobject ); G_OBJECT_CLASS( vips_image_parent_class )->dispose( gobject );
} }
static VipsObject * static VipsObject *
vips_image_new_from_file_object( const char *string ) vips_image_new_from_file_object( const char *string )
{ {
return( VIPS_OBJECT( vips_image_new_from_file( 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 static int
vips_image_write_object( VipsObject *object, const char *string ) 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; gobject_class->get_property = vips_object_get_property;
vobject_class->new_from_string = vips_image_new_from_file_object; 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_needs_arg = TRUE;
vobject_class->output_to_arg = vips_image_write_object; vobject_class->output_to_arg = vips_image_write_object;

@ -1048,11 +1048,10 @@ vips_object_set_argument_from_string( VipsObject *object,
g_assert( argument_class->flags & VIPS_ARGUMENT_INPUT ); g_assert( argument_class->flags & VIPS_ARGUMENT_INPUT );
if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) && if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
(oclass = g_type_class_ref( otype )) && (oclass = g_type_class_ref( otype )) ) {
oclass->new_from_string ) {
VipsObject *object; VipsObject *object;
if( !(object = oclass->new_from_string( value )) ) if( !(object = vips_object_new_from_string( oclass, value )) )
return( -1 ); return( -1 );
g_value_init( &gvalue, G_TYPE_OBJECT ); g_value_init( &gvalue, G_TYPE_OBJECT );
@ -1232,6 +1231,26 @@ vips_object_set_required( VipsObject *object, const char *value )
return( 0 ); 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 /* 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. * closing ')' and make sure there's no extra stuff.
*/ */
@ -1287,16 +1306,31 @@ vips_object_set_args( VipsObject *object, const char *p )
} }
VipsObject * 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; 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 ) ) { /* 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 ); g_object_unref( object );
return( NULL ); return( NULL );
} }
}
if( vips_object_build( object ) ) { if( vips_object_build( object ) ) {
g_object_unref( object ); g_object_unref( object );
@ -1306,39 +1340,6 @@ vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b )
return( object ); 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 ) );
}
static void * static void *
vips_object_to_string_required( VipsObject *object, vips_object_to_string_required( VipsObject *object,
GParamSpec *pspec, GParamSpec *pspec,
@ -1398,12 +1399,16 @@ vips_object_to_string_optional( VipsObject *object,
void void
vips_object_to_string( VipsObject *object, VipsBuf *buf ) vips_object_to_string( VipsObject *object, VipsBuf *buf )
{ {
VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( object );
gboolean first; gboolean first;
g_assert( object_class->to_string );
/* Nicknames are not guaranteed to be unique, so use the full type /* Nicknames are not guaranteed to be unique, so use the full type
* name. * name.
*/ */
vips_buf_appends( buf, G_OBJECT_TYPE_NAME( object ) ); object_class->to_string( object, buf );
first = TRUE; first = TRUE;
(void) vips_argument_map( object, (void) vips_argument_map( object,
vips_object_to_string_required, buf, &first ); vips_object_to_string_required, buf, &first );