diff --git a/libvips/conversion/bandjoin.c b/libvips/conversion/bandjoin.c index bb0f3a40..f25f6b06 100644 --- a/libvips/conversion/bandjoin.c +++ b/libvips/conversion/bandjoin.c @@ -337,7 +337,7 @@ vips_bandjoin( VipsImage **in, VipsImage **out, int n, ... ) int i; int result; - area = vips_array_object_new( n ); + area = vips_area_new_array_object( n ); array = (VipsImage **) area->data; for( i = 0; i < n; i++ ) { array[i] = in[i]; diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index f0fca809..dabc6bbb 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -1283,3 +1283,12 @@ im_clip2fmt( IMAGE *in, IMAGE *out, VipsBandFmt fmt ) return( 0 ); } +size_t +im_ref_string_get_length( const GValue *value ) +{ + size_t length; + + (void) vips_value_get_ref_string( value, &length ); + + return( length ); +} diff --git a/libvips/format/im_vips2jpeg.c b/libvips/format/im_vips2jpeg.c index 77367f5c..ca6623ba 100644 --- a/libvips/format/im_vips2jpeg.c +++ b/libvips/format/im_vips2jpeg.c @@ -594,7 +594,7 @@ update_orientation_cb( VipsImage *in, const char *name, GValue *value, void *a ) if( vips_isprefix( "exif-Orientation", name ) ) { const char *string; - if( !(string = vips_ref_string_get( value )) ) { + if( !(string = vips_value_get_ref_string( value, NULL )) ) { vips_warn( "im_jpeg2vips", "%s", _( "exif-Orientation is not a string" ) ); return( NULL ); diff --git a/libvips/include/vips/Makefile.am b/libvips/include/vips/Makefile.am index 1f170ac7..ca16e4e4 100644 --- a/libvips/include/vips/Makefile.am +++ b/libvips/include/vips/Makefile.am @@ -1,4 +1,5 @@ pkginclude_HEADERS = \ + type.h \ almostdeprecated.h \ deprecated.h \ arithmetic.h \ diff --git a/libvips/include/vips/area.h b/libvips/include/vips/area.h deleted file mode 100644 index 1a7157fc..00000000 --- a/libvips/include/vips/area.h +++ /dev/null @@ -1,79 +0,0 @@ -/* area.h - * - * 27/10/11 - * - from header.h - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifndef VIPS_AREA_H -#define VIPS_AREA_H - -#ifdef __cplusplus -extern "C" { -#endif /*__cplusplus*/ - -/* Also used for eg. vips_local() and friends. - */ -typedef int (*VipsCallbackFn)( void *a, void *b ); - -/* A ref-counted area of memory. Can hold arrays of things as well. - */ -typedef struct _VipsArea { - void *data; - size_t length; /* 0 if not known */ - - /* If this area represents an array, the number of elements in the - * array. Equal to length / sizeof(element). - */ - int n; - - /*< private >*/ - - /* Reference count. - */ - int count; - - /* Things like ICC profiles need their own free functions. - */ - VipsCallbackFn free_fn; - - /* If we are holding an array (for exmaple, an array of double), the - * GType of the elements and their size. 0 for not known. - * - * n is always length / sizeof_type, we keep it as a member for - * convenience. - */ - GType type; - size_t sizeof_type; -} VipsArea; - -#ifdef __cplusplus -} -#endif /*__cplusplus*/ - -#endif /*VIPS_AREA_H*/ diff --git a/libvips/include/vips/header.h b/libvips/include/vips/header.h index 6a182b85..14ab47da 100644 --- a/libvips/include/vips/header.h +++ b/libvips/include/vips/header.h @@ -113,75 +113,6 @@ typedef void *(*VipsImageMapFn)( VipsImage *image, const char *field, GValue *value, void *a ); void *vips_image_map( VipsImage *im, VipsImageMapFn fn, void *a ); -/** - * VIPS_TYPE_SAVE_STRING: - * - * The #GType for a "vips_save_string". - */ -#define VIPS_TYPE_SAVE_STRING (vips_save_string_get_type()) -GType vips_save_string_get_type( void ); -const char *vips_save_string_get( const GValue *value ); -void vips_save_string_set( GValue *value, const char *str ); -void vips_save_string_setf( GValue *value, const char *fmt, ... ) - __attribute__((format(printf, 2, 3))); - -/** - * VIPS_TYPE_AREA: - * - * The #GType for a #vips_area. - */ -#define VIPS_TYPE_AREA (vips_area_get_type()) -GType vips_area_get_type( void ); -VipsArea *vips_area_new_array( GType type, size_t sizeof_type, int n ); -void vips_area_unref( VipsArea *area ); -VipsArea *vips_area_copy( VipsArea *area ); - -/** - * VIPS_TYPE_REF_STRING: - * - * The #GType for a #vips_refstring. - */ -#define VIPS_TYPE_REF_STRING (vips_ref_string_get_type()) -GType vips_ref_string_get_type( void ); -int vips_ref_string_set( GValue *value, const char *str ); -const char *vips_ref_string_get( const GValue *value ); -size_t vips_ref_string_get_length( const GValue *value ); - -/** - * VIPS_TYPE_BLOB: - * - * The #GType for a #vips_blob. - */ - -#define VIPS_TYPE_BLOB (vips_blob_get_type()) -GType vips_blob_get_type( void ); -void *vips_blob_get( const GValue *value, size_t *length ); -int vips_blob_set( GValue *value, VipsCallbackFn free_fn, - void *data, size_t length ); - -/** - * VIPS_TYPE_ARRAY_DOUBLE: - * - * The #GType for a #vips_array_double. - */ - -#define VIPS_TYPE_ARRAY_DOUBLE (vips_array_double_get_type()) -GType vips_array_double_get_type( void ); -double *vips_array_double_get( const GValue *value, int *n ); -int vips_array_double_set( GValue *value, const double *array, int n ); - -/** - * VIPS_TYPE_ARRAY_IMAGE: - * - * The #GType for a #vips_array_image. - */ - -#define VIPS_TYPE_ARRAY_IMAGE (vips_array_image_get_type()) -GType vips_array_image_get_type( void ); -GObject **vips_array_object_get( const GValue *value, int *n ); -int vips_array_object_set( GValue *value, int n ); -VipsArea *vips_array_object_new( int n ); - void vips_image_set_area( VipsImage *image, const char *field, VipsCallbackFn free_fn, void *data ); int vips_image_get_area( VipsImage *image, const char *field, void **data ); diff --git a/libvips/include/vips/type.h b/libvips/include/vips/type.h index 612302af..d8242929 100644 --- a/libvips/include/vips/type.h +++ b/libvips/include/vips/type.h @@ -1,10 +1,13 @@ -/* VIPS argument types +/* area.h + * + * 27/10/11 + * - from header.h */ /* This file is part of VIPS. - + VIPS is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -27,122 +30,129 @@ */ -#ifndef IM_TYPE_H -#define IM_TYPE_H +#ifndef VIPS_AREA_H +#define VIPS_AREA_H #ifdef __cplusplus extern "C" { #endif /*__cplusplus*/ -/* Type names. Old code might use "doublevec" etc. from before we had the - * "array" type. +/* Also used for eg. vips_local() and friends. */ -#define IM_TYPE_NAME_DOUBLE "double" /* im_value_t is ptr to double */ -#define IM_TYPE_NAME_INT "integer" /* 32-bit integer */ -#define IM_TYPE_NAME_COMPLEX "complex" /* Pair of doubles */ -#define IM_TYPE_NAME_STRING "string" /* Zero-terminated char array */ -#define IM_TYPE_NAME_IMASK "intmask" /* Integer mask type */ -#define IM_TYPE_NAME_DMASK "doublemask" /* Double mask type */ -#define IM_TYPE_NAME_IMAGE "image" /* IMAGE descriptor */ -#define IM_TYPE_NAME_DISPLAY "display" /* Display descriptor */ -#define IM_TYPE_NAME_GVALUE "gvalue" /* GValue wrapper */ -#define IM_TYPE_NAME_ARRAY "array" /* Array of other values of some type */ +typedef int (*VipsCallbackFn)( void *a, void *b ); -/* Handy type lookups. +/* A ref-counted area of memory. Can hold arrays of things as well. */ -#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 )) +typedef struct _VipsArea { + void *data; + size_t length; /* 0 if not known */ -/* A VIPS type. + /* If this area represents an array, the number of elements in the + * array. Equal to length / sizeof(element). + */ + int n; + + /*< private >*/ + + /* Reference count. + */ + int count; + + /* Things like ICC profiles need their own free functions. + */ + VipsCallbackFn free_fn; + + /* If we are holding an array (for exmaple, an array of double), the + * GType of the elements and their size. 0 for not known. + * + * n is always length / sizeof_type, we keep it as a member for + * convenience. + */ + GType type; + size_t sizeof_type; +} VipsArea; + +VipsArea *vips_area_copy( VipsArea *area ); +void vips_area_unref( VipsArea *area ); + +VipsArea *vips_area_new( VipsCallbackFn free_fn, void *data ); +VipsArea *vips_area_new_blob( VipsCallbackFn free_fn, + void *blob, size_t blob_length ); +VipsArea *vips_area_new_array( GType type, size_t sizeof_type, int n ); +VipsArea *vips_area_new_array_object( int n ); + +/** + * VIPS_TYPE_AREA: + * + * The #GType for a #vips_area. */ -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; +#define VIPS_TYPE_AREA (vips_area_get_type()) +int vips_value_set_area( GValue *value, VipsCallbackFn free_fn, void *data ); +void *vips_value_get_area( const GValue *value, size_t *length ); +GType vips_area_get_type( void ); -/* 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 *). +/** + * VIPS_TYPE_SAVE_STRING: + * + * The #GType for a "vips_save_string". */ -typedef void im_value_t; +#define VIPS_TYPE_SAVE_STRING (vips_save_string_get_type()) +const char *vips_value_get_save_string( const GValue *value ); +void vips_value_set_save_string( GValue *value, const char *str ); +void vips_value_set_save_stringf( GValue *value, const char *fmt, ... ) + __attribute__((format(printf, 2, 3))); +GType vips_save_string_get_type( void ); -/* Various im_value_t values. +/** + * VIPS_TYPE_REF_STRING: + * + * The #GType for a #vips_refstring. */ -typedef struct { - char *name; /* Command-line name in */ - void *mask; /* Mask --- DOUBLE or INT */ -} im_value_mask_t; +#define VIPS_TYPE_REF_STRING (vips_ref_string_get_type()) +const char *vips_value_get_ref_string( const GValue *value, size_t *length ); +int vips_value_set_ref_string( GValue *value, const char *str ); +GType vips_ref_string_get_type( void ); -typedef struct { - int n; /* Array length */ - im_value_t **array; /* Array */ -} im_value_array_t; - -/* Flags for arguments. - * operation, +/** + * VIPS_TYPE_BLOB: + * + * The #GType for a #vips_blob. */ -typedef enum { - IM_ARGUMENT_NONE = 0, /* No flags set */ - IM_ARGUMENT_OUTPUT = 0x1 /* Is an output arg */ -} im_argument_flags; +#define VIPS_TYPE_BLOB (vips_blob_get_type()) +void *vips_value_get_blob( const GValue *value, size_t *length ); +int vips_value_set_blob( GValue *value, + VipsCallbackFn free_fn, void *data, size_t length ); +GType vips_blob_get_type( void ); -/* An argument to a VIPS operation. - */ -typedef struct im__argument_t { - const char *name; /* Eg. "in2" */ - im_type_t *type; /* Argument type */ - im_argument_flags flags; /* Output/input etc. */ -} im_argument_t; +int vips_value_set_array( GValue *value, + GType type, size_t sizeof_type, int n ); +void *vips_value_get_array( const GValue *value, + int *n, GType *type, size_t *sizeof_type ); -/* Flags for operations. Various hints for UIs about the behaviour of the - * operation, +/** + * VIPS_TYPE_ARRAY_DOUBLE: + * + * The #GType for a #vips_array_double. */ -typedef enum { - IM_OPERATION_NONE = 0, /* No flags set */ - IM_OPERATION_PIO = 0x1, /* Is a partial function */ - IM_OPERATION_TRANSFORM = 0x2, /* Performs coord transformations */ - IM_OPERATION_PTOP = 0x4, /* Point-to-point ... can be LUTted */ - IM_OPERATION_NOCACHE = 0x8 /* Result should not be cached */ -} im_operation_flags; +#define VIPS_TYPE_ARRAY_DOUBLE (vips_array_double_get_type()) +double *vips_value_get_array_double( const GValue *value, int *n ); +int vips_value_set_array_double( GValue *value, const double *array, int n ); +GType vips_array_double_get_type( void ); -/* Type of a VIPS dispatch funtion. +/** + * VIPS_TYPE_ARRAY_IMAGE: + * + * The #GType for a #vips_array_image. */ -typedef int (*im_operation_dispatch_fn)( im_value_t **argv ); +#define VIPS_TYPE_ARRAY_IMAGE (vips_array_image_get_type()) +GObject **vips_value_get_array_object( const GValue *value, int *n ); +int vips_value_set_array_object( GValue *value, int n ); +GType vips_array_image_get_type( void ); -/* A VIPS operation. - */ -typedef struct im__operation_t { - const char *name; /* eg "im_invert" */ - const char *desc; /* One line description */ - im_operation_flags flags; /* Flags for this function */ - im_operation_dispatch_fn disp; /* Dispatch */ - int argc; /* Number of args */ - im_argument_t **argv; /* Arg list */ -} im_operation_t; - -/* Register/iterate over types. - */ -im_type_t *im_type_register( const char *name, - 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 ); - -/* Register/iterate/lookup operations. - */ -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, im_argument_flags flags ); +void vips__meta_init_types( void ); #ifdef __cplusplus } #endif /*__cplusplus*/ -#endif /*IM_TYPE_H*/ +#endif /*VIPS_AREA_H*/ diff --git a/libvips/include/vips/vips.h b/libvips/include/vips/vips.h index d21ec23e..5b77b3a5 100644 --- a/libvips/include/vips/vips.h +++ b/libvips/include/vips/vips.h @@ -97,7 +97,7 @@ extern "C" { #include #include #include -#include +#include #include #include diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index 1f487fb2..0fd2c70e 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -410,16 +410,16 @@ int im_wrapmany( VipsImage **in, VipsImage *out, #define im_updatehist vips_image_history_args #define im_history_get vips_image_get_history -#define im_save_string_get vips_save_string_get -#define im_save_string_set vips_save_string_set -#define im_save_string_setf vips_save_string_setf +#define im_save_string_get vips_value_get_save_string +#define im_save_string_set vips_value_set_save_string +#define im_save_string_setf vips_value_set_save_stringf -#define im_ref_string_set vips_ref_string_set -#define im_ref_string_get vips_ref_string_get -#define im_ref_string_get_length vips_ref_string_get_length +#define im_ref_string_set vips_value_set_ref_string +#define im_ref_string_get( V ) vips_value_get_ref_string( V, NULL ) +size_t im_ref_string_get_length( const GValue *value ); -#define im_blob_get vips_blob_get -#define im_blob_set vips_blob_set +#define im_blob_get vips_value_get_blob +#define im_blob_set vips_value_set_blob #define im_meta_set( A, B, C ) (vips_image_set( A, B, C ), 0) #define im_meta_remove vips_image_remove @@ -560,6 +560,7 @@ int im_replicate( VipsImage *in, VipsImage *out, int across, int down ); int im_clip2fmt( VipsImage *in, VipsImage *out, VipsBandFormat fmt ); + /* ruby-vips uses this */ #define vips_class_map_concrete_all vips_class_map_all diff --git a/libvips/iofuncs/Makefile.am b/libvips/iofuncs/Makefile.am index bb4ce137..0d8a76a7 100644 --- a/libvips/iofuncs/Makefile.am +++ b/libvips/iofuncs/Makefile.am @@ -1,6 +1,7 @@ noinst_LTLIBRARIES = libiofuncs.la libiofuncs_la_SOURCES = \ + type.c \ enumtypes.c \ object.c \ pool.c \ diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index dbd773d6..57465121 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -911,336 +911,61 @@ vips_image_map( VipsImage *image, VipsImageMapFn fn, void *a ) return( NULL ); } -/* Save meta fields to the header. We have a new string type for header fields - * to save to XML and define transform functions to go from our meta types to - * this string type. - */ -GType -vips_save_string_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - type = g_boxed_type_register_static( "vips_save_string", - (GBoxedCopyFunc) g_strdup, - (GBoxedFreeFunc) g_free ); - } - - return( type ); -} - -/** - * vips_save_string_get: - * @value: GValue to get from - * - * Get the C string held internally by the GValue. - * - * Returns: The C string held by @value. This must not be freed. - */ -const char * -vips_save_string_get( const GValue *value ) -{ - return( (char *) g_value_get_boxed( value ) ); -} - -/** - * vips_save_string_set: - * @value: GValue to set - * @str: C string to copy into the GValue - * - * Copies the C string into @value. - */ -void -vips_save_string_set( GValue *value, const char *str ) -{ - g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_SAVE_STRING ); - - g_value_set_boxed( value, str ); -} - -/** - * vips_save_string_setf: - * @value: GValue to set - * @fmt: printf()-style format string - * @Varargs: arguments to printf()-formatted @fmt - * - * Generates a string and copies it into @value. - */ -void -vips_save_string_setf( GValue *value, const char *fmt, ... ) -{ - va_list ap; - char *str; - - g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_SAVE_STRING ); - - va_start( ap, fmt ); - str = g_strdup_vprintf( fmt, ap ); - va_end( ap ); - vips_save_string_set( value, str ); - g_free( str ); -} - -/* Transform funcs for builtin types to SAVE_STRING. - */ -static void -transform_int_save_string( const GValue *src_value, GValue *dest_value ) -{ - vips_save_string_setf( dest_value, "%d", g_value_get_int( src_value ) ); -} - -static void -transform_save_string_int( const GValue *src_value, GValue *dest_value ) -{ - g_value_set_int( dest_value, - atoi( vips_save_string_get( src_value ) ) ); -} - -static void -transform_double_save_string( const GValue *src_value, GValue *dest_value ) -{ - char buf[G_ASCII_DTOSTR_BUF_SIZE]; - - /* Need to be locale independent. - */ - g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, - g_value_get_double( src_value ) ); - vips_save_string_set( dest_value, buf ); -} - -static void -transform_save_string_double( const GValue *src_value, GValue *dest_value ) -{ - g_value_set_double( dest_value, - g_ascii_strtod( vips_save_string_get( src_value ), NULL ) ); -} - -#ifdef DEBUG -static int area_number = 0; -#endif /*DEBUG*/ - -/* An area of mem with a free func. (eg. \0-terminated string, or a struct). - * Inital count == 1, so _unref() after attaching somewhere. - */ -static VipsArea * -area_new( VipsCallbackFn free_fn, void *data ) -{ - VipsArea *area; - - if( !(area = VIPS_NEW( NULL, VipsArea )) ) - return( NULL ); - area->count = 1; - area->length = 0; - area->data = data; - area->free_fn = free_fn; - area->type = 0; - area->sizeof_type = 0; - -#ifdef DEBUG - area_number += 1; - printf( "area_new: %p count = %d (%d in total)\n", - area, area->count, area_number ); -#endif /*DEBUG*/ - - return( area ); -} - -/* An area of mem with a free func and a length (some sort of binary object, - * like an ICC profile). - */ -static VipsArea * -area_new_blob( VipsCallbackFn free_fn, void *blob, size_t blob_length ) -{ - VipsArea *area; - - if( !(area = area_new( free_fn, blob )) ) - return( NULL ); - area->length = blob_length; - - return( area ); -} - -/* An area which holds a copy of an array of elements of some GType. - */ -VipsArea * -vips_area_new_array( GType type, size_t sizeof_type, int n ) -{ - VipsArea *area; - void *array; - - array = g_malloc( n * sizeof_type ); - if( !(area = area_new( (VipsCallbackFn) g_free, array )) ) - return( NULL ); - area->n = n; - area->length = n * sizeof_type; - area->type = G_TYPE_DOUBLE; - area->sizeof_type = sizeof_type; - - return( area ); -} - -VipsArea * -vips_area_copy( VipsArea *area ) -{ - g_assert( area->count >= 0 ); - - area->count += 1; - -#ifdef DEBUG - printf( "vips_area_copy: %p count = %d\n", area, area->count ); -#endif /*DEBUG*/ - - return( area ); -} - -void -vips_area_unref( VipsArea *area ) -{ - g_assert( area->count > 0 ); - - area->count -= 1; - -#ifdef DEBUG - printf( "vips_area_unref: %p count = %d\n", area, area->count ); -#endif /*DEBUG*/ - - if( area->count == 0 && area->free_fn ) { - (void) area->free_fn( area->data, NULL ); - area->free_fn = NULL; - vips_free( area ); - -#ifdef DEBUG - area_number -= 1; - printf( "vips_area_unref: free .. total = %d\n", area_number ); -#endif /*DEBUG*/ - } -} - -/* Transform an area to a G_TYPE_STRING. - */ -static void -transform_area_g_string( const GValue *src_value, GValue *dest_value ) -{ - VipsArea *area; - char buf[256]; - - area = g_value_get_boxed( src_value ); - vips_snprintf( buf, 256, "VIPS_TYPE_AREA, count = %d, data = %p", - area->count, area->data ); - g_value_set_string( dest_value, buf ); -} - -GType -vips_area_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - type = g_boxed_type_register_static( "vips_area", - (GBoxedCopyFunc) vips_area_copy, - (GBoxedFreeFunc) vips_area_unref ); - g_value_register_transform_func( - type, - G_TYPE_STRING, - transform_area_g_string ); - } - - return( type ); -} - -/* Set value to be a ref-counted area of memory with a free function. - */ -static int -value_set_area( VipsCallbackFn free_fn, void *data, GValue *value ) -{ - VipsArea *area; - - if( !(area = area_new( free_fn, data )) ) - return( -1 ); - - g_value_init( value, VIPS_TYPE_AREA ); - g_value_set_boxed( value, area ); - vips_area_unref( area ); - - return( 0 ); -} - -/* Don't touch count (area is static). - */ -static void * -value_get_area_data( const GValue *value ) -{ - VipsArea *area; - - area = g_value_get_boxed( value ); - - return( area->data ); -} - -static size_t -value_get_area_length( const GValue *value ) -{ - VipsArea *area; - - area = g_value_get_boxed( value ); - - return( area->length ); -} - -static int -meta_get_value( VipsImage *image, - const char *field, GType type, GValue *value_copy ) -{ - if( vips_image_get( image, field, value_copy ) ) - return( -1 ); - if( G_VALUE_TYPE( value_copy ) != type ) { - vips_error( "VipsImage", - _( "field \"%s\" is of type %s, not %s" ), - field, - g_type_name( G_VALUE_TYPE( value_copy ) ), - g_type_name( type ) ); - g_value_unset( value_copy ); - return( -1 ); - } - - return( 0 ); -} - -/** +/** * vips_image_set_area: * @image: image to attach the metadata to * @field: metadata name * @free_fn: free function for @data * @data: pointer to area of memory * - * Attaches @data as a metadata item on @image under the name @field. When VIPS - * no longer needs the metadata, it will be freed with @free_fn. + * Attaches @data as a metadata item on @image under the name @field. When + * VIPS no longer needs the metadata, it will be freed with @free_fn. * * See also: vips_image_get_double(), vips_image_set() */ void -vips_image_set_area( VipsImage *image, const char *field, - VipsCallbackFn free_fn, void *data ) +vips_image_set_area( VipsImage *image, const char *field, + VipsCallbackFn free_fn, void *data ) { GValue value = { 0 }; - value_set_area( free_fn, data, &value ); + vips_value_set_area( &value, free_fn, data ); vips_image_set( image, field, &value ); g_value_unset( &value ); } -/** +static int +meta_get_value( VipsImage *image, + const char *field, GType type, GValue *value_copy ) +{ + if( vips_image_get( image, field, value_copy ) ) + return( -1 ); + if( G_VALUE_TYPE( value_copy ) != type ) { + vips_error( "VipsImage", + _( "field \"%s\" is of type %s, not %s" ), + field, + g_type_name( G_VALUE_TYPE( value_copy ) ), + g_type_name( type ) ); + g_value_unset( value_copy ); + + return( -1 ); + } + + return( 0 ); +} + +/** * vips_image_get_area: * @image: image to get the metadata from * @field: metadata name * @data: return metadata value * * Gets @data from @image under the name @field. A convenience - * function over vips_image_get(). Use vips_image_get_typeof() to test for the - * existance - * of a piece of metadata. + * function over vips_image_get(). Use vips_image_get_typeof() to test for + * the existance of a piece of metadata. * - * See also: vips_image_set_area(), vips_image_get(), vips_image_get_typeof() + * See also: vips_image_set_area(), vips_image_get(), + * vips_image_get_typeof() * * Returns: 0 on success, -1 otherwise. */ @@ -1250,7 +975,7 @@ vips_image_get_area( VipsImage *image, const char *field, void **data ) GValue value_copy = { 0 }; if( !meta_get_value( image, field, VIPS_TYPE_AREA, &value_copy ) ) { - *data = value_get_area_data( &value_copy ); + *data = vips_value_get_area( &value_copy, NULL ); g_value_unset( &value_copy ); return( 0 ); } @@ -1258,537 +983,6 @@ vips_image_get_area( VipsImage *image, const char *field, void **data ) return( -1 ); } -/** - * vips_ref_string_get: - * @value: GValue to get from - * - * Get the C string held internally by the GValue. - * - * Returns: The C string held by @value. This must not be freed. - */ -const char * -vips_ref_string_get( const GValue *value ) -{ - return( value_get_area_data( value ) ); -} - -/** - * vips_ref_string_get_length: - * @value: GValue to get from - * - * Gets the cached string length held internally by the refstring. - * - * Returns: The length of the string. - */ -size_t -vips_ref_string_get_length( const GValue *value ) -{ - return( value_get_area_length( value ) ); -} - -/** - * vips_ref_string_set: - * @value: GValue to set - * @str: C string to copy into the GValue - * - * Copies the C string @str into @value. - * - * vips_ref_string are immutable C strings that are copied between images by - * copying reference-counted pointers, making the much more efficient than - * regular GValue strings. - * - * Returns: 0 on success, -1 otherwise. - */ -int -vips_ref_string_set( GValue *value, const char *str ) -{ - VipsArea *area; - char *str_copy; - - g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_REF_STRING ); - - str_copy = g_strdup( str ); - if( !(area = area_new( (VipsCallbackFn) vips_free, str_copy )) ) { - g_free( str_copy ); - return( -1 ); - } - - /* Handy place to cache this. - */ - area->length = strlen( str ); - - g_value_set_boxed( value, area ); - vips_area_unref( area ); - - return( 0 ); -} - -/* Transform a refstring to a G_TYPE_STRING and back. - */ -static void -transform_ref_string_g_string( const GValue *src_value, GValue *dest_value ) -{ - g_value_set_string( dest_value, vips_ref_string_get( src_value ) ); -} - -static void -transform_g_string_ref_string( const GValue *src_value, GValue *dest_value ) -{ - vips_ref_string_set( dest_value, g_value_get_string( src_value ) ); -} - -/* To a save string. - */ -static void -transform_ref_string_save_string( const GValue *src_value, GValue *dest_value ) -{ - vips_save_string_setf( dest_value, - "%s", vips_ref_string_get( src_value ) ); -} - -static void -transform_save_string_ref_string( const GValue *src_value, GValue *dest_value ) -{ - vips_ref_string_set( dest_value, vips_save_string_get( src_value ) ); -} - -GType -vips_ref_string_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - type = g_boxed_type_register_static( "vips_ref_string", - (GBoxedCopyFunc) vips_area_copy, - (GBoxedFreeFunc) vips_area_unref ); - g_value_register_transform_func( type, G_TYPE_STRING, - transform_ref_string_g_string ); - g_value_register_transform_func( G_TYPE_STRING, type, - transform_g_string_ref_string ); - g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING, - transform_ref_string_save_string ); - g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type, - transform_save_string_ref_string ); - } - - return( type ); -} - -/** - * vips_blob_get: - * @value: GValue to get from - * @length: return the blob length here, optionally - * - * Get the address of the blob (binary large object) being held in @value and - * optionally return its length in @length. - * - * See also: vips_blob_set(). - * - * Returns: The blob address. - */ -void * -vips_blob_get( const GValue *value, size_t *length ) -{ - VipsArea *area; - - /* Can't check value type, because we may get called from - * vips_blob_get_type(). - */ - - area = g_value_get_boxed( value ); - if( length ) - *length = area->length; - - return( area->data ); -} - -/* Transform a blob to a G_TYPE_STRING. - */ -static void -transform_blob_g_string( const GValue *src_value, GValue *dest_value ) -{ - void *blob; - size_t blob_length; - char buf[256]; - - blob = vips_blob_get( src_value, &blob_length ); - vips_snprintf( buf, 256, "VIPS_TYPE_BLOB, data = %p, length = %zd", - blob, blob_length ); - g_value_set_string( dest_value, buf ); -} - -/* Transform a blob to a save string and back. - */ -static void -transform_blob_save_string( const GValue *src_value, GValue *dest_value ) -{ - void *blob; - size_t blob_length; - char *b64; - - blob = vips_blob_get( src_value, &blob_length ); - if( (b64 = vips__b64_encode( blob, blob_length )) ) { - vips_save_string_set( dest_value, b64 ); - vips_free( b64 ); - } -} - -static void -transform_save_string_blob( const GValue *src_value, GValue *dest_value ) -{ - const char *b64; - void *blob; - size_t blob_length; - - b64 = vips_save_string_get( src_value ); - if( (blob = vips__b64_decode( b64, &blob_length )) ) - vips_blob_set( dest_value, - (VipsCallbackFn) vips_free, blob, blob_length ); -} - -GType -vips_blob_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - type = g_boxed_type_register_static( "vips_blob", - (GBoxedCopyFunc) vips_area_copy, - (GBoxedFreeFunc) vips_area_unref ); - g_value_register_transform_func( type, G_TYPE_STRING, - transform_blob_g_string ); - g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING, - transform_blob_save_string ); - g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type, - transform_save_string_blob ); - } - - return( type ); -} - -/** - * vips_blob_set: - * @value: GValue to set - * @free_fn: free function for @data - * @data: pointer to area of memory - * @length: length of memory area - * - * Sets @value to hold a pointer to @blob. When @value is freed, @blob will be - * freed with @free_fn. @value also holds a note of the length of the memory - * area. - * - * blobs are things like ICC profiles or EXIF data. They are relocatable, and - * are saved to VIPS files for you coded as base64 inside the XML. They are - * copied by copying reference-counted pointers. - * - * See also: vips_blob_get() - * - * Returns: 0 on success, -1 otherwise. - */ -int -vips_blob_set( GValue *value, - VipsCallbackFn free_fn, void *data, size_t length ) -{ - VipsArea *area; - - g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_BLOB ); - - if( !(area = area_new_blob( free_fn, data, length )) ) - return( -1 ); - - g_value_set_boxed( value, area ); - vips_area_unref( area ); - - return( 0 ); -} - -/* Set value to be an array of things. Don't initialise the contents: get the - * pointer and write instead. - */ -static int -vips_array_set( GValue *value, GType type, size_t sizeof_type, int n ) -{ - VipsArea *area; - - if( !(area = vips_area_new_array( type, sizeof_type, n )) ) - return( -1 ); - g_value_set_boxed( value, area ); - vips_area_unref( area ); - - return( 0 ); -} - -static void * -vips_array_get( const GValue *value, - int *n, GType *type, size_t *sizeof_type ) -{ - VipsArea *area; - - /* Can't check value type, because we may get called from - * vips_*_get_type(). - */ - - area = g_value_get_boxed( value ); - if( n ) - *n = area->n; - if( type ) - *type = area->type; - if( sizeof_type ) - *sizeof_type = area->sizeof_type; - - return( area->data ); -} - -static void -transform_array_g_string( const GValue *src_value, GValue *dest_value ) -{ - char *array; - int n; - GType type; - size_t sizeof_type; - char txt[1024]; - VipsBuf buf = VIPS_BUF_STATIC( txt ); - int i; - - array = (char *) vips_array_get( src_value, - &n, &type, &sizeof_type ); - - for( i = 0; i < n; i++ ) { - GValue value = { 0, }; - char *str; - - if( i > 0 ) - vips_buf_appends( &buf, ", " ); - - g_value_init( &value, type ); - g_value_set_instance( &value, array ); - - str = g_strdup_value_contents( &value ); - vips_buf_appends( &buf, str ); - g_free( str ); - - g_value_unset( &value ); - - array += sizeof_type; - } - - g_value_set_string( dest_value, vips_buf_all( &buf ) ); -} - -/* It'd be great to be able to write a generic string->array function, but - * it doesn't seem possible. - */ -static void -transform_g_string_array_double( const GValue *src_value, GValue *dest_value ) -{ - const char *str = g_value_get_string( src_value ); - - int n; - const char *p; - int i; - double *array; - - /* Walk the string to get the number of elements. Empty string is zero - * elements. - */ - for( n = 0, p = str; p && *p; n += 1 ) { - p = strchr( p, ',' ); - if( p ) - p += 1; - } - - vips_array_set( dest_value, G_TYPE_DOUBLE, sizeof( double ), n ); - array = (double *) vips_array_get( dest_value, NULL, NULL, NULL ); - - p = str; - for( i = 0; i < n; i++ ) { - array[i] = atof( p ); - p = strchr( p, ',' ); - if( p ) - p += 1; - } -} - -GType -vips_array_double_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - type = g_boxed_type_register_static( "vips_array_double", - (GBoxedCopyFunc) vips_area_copy, - (GBoxedFreeFunc) vips_area_unref ); - g_value_register_transform_func( type, G_TYPE_STRING, - transform_array_g_string ); - g_value_register_transform_func( G_TYPE_STRING, type, - transform_g_string_array_double ); - } - - return( type ); -} - -/** - * vips_array_double_get: - * @value: #GValue to get from - * @n: return the number of elements here, optionally - * - * Return the start of the array of doubles held by @value. - * optionally return the number of elements in @n. - * - * See also: vips_array_double_set(). - * - * Returns: The array address. - */ -double * -vips_array_double_get( const GValue *value, int *n ) -{ - return( vips_array_get( value, n, NULL, NULL ) ); -} - -/** - * vips_array_double_set: - * @value: #GValue to get from - * @array: array of doubles - * @n: the number of elements - * - * Set @value to hold a copy of @array. Pass in the array length in @n. - * - * See also: vips_array_double_get(). - * - * Returns: 0 on success, -1 otherwise. - */ -int -vips_array_double_set( GValue *value, const double *array, int n ) -{ - double *array_copy; - - g_value_init( value, VIPS_TYPE_ARRAY_DOUBLE ); - vips_array_set( value, G_TYPE_DOUBLE, sizeof( double ), n ); - array_copy = vips_array_double_get( value, NULL ); - memcpy( array_copy, array, n * sizeof( double ) ); - - return( 0 ); -} - -static void -vips_array_object_free( VipsArea *area ) -{ - GObject **array = (GObject **) area->data; - - int i; - - for( i = 0; i < area->n; i++ ) - VIPS_FREEF( g_object_unref, array[i] ); - - g_free( area ); -} - -/* An area which holds an array of GObjects. - */ -VipsArea * -vips_array_object_new( int n ) -{ - GObject **array; - VipsArea *area; - - array = g_new0( GObject *, n ); - if( !(area = area_new( - (VipsCallbackFn) vips_array_object_free, array )) ) - return( NULL ); - area->n = n; - area->length = n * sizeof( GObject * ); - area->type = G_TYPE_OBJECT; - area->sizeof_type = sizeof( GObject * ); - - return( area ); -} - -/** - * vips_array_object_get: - * @value: #GValue to get from - * @n: return the number of elements here, optionally - * - * Return the start of the array of #GObject held by @value. - * optionally return the number of elements in @n. - * - * See also: vips_array_object_set(). - * - * Returns: The array address. - */ -GObject ** -vips_array_object_get( const GValue *value, int *n ) -{ - return( vips_array_get( value, n, NULL, NULL ) ); -} - -/** - * vips_array_object_set: - * @value: #GValue to set - * @n: the number of elements - * - * Set @value to hold an array of GObject. Pass in the array length in @n. - * - * See also: vips_array_object_get(). - * - * Returns: 0 on success, -1 otherwise. - */ -int -vips_array_object_set( GValue *value, int n ) -{ - VipsArea *area; - - if( !(area = vips_array_object_new( n )) ) - return( -1 ); - g_value_set_boxed( value, area ); - vips_area_unref( area ); - - return( 0 ); -} - -static void -transform_g_string_array_image( const GValue *src_value, GValue *dest_value ) -{ - char *str; - int n; - char *p, *q; - int i; - GObject **array; - - /* We need a copy of the string, since we insert \0 during - * scan. - */ - str = g_strdup_value_contents( src_value ); - for( n = 0; (q = vips_break_token( p, " " )); n++, p = q ) - ; - g_free( str ); - - vips_array_object_set( dest_value, n ); - array = vips_array_object_get( dest_value, NULL ); - - str = g_strdup_value_contents( src_value ); - for( i = 0; (q = vips_break_token( p, " " )); i++, p = q ) - /* Sadly there's no error return possible here. - */ - array[i] = G_OBJECT( vips_image_new_from_file( p ) ); - g_free( str ); -} - -GType -vips_array_image_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - type = g_boxed_type_register_static( "vips_array_image", - (GBoxedCopyFunc) vips_area_copy, - (GBoxedFreeFunc) vips_area_unref ); - g_value_register_transform_func( G_TYPE_STRING, type, - transform_g_string_array_image ); - } - - return( type ); -} - /** * vips_image_set_blob: * @image: image to attach the metadata to @@ -1810,7 +1004,7 @@ vips_image_set_blob( VipsImage *image, const char *field, GValue value = { 0 }; g_value_init( &value, VIPS_TYPE_BLOB ); - vips_blob_set( &value, free_fn, data, length ); + vips_value_set_blob( &value, free_fn, data, length ); vips_image_set( image, field, &value ); g_value_unset( &value ); } @@ -1839,7 +1033,7 @@ vips_image_get_blob( VipsImage *image, const char *field, GValue value_copy = { 0 }; if( !meta_get_value( image, field, VIPS_TYPE_BLOB, &value_copy ) ) { - *data = vips_blob_get( &value_copy, length ); + *data = vips_value_get_blob( &value_copy, length ); g_value_unset( &value_copy ); return( 0 ); } @@ -2038,7 +1232,7 @@ vips_image_set_string( VipsImage *image, const char *field, const char *str ) GValue value = { 0 }; g_value_init( &value, VIPS_TYPE_REF_STRING ); - vips_ref_string_set( &value, str ); + vips_value_set_ref_string( &value, str ); vips_image_set( image, field, &value ); g_value_unset( &value ); } @@ -2076,7 +1270,7 @@ vips_image_get_as_string( VipsImage *image, const char *field, char **out ) g_value_init( &save_value, VIPS_TYPE_SAVE_STRING ); if( !g_value_transform( &value, &save_value ) ) return( -1 ); - *out = g_strdup( vips_save_string_get( &save_value ) ); + *out = g_strdup( vips_value_get_save_string( &save_value ) ); g_value_unset( &save_value ); } else @@ -2209,27 +1403,3 @@ vips_image_get_history( VipsImage *image ) return( image->Hist ? image->Hist : "" ); } - -/* Make the types we need for basic functioning. Called from init_world(). - */ -void -vips__meta_init_types( void ) -{ - (void) vips_save_string_get_type(); - (void) vips_area_get_type(); - (void) vips_ref_string_get_type(); - (void) vips_blob_get_type(); - - /* Register transform functions to go from built-in saveable types to - * a save string. Transform functions for our own types are set - * during type creation. - */ - g_value_register_transform_func( G_TYPE_INT, VIPS_TYPE_SAVE_STRING, - transform_int_save_string ); - g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_INT, - transform_save_string_int ); - g_value_register_transform_func( G_TYPE_DOUBLE, VIPS_TYPE_SAVE_STRING, - transform_double_save_string ); - g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_DOUBLE, - transform_save_string_double ); -} diff --git a/libvips/iofuncs/array.c b/libvips/iofuncs/type.c similarity index 72% rename from libvips/iofuncs/array.c rename to libvips/iofuncs/type.c index 4dab55bf..6a763feb 100644 --- a/libvips/iofuncs/array.c +++ b/libvips/iofuncs/type.c @@ -95,11 +95,13 @@ vips_area_unref( VipsArea *area ) printf( "vips_area_unref: %p count = %d\n", area, area->count ); #endif /*DEBUG*/ - if( area->count == 0 ) - if( area->free_fn ) - VIPS_FREEF( area->free_fn, area->data ); + if( area->count == 0 ) { + if( area->free_fn && area->data ) { + area->free_fn( area->data, NULL ); + area->data = NULL; + area->free_fn = NULL; + } - area->free_fn = NULL; g_free( area ); #ifdef DEBUG @@ -128,7 +130,7 @@ vips_area_new( VipsCallbackFn free_fn, void *data ) #ifdef DEBUG vips_area_number += 1; - printf( "area_new: %p count = %d (%d in total)\n", + printf( "vips_area_new: %p count = %d (%d in total)\n", area, area->count, vips_area_number ); #endif /*DEBUG*/ @@ -143,7 +145,7 @@ vips_area_new_blob( VipsCallbackFn free_fn, void *blob, size_t blob_length ) { VipsArea *area; - area = area_new( free_fn, blob ); + area = vips_area_new( free_fn, blob ); area->length = blob_length; return( area ); @@ -159,7 +161,7 @@ vips_area_new_array( GType type, size_t sizeof_type, int n ) void *array; array = g_malloc( n * sizeof_type ); - area = area_new( (VipsCallbackFn) g_free, array ); + area = vips_area_new( (VipsCallbackFn) g_free, array ); area->n = n; area->length = n * sizeof_type; area->type = type; @@ -190,7 +192,8 @@ vips_area_new_array_object( int n ) VipsArea *area; array = g_new0( GObject *, n ); - area = area_new( (VipsCallbackFn) vips_array_object_free, array ); + area = vips_area_new( (VipsCallbackFn) vips_area_free_array_object, + array ); area->n = n; area->length = n * sizeof( GObject * ); area->type = G_TYPE_OBJECT; @@ -206,7 +209,7 @@ vips_value_set_area( GValue *value, VipsCallbackFn free_fn, void *data ) { VipsArea *area; - area = area_new( free_fn, data ); + area = vips_area_new( free_fn, data ); g_value_init( value, VIPS_TYPE_AREA ); g_value_set_boxed( value, area ); vips_area_unref( area ); @@ -259,7 +262,7 @@ vips_area_get_type( void ) } /** - * vips_value_get_ref_string: + * vips_value_get_save_string: * @value: GValue to get from * * Get the C string held internally by the GValue. @@ -267,6 +270,113 @@ vips_area_get_type( void ) * Returns: The C string held by @value. This must not be freed. */ const char * +vips_value_get_save_string( const GValue *value ) +{ + return( (char *) g_value_get_boxed( value ) ); +} + +/** + * vips_value_set_save_string: + * @value: GValue to set + * @str: C string to copy into the GValue + * + * Copies the C string into @value. + */ +void +vips_value_set_save_string( GValue *value, const char *str ) +{ + g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_SAVE_STRING ); + + g_value_set_boxed( value, str ); +} + +/** + * vips_value_set_save_stringf: + * @value: GValue to set + * @fmt: printf()-style format string + * @Varargs: arguments to printf()-formatted @fmt + * + * Generates a string and copies it into @value. + */ +void +vips_value_set_save_stringf( GValue *value, const char *fmt, ... ) +{ + va_list ap; + char *str; + + g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_SAVE_STRING ); + + va_start( ap, fmt ); + str = g_strdup_vprintf( fmt, ap ); + va_end( ap ); + vips_value_set_save_string( value, str ); + g_free( str ); +} + +/* Transform funcs for builtin types to SAVE_STRING. + */ +static void +transform_int_save_string( const GValue *src_value, GValue *dest_value ) +{ + vips_value_set_save_stringf( dest_value, + "%d", g_value_get_int( src_value ) ); +} + +static void +transform_save_string_int( const GValue *src_value, GValue *dest_value ) +{ + g_value_set_int( dest_value, + atoi( vips_value_get_save_string( src_value ) ) ); +} + +static void +transform_double_save_string( const GValue *src_value, GValue *dest_value ) +{ + char buf[G_ASCII_DTOSTR_BUF_SIZE]; + + /* Need to be locale independent. + */ + g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, + g_value_get_double( src_value ) ); + vips_value_set_save_string( dest_value, buf ); +} + +static void +transform_save_string_double( const GValue *src_value, GValue *dest_value ) +{ + g_value_set_double( dest_value, + g_ascii_strtod( vips_value_get_save_string( src_value ), + NULL ) ); +} + +/* Save meta fields to the header. We have a new string type for header fields + * to save to XML and define transform functions to go from our meta types to + * this string type. + */ +GType +vips_save_string_get_type( void ) +{ + static GType type = 0; + + if( !type ) { + type = g_boxed_type_register_static( "vips_save_string", + (GBoxedCopyFunc) g_strdup, + (GBoxedFreeFunc) g_free ); + } + + return( type ); +} + +/** + * vips_value_get_ref_string: + * @value: #GValue to get from + * @length: return length here, optionally + * + * Get the C string held internally by the GValue. + * + * Returns: The C string held by @value. This must not be freed. + */ +const char * vips_value_get_ref_string( const GValue *value, size_t *length ) { return( vips_value_get_area( value, length ) ); @@ -294,7 +404,7 @@ vips_value_set_ref_string( GValue *value, const char *str ) g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_REF_STRING ); str_copy = g_strdup( str ); - area = area_new( (VipsCallbackFn) vips_free, str_copy ); + area = vips_area_new( (VipsCallbackFn) vips_free, str_copy ); /* Handy place to cache this. */ @@ -312,7 +422,7 @@ static void transform_ref_string_g_string( const GValue *src_value, GValue *dest_value ) { g_value_set_string( dest_value, - vips_value_get_ref_string( src_value ) ); + vips_value_get_ref_string( src_value, NULL ) ); } static void @@ -361,13 +471,13 @@ vips_ref_string_get_type( void ) } /** - * vips_blob_set: + * vips_value_set_blob: * @value: GValue to set * @free_fn: free function for @data * @data: pointer to area of memory * @length: length of memory area * - * Sets @value to hold a pointer to @blob. When @value is freed, @blob will be + * Sets @value to hold a @data. When @value is freed, @data will be * freed with @free_fn. @value also holds a note of the length of the memory * area. * @@ -375,7 +485,7 @@ vips_ref_string_get_type( void ) * are saved to VIPS files for you coded as base64 inside the XML. They are * copied by copying reference-counted pointers. * - * See also: vips_value_get_area() + * See also: vips_value_get_blob() * * Returns: 0 on success, -1 otherwise. */ @@ -387,13 +497,34 @@ vips_value_set_blob( GValue *value, g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_BLOB ); - area = area_new_blob( free_fn, data, length ); + area = vips_area_new_blob( free_fn, data, length ); g_value_set_boxed( value, area ); vips_area_unref( area ); return( 0 ); } +/** + * vips_value_get_blob: + * @value: GValue to set + * @length: optionally return length of memory area + * + * Returns the data pointer from a blob. Optionally returns the length too. + * + * blobs are things like ICC profiles or EXIF data. They are relocatable, and + * are saved to VIPS files for you coded as base64 inside the XML. They are + * copied by copying reference-counted pointers. + * + * See also: vips_value_set_blob() + * + * Returns: 0 on success, -1 otherwise. + */ +void * +vips_value_get_blob( const GValue *value, size_t *length ) +{ + return( vips_value_get_area( value, length ) ); +} + /* Transform a blob to a G_TYPE_STRING. */ static void @@ -403,11 +534,11 @@ transform_blob_g_string( const GValue *src_value, GValue *dest_value ) size_t blob_length; char buf[256]; - blob = vips_blob_get( src_value, &blob_length ); + blob = vips_value_get_blob( src_value, &blob_length ); vips_snprintf( buf, 256, "VIPS_TYPE_BLOB, data = %p, length = %zd", blob, blob_length ); g_value_set_string( dest_value, buf ); -} +} /* Transform a blob to a save string and back. */ @@ -418,9 +549,9 @@ transform_blob_save_string( const GValue *src_value, GValue *dest_value ) size_t blob_length; char *b64; - blob = vips_value_get_area( src_value, &blob_length ); + blob = vips_value_get_blob( src_value, &blob_length ); if( (b64 = vips__b64_encode( blob, blob_length )) ) { - vips_save_string_set( dest_value, b64 ); + vips_value_set_save_string( dest_value, b64 ); vips_free( b64 ); } } @@ -432,9 +563,9 @@ transform_save_string_blob( const GValue *src_value, GValue *dest_value ) void *blob; size_t blob_length; - b64 = vips_save_string_get( src_value ); + b64 = vips_value_get_save_string( src_value ); if( (blob = vips__b64_decode( b64, &blob_length )) ) - vips_blob_set( dest_value, + vips_value_set_blob( dest_value, (VipsCallbackFn) vips_free, blob, blob_length ); } @@ -509,7 +640,7 @@ vips_value_get_array( const GValue *value, double * vips_value_get_array_double( const GValue *value, int *n ) { - return( vips_array_get( value, n, NULL, NULL ) ); + return( vips_value_get_array( value, n, NULL, NULL ) ); } /** @@ -530,8 +661,8 @@ vips_value_set_array_double( GValue *value, const double *array, int n ) double *array_copy; g_value_init( value, VIPS_TYPE_ARRAY_DOUBLE ); - vips_array_set( value, G_TYPE_DOUBLE, sizeof( double ), n ); - array_copy = vips_array_double_get( value, NULL ); + vips_value_set_array( value, G_TYPE_DOUBLE, sizeof( double ), n ); + array_copy = vips_value_get_array_double( value, NULL ); memcpy( array_copy, array, n * sizeof( double ) ); return( 0 ); @@ -548,7 +679,7 @@ transform_array_g_string( const GValue *src_value, GValue *dest_value ) VipsBuf buf = VIPS_BUF_STATIC( txt ); int i; - array = (char *) vips_array_get( src_value, + array = (char *) vips_value_get_array( src_value, &n, &type, &sizeof_type ); for( i = 0; i < n; i++ ) { @@ -595,8 +726,8 @@ transform_g_string_array_double( const GValue *src_value, GValue *dest_value ) p += 1; } - vips_array_set( dest_value, G_TYPE_DOUBLE, sizeof( double ), n ); - array = (double *) vips_array_get( dest_value, NULL, NULL, NULL ); + vips_value_set_array( dest_value, G_TYPE_DOUBLE, sizeof( double ), n ); + array = (double *) vips_value_get_array( dest_value, NULL, NULL, NULL ); p = str; for( i = 0; i < n; i++ ) { @@ -638,9 +769,9 @@ vips_array_double_get_type( void ) * Returns: The array address. */ GObject ** -vips_array_object_get( const GValue *value, int *n ) +vips_value_get_array_object( const GValue *value, int *n ) { - return( vips_array_get( value, n, NULL, NULL ) ); + return( vips_value_get_array( value, n, NULL, NULL ) ); } /** @@ -655,11 +786,11 @@ vips_array_object_get( const GValue *value, int *n ) * Returns: 0 on success, -1 otherwise. */ int -vips_array_object_set( GValue *value, int n ) +vips_value_set_array_object( GValue *value, int n ) { VipsArea *area; - if( !(area = vips_array_object_new( n )) ) + if( !(area = vips_area_new_array_object( n )) ) return( -1 ); g_value_set_boxed( value, area ); vips_area_unref( area ); @@ -684,8 +815,8 @@ transform_g_string_array_image( const GValue *src_value, GValue *dest_value ) ; g_free( str ); - vips_array_object_set( dest_value, n ); - array = vips_array_object_get( dest_value, NULL ); + vips_value_set_array_object( dest_value, n ); + array = vips_value_get_array_object( dest_value, NULL ); str = g_strdup_value_contents( src_value ); for( i = 0; (q = vips_break_token( p, " " )); i++, p = q ) @@ -710,3 +841,27 @@ vips_array_image_get_type( void ) return( type ); } + +/* Make the types we need for basic functioning. Called from init_world(). + */ +void +vips__meta_init_types( void ) +{ + (void) vips_save_string_get_type(); + (void) vips_area_get_type(); + (void) vips_ref_string_get_type(); + (void) vips_blob_get_type(); + + /* Register transform functions to go from built-in saveable types to + * a save string. Transform functions for our own types are set + * during type creation. + */ + g_value_register_transform_func( G_TYPE_INT, VIPS_TYPE_SAVE_STRING, + transform_int_save_string ); + g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_INT, + transform_save_string_int ); + g_value_register_transform_func( G_TYPE_DOUBLE, VIPS_TYPE_SAVE_STRING, + transform_double_save_string ); + g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_DOUBLE, + transform_save_string_double ); +} diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index dba30f50..44b092df 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -926,7 +926,7 @@ vips__gvalue_ref_string_new( const char *text ) GValue *value; value = vips__gvalue_new( VIPS_TYPE_REF_STRING ); - vips_ref_string_set( value, text ); + vips_value_set_ref_string( value, text ); return( value ); } @@ -985,8 +985,8 @@ vips__gslist_gvalue_merge( GSList *a, const GSList *b ) /* Just do a pointer compare ... good enough 99.9% of * the time. */ - if( vips_ref_string_get( value ) == - vips_ref_string_get( value2 ) ) + if( vips_value_get_ref_string( value, NULL ) == + vips_value_get_ref_string( value2, NULL ) ) break; } @@ -1016,12 +1016,14 @@ vips__gslist_gvalue_get( const GSList *list ) length = 0; for( p = list; p; p = p->next ) { GValue *value = (GValue *) p->data; + size_t l2; g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_REF_STRING ); /* +1 for the newline we will add for each item. */ - length += vips_ref_string_get_length( value ) + 1; + (void) vips_value_get_ref_string( value, &l2 ); + length += l2 + 1; } if( length == 0 ) @@ -1039,9 +1041,10 @@ vips__gslist_gvalue_get( const GSList *list ) q = all; for( p = list; p; p = p->next ) { GValue *value = (GValue *) p->data; + size_t l2; - strcpy( q, vips_ref_string_get( value ) ); - q += vips_ref_string_get_length( value ); + strcpy( q, vips_value_get_ref_string( value, &l2 ) ); + q += l2; strcpy( q, "\n" ); q += 1; } diff --git a/libvips/iofuncs/vips.c b/libvips/iofuncs/vips.c index a8854e5b..02011e8f 100644 --- a/libvips/iofuncs/vips.c +++ b/libvips/iofuncs/vips.c @@ -522,7 +522,7 @@ rebuild_header_meta( VipsImage *im, xmlNode *i ) content = (char *) xmlNodeGetContent( i ); g_value_init( &save_value, VIPS_TYPE_SAVE_STRING ); - vips_save_string_set( &save_value, content ); + vips_value_set_save_string( &save_value, content ); xmlFree( content ); g_value_init( &value, gtype ); @@ -682,7 +682,7 @@ save_fields_meta( VipsMeta *meta, xmlNode *node ) return( node ); } if( set_field( node, meta->field, g_type_name( type ), - vips_save_string_get( &save_value ) ) ) { + vips_value_get_save_string( &save_value ) ) ) { g_value_unset( &save_value ); return( node ); }