This commit is contained in:
John Cupitt 2008-08-19 16:54:55 +00:00
parent 035d9239c1
commit b1395e18b9
3 changed files with 207 additions and 75 deletions

27
TODO
View File

@ -2,16 +2,31 @@
should gvalues be inited to a specific type?
have a field in im_type_t for typeof or somesuch?
- we need init functions which are parameterizied for the specific value
need im_object_t ... im_thing_t?
im_value_double_init( value, 12.3 )
should size be called sizeof
im_value_array_init( value, 4, arrayptr )
when we compare two types, we need to consider the typeof pointer too ...
array<int> is not the same as array<double>
im_value_image_init( value, im_open( "poop", "r" ) )
the problem is that init will generally be done by the app: the app needs to
do the build-vips-value-from-my-data conversion, and since it is doing that
build, it needs to do the free as well
alternative: init from a GValue?
then we do GValue -> vips build, so we can free as well
apps need to do internal -> GValue, then call vips to dispatch
no point :( and slower
move all init/free stuff out of type, just have malloc/free with a sizeof
and perhaps some utility functions to build vips format structures and free
them
I guess we can have array<array<double>>?:wq
- needs docs in vips manual for format stuff I guess

View File

@ -48,28 +48,19 @@ extern "C" {
#define IM_TYPE_NAME_GVALUE "gvalue" /* GValue wrapper */
#define IM_TYPE_NAME_ARRAY "array" /* Array of other values of some type */
/* A VIPS type.
*/
typedef struct im__type_t {
const char *name; /* Name of type, eg. "double" */
struct im__type_t *type_param; /* What this is an array of */
size_t size; /* sizeof( im_value_t ) repres. ) */
} im_type_t;
/* Pass (array of pointers to im_value_t) to operations as the argument list.
* Cast to the appropriate type for this argument, eg. (int *) or (IMAGE *).
*/
typedef void im_value_t;
/* The arg to the init function is a pointer to the value, since we can have
* nothing allocated for eg. an IMAGE*.
*/
typedef struct im__type_t im_type_t;
typedef gboolean (*im_value_init_fn)( im_value_t **value, im_type_t *type );
typedef void (*im_value_free_fn)( im_value_t *value, im_type_t *type );
/* A VIPS type.
*/
struct im__type_t {
const char *name; /* Name of type, eg. "double" */
im_type_t *type_param; /* What this is an array of */
size_t size; /* sizeof( im_value_t ) repres. ) */
im_value_init_fn init; /* Init memory */
im_value_free_fn free; /* Destroy value */
};
/* Various im_value_t values.
*/
typedef struct {
@ -119,8 +110,7 @@ typedef struct im__operation_t {
/* Register/iterate over types.
*/
im_type_t *im_type_register( const char *name,
im_type_t *type_param, size_t size,
im_value_init_fn init, im_value_free_fn free );
im_type_t *type_param, size_t size );
void *im_type_map( VSListMap2Fn fn, void *a, void *b );
im_type_t *im_type_lookup( const char *name, im_type_t *type_param );

View File

@ -45,6 +45,10 @@
*/
static GHashTable *im_type_table = NULL;
/* Keep operations in a GHashTable, indexed by name.
*/
static GHashTable *im_operation_table = NULL;
static unsigned int
im_type_hash( im_type_t *type )
{
@ -61,8 +65,7 @@ im_type_equal( im_type_t *type1, im_type_t *type2 )
im_type_t *
im_type_register( const char *name,
im_type_t *type_param, size_t size,
im_value_init_fn init, im_value_free_fn free )
im_type_t *type_param, size_t size )
{
im_type_t *type;
@ -77,8 +80,6 @@ im_type_register( const char *name,
type->name = name;
type->type_param = type_param;
type->size = size;
type->init = init;
type->free = free;
if( !im_type_table )
im_type_table = g_hash_table_new(
@ -97,13 +98,13 @@ typedef struct {
} Pair;
static gboolean
im_type_map_predicate( const char *key, im_type_t *type, Pair *pair )
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_type_map( VSListMap2Fn fn, void *a, void *b )
im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b )
{
Pair pair;
@ -112,12 +113,17 @@ im_type_map( VSListMap2Fn fn, void *a, void *b )
pair.fn = fn;
pair.result = NULL;
g_hash_table_find( im_type_table,
(GHRFunc) im_type_map_predicate, &pair );
g_hash_table_find( hash, (GHRFunc) im_hash_table_predicate, &pair );
return( pair.result );
}
void *
im_type_map( VSListMap2Fn fn, void *a, void *b )
{
return( im_hash_table_map( im_type_table, fn, a, b ) );
}
im_type_t *
im_type_lookup( const char *name, im_type_t *type_param )
{
@ -129,59 +135,74 @@ im_type_lookup( const char *name, im_type_t *type_param )
return( (im_type_t *) g_hash_table_lookup( im_type_table, &type ) );
}
/* Register the base VIPS types.
*/
void
im__type_init( void )
{
im_type_register( IM_TYPE_NAME_DOUBLE, NULL, sizeof( double ) );
im_type_register( IM_TYPE_NAME_INT, NULL, sizeof( int ) );
im_type_register( IM_TYPE_NAME_COMPLEX, NULL, 2 * sizeof( double ) );
im_type_register( IM_TYPE_NAME_STRING, NULL, 0 );
im_type_register( IM_TYPE_NAME_IMASK, NULL, sizeof( im_value_mask_t ) );
im_type_register( IM_TYPE_NAME_DMASK, NULL, sizeof( im_value_mask_t ) );
im_type_register( IM_TYPE_NAME_IMAGE, NULL, 0 );
im_type_register( IM_TYPE_NAME_DISPLAY, NULL, 0 );
im_type_register( IM_TYPE_NAME_GVALUE, NULL, sizeof( GValue ) );
im_type_register( IM_TYPE_NAME_ARRAY,
NULL, sizeof( im_value_array_t ) );
}
/* Allocate an im_value_t.
*/
static im_value_t *
im_value_new( im_value_t **value, im_type_t *type )
im_value_new( im_type_t *type )
{
im_value_t *value;
if( type->size ) {
if( !(*value = im_malloc( NULL, type->size )) )
if( !(value = im_malloc( NULL, type->size )) )
return( NULL );
memset( *value, 0, type->size );
memset( value, 0, type->size );
}
else
*value = NULL;
value = NULL;
if( type->init )
if( type->init( value, type ) );
return( *value );
return( value );
}
/* Free an im_value_t.
*/
static void
im_value_free( im_value_t **value, im_type_t *type )
im_value_free( im_value_t *value, im_type_t *type )
{
if( type->free && *value )
type->free( *value, type );
if( type->size )
IM_FREE( *value );
IM_FREE( value );
}
/* Free a mask object.
/* Convenience functions to build and free various values.
*/
static void
im_value_imask_free( im_value_mask_t *value, im_type_t *type )
void
im_value_imask_free( im_value_mask_t *value )
{
IM_FREE( value->name );
IM_FREEF( im_free_imask, value->mask );
}
static void
im_value_dmask_free( im_value_mask_t *value, im_type_t *type )
void
im_value_dmask_free( im_value_mask_t *value )
{
IM_FREE( value->name );
IM_FREEF( im_free_dmask, value->mask );
}
static void
im_value_gvalue_free( GValue *value, im_type_t *type )
void
im_value_gvalue_free( GValue *value )
{
g_value_unset( value );
}
static void
void
im_value_array_free( im_value_array_t *value, im_type_t *type )
{
int i;
@ -190,29 +211,135 @@ im_value_array_free( im_value_array_t *value, im_type_t *type )
im_value_free( value->array[i], type->type_param );
}
/* Register the base VIPS types.
gboolean
im_value_mask_output_init( im_value_mask_t *value, const char *name )
{
if( !(value->name = im_strdup( NULL, name )) )
return( FALSE );
return( TRUE );
}
gboolean
im_value_imask_input_init( im_value_mask_t *value, const char *name )
{
INTMASK *mask;
if( !(mask = im_read_imask( name )) )
return( FALSE );
value->mask = (void *) mask;
if( !(value->name = im_strdup( NULL, name )) ) {
im_value_imask_free( value );
return( FALSE );
}
return( TRUE );
}
/* Create arguments.
*/
im_argument_t *
im_argument_new( const char *name, im_type_t *type, gboolean input )
{
im_argument_t *argument;
if( !(argument = IM_NEW( NULL, im_argument_t )) )
return( NULL );
argument->name = name;
argument->type = type;
argument->input = input;
return( argument );
}
void
im_argument_free( im_argument_t *argument )
{
im_free( argument );
}
/* Register/iterate/lookup operations.
*/
void
im__type_init( void )
im_operation_unregister( im_operation_t *operation )
{
im_type_register( IM_TYPE_NAME_DOUBLE, NULL, sizeof( double ),
NULL, NULL );
im_type_register( IM_TYPE_NAME_INT, NULL, sizeof( int ),
NULL, NULL );
im_type_register( IM_TYPE_NAME_COMPLEX, NULL, 2 * sizeof( double ),
NULL, NULL );
im_type_register( IM_TYPE_NAME_STRING, NULL, 0,
NULL, (im_value_free_fn) im_free );
im_type_register( IM_TYPE_NAME_IMASK, NULL, sizeof( im_value_mask_t ),
NULL, (im_value_free_fn) im_value_imask_free );
im_type_register( IM_TYPE_NAME_DMASK, NULL, sizeof( im_value_mask_t ),
NULL, (im_value_free_fn) im_value_dmask_free );
im_type_register( IM_TYPE_NAME_IMAGE, NULL, 0,
NULL, NULL );
im_type_register( IM_TYPE_NAME_DISPLAY, NULL, 0,
NULL, NULL );
im_type_register( IM_TYPE_NAME_GVALUE, NULL, sizeof( GValue ),
NULL, (im_value_free_fn) im_value_gvalue_free );
im_type_register( IM_TYPE_NAME_ARRAY, NULL, sizeof( im_value_array_t ),
NULL, (im_value_free_fn) im_value_array_free );
int i;
g_hash_table_remove( im_operation_table, operation->name );
for( i = 0; i < operation->argc; i++ )
IM_FREEF( im_argument_free, operation->argv[i] );
IM_FREE( operation );
}
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 *operation;
if( im_operation_lookup( name ) ) {
im_error( "im_operation_register",
_( "operation name already registered" ) );
return( NULL );
}
if( !(operation = IM_NEW( NULL, im_operation_t )) )
return( NULL );
operation->name = name;
operation->desc = desc;
operation->flags = flags;
operation->disp = disp;
operation->argc = argc;
operation->argv = NULL;
if( !(operation->argv = IM_ARRAY( NULL, argc, im_argument_t * )) ) {
im_operation_unregister( operation );
return( NULL );
}
memset( operation->argv, 0, argc * sizeof( im_argument_t * ) );
if( !im_operation_table )
im_operation_table = g_hash_table_new(
g_str_hash, g_str_equal );
g_hash_table_insert( im_operation_table, (char *) name, operation );
return( operation );
}
void *
im_operation_map( VSListMap2Fn fn, void *a, void *b )
{
return( im_hash_table_map( im_operation_table, fn, a, b ) );
}
im_operation_t *
im_operation_lookup( const char *name )
{
return( (im_operation_t *)
g_hash_table_lookup( im_operation_table, name ) );
}
static int
add_vec( im_value_t **argv )
{
return( im_add( argv[0], argv[1], argv[2] ) );
}
/* Make a sample operation.
*/
void
im__operation_init( void )
{
im_operation_t *operation;
operation = im_operation_register( "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 );
}