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