NAIDuplicable: rewrite modification check stack
[nautilus-actions.git] / src / core / na-factory-object.c
blob185e047588121a86e7b36c3340389a73c164102b
1 /*
2 * Nautilus-Actions
3 * A Nautilus extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
9 * This Program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This Program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this Library; see the file COPYING. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307, USA.
24 * Authors:
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <string.h>
39 #include <api/na-core-utils.h>
40 #include <api/na-data-types.h>
41 #include <api/na-iio-provider.h>
42 #include <api/na-ifactory-provider.h>
43 #include <api/na-data-boxed.h>
45 #include "na-factory-object.h"
46 #include "na-factory-provider.h"
48 typedef gboolean ( *NADataDefIterFunc )( NADataDef *def, void *user_data );
50 enum {
51 DATA_DEF_ITER_SET_PROPERTIES = 1,
52 DATA_DEF_ITER_SET_DEFAULTS,
53 DATA_DEF_ITER_IS_VALID,
54 DATA_DEF_ITER_READ_ITEM,
57 /* while iterating on read item
59 typedef struct {
60 NAIFactoryObject *object;
61 NAIFactoryProvider *reader;
62 void *reader_data;
63 GSList **messages;
65 NafoReadIter;
67 /* while iterating on write item
69 typedef struct {
70 NAIFactoryProvider *writer;
71 void *writer_data;
72 GSList **messages;
73 guint code;
75 NafoWriteIter;
77 /* while iterating on is_valid
79 typedef struct {
80 NAIFactoryObject *object;
81 gboolean is_valid;
83 NafoValidIter;
85 /* while iterating on set defaults
87 typedef struct {
88 NAIFactoryObject *object;
90 NafoDefaultIter;
92 extern gboolean ifactory_object_initialized;
93 extern gboolean ifactory_object_finalized;
95 static gboolean define_class_properties_iter( const NADataDef *def, GObjectClass *class );
96 static gboolean set_defaults_iter( NADataDef *def, NafoDefaultIter *data );
97 static gboolean is_valid_mandatory_iter( const NADataDef *def, NafoValidIter *data );
98 static gboolean read_data_iter( NADataDef *def, NafoReadIter *iter );
99 static gboolean write_data_iter( const NAIFactoryObject *object, NADataBoxed *boxed, NafoWriteIter *iter );
101 static NADataGroup *v_get_groups( const NAIFactoryObject *object );
102 static void v_copy( NAIFactoryObject *target, const NAIFactoryObject *source );
103 static gboolean v_are_equal( const NAIFactoryObject *a, const NAIFactoryObject *b );
104 static gboolean v_is_valid( const NAIFactoryObject *object );
105 static void v_read_start( NAIFactoryObject *serializable, const NAIFactoryProvider *reader, void *reader_data, GSList **messages );
106 static void v_read_done( NAIFactoryObject *serializable, const NAIFactoryProvider *reader, void *reader_data, GSList **messages );
107 static guint v_write_start( NAIFactoryObject *serializable, const NAIFactoryProvider *reader, void *reader_data, GSList **messages );
108 static guint v_write_done( NAIFactoryObject *serializable, const NAIFactoryProvider *reader, void *reader_data, GSList **messages );
110 static void attach_boxed_to_object( NAIFactoryObject *object, NADataBoxed *boxed );
111 static void free_data_boxed_list( NAIFactoryObject *object );
112 static void iter_on_data_defs( const NADataGroup *idgroups, guint mode, NADataDefIterFunc pfn, void *user_data );
115 * na_factory_object_define_properties:
116 * @class: the #GObjectClass.
117 * @groups: the list of #NADataGroup structure which define the data of the class.
119 * Initializes all the properties for the class.
121 void
122 na_factory_object_define_properties( GObjectClass *class, const NADataGroup *groups )
124 static const gchar *thisfn = "na_factory_object_define_properties";
126 if( ifactory_object_initialized && !ifactory_object_finalized ){
128 g_debug( "%s: class=%p (%s)",
129 thisfn, ( void * ) class, G_OBJECT_CLASS_NAME( class ));
131 g_return_if_fail( G_IS_OBJECT_CLASS( class ));
133 /* define class properties
135 iter_on_data_defs( groups, DATA_DEF_ITER_SET_PROPERTIES, ( NADataDefIterFunc ) define_class_properties_iter, class );
139 static gboolean
140 define_class_properties_iter( const NADataDef *def, GObjectClass *class )
142 static const gchar *thisfn = "na_factory_object_define_class_properties_iter";
143 gboolean stop;
144 GParamSpec *spec;
146 g_debug( "%s: def=%p (%s)", thisfn, ( void * ) def, def->name );
148 stop = FALSE;
150 spec = na_data_boxed_get_param_spec( def );
152 if( spec ){
153 g_object_class_install_property( class, g_quark_from_string( def->name ), spec );
155 } else {
156 g_warning( "%s: type=%d: unable to get a spec", thisfn, def->type );
159 return( stop );
163 * na_factory_object_get_data_def:
164 * @object: this #NAIFactoryObject object.
165 * @name: the searched name.
167 * Returns: the #NADataDef structure which describes this @name, or %NULL.
169 NADataDef *
170 na_factory_object_get_data_def( const NAIFactoryObject *object, const gchar *name )
172 NADataDef *def;
174 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), NULL );
176 def = NULL;
178 if( ifactory_object_initialized && !ifactory_object_finalized ){
180 NADataGroup *groups = v_get_groups( object );
181 while( groups->group ){
183 NADataDef *def = groups->def;
184 if( def ){
185 while( def->name ){
187 if( !strcmp( def->name, name )){
188 return( def );
190 def++;
193 groups++;
197 return( def );
201 * na_factory_object_get_data_groups:
202 * @object: the #NAIFactoryObject instance.
204 * Returns: a pointer to the list of #NADataGroup which define the data.
206 NADataGroup *
207 na_factory_object_get_data_groups( const NAIFactoryObject *object )
209 NADataGroup *groups;
211 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), NULL );
213 groups = NULL;
215 if( ifactory_object_initialized && !ifactory_object_finalized ){
217 groups = v_get_groups( object );
220 return( groups );
224 * na_factory_object_iter_on_boxed:
225 * @object: this #NAIFactoryObject object.
226 * @pfn: the function to be called.
227 * @user_data: data to be provided to the user function.
229 * Iterate on each #NADataBoxed attached to the @object.
231 * The @fn called function may return %TRUE to stop the iteration.
233 void
234 na_factory_object_iter_on_boxed( const NAIFactoryObject *object, NAFactoryObjectIterBoxedFn pfn, void *user_data )
236 GList *list, *ibox;
237 gboolean stop;
239 g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
241 if( ifactory_object_initialized && !ifactory_object_finalized ){
243 list = g_object_get_data( G_OBJECT( object ), NA_IFACTORY_OBJECT_PROP_DATA );
244 /*g_debug( "list=%p (count=%u)", ( void * ) list, g_list_length( list ));*/
245 stop = FALSE;
247 for( ibox = list ; ibox && !stop ; ibox = ibox->next ){
248 stop = ( *pfn )( object, NA_DATA_BOXED( ibox->data ), user_data );
254 * na_factory_object_get_default:
255 * @object: this #NAIFactoryObject object.
256 * @name: the searched name.
258 * Returns: the default value for this @object, as a newly allocated
259 * string which should be g_free() by the caller.
261 gchar *
262 na_factory_object_get_default( NAIFactoryObject *object, const gchar *name )
264 static const gchar *thisfn = "na_factory_object_set_defaults";
265 gchar *value;
266 NADataDef *def;
268 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), NULL );
270 value = NULL;
272 if( ifactory_object_initialized && !ifactory_object_finalized ){
274 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
276 def = na_factory_object_get_data_def( object, name );
277 if( def ){
278 value = g_strdup( def->default_value );
282 return( value );
286 * na_factory_object_set_defaults:
287 * @object: this #NAIFactoryObject object.
289 * Implement default values in this new @object.
291 void
292 na_factory_object_set_defaults( NAIFactoryObject *object )
294 static const gchar *thisfn = "na_factory_object_set_defaults";
295 NADataGroup *groups;
296 NafoDefaultIter *iter_data;
298 g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
300 if( ifactory_object_initialized && !ifactory_object_finalized ){
302 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
304 groups = v_get_groups( object );
305 if( !groups ){
306 g_warning( "%s: no NADataGroup found for %s", thisfn, G_OBJECT_TYPE_NAME( object ));
308 } else {
309 iter_data = g_new0( NafoDefaultIter, 1 );
310 iter_data->object = object;
312 iter_on_data_defs( groups, DATA_DEF_ITER_SET_DEFAULTS, ( NADataDefIterFunc ) set_defaults_iter, iter_data );
314 g_free( iter_data );
320 * because this function is called very early in the NAIFactoryObject life,
321 * we assume here that if a NADataBoxed has been allocated, then this is
322 * most probably because it is set. Thus a 'null' value is not considered
323 * as an 'unset' value.
325 static gboolean
326 set_defaults_iter( NADataDef *def, NafoDefaultIter *data )
328 NADataBoxed *boxed = na_ifactory_object_get_data_boxed( data->object, def->name );
330 if( !boxed ){
331 boxed = na_data_boxed_new( def );
332 attach_boxed_to_object( data->object, boxed );
333 na_boxed_set_from_string( NA_BOXED( boxed ), def->default_value );
336 /* do not stop */
337 return( FALSE );
341 * na_factory_object_move_boxed:
342 * @target: the target #NAIFactoryObject instance.
343 * @source: the source #NAIFactoryObject instance.
344 * @boxed: a #NADataBoxed.
346 * Move the @boxed from @source to @target, detaching from @source list
347 * to be attached to @target one.
349 void
350 na_factory_object_move_boxed( NAIFactoryObject *target, const NAIFactoryObject *source, NADataBoxed *boxed )
352 g_return_if_fail( NA_IS_IFACTORY_OBJECT( target ));
353 g_return_if_fail( NA_IS_IFACTORY_OBJECT( source ));
355 if( ifactory_object_initialized && !ifactory_object_finalized ){
357 GList *src_list = g_object_get_data( G_OBJECT( source ), NA_IFACTORY_OBJECT_PROP_DATA );
359 if( g_list_find( src_list, boxed )){
360 src_list = g_list_remove( src_list, boxed );
361 g_object_set_data( G_OBJECT( source ), NA_IFACTORY_OBJECT_PROP_DATA, src_list );
363 attach_boxed_to_object( target, boxed );
365 const NADataDef *src_def = na_data_boxed_get_data_def( boxed );
366 NADataDef *tgt_def = na_factory_object_get_data_def( target, src_def->name );
367 na_data_boxed_set_data_def( boxed, tgt_def );
373 * na_factory_object_copy:
374 * @target: the target #NAIFactoryObject instance.
375 * @source: the source #NAIFactoryObject instance.
377 * Copies one instance to another.
379 void
380 na_factory_object_copy( NAIFactoryObject *target, const NAIFactoryObject *source )
382 static const gchar *thisfn = "na_factory_object_copy";
383 GList *src_list, *isrc;
385 g_return_if_fail( NA_IS_IFACTORY_OBJECT( target ));
386 g_return_if_fail( NA_IS_IFACTORY_OBJECT( source ));
388 g_debug( "%s: target=%p (%s), source=%p (%s)",
389 thisfn,
390 ( void * ) target, G_OBJECT_TYPE_NAME( target ),
391 ( void * ) source, G_OBJECT_TYPE_NAME( source ));
393 src_list = g_object_get_data( G_OBJECT( source ), NA_IFACTORY_OBJECT_PROP_DATA );
395 for( isrc = src_list ; isrc ; isrc = isrc->next ){
397 NADataBoxed *src_boxed = NA_DATA_BOXED( isrc->data );
398 const NADataDef *def = na_data_boxed_get_data_def( src_boxed );
400 if( def->copyable ){
401 NADataBoxed *tgt_boxed = na_ifactory_object_get_data_boxed( target, def->name );
402 if( !tgt_boxed ){
403 tgt_boxed = na_data_boxed_new( def );
404 attach_boxed_to_object( target, tgt_boxed );
406 na_boxed_set_from_boxed( NA_BOXED( tgt_boxed ), NA_BOXED( src_boxed ));
410 v_copy( target, source );
414 * na_factory_object_are_equal:
415 * @a: the first (original) #NAIFactoryObject instance.
416 * @b: the second (current) #NAIFactoryObject isntance.
418 * Returns: %TRUE if @a is equal to @b, %FALSE else.
420 gboolean
421 na_factory_object_are_equal( const NAIFactoryObject *a, const NAIFactoryObject *b )
423 static const gchar *thisfn = "na_factory_object_are_equal";
424 gboolean are_equal;
425 GList *a_list, *b_list, *ia, *ib;
427 are_equal = FALSE;
429 a_list = g_object_get_data( G_OBJECT( a ), NA_IFACTORY_OBJECT_PROP_DATA );
430 b_list = g_object_get_data( G_OBJECT( b ), NA_IFACTORY_OBJECT_PROP_DATA );
432 g_debug( "%s: a=%p, b=%p", thisfn, ( void * ) a, ( void * ) b );
434 are_equal = TRUE;
435 for( ia = a_list ; ia && are_equal ; ia = ia->next ){
437 NADataBoxed *a_boxed = NA_DATA_BOXED( ia->data );
438 const NADataDef *a_def = na_data_boxed_get_data_def( a_boxed );
439 if( a_def->comparable ){
441 NADataBoxed *b_boxed = na_ifactory_object_get_data_boxed( b, a_def->name );
442 if( b_boxed ){
443 are_equal = na_boxed_are_equal( NA_BOXED( a_boxed ), NA_BOXED( b_boxed ));
444 if( !are_equal ){
445 g_debug( "%s: %s not equal as %s different", thisfn, G_OBJECT_TYPE_NAME( a ), a_def->name );
448 } else {
449 are_equal = FALSE;
450 g_debug( "%s: %s not equal as %s has disappeared", thisfn, G_OBJECT_TYPE_NAME( a ), a_def->name );
455 for( ib = b_list ; ib && are_equal ; ib = ib->next ){
457 NADataBoxed *b_boxed = NA_DATA_BOXED( ib->data );
458 const NADataDef *b_def = na_data_boxed_get_data_def( b_boxed );
459 if( b_def->comparable ){
461 NADataBoxed *a_boxed = na_ifactory_object_get_data_boxed( a, b_def->name );
462 if( !a_boxed ){
463 are_equal = FALSE;
464 g_debug( "%s: %s not equal as %s was not set", thisfn, G_OBJECT_TYPE_NAME( a ), b_def->name );
469 are_equal &= v_are_equal( a, b );
471 return( are_equal );
475 * na_factory_object_is_valid:
476 * @object: the #NAIFactoryObject instance whose validity is to be checked.
478 * Returns: %TRUE if @object is valid, %FALSE else.
480 gboolean
481 na_factory_object_is_valid( const NAIFactoryObject *object )
483 static const gchar *thisfn = "na_factory_object_is_valid";
484 gboolean is_valid;
485 NADataGroup *groups;
486 GList *list, *iv;
488 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), FALSE );
490 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
492 list = g_object_get_data( G_OBJECT( object ), NA_IFACTORY_OBJECT_PROP_DATA );
493 is_valid = TRUE;
495 /* mndatory data must be set
497 NafoValidIter iter_data;
498 iter_data.object = ( NAIFactoryObject * ) object;
499 iter_data.is_valid = TRUE;
501 groups = v_get_groups( object );
502 if( groups ){
503 iter_on_data_defs( groups, DATA_DEF_ITER_IS_VALID, ( NADataDefIterFunc ) is_valid_mandatory_iter, &iter_data );
505 is_valid = iter_data.is_valid;
507 for( iv = list ; iv && is_valid ; iv = iv->next ){
508 is_valid = na_data_boxed_is_valid( NA_DATA_BOXED( iv->data ));
511 if( is_valid ){
512 is_valid = v_is_valid( object );
515 return( is_valid );
518 static gboolean
519 is_valid_mandatory_iter( const NADataDef *def, NafoValidIter *data )
521 NADataBoxed *boxed;
523 if( def->mandatory ){
524 boxed = na_ifactory_object_get_data_boxed( data->object, def->name );
525 if( !boxed ){
526 g_debug( "na_factory_object_is_valid_mandatory_iter: invalid %s: mandatory but not set", def->name );
527 data->is_valid = FALSE;
531 /* do not stop iteration while valid */
532 return( !data->is_valid );
536 * na_factory_object_dump:
537 * @object: this #NAIFactoryObject instance.
539 * Dumps the content of @object.
541 void
542 na_factory_object_dump( const NAIFactoryObject *object )
544 static const gchar *thisfn = "na_factory_object_dump";
545 static const gchar *prefix = "na-factory-data-";
546 GList *list, *it;
547 guint length;
548 guint l_prefix;
550 length = 0;
551 l_prefix = strlen( prefix );
552 list = g_object_get_data( G_OBJECT( object ), NA_IFACTORY_OBJECT_PROP_DATA );
554 for( it = list ; it ; it = it->next ){
555 NADataBoxed *boxed = NA_DATA_BOXED( it->data );
556 const NADataDef *def = na_data_boxed_get_data_def( boxed );
557 length = MAX( length, strlen( def->name ));
560 length -= l_prefix;
561 length += 1;
563 for( it = list ; it ; it = it->next ){
564 NADataBoxed *boxed = NA_DATA_BOXED( it->data );
565 const NADataDef *def = na_data_boxed_get_data_def( boxed );
566 gchar *value = na_boxed_get_string( NA_BOXED( boxed ));
567 g_debug( "| %s: %*s=%s", thisfn, length, def->name+l_prefix, value );
568 g_free( value );
573 * na_factory_object_finalize:
574 * @object: the #NAIFactoryObject being finalized.
576 * Clears all data associated with this @object.
578 void
579 na_factory_object_finalize( NAIFactoryObject *object )
581 free_data_boxed_list( object );
585 * na_factory_object_read_item:
586 * @object: this #NAIFactoryObject instance.
587 * @reader: the #NAIFactoryProvider which is at the origin of this read.
588 * @reader_data: reader data.
589 * @messages: a pointer to a #GSList list of strings; the implementation
590 * may append messages to this list, but shouldn't reinitialize it.
592 * Unserializes the object.
594 void
595 na_factory_object_read_item( NAIFactoryObject *object, const NAIFactoryProvider *reader, void *reader_data, GSList **messages )
597 static const gchar *thisfn = "na_factory_object_read_item";
599 g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
600 g_return_if_fail( NA_IS_IFACTORY_PROVIDER( reader ));
602 if( ifactory_object_initialized && !ifactory_object_finalized ){
604 NADataGroup *groups = v_get_groups( object );
606 if( groups ){
607 v_read_start( object, reader, reader_data, messages );
609 NafoReadIter *iter = g_new0( NafoReadIter, 1 );
610 iter->object = object;
611 iter->reader = ( NAIFactoryProvider * ) reader;
612 iter->reader_data = reader_data;
613 iter->messages = messages;
615 iter_on_data_defs( groups, DATA_DEF_ITER_READ_ITEM, ( NADataDefIterFunc ) read_data_iter, iter );
617 g_free( iter );
619 v_read_done( object, reader, reader_data, messages );
621 } else {
622 g_warning( "%s: class %s doesn't return any NADataGroup structure",
623 thisfn, G_OBJECT_TYPE_NAME( object ));
628 static gboolean
629 read_data_iter( NADataDef *def, NafoReadIter *iter )
631 gboolean stop;
633 stop = FALSE;
635 NADataBoxed *boxed = na_factory_provider_read_data( iter->reader, iter->reader_data, iter->object, def, iter->messages );
637 if( boxed ){
638 NADataBoxed *exist = na_ifactory_object_get_data_boxed( iter->object, def->name );
640 if( exist ){
641 na_boxed_set_from_boxed( NA_BOXED( exist ), NA_BOXED( boxed ));
642 g_object_unref( boxed );
644 } else {
645 attach_boxed_to_object( iter->object, boxed );
649 return( stop );
653 * na_factory_object_write_item:
654 * @object: this #NAIFactoryObject instance.
655 * @writer: the #NAIFactoryProvider which is at the origin of this write.
656 * @writer_data: writer data.
657 * @messages: a pointer to a #GSList list of strings; the implementation
658 * may append messages to this list, but shouldn't reinitialize it.
660 * Serializes the object down to the @writer.
662 * Returns: a NAIIOProvider operation return code.
664 guint
665 na_factory_object_write_item( NAIFactoryObject *object, const NAIFactoryProvider *writer, void *writer_data, GSList **messages )
667 static const gchar *thisfn = "na_factory_object_write_item";
668 guint code;
669 NADataGroup *groups;
670 gchar *msg;
672 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), NA_IIO_PROVIDER_CODE_PROGRAM_ERROR );
673 g_return_val_if_fail( NA_IS_IFACTORY_PROVIDER( writer ), NA_IIO_PROVIDER_CODE_PROGRAM_ERROR );
675 code = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
677 groups = v_get_groups( object );
679 if( groups ){
680 code = v_write_start( object, writer, writer_data, messages );
682 } else {
683 msg = g_strdup_printf( "%s: class %s doesn't return any NADataGroup structure",
684 thisfn, G_OBJECT_TYPE_NAME( object ));
685 g_warning( "%s", msg );
686 *messages = g_slist_append( *messages, msg );
689 if( code == NA_IIO_PROVIDER_CODE_OK ){
691 NafoWriteIter *iter = g_new0( NafoWriteIter, 1 );
692 iter->writer = ( NAIFactoryProvider * ) writer;
693 iter->writer_data = writer_data;
694 iter->messages = messages;
695 iter->code = code;
697 na_factory_object_iter_on_boxed( object, ( NAFactoryObjectIterBoxedFn ) write_data_iter, iter );
699 code = iter->code;
700 g_free( iter );
703 if( code == NA_IIO_PROVIDER_CODE_OK ){
704 code = v_write_done( object, writer, writer_data, messages );
707 return( code );
710 static gboolean
711 write_data_iter( const NAIFactoryObject *object, NADataBoxed *boxed, NafoWriteIter *iter )
713 const NADataDef *def = na_data_boxed_get_data_def( boxed );
715 if( def->writable ){
716 iter->code = na_factory_provider_write_data( iter->writer, iter->writer_data, object, boxed, iter->messages );
719 /* iter while code is ok */
720 return( iter->code != NA_IIO_PROVIDER_CODE_OK );
724 * na_factory_object_get_as_value:
725 * @object: this #NAIFactoryObject instance.
726 * @name: the elementary data id.
727 * @value: the #GValue to be set.
729 * Set the @value with the current content of the #NADataBoxed attached
730 * to @name.
732 * This is to be read as "set value from data element".
734 void
735 na_factory_object_get_as_value( const NAIFactoryObject *object, const gchar *name, GValue *value )
737 NADataBoxed *boxed;
739 g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
741 g_value_unset( value );
743 boxed = na_ifactory_object_get_data_boxed( object, name );
744 if( boxed ){
745 na_boxed_get_as_value( NA_BOXED( boxed ), value );
750 * na_factory_object_get_as_void:
751 * @object: this #NAIFactoryObject instance.
752 * @name: the elementary data whose value is to be got.
754 * Returns: the searched value.
756 * If the type of the value is NA_DATA_TYPE_STRING, NA_DATA_TYPE_LOCALE_STRING,
757 * or NA_DATA_TYPE_STRING_LIST, then the returned value is a newly allocated
758 * one and should be g_free() (resp. na_core_utils_slist_free()) by the
759 * caller.
761 void *
762 na_factory_object_get_as_void( const NAIFactoryObject *object, const gchar *name )
764 void *value;
765 NADataBoxed *boxed;
767 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), NULL );
769 value = NULL;
771 boxed = na_ifactory_object_get_data_boxed( object, name );
772 if( boxed ){
773 value = na_boxed_get_as_void( NA_BOXED( boxed ));
776 return( value );
780 * na_factory_object_set_from_value:
781 * @object: this #NAIFactoryObject instance.
782 * @name: the elementary data id.
783 * @value: the #GValue whose content is to be got.
785 * Get from the @value the content to be set in the #NADataBoxed
786 * attached to @property_id.
788 void
789 na_factory_object_set_from_value( NAIFactoryObject *object, const gchar *name, const GValue *value )
791 static const gchar *thisfn = "na_factory_object_set_from_value";
793 g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
795 NADataBoxed *boxed = na_ifactory_object_get_data_boxed( object, name );
796 if( boxed ){
797 na_boxed_set_from_value( NA_BOXED( boxed ), value );
799 } else {
800 NADataDef *def = na_factory_object_get_data_def( object, name );
801 if( !def ){
802 g_warning( "%s: unknown NADataDef %s", thisfn, name );
804 } else {
805 boxed = na_data_boxed_new( def );
806 na_boxed_set_from_value( NA_BOXED( boxed ), value );
807 attach_boxed_to_object( object, boxed );
813 * na_factory_object_set_from_void:
814 * @object: this #NAIFactoryObject instance.
815 * @name: the elementary data whose value is to be set.
816 * @data: the value to set.
818 * Set the elementary data with the given value.
820 void
821 na_factory_object_set_from_void( NAIFactoryObject *object, const gchar *name, const void *data )
823 static const gchar *thisfn = "na_factory_object_set_from_void";
825 g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
827 NADataBoxed *boxed = na_ifactory_object_get_data_boxed( object, name );
828 if( boxed ){
829 na_boxed_set_from_void( NA_BOXED( boxed ), data );
831 } else {
832 NADataDef *def = na_factory_object_get_data_def( object, name );
833 if( !def ){
834 g_warning( "%s: unknown NADataDef %s", thisfn, name );
836 } else {
837 boxed = na_data_boxed_new( def );
838 na_boxed_set_from_void( NA_BOXED( boxed ), data );
839 attach_boxed_to_object( object, boxed );
844 static NADataGroup *
845 v_get_groups( const NAIFactoryObject *object )
847 if( NA_IFACTORY_OBJECT_GET_INTERFACE( object )->get_groups ){
848 return( NA_IFACTORY_OBJECT_GET_INTERFACE( object )->get_groups( object ));
851 return( NULL );
854 static void
855 v_copy( NAIFactoryObject *target, const NAIFactoryObject *source )
857 if( NA_IFACTORY_OBJECT_GET_INTERFACE( target )->copy ){
858 NA_IFACTORY_OBJECT_GET_INTERFACE( target )->copy( target, source );
862 static gboolean
863 v_are_equal( const NAIFactoryObject *a, const NAIFactoryObject *b )
865 gboolean are_equal;
867 are_equal = TRUE;
869 if( NA_IFACTORY_OBJECT_GET_INTERFACE( a )->are_equal ){
870 are_equal = NA_IFACTORY_OBJECT_GET_INTERFACE( a )->are_equal( a, b );
873 return( are_equal );
876 static gboolean
877 v_is_valid( const NAIFactoryObject *object )
879 if( NA_IFACTORY_OBJECT_GET_INTERFACE( object )->is_valid ){
880 return( NA_IFACTORY_OBJECT_GET_INTERFACE( object )->is_valid( object ));
883 return( FALSE );
886 static void
887 v_read_start( NAIFactoryObject *serializable, const NAIFactoryProvider *reader, void *reader_data, GSList **messages )
889 if( NA_IFACTORY_OBJECT_GET_INTERFACE( serializable )->read_start ){
890 NA_IFACTORY_OBJECT_GET_INTERFACE( serializable )->read_start( serializable, reader, reader_data, messages );
894 static void
895 v_read_done( NAIFactoryObject *serializable, const NAIFactoryProvider *reader, void *reader_data, GSList **messages )
897 if( NA_IFACTORY_OBJECT_GET_INTERFACE( serializable )->read_done ){
898 NA_IFACTORY_OBJECT_GET_INTERFACE( serializable )->read_done( serializable, reader, reader_data, messages );
902 static guint
903 v_write_start( NAIFactoryObject *serializable, const NAIFactoryProvider *writer, void *writer_data, GSList **messages )
905 guint code = NA_IIO_PROVIDER_CODE_OK;
907 if( NA_IFACTORY_OBJECT_GET_INTERFACE( serializable )->write_start ){
908 code = NA_IFACTORY_OBJECT_GET_INTERFACE( serializable )->write_start( serializable, writer, writer_data, messages );
911 return( code );
914 static guint
915 v_write_done( NAIFactoryObject *serializable, const NAIFactoryProvider *writer, void *writer_data, GSList **messages )
917 guint code = NA_IIO_PROVIDER_CODE_OK;
919 if( NA_IFACTORY_OBJECT_GET_INTERFACE( serializable )->write_done ){
920 code = NA_IFACTORY_OBJECT_GET_INTERFACE( serializable )->write_done( serializable, writer, writer_data, messages );
923 return( code );
926 static void
927 attach_boxed_to_object( NAIFactoryObject *object, NADataBoxed *boxed )
929 GList *list = g_object_get_data( G_OBJECT( object ), NA_IFACTORY_OBJECT_PROP_DATA );
930 list = g_list_prepend( list, boxed );
931 g_object_set_data( G_OBJECT( object ), NA_IFACTORY_OBJECT_PROP_DATA, list );
934 static void
935 free_data_boxed_list( NAIFactoryObject *object )
937 GList *list;
939 list = g_object_get_data( G_OBJECT( object ), NA_IFACTORY_OBJECT_PROP_DATA );
941 g_list_foreach( list, ( GFunc ) g_object_unref, NULL );
942 g_list_free( list );
944 g_object_set_data( G_OBJECT( object ), NA_IFACTORY_OBJECT_PROP_DATA, NULL );
948 * the iter function must return TRUE to stops the enumeration
950 static void
951 iter_on_data_defs( const NADataGroup *groups, guint mode, NADataDefIterFunc pfn, void *user_data )
953 static const gchar *thisfn = "na_factory_object_iter_on_data_defs";
954 NADataDef *def;
955 gboolean stop;
957 stop = FALSE;
959 while( groups->group && !stop ){
961 if( groups->def ){
963 def = groups->def;
964 while( def->name && !stop ){
966 /*g_debug( "serializable_only=%s, def->serializable=%s",
967 serializable_only ? "True":"False", def->serializable ? "True":"False" );*/
969 switch( mode ){
970 case DATA_DEF_ITER_SET_PROPERTIES:
971 if( def->has_property ){
972 stop = ( *pfn )( def, user_data );
974 break;
976 case DATA_DEF_ITER_SET_DEFAULTS:
977 if( def->default_value ){
978 stop = ( *pfn )( def, user_data );
980 break;
982 case DATA_DEF_ITER_IS_VALID:
983 stop = ( *pfn )( def, user_data );
984 break;
986 case DATA_DEF_ITER_READ_ITEM:
987 if( def->readable ){
988 stop = ( *pfn )( def, user_data );
990 break;
992 default:
993 g_warning( "%s: unknown mode=%d", thisfn, mode );
996 def++;
1000 groups++;