~ubuntu-branches/ubuntu/saucy/vips/saucy

« back to all changes in this revision

Viewing changes to libvips/iofuncs/type.c

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2012-03-18 16:54:58 UTC
  • mfrom: (1.1.17) (30.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20120318165458-6okio21v96g3bd7t
Tags: 7.28.2-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* array type 
 
2
 *
 
3
 * Unlike GArray, this has fixed length, tracks a GType for emements, and has
 
4
 * a per-element free function.
 
5
 *
 
6
 * 27/10/11
 
7
 *      - from header.c
 
8
 */
 
9
 
 
10
/*
 
11
 
 
12
    This file is part of VIPS.
 
13
    
 
14
    VIPS is free software; you can redistribute it and/or modify
 
15
    it under the terms of the GNU Lesser General Public License as published by
 
16
    the Free Software Foundation; either version 2 of the License, or
 
17
    (at your option) any later version.
 
18
 
 
19
    This program is distributed in the hope that it will be useful,
 
20
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
    GNU Lesser General Public License for more details.
 
23
 
 
24
    You should have received a copy of the GNU Lesser General Public License
 
25
    along with this program; if not, write to the Free Software
 
26
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
27
 
 
28
 */
 
29
 
 
30
/*
 
31
 
 
32
    These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
 
33
 
 
34
 */
 
35
 
 
36
/*
 
37
#define VIPS_DEBUG
 
38
#define DEBUG
 
39
 */
 
40
 
 
41
#ifdef HAVE_CONFIG_H
 
42
#include <config.h>
 
43
#endif /*HAVE_CONFIG_H*/
 
44
#include <vips/intl.h>
 
45
 
 
46
#include <stdio.h>
 
47
#include <stdlib.h>
 
48
#include <string.h>
 
49
 
 
50
#include <vips/vips.h>
 
51
#include <vips/internal.h>
 
52
#include <vips/debug.h>
 
53
 
 
54
/* A very simple boxed type for testing. Just an int.
 
55
 */
 
56
 
 
57
/**
 
58
 * vips_thing_new:
 
59
 * @n:
 
60
 *
 
61
 * Returns: (transfer full): a new #VipsThing.
 
62
 */
 
63
VipsThing *
 
64
vips_thing_new( int i )
 
65
{
 
66
        VipsThing *thing;
 
67
 
 
68
        thing = g_new( VipsThing, 1 );
 
69
        thing->i = i;
 
70
 
 
71
        printf( "vips_thing_new: %d %p\n", i, thing );
 
72
 
 
73
        return( thing );
 
74
}
 
75
 
 
76
static VipsThing *
 
77
vips_thing_copy( VipsThing *thing )
 
78
{
 
79
        VipsThing *thing2;
 
80
 
 
81
        thing2 = vips_thing_new( thing->i );
 
82
 
 
83
        printf( "vips_thing_copy: %d %p = %p\n", thing->i, thing2, thing );
 
84
 
 
85
        return( thing2 );
 
86
}
 
87
 
 
88
static void
 
89
vips_thing_free( VipsThing *thing )
 
90
{
 
91
        printf( "vips_thing_free: %d %p\n", thing->i, thing );
 
92
 
 
93
        g_free( thing );
 
94
}
 
95
 
 
96
int 
 
97
vips_thing_get_i( VipsThing *thing )
 
98
{
 
99
        printf( "vips_thing_get_i: %d %p\n", thing->i, thing );
 
100
 
 
101
        return( thing->i );
 
102
}
 
103
 
 
104
G_DEFINE_BOXED_TYPE( VipsThing, vips_thing,
 
105
        (GBoxedCopyFunc) vips_thing_copy, 
 
106
        (GBoxedFreeFunc) vips_thing_free );
 
107
 
 
108
/**
 
109
 * SECTION: VipsArea
 
110
 * @short_description: an area of memory
 
111
 * @stability: Stable
 
112
 * @see_also: <link linkend="libvips-meta">header</link>,
 
113
 * @include: vips/vips.h
 
114
 *
 
115
 * A VipsArea wraps a chunk of memory. It adds reference counting and a free
 
116
 * function. It also keeps a count and a GType, so the area can be an array.
 
117
 *
 
118
 * This type is used for things like passing an array of double or an array of
 
119
 * VipsObject pointers to operations, and for reference-countred immutable
 
120
 * strings. 
 
121
 */
 
122
 
 
123
#ifdef DEBUG
 
124
static int vips_area_number = 0;
 
125
#endif /*DEBUG*/
 
126
 
 
127
VipsArea *
 
128
vips_area_copy( VipsArea *area )
 
129
{
 
130
        g_assert( area->count >= 0 );
 
131
 
 
132
        area->count += 1;
 
133
 
 
134
#ifdef DEBUG
 
135
        printf( "vips_area_copy: %p count = %d\n", area, area->count );
 
136
#endif /*DEBUG*/
 
137
 
 
138
        return( area );
 
139
}
 
140
 
 
141
void
 
142
vips_area_unref( VipsArea *area )
 
143
{
 
144
        g_assert( area->count > 0 );
 
145
 
 
146
        area->count -= 1;
 
147
 
 
148
#ifdef DEBUG
 
149
        printf( "vips_area_unref: %p count = %d\n", area, area->count );
 
150
#endif /*DEBUG*/
 
151
 
 
152
        if( area->count == 0 ) {
 
153
                if( area->free_fn && area->data ) {
 
154
                        area->free_fn( area->data, area );
 
155
                        area->data = NULL;
 
156
                        area->free_fn = NULL;
 
157
                }
 
158
 
 
159
                g_free( area );
 
160
 
 
161
#ifdef DEBUG
 
162
                vips_area_number -= 1;
 
163
                printf( "vips_area_unref: free .. total = %d\n", 
 
164
                        vips_area_number );
 
165
#endif /*DEBUG*/
 
166
        }
 
167
}
 
168
 
 
169
/**
 
170
 * vips_area_new: 
 
171
 * @free_fn: (scope async): @data will be freed with this function
 
172
 * @data: data will be freed with this function
 
173
 *
 
174
 * An area of memory with a free function. (eg. \0-terminated string, or a 
 
175
 * struct). Inital count == 1, so _unref() after attaching somewhere.
 
176
 *
 
177
 * See also: vips_area_unref().
 
178
 *
 
179
 * Returns: (transfer full): the new #VipsArea.
 
180
 */
 
181
VipsArea *
 
182
vips_area_new( VipsCallbackFn free_fn, void *data )
 
183
{
 
184
        VipsArea *area;
 
185
 
 
186
        area = g_new( VipsArea, 1 );
 
187
        area->count = 1;
 
188
        area->length = 0;
 
189
        area->data = data;
 
190
        area->free_fn = free_fn;
 
191
        area->type = 0;
 
192
        area->sizeof_type = 0;
 
193
 
 
194
#ifdef DEBUG
 
195
        vips_area_number += 1;
 
196
        printf( "vips_area_new: %p count = %d (%d in total)\n", 
 
197
                area, area->count, vips_area_number );
 
198
#endif /*DEBUG*/
 
199
 
 
200
        return( area );
 
201
}
 
202
 
 
203
/**
 
204
 * vips_area_new_blob: 
 
205
 * @free_fn: (scope async): @data will be freed with this function
 
206
 * @data: data will be freed with this function
 
207
 * @length: number of bytes in @data
 
208
 *
 
209
 * Like vips_area_new(), but track a length as well.
 
210
 *
 
211
 * An area of mem with a free func and a length (some sort of binary object,
 
212
 * like an ICC profile).
 
213
 * 
 
214
 * See also: vips_area_unref().
 
215
 *
 
216
 * Returns: (transfer full): the new #VipsArea.
 
217
 */
 
218
VipsArea *
 
219
vips_area_new_blob( VipsCallbackFn free_fn, void *data, size_t length )
 
220
{
 
221
        VipsArea *area;
 
222
 
 
223
        area = vips_area_new( free_fn, data );
 
224
        area->length = length;
 
225
 
 
226
        return( area );
 
227
}
 
228
 
 
229
/**
 
230
 * vips_area_new_array: 
 
231
 * @type: %GType of elements to store
 
232
 * @sizeof_type: sizeof() an element in the array
 
233
 * @n: number of elements in the array
 
234
 *
 
235
 * An area which holds an array of elements of some GType. To set values for
 
236
 * the elements, get the pointer and write.
 
237
 *
 
238
 * See also: vips_area_unref().
 
239
 *
 
240
 * Returns: (transfer full): the new #VipsArea.
 
241
 */
 
242
VipsArea *
 
243
vips_area_new_array( GType type, size_t sizeof_type, int n )
 
244
{
 
245
        VipsArea *area;
 
246
        void *array;
 
247
 
 
248
        array = g_malloc( n * sizeof_type );
 
249
        area = vips_area_new( (VipsCallbackFn) g_free, array );
 
250
        area->n = n;
 
251
        area->length = n * sizeof_type;
 
252
        area->type = type;
 
253
        area->sizeof_type = sizeof_type;
 
254
 
 
255
        return( area );
 
256
}
 
257
 
 
258
static void
 
259
vips_area_free_array_object( GObject **array, VipsArea *area )
 
260
{
 
261
        int i;
 
262
 
 
263
        for( i = 0; i < area->n; i++ ) 
 
264
                VIPS_FREEF( g_object_unref, array[i] );
 
265
 
 
266
        area->n = 0;
 
267
}
 
268
 
 
269
/**
 
270
 * vips_area_new_array_object:
 
271
 * @n: number of elements in the array
 
272
 *
 
273
 * An area which holds an array of GObjects. See vips_area_new_array(). When
 
274
 * the area is freed, each %GObject will be unreffed.
 
275
 *
 
276
 * See also: vips_area_unref().
 
277
 *
 
278
 * Returns: (transfer full): the new #VipsArea.
 
279
 */
 
280
VipsArea *
 
281
vips_area_new_array_object( int n )
 
282
{
 
283
        GObject **array;
 
284
        VipsArea *area;
 
285
 
 
286
        array = g_new0( GObject *, n );
 
287
        area = vips_area_new( (VipsCallbackFn) vips_area_free_array_object, 
 
288
                array );
 
289
        area->n = n;
 
290
        area->length = n * sizeof( GObject * );
 
291
        area->type = G_TYPE_OBJECT;
 
292
        area->sizeof_type = sizeof( GObject * );
 
293
 
 
294
        return( area );
 
295
}
 
296
 
 
297
/**
 
298
 * vips_area_get_data:
 
299
 * @area: #VipsArea to fetch from
 
300
 * @length: (allow-none): optionally return length in bytes here
 
301
 * @n: (allow-none): optionally return number of elements here
 
302
 * @type: (allow-none): optionally return element type here
 
303
 * @sizeof_type: (allow-none): optionally return sizeof() element type here
 
304
 *
 
305
 * Return the data pointer plus optionally the length in bytes of an area, 
 
306
 * the number of elements, the %GType of each element and the sizeof() each
 
307
 * element.
 
308
 *
 
309
 * Returns: (transfer none): The pointer held by @area.
 
310
 */
 
311
void *
 
312
vips_area_get_data( VipsArea *area, 
 
313
        size_t *length, int *n, GType *type, size_t *sizeof_type )
 
314
{
 
315
        if( length )
 
316
                *length = area->length;
 
317
        if( n )
 
318
                *n = area->n;
 
319
        if( type )
 
320
                *type = area->type;
 
321
        if( sizeof_type )
 
322
                *sizeof_type = area->sizeof_type;
 
323
 
 
324
        return( area->data );
 
325
}
 
326
 
 
327
/* Transform an area to a G_TYPE_STRING.
 
328
 */
 
329
static void
 
330
transform_area_g_string( const GValue *src_value, GValue *dest_value )
 
331
{
 
332
        VipsArea *area;
 
333
        char buf[256];
 
334
 
 
335
        area = g_value_get_boxed( src_value );
 
336
        vips_snprintf( buf, 256, "VIPS_TYPE_AREA, count = %d, data = %p",
 
337
                area->count, area->data );
 
338
        g_value_set_string( dest_value, buf );
 
339
}
 
340
 
 
341
GType
 
342
vips_area_get_type( void )
 
343
{
 
344
        static GType type = 0;
 
345
 
 
346
        if( !type ) {
 
347
                type = g_boxed_type_register_static( "VipsArea",
 
348
                        (GBoxedCopyFunc) vips_area_copy, 
 
349
                        (GBoxedFreeFunc) vips_area_unref );
 
350
                g_value_register_transform_func( type, G_TYPE_STRING,
 
351
                        transform_area_g_string );
 
352
        }
 
353
 
 
354
        return( type );
 
355
}
 
356
 
 
357
/* Transform funcs for builtin types to SAVE_STRING.
 
358
 */
 
359
static void
 
360
transform_int_save_string( const GValue *src_value, GValue *dest_value )
 
361
{
 
362
        vips_value_set_save_stringf( dest_value, 
 
363
                "%d", g_value_get_int( src_value ) );
 
364
}
 
365
 
 
366
static void
 
367
transform_save_string_int( const GValue *src_value, GValue *dest_value )
 
368
{
 
369
        g_value_set_int( dest_value, 
 
370
                atoi( vips_value_get_save_string( src_value ) ) );
 
371
}
 
372
 
 
373
static void
 
374
transform_double_save_string( const GValue *src_value, GValue *dest_value )
 
375
{
 
376
        char buf[G_ASCII_DTOSTR_BUF_SIZE];
 
377
 
 
378
        /* Need to be locale independent.
 
379
         */
 
380
        g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, 
 
381
                g_value_get_double( src_value ) );
 
382
        vips_value_set_save_string( dest_value, buf );
 
383
}
 
