static void vips_cache_unref( VipsOperation *operation ) { (void) vips_argument_map( VIPS_OBJECT( operation ), vips_object_unref_arg, NULL, NULL ); g_object_unref( operation ); }
/* Make a vo and supply args from nip2. */ static gboolean vo_args( Vo *vo, PElement *required, PElement *optional ) { /* Gather supplied required input args list. */ if( heap_map_list( required, (heap_map_list_fn) vo_gather_required, vo, NULL ) ) return( FALSE ); /* Set required input arguments. */ if( vips_argument_map( VIPS_OBJECT( vo->object ), (VipsArgumentMapFn) vo_set_required_input, vo, NULL ) ) return( FALSE ); if( vo->nargs_supplied != vo->nargs_required ) { error_top( _( "Wrong number of required arguments." ) ); error_sub( _( "Operation \"%s\" has %d required arguments, " "you supplied %d." ), vo->name, vo->nargs_required, vo->nargs_supplied ); return( FALSE ); } /* Set all optional input args. */ if( !vo_set_optional( vo, optional ) ) return( FALSE ); return( TRUE ); }
/* Ref an operation for the cache. The operation itself, plus all the output * objects it makes. */ static void vips_cache_ref( VipsOperation *operation ) { g_object_ref( operation ); (void) vips_argument_map( VIPS_OBJECT( operation ), vips_object_ref_arg, NULL, NULL ); vips_operation_touch( operation ); }
/* Are two objects equal, ie. have the same inputs. */ static gboolean vips_operation_equal( VipsOperation *a, VipsOperation *b ) { if( a == b ) return( TRUE ); if( G_OBJECT_TYPE( a ) == G_OBJECT_TYPE( b ) && vips_operation_hash( a ) == vips_operation_hash( b ) && !vips_argument_map( VIPS_OBJECT( a ), vips_object_equal_arg, b, NULL ) ) return( TRUE ); return( FALSE ); }
/* Find a hash from the input arguments to a VipsOperstion. */ static unsigned int vips_operation_hash( VipsOperation *operation ) { if( !operation->found_hash ) { guint hash; /* Include the operation type in the hash. */ hash = (guint) G_OBJECT_TYPE( operation ); (void) vips_argument_map( VIPS_OBJECT( operation ), vips_object_hash_arg, &hash, NULL ); /* Make sure we can't have a zero hash value. */ hash |= 1; operation->hash = hash; operation->found_hash = TRUE; } return( operation->hash ); }
/* Run a VipsOperation. Like vo_object_new(), but we return the output args * rather than the operation. */ void vo_call( Reduce *rc, const char *name, PElement *required, PElement *optional, PElement *out ) { Vo *vo; PElement pe; if( !(vo = vo_new( rc, name )) ) reduce_throw( rc ); if( !vo_args( vo, required, optional ) ) { vo_free( vo ); reduce_throw( rc ); } /* Ask the object to construct. This can update vo->operation with an * old one from the cache. */ if( vips_cache_operation_buildp( (VipsOperation **) &vo->object ) ) { error_top( _( "VIPS library error." ) ); error_sub( "%s", im_error_buffer() ); im_error_clear(); vips_object_unref_outputs( vo->object ); vo_free( vo ); reduce_throw( rc ); } /* We can't build the output object directly on out, since it might be * one of our inputs. We use the safe Element in vo for the build, * then copy at the end. */ /* Empty output list. */ PEPOINTE( &pe, &vo->out ); heap_list_init( &pe ); /* Append required outputs. */ if( vips_argument_map( VIPS_OBJECT( vo->object ), (VipsArgumentMapFn) vo_get_required_output, vo, &pe ) ) { vips_object_unref_outputs( vo->object ); vo_free( vo ); reduce_throw( rc ); } /* Append optional outputs. */ if( !vo_get_optional( vo, optional, &pe ) ) { vips_object_unref_outputs( vo->object ); vo_free( vo ); reduce_throw( rc ); } /* Now write the output object to out. */ PEPUTE( out, &vo->out ); vips_object_unref_outputs( vo->object ); vo_free( vo ); }