break out libvip gtypes

all libvips gtype definitions broken out and renamed for consistency
This commit is contained in:
John Cupitt 2011-10-28 10:28:31 +01:00
parent 7dcda5c0c9
commit c1f1957e88
14 changed files with 363 additions and 1161 deletions

View File

@ -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];

View File

@ -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 );
}

View File

@ -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 );

View File

@ -1,4 +1,5 @@
pkginclude_HEADERS = \
type.h \
almostdeprecated.h \
deprecated.h \
arithmetic.h \

View File

@ -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*/

View File

@ -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 );

View File

@ -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*/

View File

@ -97,7 +97,7 @@ extern "C" {
#include <vips/buf.h>
#include <vips/util.h>
#include <vips/object.h>
#include <vips/area.h>
#include <vips/type.h>
#include <vips/pool.h>
#include <vips/version.h>

View File

@ -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

View File

@ -1,6 +1,7 @@
noinst_LTLIBRARIES = libiofuncs.la
libiofuncs_la_SOURCES = \
type.c \
enumtypes.c \
object.c \
pool.c \

View File

@ -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 );
}

View File

@ -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 );
}

View File

@ -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;
}

View File

@ -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 );
}