384
 
 
385
static void
 
386
transform_save_string_double( const GValue *src_value, GValue *dest_value )
 
387
{
 
388
        g_value_set_double( dest_value, 
 
389
                g_ascii_strtod( vips_value_get_save_string( src_value ), 
 
390
                        NULL ) );
 
391
}
 
392
 
 
393
/* Save meta fields to the header. We have a new string type for header fields
 
394
 * to save to XML and define transform functions to go from our meta types to
 
395
 * this string type.
 
396
 */
 
397
GType
 
398
vips_save_string_get_type( void )
 
399
{
 
400
        static GType type = 0;
 
401
 
 
402
        if( !type ) {
 
403
                type = g_boxed_type_register_static( "VipsSaveString",
 
404
                        (GBoxedCopyFunc) g_strdup, 
 
405
                        (GBoxedFreeFunc) g_free );
 
406
        }
 
407
 
 
408
        return( type );
 
409
}
 
410
 
 
411
/* Transform a refstring to a G_TYPE_STRING and back.
 
412
 */
 
413
static void
 
414
transform_ref_string_g_string( const GValue *src_value, GValue *dest_value )
 
415
{
 
416
        g_value_set_string( dest_value, 
 
417
                vips_value_get_ref_string( src_value, NULL ) );
 
418
}
 
