diff --git a/TODO b/TODO index b9e95399..bea07a0d 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,17 @@ +- have vips -> gvalue and gvalue -> vips methods in type struct + + converters need arg flags too, so they know whether it's read or write + + is this enough? maybe + + + - do we need init functions? maybe for arrays I guess should gvalues be inited to a specific type? + + - we need init functions which are parameterizied for the specific value im_value_double_init( value, 12.3 ) diff --git a/include/vips/type.h b/include/vips/type.h index 76e3ea66..612302af 100644 --- a/include/vips/type.h +++ b/include/vips/type.h @@ -48,6 +48,11 @@ extern "C" { #define IM_TYPE_NAME_GVALUE "gvalue" /* GValue wrapper */ #define IM_TYPE_NAME_ARRAY "array" /* Array of other values of some type */ +/* Handy type lookups. + */ +#define IM_TYPE_IM (im_type_lookup( IM_TYPE_NAME_IMAGE, NULL )) +#define IM_TYPE_AR( OF ) (im_type_lookup( IM_TYPE_NAME_ARRAY, OF )) + /* A VIPS type. */ typedef struct im__type_t { @@ -73,12 +78,20 @@ typedef struct { im_value_t **array; /* Array */ } im_value_array_t; +/* Flags for arguments. + * operation, + */ +typedef enum { + IM_ARGUMENT_NONE = 0, /* No flags set */ + IM_ARGUMENT_OUTPUT = 0x1 /* Is an output arg */ +} im_argument_flags; + /* An argument to a VIPS operation. */ typedef struct im__argument_t { const char *name; /* Eg. "in2" */ im_type_t *type; /* Argument type */ - gboolean input; /* TRUE means arg to operation */ + im_argument_flags flags; /* Output/input etc. */ } im_argument_t; /* Flags for operations. Various hints for UIs about the behaviour of the @@ -118,13 +131,15 @@ im_type_t *im_type_lookup( const char *name, im_type_t *type_param ); */ im_operation_t *im_operation_register( const char *name, const char *desc, im_operation_flags flags, im_operation_dispatch_fn disp, int argc ); +im_operation_t *im_operation_registerv( const char *name, const char *desc, + im_operation_flags flags, im_operation_dispatch_fn disp, ... ); void *im_operation_map( VSListMap2Fn fn, void *a, void *b ); im_operation_t *im_operation_lookup( const char *name ); /* Create arguments. */ im_argument_t *im_argument_new( const char *name, - im_type_t *type, gboolean input ); + im_type_t *type, im_argument_flags flags ); #ifdef __cplusplus } diff --git a/include/vips/util.h b/include/vips/util.h index f6c9bfa5..31a27a5d 100644 --- a/include/vips/util.h +++ b/include/vips/util.h @@ -291,6 +291,8 @@ void im_slist_free_all( GSList *list ); void *im_map_equal( void *a, void *b ); +void *im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b ); + char *im_strncpy( char *dest, const char *src, int n ); char *im_strrstr( const char *haystack, const char *needle ); char *im_strdup( IMAGE *im, const char *str ); diff --git a/libsrc/iofuncs/type.c b/libsrc/iofuncs/type.c index c7451a81..d3ca9e51 100644 --- a/libsrc/iofuncs/type.c +++ b/libsrc/iofuncs/type.c @@ -34,6 +34,7 @@ #include #include +#include #include @@ -90,34 +91,6 @@ im_type_register( const char *name, return( type ); } -typedef struct { - void *a; - void *b; - VSListMap2Fn fn; - void *result; -} Pair; - -static gboolean -im_hash_table_predicate( const char *key, im_type_t *type, Pair *pair ) -{ - return( (pair->result == pair->fn( type, pair->a, pair->b )) ); -} - -void * -im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b ) -{ - Pair pair; - - pair.a = a; - pair.b = b; - pair.fn = fn; - pair.result = NULL; - - g_hash_table_find( hash, (GHRFunc) im_hash_table_predicate, &pair ); - - return( pair.result ); -} - void * im_type_map( VSListMap2Fn fn, void *a, void *b ) { @@ -127,12 +100,27 @@ im_type_map( VSListMap2Fn fn, void *a, void *b ) im_type_t * im_type_lookup( const char *name, im_type_t *type_param ) { - im_type_t type; + im_type_t tmp; + im_type_t *type; - type.name = name; - type.type_param = type_param; + /* Look for this exact type. + */ + tmp.name = name; + tmp.type_param = type_param; + if( !(type = (im_type_t *) + g_hash_table_lookup( im_type_table, &tmp )) ) { + /* Not found. Look for just the name type, eg. "array". + */ + tmp.type_param = NULL; + if( (type = (im_type_t *) + g_hash_table_lookup( im_type_table, &tmp )) ) + /* Found it. Register a new compound type with this + * param. + */ + type = im_type_register( name, type_param, type->size ); + } - return( (im_type_t *) g_hash_table_lookup( im_type_table, &type ) ); + return( type ); } /* Register the base VIPS types. @@ -239,7 +227,7 @@ im_value_imask_input_init( im_value_mask_t *value, const char *name ) /* Create arguments. */ im_argument_t * -im_argument_new( const char *name, im_type_t *type, gboolean input ) +im_argument_new( const char *name, im_type_t *type, im_argument_flags flags ) { im_argument_t *argument; @@ -247,7 +235,7 @@ im_argument_new( const char *name, im_type_t *type, gboolean input ) return( NULL ); argument->name = name; argument->type = type; - argument->input = input; + argument->flags = flags; return( argument ); } @@ -306,6 +294,30 @@ im_operation_register( const char *name, const char *desc, return( operation ); } +im_operation_t * +im_operation_registerv( const char *name, const char *desc, + im_operation_flags flags, im_operation_dispatch_fn disp, ... ) +{ + im_operation_t *operation; + im_argument_t *argument; + va_list ap; + int argc; + int i; + + va_start( ap, disp ); + for( argc = 0; va_arg( ap, im_argument_t * ); argc++ ) + ; + va_end( ap ); + + operation = im_operation_register( name, desc, flags, disp, argc ); + va_start( ap, disp ); + for( i = 0; (argument = va_arg( ap, im_argument_t * )); i++ ) + operation->argv[i] = argument; + va_end( ap ); + + return( operation ); +} + void * im_operation_map( VSListMap2Fn fn, void *a, void *b ) { @@ -330,16 +342,11 @@ add_vec( im_value_t **argv ) void im__operation_init( void ) { - im_operation_t *operation; - - operation = im_operation_register( "im_add", _( "add two images" ), + im_operation_registerv( "im_add", _( "add two images" ), IM_FN_PIO | IM_FN_PTOP, add_vec, - 3 ); - operation->argv[0] = im_argument_new( "in1", - im_type_lookup( IM_TYPE_NAME_IMAGE, NULL ), TRUE ); - operation->argv[1] = im_argument_new( "in2", - im_type_lookup( IM_TYPE_NAME_IMAGE, NULL ), TRUE ); - operation->argv[2] = im_argument_new( "out", - im_type_lookup( IM_TYPE_NAME_IMAGE, NULL ), TRUE ); + im_argument_new( "in1", IM_TYPE_IM, 0 ), + im_argument_new( "in2", IM_TYPE_IM, 0 ), + im_argument_new( "out", IM_TYPE_IM, IM_ARGUMENT_OUTPUT ), + NULL ); } diff --git a/libsrc/iofuncs/util.c b/libsrc/iofuncs/util.c index cd5f5a8b..fb545873 100644 --- a/libsrc/iofuncs/util.c +++ b/libsrc/iofuncs/util.c @@ -212,6 +212,36 @@ im_slist_filter( GSList *list, VSListMap2Fn fn, void *a, void *b ) return( list ); } +typedef struct { + void *a; + void *b; + VSListMap2Fn fn; + void *result; +} Pair; + +static gboolean +im_hash_table_predicate( const char *key, im_type_t *type, Pair *pair ) +{ + return( (pair->result == pair->fn( type, pair->a, pair->b )) ); +} + +/* Like slist map, but for a hash table. + */ +void * +im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b ) +{ + Pair pair; + + pair.a = a; + pair.b = b; + pair.fn = fn; + pair.result = NULL; + + g_hash_table_find( hash, (GHRFunc) im_hash_table_predicate, &pair ); + + return( pair.result ); +} + /* Like strncpy(), but always NULL-terminate, and don't pad with NULLs. */ char *