1 /* abstract base class for all vips objects
2  */
3 
4 /*
5 
6     Copyright (C) 1991-2003 The National Gallery
7 
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation; either
11     version 2.1 of the License, or (at your option) any later version.
12 
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17 
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21     02110-1301  USA
22 
23  */
24 
25 /*
26 
27     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
28 
29  */
30 
31 #ifndef VIPS_OBJECT_H
32 #define VIPS_OBJECT_H
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif /*__cplusplus*/
37 
38 /* Handy!
39  */
40 #ifdef VIPS_DEBUG
41 #define VIPS_UNREF( X ) G_STMT_START { \
42 	if( X ) { \
43 		g_assert( G_OBJECT( X )->ref_count > 0 ); \
44 		g_object_unref( X ); \
45 		(X) = 0; \
46 	} \
47 } G_STMT_END
48 #else /*!VIPS_DEBUG*/
49 #define VIPS_UNREF( X ) VIPS_FREEF( g_object_unref, (X) )
50 #endif /*VIPS_DEBUG*/
51 
52 typedef struct _VipsObject VipsObject;
53 typedef struct _VipsObjectClass VipsObjectClass;
54 
55 /* Track extra stuff for arguments to objects
56  */
57 
58 typedef enum /*< flags >*/ {
59 	VIPS_ARGUMENT_NONE = 0,
60 	VIPS_ARGUMENT_REQUIRED = 1,
61 	VIPS_ARGUMENT_CONSTRUCT = 2,
62 	VIPS_ARGUMENT_SET_ONCE = 4,
63 	VIPS_ARGUMENT_SET_ALWAYS = 8,
64 	VIPS_ARGUMENT_INPUT = 16,
65 	VIPS_ARGUMENT_OUTPUT = 32,
66 	VIPS_ARGUMENT_DEPRECATED = 64,
67 	VIPS_ARGUMENT_MODIFY = 128
68 } VipsArgumentFlags;
69 
70 /* Useful flag combinations. User-visible ones are:
71 
72 VIPS_ARGUMENT_REQUIRED_INPUT 	Eg. the "left" argument for an add operation
73 
74 VIPS_ARGUMENT_OPTIONAL_INPUT 	Eg. the "caption" for an object
75 
76 VIPS_ARGUMENT_REQUIRED_OUTPUT  	Eg. the "result" of an add operation
77 
78 VIPS_ARGUMENT_OPTIONAL_OUTPUT   Eg. the x pos of the image minimum
79 
80    Other combinations are used internally, eg. supplying the cast-table for an
81    arithmetic operation
82 
83  */
84 
85 #define VIPS_ARGUMENT_REQUIRED_INPUT \
86 	(VIPS_ARGUMENT_INPUT | \
87 	 VIPS_ARGUMENT_REQUIRED | \
88 	 VIPS_ARGUMENT_CONSTRUCT)
89 
90 #define VIPS_ARGUMENT_OPTIONAL_INPUT \
91 	(VIPS_ARGUMENT_INPUT | \
92 	 VIPS_ARGUMENT_CONSTRUCT)
93 
94 #define VIPS_ARGUMENT_REQUIRED_OUTPUT \
95 	(VIPS_ARGUMENT_OUTPUT | \
96 	 VIPS_ARGUMENT_REQUIRED | \
97 	 VIPS_ARGUMENT_CONSTRUCT)
98 
99 #define VIPS_ARGUMENT_OPTIONAL_OUTPUT \
100 	(VIPS_ARGUMENT_OUTPUT | \
101 	 VIPS_ARGUMENT_CONSTRUCT)
102 
103 #define VIPS_ARG_IMAGE( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) { \
104 	GParamSpec *pspec; \
105 	\
106 	pspec = g_param_spec_object( (NAME), (LONG), (DESC),  \
107 		VIPS_TYPE_IMAGE, \
108 		(GParamFlags) (G_PARAM_READWRITE) ); \
109 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
110 		vips_argument_get_id(), pspec ); \
111 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
112 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
113 }
114 
115 #define VIPS_ARG_OBJECT( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, TYPE ) { \
116 	GParamSpec *pspec; \
117 	\
118 	pspec = g_param_spec_object( (NAME), (LONG), (DESC),  \
119 		TYPE, \
120 		(GParamFlags) (G_PARAM_READWRITE) ); \
121 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
122 		vips_argument_get_id(), pspec ); \
123 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
124 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
125 }
126 
127 #define VIPS_ARG_INTERPOLATE( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) \
128 	VIPS_ARG_OBJECT( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, VIPS_TYPE_INTERPOLATE )
129 
130 #define VIPS_ARG_BOOL( CLASS, NAME, PRIORITY, LONG, DESC, \
131 	FLAGS, OFFSET, VALUE ) { \
132 	GParamSpec *pspec; \
133 	\
134 	pspec = g_param_spec_boolean( (NAME), (LONG), (DESC), \
135 		(VALUE), \
136 		(GParamFlags) (G_PARAM_READWRITE) ); \
137 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
138 		vips_argument_get_id(), pspec ); \
139 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
140 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
141 }
142 
143 #define VIPS_ARG_DOUBLE( CLASS, NAME, PRIORITY, LONG, DESC, \
144 	FLAGS, OFFSET, MIN, MAX, VALUE ) { \
145 	GParamSpec *pspec; \
146 	\
147 	pspec = g_param_spec_double( (NAME), (LONG), (DESC), \
148 		(MIN), (MAX), (VALUE), \
149 		(GParamFlags) (G_PARAM_READWRITE) );\
150 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
151 		vips_argument_get_id(), pspec ); \
152 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
153 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
154 }
155 
156 #define VIPS_ARG_BOXED( CLASS, NAME, PRIORITY, LONG, DESC, \
157 	FLAGS, OFFSET, TYPE ) { \
158 	GParamSpec *pspec; \
159 	\
160 	pspec = g_param_spec_boxed( (NAME), (LONG), (DESC), \
161 		(TYPE), \
162 		(GParamFlags) (G_PARAM_READWRITE) );\
163 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
164 		vips_argument_get_id(), pspec ); \
165 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
166 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
167 }
168 
169 #define VIPS_ARG_INT( CLASS, NAME, PRIORITY, LONG, DESC, \
170 	FLAGS, OFFSET, MIN, MAX, VALUE ) { \
171 	GParamSpec *pspec; \
172 	\
173 	pspec = g_param_spec_int( (NAME), (LONG), (DESC), \
174 		(MIN), (MAX), (VALUE), \
175 		(GParamFlags) (G_PARAM_READWRITE) );\
176 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
177 		vips_argument_get_id(), pspec ); \
178 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
179 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
180 }
181 
182 #define VIPS_ARG_UINT64( CLASS, NAME, PRIORITY, LONG, DESC, \
183 	FLAGS, OFFSET, MIN, MAX, VALUE ) { \
184 	GParamSpec *pspec; \
185 	\
186 	pspec = g_param_spec_uint64( (NAME), (LONG), (DESC), \
187 		(MIN), (MAX), (VALUE), \
188 		(GParamFlags) (G_PARAM_READWRITE) );\
189 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
190 		vips_argument_get_id(), pspec ); \
191 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
192 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
193 }
194 
195 #define VIPS_ARG_ENUM( CLASS, NAME, PRIORITY, LONG, DESC, \
196 	FLAGS, OFFSET, TYPE, VALUE ) { \
197 	GParamSpec *pspec; \
198 	\
199 	pspec = g_param_spec_enum( (NAME), (LONG), (DESC), \
200 		(TYPE), (VALUE), \
201 		(GParamFlags) (G_PARAM_READWRITE) );\
202 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
203 		vips_argument_get_id(), pspec ); \
204 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
205 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
206 }
207 
208 #define VIPS_ARG_FLAGS( CLASS, NAME, PRIORITY, LONG, DESC, \
209 	FLAGS, OFFSET, TYPE, VALUE ) { \
210 	GParamSpec *pspec; \
211 	\
212 	pspec = g_param_spec_flags( (NAME), (LONG), (DESC), \
213 		(TYPE), (VALUE), \
214 		(GParamFlags) (G_PARAM_READWRITE) );\
215 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
216 		vips_argument_get_id(), pspec ); \
217 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
218 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
219 }
220 
221 #define VIPS_ARG_STRING( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
222 	VALUE ) { \
223 	GParamSpec *pspec; \
224 	\
225 	pspec = g_param_spec_string( (NAME), (LONG), (DESC), \
226 		(VALUE), \
227 		(GParamFlags) (G_PARAM_READWRITE) ); \
228 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
229 		vips_argument_get_id(), pspec ); \
230 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
231 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
232 }
233 
234 #define VIPS_ARG_POINTER( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) { \
235 	GParamSpec *pspec; \
236 	\
237 	pspec = g_param_spec_pointer( (NAME), (LONG), (DESC), \
238 		(GParamFlags) (G_PARAM_READWRITE) ); \
239 	g_object_class_install_property( G_OBJECT_CLASS( CLASS ),  \
240 		vips_argument_get_id(), pspec ); \
241 	vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
242 		pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
243 }
244 
245 /* Keep one of these for every argument.
246  */
247 typedef struct _VipsArgument {
248 	GParamSpec *pspec;	/* pspec for this argument */
249 
250 	/* More stuff, see below */
251 } VipsArgument;
252 
253 /* Keep one of these in the class struct for every argument.
254  */
255 typedef struct _VipsArgumentClass {
256 	VipsArgument parent;
257 
258 	/* The class of the object we are an arg for.
259 	 */
260 	VipsObjectClass *object_class;
261 
262 	VipsArgumentFlags flags;
263 	int priority;		/* Order args by this */
264 	guint offset;		/* G_STRUCT_OFFSET of member in object */
265 } VipsArgumentClass;
266 
267 /* Keep one of these in the object struct for every argument instance.
268  */
269 typedef struct _VipsArgumentInstance {
270 	VipsArgument parent;
271 
272 	/* The class we are part of.
273 	 */
274 	VipsArgumentClass *argument_class;
275 
276 	/* The object we are attached to.
277 	 */
278 	VipsObject *object;
279 
280 	/* Has been set.
281 	 */
282 	gboolean assigned;
283 
284 	/* If this is an output argument, keep the id of our "close" handler
285 	 * here.
286 	 */
287 	gulong close_id;
288 
289 	/* We need to listen for "invalidate" on input images and send our own
290 	 * "invalidate" out. If we go, we need to disconnect.
291 	 */
292 	gulong invalidate_id;
293 } VipsArgumentInstance;
294 
295 /* Need to look up our VipsArgument structs from a pspec. Just hash the
296  * pointer (ie. we assume pspecs are never shared, is this correct?)
297  */
298 typedef GHashTable VipsArgumentTable;
299 
300 int vips_argument_get_id( void );
301 void vips__object_set_member( VipsObject *object, GParamSpec *pspec,
302 	GObject **member, GObject *argument );
303 typedef void *(*VipsArgumentMapFn)( VipsObject *object, GParamSpec *pspec,
304 	VipsArgumentClass *argument_class,
305 	VipsArgumentInstance *argument_instance, void *a, void *b );
306 void *vips_argument_map( VipsObject *object,
307 	VipsArgumentMapFn fn, void *a, void *b );
308 int vips_object_get_args( VipsObject *object,
309 	const char ***names, int **flags, int *n_args );
310 typedef void *(*VipsArgumentClassMapFn)( VipsObjectClass *object_class,
311 	GParamSpec *pspec,
312 	VipsArgumentClass *argument_class, void *a, void *b );
313 void *vips_argument_class_map( VipsObjectClass *object_class,
314 	VipsArgumentClassMapFn fn, void *a, void *b );
315 gboolean vips_argument_class_needsstring( VipsArgumentClass *argument_class );
316 int vips_object_get_argument( VipsObject *object, const char *name,
317 	GParamSpec **pspec,
318 	VipsArgumentClass **argument_class,
319 	VipsArgumentInstance **argument_instance );
320 gboolean vips_object_argument_isset( VipsObject *object, const char *name );
321 VipsArgumentFlags vips_object_get_argument_flags( VipsObject *object,
322 	const char *name );
323 int vips_object_get_argument_priority( VipsObject *object, const char *name );
324 
325 /* We have to loop over an objects args in several places, and we can't always
326  * use vips_argument_map(), the preferred looper. Have the loop code as a
327  * macro as well for these odd cases.
328  */
329 #define VIPS_ARGUMENT_FOR_ALL( OBJECT, PSPEC, ARG_CLASS, ARG_INSTANCE ) { \
330 	VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( OBJECT ); \
331 	GSList *p; \
332  	\
333 	for( p = object_class->argument_table_traverse; p; p = p->next ) { \
334 		VipsArgumentClass *ARG_CLASS = \
335 			(VipsArgumentClass *) p->data; \
336 		VipsArgument *argument = (VipsArgument *) argument_class; \
337 		GParamSpec *PSPEC = argument->pspec; \
338 		VipsArgumentInstance *ARG_INSTANCE __attribute__ ((unused)) = \
339 			vips__argument_get_instance( argument_class, \
340 			VIPS_OBJECT( OBJECT ) ); \
341 
342 #define VIPS_ARGUMENT_FOR_ALL_END } }
343 
344 /* And some macros to collect args from a va list.
345  *
346  * Use something like this:
347 
348 	GParamSpec *pspec;
349 	VipsArgumentClass *argument_class;
350 	VipsArgumentInstance *argument_instance;
351 
352 	if( vips_object_get_argument( VIPS_OBJECT( operation ), name,
353 		&pspec, &argument_class, &argument_instance ) )
354 		return( -1 );
355 
356 	VIPS_ARGUMENT_COLLECT_SET( pspec, argument_class, ap );
357 
358 		GValue value holds the value of an input argument, do
359 		something with it
360 
361 	VIPS_ARGUMENT_COLLECT_GET( pspec, argument_class, ap );
362 
363 		void **arg points to where to write an output argument
364 
365 	VIPS_ARGUMENT_COLLECT_END
366 
367  */
368 #define VIPS_ARGUMENT_COLLECT_SET( PSPEC, ARG_CLASS, AP ) \
369 	if( (ARG_CLASS->flags & VIPS_ARGUMENT_INPUT) ) { \
370 		GValue value = { 0, }; \
371 		gchar *error = NULL; \
372  		\
373 		/* Input args are given inline, eg. ("factor", 12.0)  \
374 		 * and must be collected. \
375 		 */ \
376 		G_VALUE_COLLECT_INIT( &value, \
377 				G_PARAM_SPEC_VALUE_TYPE( PSPEC ), AP, 0, &error ); \
378 		\
379 		/* Don't bother with the error message. \
380 		 */ \
381 		if( error ) { \
382 			VIPS_DEBUG_MSG( "VIPS_OBJECT_COLLECT_SET: err\n" ); \
383 			g_free( error ); \
384 		}
385 
386 #define VIPS_ARGUMENT_COLLECT_GET( PSPEC, ARG_CLASS, AP ) \
387 		g_value_unset( &value ); \
388 	} \
389 	else if( (ARG_CLASS->flags & VIPS_ARGUMENT_OUTPUT) ) { \
390 		void **arg __attribute__ ((unused)); \
391  		\
392 		/* Output args are a pointer to where to send the \
393 		 * result. \
394 		 */ \
395 		arg = va_arg( AP, void ** );
396 
397 #define VIPS_ARGUMENT_COLLECT_END \
398 	}
399 
400 #define VIPS_TYPE_OBJECT (vips_object_get_type())
401 #define VIPS_OBJECT( obj ) \
402 	(G_TYPE_CHECK_INSTANCE_CAST( (obj), VIPS_TYPE_OBJECT, VipsObject ))
403 #define VIPS_OBJECT_CLASS( klass ) \
404 	(G_TYPE_CHECK_CLASS_CAST( (klass), VIPS_TYPE_OBJECT, VipsObjectClass))
405 #define VIPS_IS_OBJECT( obj ) \
406 	(G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_OBJECT ))
407 #define VIPS_IS_OBJECT_CLASS( klass ) \
408 	(G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_OBJECT ))
409 #define VIPS_OBJECT_GET_CLASS( obj ) \
410 	(G_TYPE_INSTANCE_GET_CLASS( (obj), VIPS_TYPE_OBJECT, VipsObjectClass ))
411 
412 struct _VipsObject {
413 	GObject parent_instance;
414 
415 	/* Set after ->build() has run succesfully: construct is fully done
416 	 * and checked.
417 	 */
418 	gboolean constructed;
419 
420 	/* Set for static objects which are allocated at startup and never
421 	 * freed. These objects are ommitted from leak reports.
422 	 */
423 	gboolean static_object;
424 
425 	/* Table of argument instances for this class and any derived classes.
426 	 */
427 	VipsArgumentTable *argument_table;
428 
429 	/* Class properties (see below), duplicated in the instance so we can
430 	 * get at them easily via the property system.
431 	 */
432 	char *nickname;
433 	char *description;
434 
435 	/* The pre/post/close callbacks are all fire-once.
436 	 */
437 	gboolean preclose;
438 	gboolean close;
439 	gboolean postclose;
440 
441 	/* Total memory allocated relative to this object, handy for
442 	 * profiling.
443 	 */
444 	size_t local_memory;
445 
446 };
447 
448 struct _VipsObjectClass {
449 	GObjectClass parent_class;
450 
451 	/* Build the object ... all argument properties have been set,
452 	 * now build the thing.
453 	 */
454 	int (*build)( VipsObject *object );
455 
456 	/* Just after build ... the object is fully ready for work.
457 	 */
458 	int (*postbuild)( VipsObject *object, void *data );
459 
460 	/* Try to print something about the class, handy for help displays.
461 	 * Keep to one line.
462 	 */
463 	void (*summary_class)( struct _VipsObjectClass *cls, VipsBuf *buf );
464 
465 	/* Try to print a one-line summary for the object, the user can see
466 	 * this output via things like "header fred.tif", --vips-cache-trace,
467 	 * etc.
468 	 */
469 	void (*summary)( VipsObject *object, VipsBuf *buf );
470 
471 	/* Try to print everything about the object, handy for debugging.
472 	 */
473 	void (*dump)( VipsObject *object, VipsBuf *buf );
474 
475 	/* Sanity-check the object. Print messages and stuff.
476 	 * Handy for debugging.
477 	 */
478 	void (*sanity)( VipsObject *object, VipsBuf *buf );
479 
480 	/* Rewind. Save and restore any stuff that needs to survive a
481 	 * dispose().
482 	 */
483 	void (*rewind)( VipsObject *object );
484 
485 	/* Just before close, everything is still alive.
486 	 */
487 	void (*preclose)( VipsObject *object );
488 
489 	/* Close, time to free stuff.
490 	 */
491 	void (*close)( VipsObject *object );
492 
493 	/* Post-close, everything is dead, except the VipsObject pointer.
494 	 * Useful for eg. deleting the file associated with a temp image.
495 	 */
496 	void (*postclose)( VipsObject *object );
497 
498 	/* The CLI interface. Implement these four to get CLI input and output
499 	 * for your object.
500 	 */
501 
502 	/* Given a command-line arg (eg. a filename), make an instance of the
503 	 * object. Just do the g_object_new(), don't call _build().
504 	 *
505 	 * Don't call this directly, see vips_object_new_from_string().
506 	 */
507 	VipsObject *(*new_from_string)( const char *string );
508 
509 	/* The inverse of ^^. Given an object, output what ->new_from_string()
510 	 * would have been given to make that object.
511 	 */
512 	void (*to_string)( VipsObject *object, VipsBuf *buf );
513 
514 	/* Does this output arg need an arg from the command line? Image
515 	 * output, for example, needs a filename to write to.
516 	 */
517 	gboolean output_needs_arg;
518 
519 	/* Write the object to the string. Return 0 for success, or -1 on
520 	 * error, setting vips_error(). string is NULL if output_needs_arg()
521 	 * was FALSE.
522 	 */
523 	int (*output_to_arg)( VipsObject *object, const char *string );
524 
525 	/* Class nickname, eg. "VipsInterpolateBicubic" has "bicubic" as a
526 	 * nickname. Not internationalised.
527 	 */
528 	const char *nickname;
529 
530 	/* Class description. Used for help messages, so internationalised.
531 	 */
532 	const char *description;
533 
534 	/* Hash from pspec to VipsArgumentClass.
535 	 *
536 	 * This records the VipsArgumentClass for every pspec used in
537 	 * VipsObject and any subclass (ie. everywhere), so it's huge. Don't
538 	 * loop over this hash! Fine for lookups though.
539 	 */
540 	VipsArgumentTable *argument_table;
541 
542 	/* A sorted (by priority) list of the VipsArgumentClass for this class
543 	 * and any superclasses. This is small and specific to this class.
544 	 *
545 	 * Use the stored GType to work out when to restart the list for a
546 	 * subclass.
547 	 */
548 	GSList *argument_table_traverse;
549 	GType argument_table_traverse_gtype;
550 
551 	/* This class is deprecated and therefore hidden from various UI bits.
552 	 *
553 	 * VipsOperation has a deprecated flag, use that in preference to this
554 	 * if you can.
555 	 */
556 	gboolean deprecated;
557 
558 	/* Reserved for future expansion.
559 	 */
560 	void (*_vips_reserved1)( void );
561 	void (*_vips_reserved2)( void );
562 	void (*_vips_reserved3)( void );
563 	void (*_vips_reserved4)( void );
564 };
565 
566 gboolean vips_value_is_null( GParamSpec *psoec, const GValue *value );
567 void vips_object_set_property( GObject *gobject,
568 	guint property_id, const GValue *value, GParamSpec *pspec );
569 void vips_object_get_property( GObject *gobject,
570 	guint property_id, GValue *value, GParamSpec *pspec );
571 
572 void vips_object_preclose( VipsObject *object );
573 int vips_object_build( VipsObject *object );
574 
575 void vips_object_summary_class( VipsObjectClass *klass, VipsBuf *buf );
576 void vips_object_summary( VipsObject *object, VipsBuf *buf );
577 void vips_object_dump( VipsObject *object, VipsBuf *buf );
578 
579 void vips_object_print_summary_class( VipsObjectClass *klass );
580 void vips_object_print_summary( VipsObject *object );
581 void vips_object_print_dump( VipsObject *object );
582 void vips_object_print_name( VipsObject *object );
583 
584 gboolean vips_object_sanity( VipsObject *object );
585 
586 /* Don't put spaces around void here, it breaks gtk-doc.
587  */
588 GType vips_object_get_type(void);
589 
590 void vips_object_class_install_argument( VipsObjectClass *cls,
591 	GParamSpec *pspec, VipsArgumentFlags flags,
592 	int priority, guint offset );
593 int vips_object_set_argument_from_string( VipsObject *object,
594 	const char *name, const char *value );
595 gboolean vips_object_argument_needsstring( VipsObject *object,
596 	const char *name );
597 int vips_object_get_argument_to_string( VipsObject *object,
598 	const char *name, const char *arg );
599 int vips_object_set_required( VipsObject *object, const char *value );
600 
601 typedef void *(*VipsObjectSetArguments)( VipsObject *object, void *a, void *b );
602 VipsObject *vips_object_new( GType type,
603 	VipsObjectSetArguments set, void *a, void *b );
604 
605 int vips_object_set_valist( VipsObject *object, va_list ap );
606 int vips_object_set( VipsObject *object, ... )
607 	__attribute__((sentinel));
608 int vips_object_set_from_string( VipsObject *object, const char *string );
609 
610 VipsObject *vips_object_new_from_string( VipsObjectClass *object_class,
611 	const char *p );
612 void vips_object_to_string( VipsObject *object, VipsBuf *buf );
613 
614 void *vips_object_map( VipsSListMap2Fn fn, void *a, void *b );
615 
616 typedef void *(*VipsTypeMapFn)( GType type, void *a );
617 typedef void *(*VipsTypeMap2Fn)( GType type, void *a, void *b );
618 typedef void *(*VipsClassMapFn)( VipsObjectClass *cls, void *a );
619 void *vips_type_map( GType base, VipsTypeMap2Fn fn, void *a, void *b );
620 void *vips_type_map_all( GType base, VipsTypeMapFn fn, void *a );
621 int vips_type_depth( GType type );
622 GType vips_type_find( const char *basename, const char *nickname );
623 const char *vips_nickname_find( GType type );
624 
625 void *vips_class_map_all( GType type, VipsClassMapFn fn, void *a );
626 const VipsObjectClass *vips_class_find( const char *basename,
627 	const char *nickname );
628 
629 VipsObject **vips_object_local_array( VipsObject *parent, int n );
630 
631 void vips_object_local_cb( VipsObject *vobject, GObject *gobject );
632 #define vips_object_local( V, G ) \
633 	(g_signal_connect( V, "close", G_CALLBACK( vips_object_local_cb ), G ))
634 
635 void vips_object_set_static( VipsObject *object, gboolean static_object );
636 void vips_object_print_all( void );
637 void vips_object_sanity_all( void );
638 
639 void vips_object_rewind( VipsObject *object );
640 
641 void vips_object_unref_outputs( VipsObject *object );
642 
643 const char *vips_object_get_description( VipsObject *object );
644 
645 #ifdef __cplusplus
646 }
647 #endif /*__cplusplus*/
648 
649 #endif /*VIPS_OBJECT_H*/
650 
651 
652