419
 
 
420
static void
 
421
transform_g_string_ref_string( const GValue *src_value, GValue *dest_value )
 
422
{
 
423
        vips_value_set_ref_string( dest_value, 
 
424
                g_value_get_string( src_value ) );
 
425
}
 
426
 
 
427
/* To a save string.
 
428
 */
 
429
static void
 
430
transform_ref_string_save_string( const GValue *src_value, GValue *dest_value )
 
431
{
 
432
        vips_value_set_save_stringf( dest_value, 
 
433
                "%s", vips_value_get_ref_string( src_value, NULL ) );
 
434
}
 
435
 
 
436
static void
 
437
transform_save_string_ref_string( const GValue *src_value, GValue *dest_value )
 
438
{
 
439
        vips_value_set_ref_string( dest_value, 
 
440
                vips_value_get_save_string( src_value ) );
 
441
}
 
442
 
 
443
GType
 
444
vips_ref_string_get_type( void )
 
445
{
 
446
        static GType type = 0;
 
447
 
 
448
        if( !type ) {
 
449
                type = g_boxed_type_register_static( "VipsRefString",
 
450
                        (GBoxedCopyFunc) vips_area_copy, 
 
451
                        (GBoxedFreeFunc) vips_area_unref );
 
452
                g_value_register_transform_func( type, G_TYPE_STRING,
 
453
                        transform_ref_string_g_string );
 
454
                g_value_register_transform_func( G_TYPE_STRING, type,
 
455
                        transform_g_string_ref_string );
 
456
                g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING,
 
457
                        transform_ref_string_save_string );
 
458
                g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type,
 
459
                        transform_save_string_ref_string );
 
