1 /* array type
2  *
3  * Unlike GArray, this has fixed length, tracks a GType for elements, and has
4  * a per-element free function.
5  *
6  * 27/10/11
7  * 	- from header.c
8  * 16/7/13
9  * 	- leakcheck VipsArea
10  * 16/8/17
11  * 	- validate strings as utf-8 on set
12  */
13 
14 /*
15 
16     This file is part of VIPS.
17 
18     VIPS is free software; you can redistribute it and/or modify
19     it under the terms of the GNU Lesser General Public License as published by
20     the Free Software Foundation; either version 2 of the License, or
21     (at your option) any later version.
22 
23     This program is distributed in the hope that it will be useful,
24     but WITHOUT ANY WARRANTY; without even the implied warranty of
25     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26     GNU Lesser General Public License for more details.
27 
28     You should have received a copy of the GNU Lesser General Public License
29     along with this program; if not, write to the Free Software
30     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31     02110-1301  USA
32 
33  */
34 
35 /*
36 
37     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
38 
39  */
40 
41 /*
42 #define VIPS_DEBUG
43 #define DEBUG
44  */
45 
46 #ifdef HAVE_CONFIG_H
47 #include <config.h>
48 #endif /*HAVE_CONFIG_H*/
49 #include <vips/intl.h>
50 
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <stdarg.h>
55 
56 #include <vips/vips.h>
57 #include <vips/internal.h>
58 #include <vips/debug.h>
59 
60 /**
61  * SECTION: basic
62  * @short_description: a few typedefs used everywhere
63  * @stability: Stable
64  * @include: vips/vips.h
65  *
66  * A few simple typedefs used by VIPS.
67  */
68 
69 /**
70  * SECTION: type
71  * @short_description: basic types
72  * @stability: Stable
73  * @see_also: <link linkend="libvips-header">header</link>
74  * @include: vips/vips.h
75  *
76  * A selection of %GType defintions used by VIPS.
77  */
78 
79 /* A very simple boxed type for testing. Just an int.
80  *
81  * You can manipulate this thing from Python (for example) with:
82  *
83  * from gi.repository import Vips
84  * a = Vips.Thing.new(12)
85  * print a.i
86  * b = a
87  * del a
88  * print b.i
89  * del b
90  */
91 
92 /**
93  * vips_thing_new:
94  * @i:
95  *
96  * Returns: (transfer full): a new #VipsThing.
97  */
98 VipsThing *
vips_thing_new(int i)99 vips_thing_new( int i )
100 {
101 	VipsThing *thing;
102 
103 	thing = g_new( VipsThing, 1 );
104 	thing->i = i;
105 
106 	printf( "vips_thing_new: %d %p\n", i, thing );
107 
108 	return( thing );
109 }
110 
111 static VipsThing *
vips_thing_copy(VipsThing * thing)112 vips_thing_copy( VipsThing *thing )
113 {
114 	VipsThing *thing2;
115 
116 	thing2 = vips_thing_new( thing->i );
117 
118 	printf( "vips_thing_copy: %d %p = %p\n", thing->i, thing2, thing );
119 
120 	return( thing2 );
121 }
122 
123 static void
vips_thing_free(VipsThing * thing)124 vips_thing_free( VipsThing *thing )
125 {
126 	printf( "vips_thing_free: %d %p\n", thing->i, thing );
127 
128 	g_free( thing );
129 }
130 
131 /*
132  * glib-2.26+ only
133 
134 G_DEFINE_BOXED_TYPE( VipsThing, vips_thing,
135 	(GBoxedCopyFunc) vips_thing_copy,
136 	(GBoxedFreeFunc) vips_thing_free );
137 
138  */
139 
140 GType
vips_thing_get_type(void)141 vips_thing_get_type( void )
142 {
143 	static GType type = 0;
144 
145 	if( !type ) {
146 		type = g_boxed_type_register_static( "VipsThing",
147 			(GBoxedCopyFunc) vips_thing_copy,
148 			(GBoxedFreeFunc) vips_thing_free );
149 	}
150 
151 	return( type );
152 }
153 
154 static GSList *vips_area_all = NULL;
155 
156 VipsArea *
vips_area_copy(VipsArea * area)157 vips_area_copy( VipsArea *area )
158 {
159 	g_mutex_lock( area->lock );
160 
161 	g_assert( area->count > 0 );
162 
163 	area->count += 1;
164 
165 #ifdef DEBUG
166 	printf( "vips_area_copy: %p count = %d\n", area, area->count );
167 #endif /*DEBUG*/
168 
169 	g_mutex_unlock( area->lock );
170 
171 	return( area );
172 }
173 
174 int
vips_area_free_cb(void * mem,VipsArea * area)175 vips_area_free_cb( void *mem, VipsArea *area )
176 {
177 	g_free( mem );
178 
179 	return( 0 );
180 }
181 
182 void
vips_area_free(VipsArea * area)183 vips_area_free( VipsArea *area )
184 {
185 	if( area->free_fn &&
186 		area->data ) {
187 		area->free_fn( area->data, area );
188 		area->free_fn = NULL;
189 	}
190 
191 	area->data = NULL;
192 }
193 
194 void
vips_area_unref(VipsArea * area)195 vips_area_unref( VipsArea *area )
196 {
197 	g_mutex_lock( area->lock );
198 
199 	g_assert( area->count > 0 );
200 
201 	area->count -= 1;
202 
203 #ifdef DEBUG
204 	printf( "vips_area_unref: %p count = %d\n", area, area->count );
205 #endif /*DEBUG*/
206 
207 	if( vips__leak ) {
208 		g_mutex_lock( vips__global_lock );
209 		g_assert( g_slist_find( vips_area_all, area ) );
210 		g_mutex_unlock( vips__global_lock );
211 	}
212 
213 	if( area->count == 0 ) {
214 		vips_area_free( area );
215 
216 		g_mutex_unlock( area->lock );
217 
218 		VIPS_FREEF( vips_g_mutex_free, area->lock );
219 
220 		g_free( area );
221 
222 		if( vips__leak ) {
223 			g_mutex_lock( vips__global_lock );
224 			vips_area_all = g_slist_remove( vips_area_all, area );
225 			g_mutex_unlock( vips__global_lock );
226 		}
227 
228 #ifdef DEBUG
229 		g_mutex_lock( vips__global_lock );
230 		printf( "vips_area_unref: free .. total = %d\n",
231 			g_slist_length( vips_area_all ) );
232 		g_mutex_unlock( vips__global_lock );
233 #endif /*DEBUG*/
234 	}
235 	else
236 		g_mutex_unlock( area->lock );
237 }
238 
239 /**
240  * vips_area_new: (constructor)
241  * @free_fn: (scope async): @data will be freed with this function
242  * @data: data will be freed with this function
243  *
244  * A VipsArea wraps a chunk of memory. It adds reference counting and a free
245  * function. It also keeps a count and a %GType, so the area can be an array.
246  *
247  * This type is used for things like passing an array of double or an array of
248  * #VipsObject pointers to operations, and for reference-counted immutable
249  * strings.
250  *
251  * Inital count == 1, so _unref() after attaching somewhere.
252  *
253  * See also: vips_area_unref().
254  *
255  * Returns: (transfer full): the new #VipsArea.
256  */
257 VipsArea *
vips_area_new(VipsCallbackFn free_fn,void * data)258 vips_area_new( VipsCallbackFn free_fn, void *data )
259 {
260 	VipsArea *area;
261 
262 	area = g_new( VipsArea, 1 );
263 	area->count = 1;
264 	area->lock = vips_g_mutex_new();
265 	area->length = 0;
266 	area->data = data;
267 	area->free_fn = free_fn;
268 	area->type = 0;
269 	area->sizeof_type = 0;
270 
271 	if( vips__leak ) {
272 		g_mutex_lock( vips__global_lock );
273 		vips_area_all = g_slist_prepend( vips_area_all, area );
274 		g_mutex_unlock( vips__global_lock );
275 	}
276 
277 #ifdef DEBUG
278 	g_mutex_lock( vips__global_lock );
279 	printf( "vips_area_new: %p count = %d (%d in total)\n",
280 		area, area->count,
281 		g_slist_length( vips_area_all ) );
282 	g_mutex_unlock( vips__global_lock );
283 #endif /*DEBUG*/
284 
285 	return( area );
286 }
287 
288 int
vips__type_leak(void)289 vips__type_leak( void )
290 {
291 	int n_leaks;
292 
293 	n_leaks = 0;
294 
295 	if( vips_area_all ) {
296 		GSList *p;
297 
298 		fprintf( stderr, "%d VipsArea alive\n",
299 			g_slist_length( vips_area_all ) );
300 		for( p = vips_area_all; p; p = p->next ) {
301 			VipsArea *area = VIPS_AREA( p->data );
302 
303 			fprintf( stderr, "\t%p count = %d, bytes = %zd\n",
304 				area, area->count, area->length );
305 
306 			n_leaks += 1;
307 		}
308 	}
309 
310 	return( n_leaks );
311 }
312 
313 /**
314  * vips_area_new_array:
315  * @type: %GType of elements to store
316  * @sizeof_type: sizeof() an element in the array
317  * @n: number of elements in the array
318  *
319  * An area which holds an array of elements of some %GType. To set values for
320  * the elements, get the pointer and write.
321  *
322  * See also: vips_area_unref().
323  *
324  * Returns: (transfer full): the new #VipsArea.
325  */
326 VipsArea *
vips_area_new_array(GType type,size_t sizeof_type,int n)327 vips_area_new_array( GType type, size_t sizeof_type, int n )
328 {
329 	VipsArea *area;
330 	void *array;
331 
332 	array = g_malloc( n * sizeof_type );
333 	area = vips_area_new( (VipsCallbackFn) vips_area_free_cb, array );
334 	area->n = n;
335 	area->length = n * sizeof_type;
336 	area->type = type;
337 	area->sizeof_type = sizeof_type;
338 
339 	return( area );
340 }
341 
342 static int
vips_area_free_array_object(GObject ** array,VipsArea * area)343 vips_area_free_array_object( GObject **array, VipsArea *area )
344 {
345 	int i;
346 
347 	for( i = 0; i < area->n; i++ )
348 		VIPS_FREEF( g_object_unref, array[i] );
349 	VIPS_FREE( array );
350 
351 	area->n = 0;
352 
353 	return( 0 );
354 }
355 
356 /**
357  * vips_area_new_array_object: (constructor)
358  * @n: number of elements in the array
359  *
360  * An area which holds an array of %GObject s. See vips_area_new_array(). When
361  * the area is freed, each %GObject will be unreffed.
362  *
363  * Add an extra NULL element at the end, handy for eg.
364  * vips_image_pipeline_array() etc.
365  *
366  * See also: vips_area_unref().
367  *
368  * Returns: (transfer full): the new #VipsArea.
369  */
370 VipsArea *
vips_area_new_array_object(int n)371 vips_area_new_array_object( int n )
372 {
373 	GObject **array;
374 	VipsArea *area;
375 
376 	array = g_new0( GObject *, n + 1 );
377 	area = vips_area_new( (VipsCallbackFn) vips_area_free_array_object,
378 		array );
379 	area->n = n;
380 	area->length = n * sizeof( GObject * );
381 	area->type = G_TYPE_OBJECT;
382 	area->sizeof_type = sizeof( GObject * );
383 
384 	return( area );
385 }
386 
387 /**
388  * vips_area_get_data: (method)
389  * @area: #VipsArea to fetch from
390  * @length: (optional): optionally return length in bytes here
391  * @n: (optional): optionally return number of elements here
392  * @type: (optional): optionally return element type here
393  * @sizeof_type: (optional): optionally return sizeof() element type here
394  *
395  * Return the data pointer plus optionally the length in bytes of an area,
396  * the number of elements, the %GType of each element and the sizeof() each
397  * element.
398  *
399  * Returns: (transfer none): The pointer held by @area.
400  */
401 void *
vips_area_get_data(VipsArea * area,size_t * length,int * n,GType * type,size_t * sizeof_type)402 vips_area_get_data( VipsArea *area,
403 	size_t *length, int *n, GType *type, size_t *sizeof_type )
404 {
405 	if( !area )
406 		return( NULL );
407 
408 	if( length )
409 		*length = area->length;
410 	if( n )
411 		*n = area->n;
412 	if( type )
413 		*type = area->type;
414 	if( sizeof_type )
415 		*sizeof_type = area->sizeof_type;
416 
417 	return( area->data );
418 }
419 
420 /* Transform an area to a G_TYPE_STRING.
421  */
422 static void
transform_area_g_string(const GValue * src_value,GValue * dest_value)423 transform_area_g_string( const GValue *src_value, GValue *dest_value )
424 {
425 	VipsArea *area;
426 	char buf[256];
427 
428 	area = g_value_get_boxed( src_value );
429 	vips_snprintf( buf, 256, "VIPS_TYPE_AREA, count = %d, data = %p",
430 		area->count, area->data );
431 	g_value_set_string( dest_value, buf );
432 }
433 
434 GType
vips_area_get_type(void)435 vips_area_get_type( void )
436 {
437 	static GType type = 0;
438 
439 	if( !type ) {
440 		type = g_boxed_type_register_static( "VipsArea",
441 			(GBoxedCopyFunc) vips_area_copy,
442 			(GBoxedFreeFunc) vips_area_unref );
443 		g_value_register_transform_func( type, G_TYPE_STRING,
444 			transform_area_g_string );
445 	}
446 
447 	return( type );
448 }
449 
450 /* Transform funcs for builtin types to SAVE_STRING.
451  */
452 static void
transform_int_save_string(const GValue * src_value,GValue * dest_value)453 transform_int_save_string( const GValue *src_value, GValue *dest_value )
454 {
455 	vips_value_set_save_stringf( dest_value,
456 		"%d", g_value_get_int( src_value ) );
457 }
458 
459 static void
transform_save_string_int(const GValue * src_value,GValue * dest_value)460 transform_save_string_int( const GValue *src_value, GValue *dest_value )
461 {
462 	g_value_set_int( dest_value,
463 		atoi( vips_value_get_save_string( src_value ) ) );
464 }
465 
466 static void
transform_double_save_string(const GValue * src_value,GValue * dest_value)467 transform_double_save_string( const GValue *src_value, GValue *dest_value )
468 {
469 	char buf[G_ASCII_DTOSTR_BUF_SIZE];
470 
471 	/* Need to be locale independent.
472 	 */
473 	g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE,
474 		g_value_get_double( src_value ) );
475 	vips_value_set_save_string( dest_value, buf );
476 }
477 
478 static void
transform_save_string_double(const GValue * src_value,GValue * dest_value)479 transform_save_string_double( const GValue *src_value, GValue *dest_value )
480 {
481 	g_value_set_double( dest_value,
482 		g_ascii_strtod( vips_value_get_save_string( src_value ),
483 			NULL ) );
484 }
485 
486 static void
transform_float_save_string(const GValue * src_value,GValue * dest_value)487 transform_float_save_string( const GValue *src_value, GValue *dest_value )
488 {
489 	char buf[G_ASCII_DTOSTR_BUF_SIZE];
490 
491 	/* Need to be locale independent.
492 	 */
493 	g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE,
494 		g_value_get_float( src_value ) );
495 	vips_value_set_save_string( dest_value, buf );
496 }
497 
498 static void
transform_save_string_float(const GValue * src_value,GValue * dest_value)499 transform_save_string_float( const GValue *src_value, GValue *dest_value )
500 {
501 	g_value_set_float( dest_value,
502 		g_ascii_strtod( vips_value_get_save_string( src_value ),
503 			NULL ) );
504 }
505 
506 /* Save meta fields to the header. We have a new string type for header fields
507  * to save to XML and define transform functions to go from our meta types to
508  * this string type.
509  */
510 GType
vips_save_string_get_type(void)511 vips_save_string_get_type( void )
512 {
513 	static GType type = 0;
514 
515 	if( !type ) {
516 		type = g_boxed_type_register_static( "VipsSaveString",
517 			(GBoxedCopyFunc) g_strdup,
518 			(GBoxedFreeFunc) g_free );
519 	}
520 
521 	return( type );
522 }
523 
524 /* Transform a refstring to a G_TYPE_STRING and back.
525  */
526 static void
transform_ref_string_g_string(const GValue * src_value,GValue * dest_value)527 transform_ref_string_g_string( const GValue *src_value, GValue *dest_value )
528 {
529 	g_value_set_string( dest_value,
530 		vips_value_get_ref_string( src_value, NULL ) );
531 }
532 
533 static void
transform_g_string_ref_string(const GValue * src_value,GValue * dest_value)534 transform_g_string_ref_string( const GValue *src_value, GValue *dest_value )
535 {
536 	vips_value_set_ref_string( dest_value,
537 		g_value_get_string( src_value ) );
538 }
539 
540 /* To a save string.
541  */
542 static void
transform_ref_string_save_string(const GValue * src_value,GValue * dest_value)543 transform_ref_string_save_string( const GValue *src_value, GValue *dest_value )
544 {
545 	vips_value_set_save_stringf( dest_value,
546 		"%s", vips_value_get_ref_string( src_value, NULL ) );
547 }
548 
549 static void
transform_save_string_ref_string(const GValue * src_value,GValue * dest_value)550 transform_save_string_ref_string( const GValue *src_value, GValue *dest_value )
551 {
552 	vips_value_set_ref_string( dest_value,
553 		vips_value_get_save_string( src_value ) );
554 }
555 
556 /**
557  * vips_ref_string_new:
558  * @str: (transfer none): string to store
559  *
560  * Create a new refstring. These are reference-counted immutable strings, used
561  * to store string data in vips image metadata.
562  *
563  * Strings must be valid utf-8; use blob for binary data.
564  *
565  * See also: vips_area_unref().
566  *
567  * Returns: (transfer full): the new #VipsRefString, or NULL on error.
568  */
569 VipsRefString *
vips_ref_string_new(const char * str)570 vips_ref_string_new( const char *str )
571 {
572 	VipsArea *area;
573 
574 	if( !g_utf8_validate( str, -1, NULL ) )
575 		str = "<invalid utf-8 string>";
576 
577 	area = vips_area_new( (VipsCallbackFn) vips_area_free_cb, g_strdup( str ) );
578 
579 	/* Handy place to cache this.
580 	 */
581 	area->length = strlen( str );
582 
583 	return( (VipsRefString *) area );
584 }
585 
586 /**
587  * vips_ref_string_get:
588  * @refstr: the #VipsRefString to fetch from
589  * @length: (allow-none): return length here, optionally
590  *
591  * Get a pointer to the private string inside a refstr. Handy for language
592  * bindings.
593  *
594  * See also: vips_value_get_ref_string().
595  *
596  * Returns: (transfer none): The C string held by @refstr.
597  */
598 const char *
vips_ref_string_get(VipsRefString * refstr,size_t * length)599 vips_ref_string_get( VipsRefString *refstr, size_t *length )
600 {
601 	VipsArea *area = VIPS_AREA( refstr );
602 
603 	return( vips_area_get_data( area, length, NULL, NULL, NULL ) );
604 }
605 
606 GType
vips_ref_string_get_type(void)607 vips_ref_string_get_type( void )
608 {
609 	static GType type = 0;
610 
611 	if( !type ) {
612 		type = g_boxed_type_register_static( "VipsRefString",
613 			(GBoxedCopyFunc) vips_area_copy,
614 			(GBoxedFreeFunc) vips_area_unref );
615 		g_value_register_transform_func( type, G_TYPE_STRING,
616 			transform_ref_string_g_string );
617 		g_value_register_transform_func( G_TYPE_STRING, type,
618 			transform_g_string_ref_string );
619 		g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING,
620 			transform_ref_string_save_string );
621 		g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type,
622 			transform_save_string_ref_string );
623 	}
624 
625 	return( type );
626 }
627 
628 /**
629  * vips_blob_new:
630  * @free_fn: (scope async) (allow-none): @data will be freed with this function
631  * @data: (array length=length) (element-type guint8) (transfer full): data to store
632  * @length: number of bytes in @data
633  *
634  * Like vips_area_new(), but track a length as well. The returned #VipsBlob
635  * takes ownership of @data and will free it with @free_fn. Pass NULL for
636  * @free_fn to not transfer ownership.
637  *
638  * An area of mem with a free func and a length (some sort of binary object,
639  * like an ICC profile).
640  *
641  * See also: vips_area_unref().
642  *
643  * Returns: (transfer full): the new #VipsBlob.
644  */
645 VipsBlob *
vips_blob_new(VipsCallbackFn free_fn,const void * data,size_t length)646 vips_blob_new( VipsCallbackFn free_fn, const void *data, size_t length )
647 {
648 	VipsArea *area;
649 
650 	area = vips_area_new( free_fn, (void *) data );
651 	area->length = length;
652 
653 	return( (VipsBlob *) area );
654 }
655 
656 /**
657  * vips_blob_copy:
658  * @data: (array length=length) (element-type guint8) (transfer none): data to store
659  * @length: number of bytes in @data
660  *
661  * Like vips_blob_new(), but take a copy of the data. Useful for bindings
662  * which struggle with callbacks.
663  *
664  * See also: vips_blob_new().
665  *
666  * Returns: (transfer full): the new #VipsBlob.
667  */
668 VipsBlob *
vips_blob_copy(const void * data,size_t length)669 vips_blob_copy( const void *data, size_t length )
670 {
671 	void *data_copy;
672 	VipsArea *area;
673 
674 	data_copy = g_malloc( length );
675 	memcpy( data_copy, data, length );
676 	area = vips_area_new( (VipsCallbackFn) vips_area_free_cb, data_copy );
677 	area->length = length;
678 
679 	return( (VipsBlob *) area );
680 }
681 
682 /**
683  * vips_blob_get:
684  * @blob: #VipsBlob to fetch from
685  * @length: return number of bytes of data
686  *
687  * Get the data from a #VipsBlob.
688  *
689  * See also: vips_blob_new().
690  *
691  * Returns: (array length=length) (element-type guint8) (transfer none): the
692  * data
693  */
694 const void *
vips_blob_get(VipsBlob * blob,size_t * length)695 vips_blob_get( VipsBlob *blob, size_t *length )
696 {
697 	return( vips_area_get_data( VIPS_AREA( blob ),
698 		length, NULL, NULL, NULL ) );
699 }
700 
701 /* vips_blob_set:
702  * @blob: #VipsBlob to set
703  * @free_fn: (scope async) (allow-none): @data will be freed with this function
704  * @data: (array length=length) (element-type guint8) (transfer full): data to store
705  * @length: number of bytes in @data
706  *
707  * Any old data is freed and new data attached.
708  *
709  * It's sometimes useful to be able to create blobs as empty and then fill
710  * them later.
711  *
712  * See also: vips_blob_new().
713  */
714 void
vips_blob_set(VipsBlob * blob,VipsCallbackFn free_fn,const void * data,size_t length)715 vips_blob_set( VipsBlob *blob,
716 	VipsCallbackFn free_fn, const void *data, size_t length )
717 {
718 	VipsArea *area = VIPS_AREA( blob );
719 
720 	g_mutex_lock( area->lock );
721 
722 	vips_area_free( area );
723 
724 	area->free_fn = free_fn;
725 	area->length = length;
726 	area->data = (void *) data;
727 
728 	g_mutex_unlock( area->lock );
729 }
730 
731 /* Transform a blob to a G_TYPE_STRING.
732  */
733 static void
transform_blob_g_string(const GValue * src_value,GValue * dest_value)734 transform_blob_g_string( const GValue *src_value, GValue *dest_value )
735 {
736 	void *blob;
737 	size_t length;
738 	char buf[256];
739 
740 	blob = vips_value_get_blob( src_value, &length );
741 	vips_snprintf( buf, 256, "VIPS_TYPE_BLOB, data = %p, length = %zd",
742 		blob, length );
743 	g_value_set_string( dest_value, buf );
744 }
745 
746 /* Transform a blob to a save string and back.
747  */
748 static void
transform_blob_save_string(const GValue * src_value,GValue * dest_value)749 transform_blob_save_string( const GValue *src_value, GValue *dest_value )
750 {
751 	void *blob;
752 	size_t length;
753 	char *b64;
754 
755 	blob = vips_value_get_blob( src_value, &length );
756 	if( (b64 = g_base64_encode( blob, length )) ) {
757 		vips_value_set_save_string( dest_value, b64 );
758 		g_free( b64 );
759 	}
760 	else
761 		/* No error return from transform, but we should set it to
762 		 * something.
763 		 */
764 		vips_value_set_save_string( dest_value, "" );
765 }
766 
767 static void
transform_save_string_blob(const GValue * src_value,GValue * dest_value)768 transform_save_string_blob( const GValue *src_value, GValue *dest_value )
769 {
770 	const char *b64;
771 	void *blob;
772 	size_t length;
773 
774 	b64 = vips_value_get_save_string( src_value );
775 	if( (blob = g_base64_decode( b64, &length )) )
776 		vips_value_set_blob( dest_value,
777 			(VipsCallbackFn) vips_area_free_cb, blob, length );
778 	else
779 		/* No error return from transform, but we should set it to
780 		 * something.
781 		 */
782 		vips_value_set_blob( dest_value, NULL, NULL, 0 );
783 }
784 
785 GType
vips_blob_get_type(void)786 vips_blob_get_type( void )
787 {
788 	static GType type = 0;
789 
790 	if( !type ) {
791 		type = g_boxed_type_register_static( "VipsBlob",
792 			(GBoxedCopyFunc) vips_area_copy,
793 			(GBoxedFreeFunc) vips_area_unref );
794 		g_value_register_transform_func( type, G_TYPE_STRING,
795 			transform_blob_g_string );
796 		g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING,
797 			transform_blob_save_string );
798 		g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type,
799 			transform_save_string_blob );
800 	}
801 
802 	return( type );
803 }
804 
805 /**
806  * vips_array_int_new:
807  * @array: (array length=n): array of int
808  * @n: number of ints
809  *
810  * Allocate a new array of ints and copy @array into it. Free with
811  * vips_area_unref().
812  *
813  * See also: #VipsArea.
814  *
815  * Returns: (transfer full): A new #VipsArrayInt.
816  */
817 VipsArrayInt *
vips_array_int_new(const int * array,int n)818 vips_array_int_new( const int *array, int n )
819 {
820 	VipsArea *area;
821 	int *array_copy;
822 
823 	area = vips_area_new_array( G_TYPE_INT, sizeof( int ), n );
824 	array_copy = vips_area_get_data( area, NULL, NULL, NULL, NULL );
825 	memcpy( array_copy, array, n * sizeof( int ) );
826 
827 	return( (VipsArrayInt *) area );
828 }
829 
830 /**
831  * vips_array_int_newv:
832  * @n: number of ints
833  * @...: list of int arguments
834  *
835  * Allocate a new array of @n ints and copy @... into it. Free with
836  * vips_area_unref().
837  *
838  * See also: vips_array_int_new()
839  *
840  * Returns: (transfer full): A new #VipsArrayInt.
841  */
842 VipsArrayInt *
vips_array_int_newv(int n,...)843 vips_array_int_newv( int n, ... )
844 {
845 	va_list ap;
846 	VipsArea *area;
847 	int *array;
848 	int i;
849 
850 	area = vips_area_new_array( G_TYPE_INT, sizeof( int ), n );
851 	array = vips_area_get_data( area, NULL, NULL, NULL, NULL );
852 
853 	va_start( ap, n );
854 	for( i = 0; i < n; i++ )
855 		array[i] = va_arg( ap, int );
856 	va_end( ap );
857 
858 	return( (VipsArrayInt *) area );
859 }
860 
861 /**
862  * vips_array_int_get:
863  * @array: the #VipsArrayInt to fetch from
864  * @n: length of array
865  *
866  * Fetch an int array from a #VipsArrayInt. Useful for language bindings.
867  *
868  * Returns: (array length=n) (transfer none): array of int
869  */
870 int *
vips_array_int_get(VipsArrayInt * array,int * n)871 vips_array_int_get( VipsArrayInt *array, int *n )
872 {
873 	VipsArea *area = VIPS_AREA( array );
874 
875 	g_assert( area->type == G_TYPE_INT );
876 
877 	if( n )
878 		*n = area->n;
879 
880 	return( (int *) VIPS_ARRAY_ADDR( array, 0 ) );
881 }
882 
883 static void
transform_array_int_g_string(const GValue * src_value,GValue * dest_value)884 transform_array_int_g_string( const GValue *src_value, GValue *dest_value )
885 {
886 	int n;
887 	int *array;
888 
889 	char txt[1024];
890 	VipsBuf buf = VIPS_BUF_STATIC( txt );
891 	int i;
892 
893 	if( (array = vips_value_get_array_int( src_value, &n )) )
894 		for( i = 0; i < n; i++ )
895 			/* Use space as a separator since ',' may be a
896 			 * decimal point in this locale.
897 			 */
898 			vips_buf_appendf( &buf, "%d ", array[i] );
899 
900 	g_value_set_string( dest_value, vips_buf_all( &buf ) );
901 }
902 
903 static void
transform_array_int_save_string(const GValue * src_value,GValue * dest_value)904 transform_array_int_save_string( const GValue *src_value, GValue *dest_value )
905 {
906 	GValue intermediate = { 0 };
907 
908 	g_value_init( &intermediate, G_TYPE_STRING );
909 
910 	transform_array_int_g_string( src_value, &intermediate );
911 
912 	vips_value_set_save_string( dest_value,
913 		g_value_get_string( &intermediate ) );
914 
915 	g_value_unset( &intermediate );
916 }
917 
918 /* It'd be great to be able to write a generic string->array function, but
919  * it doesn't seem possible.
920  */
921 static void
transform_g_string_array_int(const GValue * src_value,GValue * dest_value)922 transform_g_string_array_int( const GValue *src_value, GValue *dest_value )
923 {
924 	char *str;
925 	int n;
926 	char *p, *q;
927 	int i;
928 	int *array;
929 
930 	/* Walk the string to get the number of elements.
931 	 * We need a copy of the string, since we insert \0 during
932 	 * scan.
933 	 *
934 	 * We can't allow ',' as a separator, since some locales use it as a
935 	 * decimal point.
936 	 */
937 	str = g_value_dup_string( src_value );
938 
939 	n = 0;
940 	for( p = str; (q = vips_break_token( p, "\t; " )); p = q )
941 		n += 1;
942 
943 	g_free( str );
944 
945 	vips_value_set_array_int( dest_value, NULL, n );
946 	array = vips_value_get_array_int( dest_value, NULL );
947 
948 	str = g_value_dup_string( src_value );
949 
950 	i = 0;
951 	for( p = str; (q = vips_break_token( p, "\t; " )); p = q ) {
952 		if( sscanf( p, "%d", &array[i] ) != 1 ) {
953 			/* Set array to length zero to indicate an error.
954 			 */
955 			vips_error( "vipstype",
956 				_( "unable to convert \"%s\" to int" ), p );
957 			vips_value_set_array( dest_value,
958 				0, G_TYPE_INT, sizeof( int ) );
959 			g_free( str );
960 			return;
961 		}
962 
963 		i += 1;
964 	}
965 
966 	g_free( str );
967 }
968 
969 static void
transform_save_string_array_int(const GValue * src_value,GValue * dest_value)970 transform_save_string_array_int( const GValue *src_value, GValue *dest_value )
971 {
972 	GValue intermediate = { 0 };
973 
974 	g_value_init( &intermediate, G_TYPE_STRING );
975 
976 	g_value_set_string( &intermediate,
977 		vips_value_get_save_string( src_value ) );
978 
979 	transform_g_string_array_int( &intermediate, dest_value );
980 
981 	g_value_unset( &intermediate );
982 }
983 
984 /* We need a arrayint, we have an int, make a one-element array.
985  */
986 static void
transform_int_array_int(const GValue * src_value,GValue * dest_value)987 transform_int_array_int( const GValue *src_value, GValue *dest_value )
988 {
989 	int *array;
990 
991 	vips_value_set_array_int( dest_value, NULL, 1 );
992 	array = vips_value_get_array_int( dest_value, NULL );
993 	array[0] = g_value_get_int( src_value );
994 }
995 
996 static void
transform_double_array_int(const GValue * src_value,GValue * dest_value)997 transform_double_array_int( const GValue *src_value, GValue *dest_value )
998 {
999 	int *array;
1000 
1001 	vips_value_set_array_int( dest_value, NULL, 1 );
1002 	array = vips_value_get_array_int( dest_value, NULL );
1003 	array[0] = g_value_get_double( src_value );
1004 }
1005 
1006 static void
transform_array_double_array_int(const GValue * src_value,GValue * dest_value)1007 transform_array_double_array_int( const GValue *src_value, GValue *dest_value )
1008 {
1009 	int n;
1010 	double *array_double = vips_value_get_array_double( src_value, &n );
1011 	int *array_int;
1012 	int i;
1013 
1014 	vips_value_set_array_int( dest_value, NULL, n );
1015 	array_int = vips_value_get_array_int( dest_value, NULL );
1016 	for( i = 0; i < n; i++ )
1017 		array_int[i] = array_double[i];
1018 }
1019 
1020 GType
vips_array_int_get_type(void)1021 vips_array_int_get_type( void )
1022 {
1023 	static GType type = 0;
1024 
1025 	if( !type ) {
1026 		type = g_boxed_type_register_static( "VipsArrayInt",
1027 			(GBoxedCopyFunc) vips_area_copy,
1028 			(GBoxedFreeFunc) vips_area_unref );
1029 		g_value_register_transform_func( type, G_TYPE_STRING,
1030 			transform_array_int_g_string );
1031 		g_value_register_transform_func( G_TYPE_STRING, type,
1032 			transform_g_string_array_int );
1033 		g_value_register_transform_func( G_TYPE_INT, type,
1034 			transform_int_array_int );
1035 		g_value_register_transform_func( G_TYPE_DOUBLE, type,
1036 			transform_double_array_int );
1037 		g_value_register_transform_func( VIPS_TYPE_ARRAY_DOUBLE, type,
1038 			transform_array_double_array_int );
1039 		g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING,
1040 			transform_array_int_save_string );
1041 		g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type,
1042 			transform_save_string_array_int );
1043 	}
1044 
1045 	return( type );
1046 }
1047 
1048 /**
1049  * vips_array_double_new:
1050  * @array: (array length=n): array of double
1051  * @n: number of doubles
1052  *
1053  * Allocate a new array of doubles and copy @array into it. Free with
1054  * vips_area_unref().
1055  *
1056  * See also: #VipsArea.
1057  *
1058  * Returns: (transfer full): A new #VipsArrayDouble.
1059  */
1060 VipsArrayDouble *
vips_array_double_new(const double * array,int n)1061 vips_array_double_new( const double *array, int n )
1062 {
1063 	VipsArea *area;
1064 	double *array_copy;
1065 
1066 	area = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), n );
1067 	array_copy = vips_area_get_data( area, NULL, NULL, NULL, NULL );
1068 	memcpy( array_copy, array, n * sizeof( double ) );
1069 
1070 	return( (VipsArrayDouble *) area );
1071 }
1072 
1073 /**
1074  * vips_array_double_newv:
1075  * @n: number of doubles
1076  * @...: list of double arguments
1077  *
1078  * Allocate a new array of @n doubles and copy @... into it. Free with
1079  * vips_area_unref().
1080  *
1081  * See also: vips_array_double_new()
1082  *
1083  * Returns: (transfer full): A new #VipsArrayDouble.
1084  */
1085 VipsArrayDouble *
vips_array_double_newv(int n,...)1086 vips_array_double_newv( int n, ... )
1087 {
1088 	va_list ap;
1089 	VipsArea *area;
1090 	double *array;
1091 	int i;
1092 
1093 	area = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), n );
1094 	array = vips_area_get_data( area, NULL, NULL, NULL, NULL );
1095 
1096 	va_start( ap, n );
1097 	for( i = 0; i < n; i++ )
1098 		array[i] = va_arg( ap, double );
1099 	va_end( ap );
1100 
1101 	return( (VipsArrayDouble *) area );
1102 }
1103 
1104 /**
1105  * vips_array_double_get:
1106  * @array: the #VipsArrayDouble to fetch from
1107  * @n: length of array
1108  *
1109  * Fetch a double array from a #VipsArrayDouble. Useful for language bindings.
1110  *
1111  * Returns: (array length=n) (transfer none): array of double
1112  */
1113 double *
vips_array_double_get(VipsArrayDouble * array,int * n)1114 vips_array_double_get( VipsArrayDouble *array, int *n )
1115 {
1116 	VipsArea *area = VIPS_AREA( array );
1117 
1118 	g_assert( area->type == G_TYPE_DOUBLE );
1119 
1120 	if( n )
1121 		*n = area->n;
1122 
1123 	return( VIPS_ARRAY_ADDR( array, 0 ) );
1124 }
1125 
1126 static void
transform_array_double_g_string(const GValue * src_value,GValue * dest_value)1127 transform_array_double_g_string( const GValue *src_value, GValue *dest_value )
1128 {
1129 	int n;
1130 	double *array;
1131 
1132 	char txt[1024];
1133 	VipsBuf buf = VIPS_BUF_STATIC( txt );
1134 	int i;
1135 
1136 	if( (array = vips_value_get_array_double( src_value, &n )) )
1137 		for( i = 0; i < n; i++ )
1138 			/* Use space as a separator since ',' may be a decimal
1139 			 * point in this locale.
1140 			 */
1141 			vips_buf_appendf( &buf, "%g ", array[i] );
1142 
1143 	g_value_set_string( dest_value, vips_buf_all( &buf ) );
1144 }
1145 
1146 /* It'd be great to be able to write a generic string->array function, but
1147  * it doesn't seem possible.
1148  */
1149 static void
transform_g_string_array_double(const GValue * src_value,GValue * dest_value)1150 transform_g_string_array_double( const GValue *src_value, GValue *dest_value )
1151 {
1152 	char *str;
1153 	int n;
1154 	char *p, *q;
1155 	int i;
1156 	double *array;
1157 
1158 	/* Walk the string to get the number of elements.
1159 	 * We need a copy of the string, since we insert \0 during scan.
1160 	 *
1161 	 * We can't allow ',' as a separator since some locales use it as a
1162 	 * decimal point.
1163 	 */
1164 	str = g_value_dup_string( src_value );
1165 
1166 	n = 0;
1167 	for( p = str; (q = vips_break_token( p, "\t; " )); p = q )
1168 		n += 1;
1169 
1170 	g_free( str );
1171 
1172 	vips_value_set_array_double( dest_value, NULL, n );
1173 	array = vips_value_get_array_double( dest_value, NULL );
1174 
1175 	str = g_value_dup_string( src_value );
1176 
1177 	i = 0;
1178 	for( p = str; (q = vips_break_token( p, "\t; " )); p = q ) {
1179 		if( sscanf( p, "%lf", &array[i] ) != 1 ) {
1180 			/* Set array to length zero to indicate an error.
1181 			 */
1182 			vips_error( "vipstype",
1183 				_( "unable to convert \"%s\" to float" ), p );
1184 			vips_value_set_array_double( dest_value, NULL, 0 );
1185 			g_free( str );
1186 			return;
1187 		}
1188 
1189 		i += 1;
1190 	}
1191 
1192 	g_free( str );
1193 }
1194 
1195 /* We need a arraydouble, we have a double, make a one-element array.
1196  */
1197 static void
transform_double_array_double(const GValue * src_value,GValue * dest_value)1198 transform_double_array_double( const GValue *src_value, GValue *dest_value )
1199 {
1200 	double *array;
1201 
1202 	vips_value_set_array_double( dest_value, NULL, 1 );
1203 	array = vips_value_get_array_double( dest_value, NULL );
1204 	array[0] = g_value_get_double( src_value );
1205 }
1206 
1207 static void
transform_int_array_double(const GValue * src_value,GValue * dest_value)1208 transform_int_array_double( const GValue *src_value, GValue *dest_value )
1209 {
1210 	double *array;
1211 
1212 	vips_value_set_array_double( dest_value, NULL, 1 );
1213 	array = vips_value_get_array_double( dest_value, NULL );
1214 	array[0] = g_value_get_int( src_value );
1215 }
1216 
1217 static void
transform_array_int_array_double(const GValue * src_value,GValue * dest_value)1218 transform_array_int_array_double( const GValue *src_value, GValue *dest_value )
1219 {
1220 	int n;
1221 	int *array_int = vips_value_get_array_int( src_value, &n );
1222 	double *array_double;
1223 	int i;
1224 
1225 	vips_value_set_array_double( dest_value, NULL, n );
1226 	array_double = vips_value_get_array_double( dest_value, NULL );
1227 	for( i = 0; i < n; i++ )
1228 		array_double[i] = array_int[i];
1229 }
1230 
1231 /* You can set enums from ints, but not doubles. Add a double converter too.
1232  */
1233 static void
transform_double_enum(const GValue * src_value,GValue * dest_value)1234 transform_double_enum( const GValue *src_value, GValue *dest_value )
1235 {
1236 	g_value_set_enum( dest_value, g_value_get_double( src_value ) );
1237 }
1238 
1239 GType
vips_array_double_get_type(void)1240 vips_array_double_get_type( void )
1241 {
1242 	static GType type = 0;
1243 
1244 	if( !type ) {
1245 		type = g_boxed_type_register_static( "VipsArrayDouble",
1246 			(GBoxedCopyFunc) vips_area_copy,
1247 			(GBoxedFreeFunc) vips_area_unref );
1248 		g_value_register_transform_func( type, G_TYPE_STRING,
1249 			transform_array_double_g_string );
1250 		g_value_register_transform_func( G_TYPE_STRING, type,
1251 			transform_g_string_array_double );
1252 		g_value_register_transform_func( G_TYPE_DOUBLE, type,
1253 			transform_double_array_double );
1254 		g_value_register_transform_func( G_TYPE_INT, type,
1255 			transform_int_array_double );
1256 		g_value_register_transform_func( VIPS_TYPE_ARRAY_INT, type,
1257 			transform_array_int_array_double );
1258 		g_value_register_transform_func( G_TYPE_DOUBLE, G_TYPE_ENUM,
1259 			transform_double_enum );
1260 	}
1261 
1262 	return( type );
1263 }
1264 
1265 /**
1266  * vips_array_image_new: (constructor)
1267  * @array: (array length=n): array of #VipsImage
1268  * @n: number of images
1269  *
1270  * Allocate a new array of images and copy @array into it. Free with
1271  * vips_area_unref().
1272  *
1273  * The images will all be reffed by this function. They
1274  * will be automatically unreffed for you by
1275  * vips_area_unref().
1276  *
1277  * Add an extra NULL element at the end, handy for eg.
1278  * vips_image_pipeline_array() etc.
1279  *
1280  * See also: #VipsArea.
1281  *
1282  * Returns: (transfer full): A new #VipsArrayImage.
1283  */
1284 VipsArrayImage *
vips_array_image_new(VipsImage ** array,int n)1285 vips_array_image_new( VipsImage **array, int n )
1286 {
1287 	VipsArea *area;
1288 	VipsImage **array_copy;
1289 	int i;
1290 
1291 	area = vips_area_new_array_object( n );
1292 	area->type = VIPS_TYPE_IMAGE;
1293 
1294 	array_copy = vips_area_get_data( area, NULL, NULL, NULL, NULL );
1295 	for( i = 0; i < n; i++ ) {
1296 		array_copy[i] = (VipsImage *) array[i];
1297 		g_object_ref( array_copy[i] );
1298 	}
1299 
1300 	return( (VipsArrayImage *) area );
1301 }
1302 
1303 /**
1304  * vips_array_image_newv: (constructor)
1305  * @n: number of images
1306  * @...: list of #VipsImage arguments
1307  *
1308  * Allocate a new array of @n #VipsImage and copy @... into it. Free with
1309  * vips_area_unref().
1310  *
1311  * The images will all be reffed by this function. They
1312  * will be automatically unreffed for you by
1313  * vips_area_unref().
1314  *
1315  * Add an extra NULL element at the end, handy for eg.
1316  * vips_image_pipeline_array() etc.
1317  *
1318  * See also: vips_array_image_new()
1319  *
1320  * Returns: (transfer full): A new #VipsArrayImage.
1321  */
1322 VipsArrayImage *
vips_array_image_newv(int n,...)1323 vips_array_image_newv( int n, ... )
1324 {
1325 	va_list ap;
1326 	VipsArea *area;
1327 	VipsImage **array;
1328 	int i;
1329 
1330 	area = vips_area_new_array_object( n );
1331 	area->type = VIPS_TYPE_IMAGE;
1332 
1333 	array = vips_area_get_data( area, NULL, NULL, NULL, NULL );
1334 	va_start( ap, n );
1335 	for( i = 0; i < n; i++ ) {
1336 		array[i] = va_arg( ap, VipsImage * );
1337 		g_object_ref( array[i] );
1338 	}
1339 	va_end( ap );
1340 
1341 	return( (VipsArrayImage *) area );
1342 }
1343 
1344 VipsArrayImage *
vips_array_image_new_from_string(const char * string,VipsAccess access)1345 vips_array_image_new_from_string( const char *string, VipsAccess access )
1346 {
1347 	char *str;
1348 	int n;
1349 	VipsArea *area;
1350 	VipsImage **array;
1351 	char *p, *q;
1352 	int i;
1353 
1354 	/* We need a copy of the string, since we insert \0 during
1355 	 * scan.
1356 	 */
1357 	str = g_strdup( string );
1358 
1359 	n = 0;
1360 	for( p = str; (q = vips_break_token( p, " \n\t\r" )); p = q )
1361 		n += 1;
1362 
1363 	g_free( str );
1364 
1365 	area = vips_area_new_array_object( n );
1366 	area->type = VIPS_TYPE_IMAGE;
1367 
1368 	array = vips_area_get_data( area, NULL, NULL, NULL, NULL );
1369 
1370 	str = g_strdup( string );
1371 
1372 	i = 0;
1373 	for( p = str; (q = vips_break_token( p, " \n\t\r" )); p = q ) {
1374 		if( !(array[i] = vips_image_new_from_file( p,
1375 			"access", access,
1376 			NULL )) ) {
1377 			vips_area_unref( area );
1378 			g_free( str );
1379 			return( NULL );
1380 		}
1381 
1382 		i += 1;
1383 	}
1384 
1385 	g_free( str );
1386 
1387 	return( (VipsArrayImage *) area );
1388 }
1389 
1390 /**
1391  * vips_array_image_empty: (constructor)
1392  *
1393  * Make an empty image array.
1394  * Handy with vips_array_image_add() for bindings
1395  * which can't handle object array arguments.
1396  *
1397  * See also: vips_array_image_add().
1398  *
1399  * Returns: (transfer full): A new #VipsArrayImage.
1400  */
1401 VipsArrayImage *
vips_array_image_empty(void)1402 vips_array_image_empty( void )
1403 {
1404 	return( vips_array_image_new( NULL, 0 ) );
1405 }
1406 
1407 /**
1408  * vips_array_image_append: (method)
1409  * @array: (transfer none): append to this
1410  * @image: add this
1411  *
1412  * Make a new #VipsArrayImage, one larger than @array, with @image appended
1413  * to the end.
1414  * Handy with vips_array_image_empty() for bindings
1415  * which can't handle object array arguments.
1416  *
1417  * See also: vips_array_image_empty().
1418  *
1419  * Returns: (transfer full): A new #VipsArrayImage.
1420  */
1421 VipsArrayImage *
vips_array_image_append(VipsArrayImage * array,VipsImage * image)1422 vips_array_image_append( VipsArrayImage *array, VipsImage *image )
1423 {
1424 	VipsArea *old_area = VIPS_AREA( array );
1425 	int n = old_area->n;
1426 
1427 	VipsArea *new_area;
1428 	VipsImage **old_vector;
1429 	VipsImage **new_vector;
1430 	int i;
1431 
1432 	new_area = vips_area_new_array_object( n + 1 );
1433 	new_area->type = VIPS_TYPE_IMAGE;
1434 
1435 	old_vector = vips_area_get_data( old_area, NULL, NULL, NULL, NULL );
1436 	new_vector = vips_area_get_data( new_area, NULL, NULL, NULL, NULL );
1437 	for( i = 0; i < n; i++ ) {
1438 		new_vector[i] = (VipsImage *) old_vector[i];
1439 		g_object_ref( new_vector[i] );
1440 	}
1441 	new_vector[i] = image;
1442 	g_object_ref( new_vector[i] );
1443 
1444 	return( (VipsArrayImage *) new_area );
1445 }
1446 
1447 /**
1448  * vips_array_image_get: (method)
1449  * @array: the #VipsArrayImage to fetch from
1450  * @n: length of array
1451  *
1452  * Fetch an image array from a #VipsArrayImage. Useful for language bindings.
1453  *
1454  * Returns: (array length=n) (transfer none): array of #VipsImage
1455  */
1456 VipsImage **
vips_array_image_get(VipsArrayImage * array,int * n)1457 vips_array_image_get( VipsArrayImage *array, int *n )
1458 {
1459 	VipsArea *area = VIPS_AREA( array );
1460 
1461 	g_assert( area->type == VIPS_TYPE_IMAGE );
1462 
1463 	if( n )
1464 		*n = area->n;
1465 
1466 	return( (VipsImage **) VIPS_ARRAY_ADDR( array, 0 ) );
1467 }
1468 
1469 static void
transform_g_string_array_image(const GValue * src_value,GValue * dest_value)1470 transform_g_string_array_image( const GValue *src_value, GValue *dest_value )
1471 {
1472 	char *str;
1473 	VipsArrayImage *array_image;
1474 
1475 	str = g_value_dup_string( src_value );
1476 
1477 	/* We can't get access here, just assume nothing. See the special case
1478 	 * in vips_object_new_from_string() for how we usually get this right.
1479 	 */
1480 	if( !(array_image = vips_array_image_new_from_string( str, 0 )) ) {
1481 		/* Set the dest to length zero to indicate error.
1482 		 */
1483 		vips_value_set_array_image( dest_value, 0 );
1484 		g_free( str );
1485 		return;
1486 	}
1487 
1488 	g_free( str );
1489 
1490 	g_value_set_boxed( dest_value, array_image );
1491 	vips_area_unref( VIPS_AREA( array_image ) );
1492 }
1493 
1494 GType
vips_array_image_get_type(void)1495 vips_array_image_get_type( void )
1496 {
1497 	static GType type = 0;
1498 
1499 	if( !type ) {
1500 		type = g_boxed_type_register_static( "VipsArrayImage",
1501 			(GBoxedCopyFunc) vips_area_copy,
1502 			(GBoxedFreeFunc) vips_area_unref );
1503 		g_value_register_transform_func( G_TYPE_STRING, type,
1504 			transform_g_string_array_image );
1505 	}
1506 
1507 	return( type );
1508 }
1509 
1510 /**
1511  * vips_value_set_area:
1512  * @value: (out): set this value
1513  * @free_fn: (scope async): data will be freed with this function
1514  * @data: set @value to track this pointer
1515  *
1516  * Set value to be a ref-counted area of memory with a free function.
1517  */
1518 void
vips_value_set_area(GValue * value,VipsCallbackFn free_fn,void * data)1519 vips_value_set_area( GValue *value, VipsCallbackFn free_fn, void *data )
1520 {
1521 	VipsArea *area;
1522 
1523 	area = vips_area_new( free_fn, data );
1524 	g_value_init( value, VIPS_TYPE_AREA );
1525 	g_value_set_boxed( value, area );
1526 	vips_area_unref( area );
1527 }
1528 
1529 /**
1530  * vips_value_get_area:
1531  * @value: get from this value
1532  * @length: (allow-none): optionally return length here
1533  *
1534  * Get the pointer from an area. Don't touch count (area is static).
1535  *
1536  * Returns: (transfer none): The pointer held by @value.
1537  */
1538 void *
vips_value_get_area(const GValue * value,size_t * length)1539 vips_value_get_area( const GValue *value, size_t *length )
1540 {
1541 	VipsArea *area;
1542 
1543 	area = g_value_get_boxed( value );
1544 
1545 	return( vips_area_get_data( area, length, NULL, NULL, NULL ) );
1546 }
1547 
1548 /**
1549  * vips_value_get_save_string:
1550  * @value: GValue to get from
1551  *
1552  * Get the C string held internally by the GValue.
1553  *
1554  * Returns: (transfer none): The C string held by @value.
1555  */
1556 const char *
vips_value_get_save_string(const GValue * value)1557 vips_value_get_save_string( const GValue *value )
1558 {
1559 	return( (char *) g_value_get_boxed( value ) );
1560 }
1561 
1562 /**
1563  * vips_value_set_save_string:
1564  * @value: (out): GValue to set
1565  * @str: C string to copy into the GValue
1566  *
1567  * Copies the C string into @value.
1568  *
1569  * @str should be a valid utf-8 string.
1570  */
1571 void
vips_value_set_save_string(GValue * value,const char * str)1572 vips_value_set_save_string( GValue *value, const char *str )
1573 {
1574 	g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_SAVE_STRING );
1575 
1576 	if( !g_utf8_validate( str, -1, NULL ) )
1577 		str = "<invalid utf-8 string>";
1578 
1579 	g_value_set_boxed( value, str );
1580 }
1581 
1582 /**
1583  * vips_value_set_save_stringf:
1584  * @value: (out): GValue to set
1585  * @fmt: printf()-style format string
1586  * @...: arguments to printf()-formatted @fmt
1587  *
1588  * Generates a string and copies it into @value.
1589  */
1590 void
vips_value_set_save_stringf(GValue * value,const char * fmt,...)1591 vips_value_set_save_stringf( GValue *value, const char *fmt, ... )
1592 {
1593 	va_list ap;
1594 	char *str;
1595 
1596 	g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_SAVE_STRING );
1597 
1598 	va_start( ap, fmt );
1599 	str = g_strdup_vprintf( fmt, ap );
1600 	va_end( ap );
1601 	vips_value_set_save_string( value, str );
1602 	g_free( str );
1603 }
1604 
1605 /**
1606  * vips_value_get_ref_string:
1607  * @value: %GValue to get from
1608  * @length: (allow-none): return length here, optionally
1609  *
1610  * Get the C string held internally by the %GValue.
1611  *
1612  * Returns: (transfer none): The C string held by @value.
1613  */
1614 const char *
vips_value_get_ref_string(const GValue * value,size_t * length)1615 vips_value_get_ref_string( const GValue *value, size_t *length )
1616 {
1617 	return( vips_value_get_area( value, length ) );
1618 }
1619 
1620 /**
1621  * vips_value_set_ref_string:
1622  * @value: (out): %GValue to set
1623  * @str: C string to copy into the GValue
1624  *
1625  * Copies the C string @str into @value.
1626  *
1627  * vips_ref_string are immutable C strings that are copied between images by
1628  * copying reference-counted pointers, making them much more efficient than
1629  * regular %GValue strings.
1630  *
1631  * @str should be a valid utf-8 string.
1632  */
1633 void
vips_value_set_ref_string(GValue * value,const char * str)1634 vips_value_set_ref_string( GValue *value, const char *str )
1635 {
1636 	VipsRefString *ref_str;
1637 
1638 	g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_REF_STRING );
1639 
1640 	ref_str = vips_ref_string_new( str );
1641 	g_value_set_boxed( value, ref_str );
1642 	vips_area_unref( VIPS_AREA( ref_str ) );
1643 }
1644 
1645 /**
1646  * vips_value_set_blob:
1647  * @value: (out): GValue to set
1648  * @free_fn: (scope async): free function for @data
1649  * @data: pointer to area of memory
1650  * @length: length of memory area
1651  *
1652  * Sets @value to hold a @data. When @value is freed, @data will be
1653  * freed with @free_fn. @value also holds a note of the size of the memory
1654  * area.
1655  *
1656  * blobs are things like ICC profiles or EXIF data. They are relocatable, and
1657  * are saved to VIPS files for you coded as base64 inside the XML. They are
1658  * copied by copying reference-counted pointers.
1659  *
1660  * See also: vips_value_get_blob()
1661  */
1662 void
vips_value_set_blob(GValue * value,VipsCallbackFn free_fn,const void * data,size_t length)1663 vips_value_set_blob( GValue *value,
1664 	VipsCallbackFn free_fn, const void *data, size_t length )
1665 {
1666 	VipsBlob *blob;
1667 
1668 	g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_BLOB );
1669 
1670 	blob = vips_blob_new( free_fn, data, length );
1671 	g_value_set_boxed( value, blob );
1672 	vips_area_unref( VIPS_AREA( blob ) );
1673 }
1674 
1675 /**
1676  * vips_value_set_blob_free:
1677  * @value: (out): GValue to set
1678  * @data: pointer to area of memory
1679  * @length: length of memory area
1680  *
1681  * Just like vips_value_set_blob(), but when
1682  * @value is freed, @data will be
1683  * freed with g_free().
1684  *
1685  * This can be easier to call for language bindings.
1686  *
1687  * See also: vips_value_set_blob()
1688  */
1689 void
vips_value_set_blob_free(GValue * value,void * data,size_t length)1690 vips_value_set_blob_free( GValue *value, void *data, size_t length )
1691 {
1692 	VipsBlob *blob;
1693 
1694 	g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_BLOB );
1695 
1696 	blob = vips_blob_new( (VipsCallbackFn) vips_area_free_cb, data, length );
1697 	g_value_set_boxed( value, blob );
1698 	vips_area_unref( VIPS_AREA( blob ) );
1699 }
1700 
1701 /**
1702  * vips_value_get_blob:
1703  * @value: GValue to set
1704  * @length: (allow-none): optionally return length of memory area
1705  *
1706  * Returns the data pointer from a blob. Optionally returns the length too.
1707  *
1708  * blobs are things like ICC profiles or EXIF data. They are relocatable, and
1709  * are saved to VIPS files for you coded as base64 inside the XML. They are
1710  * copied by copying reference-counted pointers.
1711  *
1712  * See also: vips_value_set_blob()
1713  *
1714  * Returns: (transfer none): The pointer held by @value.
1715  */
1716 void *
vips_value_get_blob(const GValue * value,size_t * length)1717 vips_value_get_blob( const GValue *value, size_t *length )
1718 {
1719 	return( vips_value_get_area( value, length ) );
1720 }
1721 
1722 /**
1723  * vips_value_set_array:
1724  * @value: (out): %GValue to set
1725  * @n: number of elements
1726  * @type: the type of each element
1727  * @sizeof_type: the sizeof each element
1728  *
1729  * Set @value to be an array of things.
1730  *
1731  * This allocates memory but does not
1732  * initialise the contents: get the pointer and write instead.
1733  */
1734 void
vips_value_set_array(GValue * value,int n,GType type,size_t sizeof_type)1735 vips_value_set_array( GValue *value, int n, GType type, size_t sizeof_type )
1736 {
1737 	VipsArea *area;
1738 
1739 	area = vips_area_new_array( type, sizeof_type, n );
1740 	g_value_set_boxed( value, area );
1741 	vips_area_unref( area );
1742 }
1743 
1744 /**
1745  * vips_value_get_array:
1746  * @value: %GValue to get from
1747  * @n: (allow-none): return the number of elements here, optionally
1748  * @type: (allow-none): return the type of each element here, optionally
1749  * @sizeof_type: (allow-none): return the sizeof each element here, optionally
1750  *
1751  * Return the pointer to the array held by @value.
1752  * Optionally return the other properties of the array in @n, @type,
1753  * @sizeof_type.
1754  *
1755  * See also: vips_value_set_array().
1756  *
1757  * Returns: (transfer none): The array address.
1758  */
1759 void *
vips_value_get_array(const GValue * value,int * n,GType * type,size_t * sizeof_type)1760 vips_value_get_array( const GValue *value,
1761 	int *n, GType *type, size_t *sizeof_type )
1762 {
1763 	VipsArea *area;
1764 
1765 	/* Can't check value type, because we may get called from
1766 	 * vips_*_get_type().
1767 	 */
1768 
1769 	if( !(area = g_value_get_boxed( value )) )
1770 		return( NULL );
1771 	if( n )
1772 		*n = area->n;
1773 	if( type )
1774 		*type = area->type;
1775 	if( sizeof_type )
1776 		*sizeof_type = area->sizeof_type;
1777 
1778 	return( area->data );
1779 }
1780 
1781 /**
1782  * vips_value_get_array_int:
1783  * @value: %GValue to get from
1784  * @n: (allow-none): return the number of elements here, optionally
1785  *
1786  * Return the start of the array of ints held by @value.
1787  * optionally return the number of elements in @n.
1788  *
1789  * See also: vips_array_int_new().
1790  *
1791  * Returns: (transfer none): The array address.
1792  */
1793 int *
vips_value_get_array_int(const GValue * value,int * n)1794 vips_value_get_array_int( const GValue *value, int *n )
1795 {
1796 	return( vips_value_get_array( value, n, NULL, NULL ) );
1797 }
1798 
1799 /**
1800  * vips_value_set_array_int:
1801  * @value: (out): %GValue to get from
1802  * @array: (array length=n) (allow-none): array of ints
1803  * @n: the number of elements
1804  *
1805  * Set @value to hold a copy of @array. Pass in the array length in @n.
1806  *
1807  * See also: vips_array_int_get().
1808  */
1809 void
vips_value_set_array_int(GValue * value,const int * array,int n)1810 vips_value_set_array_int( GValue *value, const int *array, int n )
1811 {
1812 	vips_value_set_array( value, n, G_TYPE_INT, sizeof( int ) );
1813 
1814 	if( array ) {
1815 		int *array_copy;
1816 
1817 		array_copy = vips_value_get_array_int( value, NULL );
1818 		memcpy( array_copy, array, n * sizeof( int ) );
1819 	}
1820 }
1821 
1822 /**
1823  * vips_value_get_array_double:
1824  * @value: %GValue to get from
1825  * @n: (allow-none): return the number of elements here, optionally
1826  *
1827  * Return the start of the array of doubles held by @value.
1828  * optionally return the number of elements in @n.
1829  *
1830  * See also: vips_array_double_new().
1831  *
1832  * Returns: (transfer none): The array address.
1833  */
1834 double *
vips_value_get_array_double(const GValue * value,int * n)1835 vips_value_get_array_double( const GValue *value, int *n )
1836 {
1837 	return( vips_value_get_array( value, n, NULL, NULL ) );
1838 }
1839 
1840 /**
1841  * vips_value_set_array_double:
1842  * @value: (out): %GValue to get from
1843  * @array: (array length=n) (allow-none): array of doubles
1844  * @n: the number of elements
1845  *
1846  * Set @value to hold a copy of @array. Pass in the array length in @n.
1847  *
1848  * See also: vips_array_double_get().
1849  */
1850 void
vips_value_set_array_double(GValue * value,const double * array,int n)1851 vips_value_set_array_double( GValue *value, const double *array, int n )
1852 {
1853 	vips_value_set_array( value, n, G_TYPE_DOUBLE, sizeof( double ) );
1854 
1855 	if( array ) {
1856 		double *array_copy;
1857 
1858 		array_copy = vips_value_get_array_double( value, NULL );
1859 		memcpy( array_copy, array, n * sizeof( double ) );
1860 	}
1861 }
1862 
1863 /**
1864  * vips_value_get_array_image:
1865  * @value: %GValue to get from
1866  * @n: (allow-none): return the number of elements here, optionally
1867  *
1868  * Return the start of the array of images held by @value.
1869  * optionally return the number of elements in @n.
1870  *
1871  * See also: vips_value_set_array_image().
1872  *
1873  * Returns: (transfer none): The array address.
1874  */
1875 VipsImage **
vips_value_get_array_image(const GValue * value,int * n)1876 vips_value_get_array_image( const GValue *value, int *n )
1877 {
1878 	return( vips_value_get_array( value, n, NULL, NULL ) );
1879 }
1880 
1881 /**
1882  * vips_value_set_array_image:
1883  * @value: (out): %GValue to get from
1884  * @n: the number of elements
1885  *
1886  * Set @value to hold an array of images. Pass in the array length in @n.
1887  *
1888  * See also: vips_array_image_get().
1889  */
1890 void
vips_value_set_array_image(GValue * value,int n)1891 vips_value_set_array_image( GValue *value, int n )
1892 {
1893 	VipsArea *area;
1894 
1895 	area = vips_area_new_array_object( n );
1896 	area->type = VIPS_TYPE_IMAGE;
1897 	g_value_set_boxed( value, area );
1898 	vips_area_unref( area );
1899 }
1900 
1901 /**
1902  * vips_value_get_array_object: (skip)
1903  * @value: %GValue to get from
1904  * @n: (allow-none): return the number of elements here, optionally
1905  *
1906  * Return the start of the array of %GObject held by @value.
1907  * Optionally return the number of elements in @n.
1908  *
1909  * See also: vips_area_new_array_object().
1910  *
1911  * Returns: (transfer none): The array address.
1912  */
1913 GObject **
vips_value_get_array_object(const GValue * value,int * n)1914 vips_value_get_array_object( const GValue *value, int *n )
1915 {
1916 	return( vips_value_get_array( value, n, NULL, NULL ) );
1917 }
1918 
1919 /**
1920  * vips_value_set_array_object:
1921  * @value: (out): %GValue to set
1922  * @n: the number of elements
1923  *
1924  * Set @value to hold an array of %GObject. Pass in the array length in @n.
1925  *
1926  * See also: vips_value_get_array_object().
1927  */
1928 void
vips_value_set_array_object(GValue * value,int n)1929 vips_value_set_array_object( GValue *value, int n )
1930 {
1931 	VipsArea *area;
1932 
1933 	area = vips_area_new_array_object( n );
1934 	g_value_set_boxed( value, area );
1935 	vips_area_unref( area );
1936 }
1937 
1938 /* Make the types we need for basic functioning. Called from vips_init().
1939  */
1940 void
vips__meta_init_types(void)1941 vips__meta_init_types( void )
1942 {
1943 	(void) vips_thing_get_type();
1944 	(void) vips_save_string_get_type();
1945 	(void) vips_area_get_type();
1946 	(void) vips_ref_string_get_type();
1947 	(void) vips_blob_get_type();
1948 	(void) vips_array_int_get_type();
1949 	(void) vips_array_double_get_type();
1950 	(void) vips_array_image_get_type();
1951 
1952 	/* Register transform functions to go from built-in saveable types to
1953 	 * a save string. Transform functions for our own types are set
1954 	 * during type creation.
1955 	 */
1956 	g_value_register_transform_func( G_TYPE_INT, VIPS_TYPE_SAVE_STRING,
1957 		transform_int_save_string );
1958 	g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_INT,
1959 		transform_save_string_int );
1960 	g_value_register_transform_func( G_TYPE_DOUBLE, VIPS_TYPE_SAVE_STRING,
1961 		transform_double_save_string );
1962 	g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_DOUBLE,
1963 		transform_save_string_double );
1964 	g_value_register_transform_func( G_TYPE_FLOAT, VIPS_TYPE_SAVE_STRING,
1965 		transform_float_save_string );
1966 	g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_FLOAT,
1967 		transform_save_string_float );
1968 }
1969