460
        }
 
461
 
 
462
        return( type );
 
463
}
 
464
 
 
465
/* Transform a blob to a G_TYPE_STRING.
 
466
 */
 
467
static void
 
468
transform_blob_g_string( const GValue *src_value, GValue *dest_value )
 
469
{
 
470
        void *blob;
 
471
        size_t blob_length;
 
472
        char buf[256];
 
473
 
 
474
        blob = vips_value_get_blob( src_value, &blob_length );
 
475
        vips_snprintf( buf, 256, "VIPS_TYPE_BLOB, data = %p, length = %zd",
 
476
                blob, blob_length );
 
477
        g_value_set_string( dest_value, buf );
 
478
 
479
 
 
480
/* Transform a blob to a save string and back.
 
481
 */
 
482
static void
 
483
transform_blob_save_string( const GValue *src_value, GValue *dest_value )
 
484
{
 
485
        void *blob;
 
486
        size_t blob_length;
 
487
        char *b64;
 
488
 
 
489
        blob = vips_value_get_blob( src_value, &blob_length );
 
490
        if( (b64 = vips__b64_encode( blob, blob_length )) ) {
 
491
                vips_value_set_save_string( dest_value, b64 );
 
492
                vips_free( b64 );
 
493
        }
 
494
}
 
495
 
 
496
static void
 
497
transform_save_string_blob( const GValue *src_value, GValue *dest_value )
 
498
{
 
499
        const char *b64;
 
500
        void *blob;
 
501
        size_t blob_length;
 
502
 
 
503
        b64 = vips_value_get_save_string( src_value );
 
504
        if( (blob = vips__b64_decode( b64, &blob_length )) )
 
505
                vips_value_set_blob( dest_value, 
 
506
                        (VipsCallbackFn) vips_free, blob, blob_length );
 
507
}
 
508
 
 
509
GType
 
510
vips_blob_get_type( void )
 
511
{
 
512
        static GType type = 0;
 
513
 
 
514
        if( !type ) {
 
515
                type = g_boxed_type_register_static( "VipsBlob",
 
516
                        (GBoxedCopyFunc) vips_area_copy, 
 
517
                        (GBoxedFreeFunc) vips_area_unref );
 
518
                g_value_register_transform_func( type, G_TYPE_STRING,
 
519
                        transform_blob_g_string );
 
520
                g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING,
 
521
                        transform_blob_save_string );
 
522
                g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type,
 
523
                        transform_save_string_blob );
 
524
        }
 
525
 
 
526
        return( type );
 
527
}
 
528
 
 
529
static void
 
530
transform_array_double_g_string( const GValue *src_value, GValue *dest_value )
 
531
{
 
532
        int n;
 
533
        double *array = vips_value_get_array_double( src_value, &n );
 
534
 
 
535
        char txt[1024];
 
536
        VipsBuf buf = VIPS_BUF_STATIC( txt );
 
537
        int i;
 
538
 
 
539
        for( i = 0; i < n; i++ ) 
 
540
                /* Use space as a separator since ',' may be a decimal point
 
541
                 * in this locale.
 
542
                 */
 
543
                vips_buf_appendf( &buf, "%g ", array[i] );
 
544
 
 
545
        g_value_set_string( dest_value, vips_buf_all( &buf ) );
 
546
}
 
547
 
 
548
/* It'd be great to be able to write a generic string->array function, but
 
549
 * it doesn't seem possible.
 
550
 */
 
551
static void
 
552
transform_g_string_array_double( const GValue *src_value, GValue *dest_value )
 
553
{
 
554
        char *str;
 
555
        int n;
 
556
        char *p, *q;
 
557
        int i;
 
558
        double *array;
 
559
 
 
560
        /* Walk the string to get the number of elements. 
 
561
         * We need a copy of the string, since we insert \0 during
 
562
         * scan.
 
563
         *
 
564
         * We can't allow ',' as a separator, since some locales use it as a
 
565
         * decimal point.
 
566
         */
 
567
        str = g_value_dup_string( src_value );
 
568
        n = 0;
 
569
        for( p = str; (q = vips_break_token( p, "\t; " )); p = q ) 
 
570
                n += 1;
 
571
        g_free( str );
 
572
 
 
573
        vips_value_set_array( dest_value, n, G_TYPE_DOUBLE, sizeof( double ) );
 
574
        array = (double *) vips_value_get_array( dest_value, NULL, NULL, NULL );
 
575
 
 
576
        str = g_value_dup_string( src_value );
 
577
        i = 0;
 
578
        for( p = str; (q = vips_break_token( p, "\t; " )); p = q ) 
 
579
                array[i++] = atof( p );
 
580
        g_free( str );
 
581
}
 
582
 
 
583
GType
 
584
vips_array_double_get_type( void )
 
585
{
 
586
        static GType type = 0;
 
587
 
 
588
        if( !type ) {
 
589
                type = g_boxed_type_register_static( "VipsArrayDouble",
 
590
                        (GBoxedCopyFunc) vips_area_copy, 
 
591
                        (GBoxedFreeFunc) vips_area_unref );
 
592
                g_value_register_transform_func( type, G_TYPE_STRING,
 
593
                        transform_array_double_g_string );
 
594
                g_value_register_transform_func( G_TYPE_STRING, type,
 
595
                        transform_g_string_array_double );
 
596
        }
 
597
 
 
598
        return( type );
 
599
}
 
600
 
 
601
static void
 
602
transform_g_string_array_image( const GValue *src_value, GValue *dest_value )
 
603
{
 
604
        char *str;
 
605
        int n;
 
606
        char *p, *q;
 
607
        int i;
 
608
        GObject **array;
 
609
 
 
610
        /* We need a copy of the string, since we insert \0 during
 
611
         * scan.
 
612
         */
 
613
        str = g_value_dup_string( src_value );
 
614
        n = 0;
 
615
        for( p = str; (q = vips_break_token( p, " " )); p = q ) 
 
616
                n += 1;
 
617
        g_free( str );
 
618
 
 
619
        vips_value_set_array_object( dest_value, n );
 
620
        array = vips_value_get_array_object( dest_value, NULL );
 
621
 
 
622
        str = g_value_dup_string( src_value );
 
623
        for( i = 0, p = str; (q = vips_break_token( p, " " )); i++, p = q )
 
624
                if( !(array[i] = G_OBJECT( vips_image_new_from_file( p ) )) ) {
 
625
                        /* Set the dest to length zero to indicate error.
 
626
                         */
 
627
                        vips_value_set_array_object( dest_value, 0 );
 
628
                        g_free( str );
 
629
                        return;
 
630
                }
 
631
        g_free( str );
 
632
}
 
633
 
 
634
GType
 
635
vips_array_image_get_type( void )
 
636
{
 
637
        static GType type = 0;
 
638
 
 
639
        if( !type ) {
 
640
                type = g_boxed_type_register_static( "VipsArrayImage",
 
641
                        (GBoxedCopyFunc) vips_area_copy, 
 
642
                        (GBoxedFreeFunc) vips_area_unref );
 
643
                g_value_register_transform_func( G_TYPE_STRING, type,
 
644
                        transform_g_string_array_image );
 
645
        }
 
646
 
 
647
        return( type );
 
648
}
 
649
 
 
650
/**
 
651
 * vips_value_set_area:
 
652
 * @value: (out): set this value
 
653
 * @free_fn: (scope async): data will be freed with this function
 
654
 * @data: set @value to track this pointer
 
655
 *
 
656
 * Set value to be a ref-counted area of memory with a free function.
 
657
 */
 
658
void
 
659
vips_value_set_area( GValue *value, VipsCallbackFn free_fn, void *data )
 
660
{
 
661
        VipsArea *area;
 
662
 
 
663
        area = vips_area_new( free_fn, data );
 
664
        g_value_init( value, VIPS_TYPE_AREA );
 
665
        g_value_set_boxed( value, area );
 
666
        vips_area_unref( area );
 
667
}
 
668
 
 
669
/**
 
670
 * vips_value_get_area:
 
671
 * @value: get from this value
 
672
 * @length: (allow-none): optionally return length here
 
673
 *
 
674
 * Get the pointer from an area. Don't touch count (area is static).
 
675
 *
 
676
 * Returns: (transfer none): The pointer held by @value. 
 
677
 */
 
678
void *
 
679
vips_value_get_area( const GValue *value, size_t *length )
 
680
{
 
681
        VipsArea *area;
 
682
 
 
683
        area = g_value_get_boxed( value );
 
684
 
 
685
        return( vips_area_get_data( area, length, NULL, NULL, NULL ) ); 
 
686
}
 
687
 
 
688
/** 
 
689
 * vips_value_get_save_string:
 
690
 * @value: GValue to get from
 
691
 *
 
692
 * Get the C string held internally by the GValue.
 
693
 *
 
694
 * Returns: (transfer none): The C string held by @value. 
 
695
 */
 
696
const char *
 
697
vips_value_get_save_string( const GValue *value )
 
698
{
 
699
        return( (char *) g_value_get_boxed( value ) );
 
700
}
 
701
 
 
702
/** 
 
703
 * vips_value_set_save_string:
 
704
 * @value: (out): GValue to set
 
705
 * @str: C string to copy into the GValue
 
706
 *
 
707
 * Copies the C string into @value.
 
708
 */
 
709
void
 
710
vips_value_set_save_string( GValue *value, const char *str )
 
711
{
 
712
        g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_SAVE_STRING );
 
713
 
 
714
        g_value_set_boxed( value, str );
 
715
}
 
716
 
 
717
/** 
 
718
 * vips_value_set_save_stringf:
 
719
 * @value: (out): GValue to set
 
720
 * @fmt: printf()-style format string
 
721
 * @Varargs: arguments to printf()-formatted @fmt
 
722
 *
 
723
 * Generates a string and copies it into @value.
 
724
 */
 
725
void
 
726
vips_value_set_save_stringf( GValue *value, const char *fmt, ... )
 
727
{
 
728
        va_list ap;
 
729
        char *str;
 
730
 
 
731
        g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_SAVE_STRING );
 
732
 
 
733
        va_start( ap, fmt );
 
734
        str = g_strdup_vprintf( fmt, ap );
 
735
        va_end( ap );
 
736
        vips_value_set_save_string( value, str );
 
737
        g_free( str );
 
738
}
 
739
 
 
740
/** 
 
741
 * vips_value_get_ref_string:
 
742
 * @value: %GValue to get from
 
743
 * @length: (allow-none): return length here, optionally
 
744
 *
 
745
 * Get the C string held internally by the GValue.
 
746
 *
 
747
 * Returns: (transfer none): The C string held by @value. 
 
748
 */
 
749
const char *
 
750
vips_value_get_ref_string( const GValue *value, size_t *length )
 
751
{
 
752
        return( vips_value_get_area( value, length ) );
 
753
}
 
754
 
 
755
/** 
 
756
 * vips_value_set_ref_string:
 
757
 * @value: (out): GValue to set
 
758
 * @str: C string to copy into the GValue
 
759
 *
 
760
 * Copies the C string @str into @value. 
 
761
 *
 
762
 * vips_ref_string are immutable C strings that are copied between images by
 
763
 * copying reference-counted pointers, making the much more efficient than
 
764
 * regular GValue strings.
 
765
 *
 
766
 * Returns: 0 on success, -1 otherwise.
 
767
 */
 
768
int
 
769
vips_value_set_ref_string( GValue *value, const char *str )
 
770
{
 
771
        VipsArea *area;
 
772
        char *str_copy;
 
773
 
 
774
        g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_REF_STRING );
 
775
 
 
776
        str_copy = g_strdup( str );
 
777
        area = vips_area_new( (VipsCallbackFn) vips_free, str_copy );
 
778
 
 
779
        /* Handy place to cache this.
 
780
         */
 
781
        area->length = strlen( str );
 
782
 
 
783
        g_value_set_boxed( value, area );
 
784
        vips_area_unref( area );
 
785
 
 
786
        return( 0 );
 
787
}
 
788
 
 
789
/** 
 
790
 * vips_value_set_blob:
 
791
 * @value: (out): GValue to set
 
792
 * @free_fn: (scope async): free function for @data
 
793
 * @data: pointer to area of memory
 
794
 * @length: length of memory area
 
795
 *
 
796
 * Sets @value to hold a @data. When @value is freed, @data will be
 
797
 * freed with @free_fn. @value also holds a note of the length of the memory
 
798
 * area.
 
799
 *
 
800
 * blobs are things like ICC profiles or EXIF data. They are relocatable, and
 
801
 * are saved to VIPS files for you coded as base64 inside the XML. They are
 
802
 * copied by copying reference-counted pointers.
 
803
 *
 
804
 * See also: vips_value_get_blob()
 
805
 */
 
806
void
 
807
vips_value_set_blob( GValue *value, 
 
808
        VipsCallbackFn free_fn, void *data, size_t length ) 
 
809
{
 
810
        VipsArea *area;
 
811
 
 
812
        g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_BLOB );
 
813
 
 
814
        area = vips_area_new_blob( free_fn, data, length );
 
815
        g_value_set_boxed( value, area );
 
816
        vips_area_unref( area );
 
817
}
 
818
 
 
819
/** 
 
820
 * vips_value_get_blob:
 
821
 * @value: GValue to set
 
822
 * @length: (allow-none): optionally return length of memory area
 
823
 *
 
824
 * Returns the data pointer from a blob. Optionally returns the length too.
 
825
 *
 
826
 * blobs are things like ICC profiles or EXIF data. They are relocatable, and
 
827
 * are saved to VIPS files for you coded as base64 inside the XML. They are
 
828
 * copied by copying reference-counted pointers.
 
829
 *
 
830
 * See also: vips_value_set_blob()
 
831
 *
 
832
 * Returns: (transfer none): The pointer held by @value.
 
833
 */
 
834
void *
 
835
vips_value_get_blob( const GValue *value, size_t *length )
 
836
{
 
837
        return( vips_value_get_area( value, length ) );
 
838
}
 
839
 
 
840
/**
 
841
 * vips_value_set_array: 
 
842
 * @value: (out): %GValue to set
 
843
 * @n: number of elements 
 
844
 * @type: the type of each element 
 
845
 * @sizeof_type: the sizeof each element 
 
846
 *
 
847
 * Set @value to be an array of things. 
 
848
 *
 
849
 * This allocates memory but does not 
 
850
 * initialise the contents: get the pointer and write instead.
 
851
 */
 
852
void
 
853
vips_value_set_array( GValue *value, int n, GType type, size_t sizeof_type )
 
854
{
 
855
        VipsArea *area;
 
856
 
 
857
        area = vips_area_new_array( type, sizeof_type, n );
 
858
        g_value_set_boxed( value, area );
 
859
        vips_area_unref( area );
 
860
}
 
861
 
 
862
/** 
 
863
 * vips_value_get_array:
 
864
 * @value: %GValue to get from
 
865
 * @n: (allow-none): return the number of elements here, optionally
 
866
 * @type: (allow-none): return the type of each element here, optionally
 
867
 * @sizeof_type: (allow-none): return the sizeof each element here, optionally
 
868
 *
 
869
 * Return the pointer to the array held by @value.
 
870
 * Optionally return the other properties of the array in @n, @type,
 
871
 * @sizeof_type.
 
872
 *
 
873
 * See also: vips_value_set_array().
 
874
 *
 
875
 * Returns: (transfer none): The array address.
 
876
 */
 
877
void *
 
878
vips_value_get_array( const GValue *value, 
 
879
        int *n, GType *type, size_t *sizeof_type )
 
880
{
 
881
        VipsArea *area;
 
882
 
 
883
        /* Can't check value type, because we may get called from
 
884
         * vips_*_get_type().
 
885
         */
 
886
 
 
887
        area = g_value_get_boxed( value );
 
888
        if( n )
 
889
                *n = area->n;
 
890
        if( type )
 
891
                *type = area->type;
 
892
        if( sizeof_type )
 
893
                *sizeof_type = area->sizeof_type;
 
894
 
 
895
        return( area->data );
 
896
}
 
897
 
 
898
/**
 
899
 * vips_array_double_new:
 
900
 * @array: (array length=n): array of double
 
901
 * @n: number of doubles
 
902
 *
 
903
 * Allocate a new array of doubles and copy @array into it. Free with
 
904
 * vips_area_unref().
 
905
 *
 
906
 * See also: #VipsArea.
 
907
 *
 
908
 * Returns: (transfer full): A new #VipsArrayDouble.
 
909
 */
 
910
VipsArrayDouble *
 
911
vips_array_double_new( const double *array, int n )
 
912
{
 
913
        VipsArea *area;
 
914
        double *array_copy;
 
915
 
 
916
        printf( "hello, world!\n" );
 
917
 
 
918
        area = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), n );
 
919
        array_copy = vips_area_get_data( area, NULL, NULL, NULL, NULL );
 
920
        memcpy( array_copy, array, n * sizeof( double ) );
 
921
 
 
922
        return( area );
 
923
}
 
924
 
 
925
/** 
 
926
 * vips_value_get_array_double:
 
927
 * @value: %GValue to get from
 
928
 * @n: (allow-none): return the number of elements here, optionally
 
929
 *
 
930
 * Return the start of the array of doubles held by @value.
 
931
 * optionally return the number of elements in @n.
 
932
 *
 
933
 * See also: vips_array_double_set().
 
934
 *
 
935
 * Returns: (transfer none): The array address.
 
936
 */
 
937
double *
 
938
vips_value_get_array_double( const GValue *value, int *n )
 
939
{
 
940
        return( vips_value_get_array( value, n, NULL, NULL ) );
 
941
}
 
942
 
 
943
/** 
 
944
 * vips_value_set_array_double:
 
945
 * @value: (out): %GValue to get from
 
946
 * @array: (array length=n): array of doubles
 
947
 * @n: the number of elements 
 
948
 *
 
949
 * Set @value to hold a copy of @array. Pass in the array length in @n. 
 
950
 *
 
951
 * See also: vips_array_double_get().
 
952
 *
 
953
 * Returns: 0 on success, -1 otherwise.
 
954
 */
 
955
int
 
956
vips_value_set_array_double( GValue *value, const double *array, int n )
 
957
{
 
958
        double *array_copy;
 
959
 
 
960
        g_value_init( value, VIPS_TYPE_ARRAY_DOUBLE );
 
961
        vips_value_set_array( value, n, G_TYPE_DOUBLE, sizeof( double ) );
 
962
        array_copy = vips_value_get_array_double( value, NULL );
 
963
        memcpy( array_copy, array, n * sizeof( double ) );
 
964
 
 
965
        return( 0 );
 
966
}
 
967
 
 
968
/** 
 
969
 * vips_value_get_array_object: (skip)
 
970
 * @value: %GValue to get from
 
971
 * @n: (allow-none): return the number of elements here, optionally
 
972
 *
 
973
 * Return the start of the array of %GObject held by @value.
 
974
 * optionally return the number of elements in @n.
 
975
 *
 
976
 * See also: vips_array_object_set().
 
977
 *
 
978
 * Returns: (transfer none): The array address.
 
979
 */
 
980
GObject **
 
981
vips_value_get_array_object( const GValue *value, int *n )
 
982
{
 
983
        return( vips_value_get_array( value, n, NULL, NULL ) );
 
984
}
 
985
 
 
986
/** 
 
987
 * vips_array_object_set:
 
988
 * @value: (out): %GValue to set
 
989
 * @n: the number of elements 
 
990
 *
 
991
 * Set @value to hold an array of GObject. Pass in the array length in @n. 
 
992
 *
 
993
 * See also: vips_array_object_get().
 
994
 *
 
995
 * Returns: 0 on success, -1 otherwise.
 
996
 */
 
997
int
 
998
vips_value_set_array_object( GValue *value, int n )
 
999
{
 
1000
        VipsArea *area;
 
1001
 
 
1002
        if( !(area = vips_area_new_array_object( n )) )
 
1003
                return( -1 );
 
1004
        g_value_set_boxed( value, area );
 
1005
        vips_area_unref( area );
 
1006
 
 
1007
        return( 0 );
 
1008
}
 
1009
 
 
1010
/* Make the types we need for basic functioning. Called from init_world().
 
1011
 */
 
1012
void
 
1013
vips__meta_init_types( void )
 
1014
{
 
1015
        (void) vips_thing_get_type();
 
1016
        (void) vips_save_string_get_type();
 
1017
        (void) vips_area_get_type();
 
1018
        (void) vips_ref_string_get_type();
 
1019
        (void) vips_blob_get_type();
 
1020
        (void) vips_array_double_get_type();
 
1021
        (void) vips_array_image_get_type();
 
1022
 
 
1023
        /* Register transform functions to go from built-in saveable types to 
 
1024
         * a save string. Transform functions for our own types are set 
 
1025
         * during type creation. 
 
1026
         */
 
1027
        g_value_register_transform_func( G_TYPE_INT, VIPS_TYPE_SAVE_STRING,
 
1028
                transform_int_save_string );
 
1029
        g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_INT,
 
1030
                transform_save_string_int );
 
1031
        g_value_register_transform_func( G_TYPE_DOUBLE, VIPS_TYPE_SAVE_STRING,
 
1032
                transform_double_save_string );
 
1033
        g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, G_TYPE_DOUBLE,
 
1034
                transform_save_string_double );
 
1035
}