1 /* SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later */
2 
3 #include <config.h>
4 #undef G_DISABLE_ASSERT
5 
6 #include <string.h>
7 #include <glib/gi18n.h>
8 #include <glib-object.h>
9 #include "my-object.h"
10 
11 #include "test-service-glib-glue.h"
12 
13 /* Properties */
14 enum
15 {
16   PROP_0,
17   PROP_THIS_IS_A_STRING,
18   PROP_NO_TOUCHING,
19   PROP_SUPER_STUDLY,
20   PROP_SHOULD_BE_HIDDEN
21 };
22 
23 enum
24 {
25   FROBNICATE,
26   OBJECTIFIED,
27   SIG0,
28   SIG1,
29   SIG2,
30   LAST_SIGNAL
31 };
32 
33 static guint signals[LAST_SIGNAL] = { 0 };
34 
G_DEFINE_TYPE(MyObject,my_object,G_TYPE_OBJECT)35 G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT)
36 
37 static void
38 my_object_finalize (GObject *object)
39 {
40   MyObject *mobject = MY_OBJECT (object);
41 
42   g_free (mobject->this_is_a_string);
43   g_clear_error (&mobject->saved_error);
44 
45   (G_OBJECT_CLASS (my_object_parent_class)->finalize) (object);
46 }
47 
48 static void
my_object_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)49 my_object_set_property (GObject      *object,
50                         guint         prop_id,
51                         const GValue *value,
52                         GParamSpec   *pspec)
53 {
54   MyObject *mobject;
55 
56   mobject = MY_OBJECT (object);
57 
58   switch (prop_id)
59     {
60     case PROP_THIS_IS_A_STRING:
61       g_free (mobject->this_is_a_string);
62       mobject->this_is_a_string = g_value_dup_string (value);
63       break;
64 
65     case PROP_NO_TOUCHING:
66       mobject->notouching = g_value_get_uint (value);
67       break;
68 
69     case PROP_SUPER_STUDLY:
70       mobject->super_studly = g_value_get_double (value);
71       break;
72 
73     case PROP_SHOULD_BE_HIDDEN:
74       mobject->should_be_hidden = g_value_get_boolean (value);
75       break;
76 
77     default:
78       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
79       break;
80     }
81 }
82 
83 static void
my_object_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)84 my_object_get_property (GObject      *object,
85                         guint         prop_id,
86                         GValue       *value,
87                         GParamSpec   *pspec)
88 {
89   MyObject *mobject;
90 
91   mobject = MY_OBJECT (object);
92 
93   switch (prop_id)
94     {
95     case PROP_THIS_IS_A_STRING:
96       g_value_set_string (value, mobject->this_is_a_string);
97       break;
98 
99     case PROP_NO_TOUCHING:
100       g_value_set_uint (value, mobject->notouching);
101       break;
102 
103     case PROP_SUPER_STUDLY:
104       g_value_set_double (value, mobject->super_studly);
105       break;
106 
107     case PROP_SHOULD_BE_HIDDEN:
108       g_value_set_boolean (value, mobject->should_be_hidden);
109       break;
110 
111     default:
112       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
113       break;
114     }
115 }
116 
117 static void
my_object_init(MyObject * obj)118 my_object_init (MyObject *obj)
119 {
120   obj->val = 0;
121   obj->notouching = 42;
122   obj->saved_error = g_error_new_literal (MY_OBJECT_ERROR,
123       MY_OBJECT_ERROR_FOO, "this method always loses");
124 }
125 
126 static void
my_object_class_init(MyObjectClass * mobject_class)127 my_object_class_init (MyObjectClass *mobject_class)
128 {
129   GObjectClass *gobject_class = G_OBJECT_CLASS (mobject_class);
130 
131   dbus_g_object_type_install_info (MY_TYPE_OBJECT,
132 				   &dbus_glib_my_object_object_info);
133 
134   gobject_class->finalize = my_object_finalize;
135   gobject_class->set_property = my_object_set_property;
136   gobject_class->get_property = my_object_get_property;
137 
138   g_object_class_install_property (gobject_class,
139 				   PROP_THIS_IS_A_STRING,
140 				   g_param_spec_string ("this_is_a_string",
141                                                         _("Sample string"),
142                                                         _("Example of a string property"),
143                                                         "default value",
144                                                         G_PARAM_READWRITE));
145   g_object_class_install_property (gobject_class,
146                                    PROP_NO_TOUCHING,
147                                    g_param_spec_uint ("no_touching",
148                                                       _("Don't touch"),
149                                                       _("Example of a readonly property (for export)"),
150                                                       0, 100, 42,
151                                                       G_PARAM_READWRITE));
152 
153   g_object_class_install_property (gobject_class,
154                 				   PROP_SUPER_STUDLY,
155 				                   g_param_spec_double ("super-studly",
156                                                         _("In Studly Caps"),
157                                                         _("Example of a StudlyCaps property"),
158                                                         0, 256, 128,
159                                                         G_PARAM_READWRITE));
160 
161   g_object_class_install_property (gobject_class,
162                 				   PROP_SHOULD_BE_HIDDEN,
163 				                   g_param_spec_boolean ("should-be-hidden",
164                                                         _("A non-exported property"),
165                                                         _("Example of a property we don't want exported"),
166                                                         FALSE,
167                                                         G_PARAM_READWRITE));
168 
169   signals[FROBNICATE] =
170     g_signal_new ("frobnicate",
171 		  G_OBJECT_CLASS_TYPE (mobject_class),
172                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
173                   0,
174                   NULL, NULL,
175                   g_cclosure_marshal_VOID__INT,
176                   G_TYPE_NONE, 1, G_TYPE_INT);
177 
178   signals[OBJECTIFIED] =
179     g_signal_new ("objectified",
180                   G_OBJECT_CLASS_TYPE (mobject_class),
181                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
182                   0,
183                   NULL, NULL,
184                   g_cclosure_marshal_VOID__OBJECT,
185                   G_TYPE_NONE, 1, G_TYPE_OBJECT);
186 
187   signals[SIG0] =
188     g_signal_new ("sig0",
189 		  G_OBJECT_CLASS_TYPE (mobject_class),
190                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
191                   0,
192                   NULL, NULL, NULL,
193                   G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
194 
195   signals[SIG1] =
196     g_signal_new ("sig1",
197 		  G_OBJECT_CLASS_TYPE (mobject_class),
198                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
199                   0,
200                   NULL, NULL, NULL,
201                   G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VALUE);
202 
203   signals[SIG2] =
204     g_signal_new ("sig2",
205 		  G_OBJECT_CLASS_TYPE (mobject_class),
206                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
207                   0,
208                   NULL, NULL,
209                   g_cclosure_marshal_VOID__BOXED,
210                   G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
211 }
212 
213 GQuark
my_object_error_quark(void)214 my_object_error_quark (void)
215 {
216   static GQuark quark = 0;
217   if (!quark)
218     quark = g_quark_from_static_string ("my_object_error");
219 
220   return quark;
221 }
222 
223 /* This should really be standard. */
224 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
225 
226 GType
my_object_error_get_type(void)227 my_object_error_get_type (void)
228 {
229 	static GType etype = 0;
230 
231 	if (etype == 0)
232 	{
233 		static const GEnumValue values[] =
234 		{
235 
236 			ENUM_ENTRY (MY_OBJECT_ERROR_FOO, "Foo"),
237 			ENUM_ENTRY (MY_OBJECT_ERROR_BAR, "Bar"),
238 			ENUM_ENTRY (MY_OBJECT_ERROR_MULTI_WORD, "Multi-word"),
239 			ENUM_ENTRY (MY_OBJECT_ERROR_UNDER_SCORE, "Under_score"),
240 			{ 0, 0, 0 }
241 		};
242 
243 		etype = g_enum_register_static ("MyObjectError", values);
244 	}
245 
246 	return etype;
247 }
248 
249 gboolean
my_object_do_nothing(MyObject * obj,GError ** error)250 my_object_do_nothing (MyObject *obj, GError **error)
251 {
252   return TRUE;
253 }
254 
255 gboolean
my_object_increment(MyObject * obj,gint32 x,gint32 * ret,GError ** error)256 my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error)
257 {
258   *ret = x +1;
259   return TRUE;
260 }
261 
262 gint32
my_object_increment_retval(MyObject * obj,gint32 x)263 my_object_increment_retval (MyObject *obj, gint32 x)
264 {
265   return x + 1;
266 }
267 
268 gint32
my_object_increment_retval_error(MyObject * obj,gint32 x,GError ** error)269 my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error)
270 {
271   if (x + 1 > 10)
272     {
273       g_set_error (error,
274 		   MY_OBJECT_ERROR,
275 		   MY_OBJECT_ERROR_FOO,
276 		   "%s",
277 		   "x is bigger than 9");
278       return FALSE;
279     }
280   return x + 1;
281 }
282 
283 void
my_object_save_error(MyObject * obj,GQuark domain,gint code,const gchar * message)284 my_object_save_error (MyObject *obj,
285     GQuark domain,
286     gint code,
287     const gchar *message)
288 {
289   g_clear_error (&obj->saved_error);
290   g_set_error_literal (&obj->saved_error, domain, code, message);
291 }
292 
293 gboolean
my_object_throw_error(MyObject * obj,GError ** error)294 my_object_throw_error (MyObject *obj, GError **error)
295 {
296   g_set_error_literal (error, obj->saved_error->domain,
297       obj->saved_error->code, obj->saved_error->message);
298   return FALSE;
299 }
300 
301 gboolean
my_object_throw_unregistered_error(MyObject * obj,GError ** error)302 my_object_throw_unregistered_error (MyObject *obj, GError **error)
303 {
304   /* Unregistered errors shouldn't cause a dbus abort.  See
305    * https://bugzilla.redhat.com/show_bug.cgi?id=581794
306    *
307    * This is arguably invalid usage - a domain of 0 (which stringifies
308    * to NULL) is meaningless. (See GNOME#660731.)
309    *
310    * We can't just use my_object_save_error() and ThrowError() for
311    * this, because g_error_new() is stricter about the domain than
312    * g_error_new_valist(). Perhaps this method should be removed entirely,
313    * though.
314    */
315   g_set_error (error, 0, 0,
316 	       "%s",
317 	       "this method always loses more");
318   return FALSE;
319 }
320 
321 
322 gboolean
my_object_uppercase(MyObject * obj,const char * str,char ** ret,GError ** error)323 my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error)
324 {
325   *ret = g_ascii_strup (str, -1);
326   return TRUE;
327 }
328 
329 gboolean
my_object_many_args(MyObject * obj,guint32 x,const char * str,double trouble,double * d_ret,char ** str_ret,GError ** error)330 my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error)
331 {
332   *d_ret = trouble + (x * 2);
333   *str_ret = g_ascii_strup (str, -1);
334   return TRUE;
335 }
336 
337 gboolean
my_object_many_return(MyObject * obj,guint32 * arg0,char ** arg1,gint32 * arg2,guint32 * arg3,guint32 * arg4,const char ** arg5,GError ** error)338 my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint32 *arg2, guint32 *arg3, guint32 *arg4, const char **arg5, GError **error)
339 {
340   *arg0 = 42;
341   *arg1 = g_strdup ("42");
342   *arg2 = -67;
343   *arg3 = 2;
344   *arg4 = 26;
345   *arg5 = "hello world"; /* Annotation specifies as const */
346   return TRUE;
347 }
348 
349 gboolean
my_object_stringify(MyObject * obj,GValue * value,char ** ret,GError ** error)350 my_object_stringify (MyObject *obj, GValue *value, char **ret, GError **error)
351 {
352   GValue valstr = {0, };
353 
354   g_value_init (&valstr, G_TYPE_STRING);
355   if (!g_value_transform (value, &valstr))
356     {
357       g_set_error (error,
358 		   MY_OBJECT_ERROR,
359 		   MY_OBJECT_ERROR_FOO,
360 		   "couldn't transform value");
361       return FALSE;
362     }
363   *ret = g_value_dup_string (&valstr);
364   g_value_unset (&valstr);
365   return TRUE;
366 }
367 
368 gboolean
my_object_unstringify(MyObject * obj,const char * str,GValue * value,GError ** error)369 my_object_unstringify (MyObject *obj, const char *str, GValue *value, GError **error)
370 {
371   if (str[0] == '\0' || !g_ascii_isdigit (str[0])) {
372     g_value_init (value, G_TYPE_STRING);
373     g_value_set_string (value, str);
374   } else {
375     g_value_init (value, G_TYPE_INT);
376     g_value_set_int (value, (int) g_ascii_strtoull (str, NULL, 10));
377   }
378   return TRUE;
379 }
380 
381 gboolean
my_object_recursive1(MyObject * obj,GArray * array,guint32 * len_ret,GError ** error)382 my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error)
383 {
384   *len_ret = array->len;
385   return TRUE;
386 }
387 
388 gboolean
my_object_recursive2(MyObject * obj,guint32 reqlen,GArray ** ret,GError ** error)389 my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **ret, GError **error)
390 {
391   guint32 val;
392   GArray *array;
393 
394   array = g_array_new (FALSE, TRUE, sizeof (guint32));
395 
396   while (reqlen > 0) {
397     val = 42;
398     g_array_append_val (array, val);
399     val = 26;
400     g_array_append_val (array, val);
401     reqlen--;
402   }
403   val = 2;
404   g_array_append_val (array, val);
405   *ret = array;
406   return TRUE;
407 }
408 
409 gboolean
my_object_many_uppercase(MyObject * obj,const char * const * in,char *** out,GError ** error)410 my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GError **error)
411 {
412   int len;
413   int i;
414 
415   len = g_strv_length ((char**) in);
416 
417   *out = g_new0 (char *, len + 1);
418   for (i = 0; i < len; i++)
419     {
420       (*out)[i] = g_ascii_strup (in[i], -1);
421     }
422   (*out)[i] = NULL;
423 
424   return TRUE;
425 }
426 
427 static void
hash_foreach_stringify(gpointer key,gpointer val,gpointer user_data)428 hash_foreach_stringify (gpointer key, gpointer val, gpointer user_data)
429 {
430   const char *keystr = key;
431   const GValue *value = val;
432   GValue *sval;
433   GHashTable *ret = user_data;
434 
435   sval = g_new0 (GValue, 1);
436   g_value_init (sval, G_TYPE_STRING);
437   if (!g_value_transform (value, sval))
438     g_assert_not_reached ();
439 
440   g_hash_table_insert (ret, g_strdup (keystr), sval);
441 }
442 
443 static void
unset_and_free_gvalue(gpointer val)444 unset_and_free_gvalue (gpointer val)
445 {
446   g_value_unset (val);
447   g_free (val);
448 }
449 
450 gboolean
my_object_many_stringify(MyObject * obj,GHashTable * vals,GHashTable ** ret,GError ** error)451 my_object_many_stringify (MyObject *obj, GHashTable /* char * -> GValue * */ *vals, GHashTable /* char * -> GValue * */ **ret, GError **error)
452 {
453   *ret = g_hash_table_new_full (g_str_hash, g_str_equal,
454 				g_free, unset_and_free_gvalue);
455   g_hash_table_foreach (vals, hash_foreach_stringify, *ret);
456   return TRUE;
457 }
458 
459 gboolean
my_object_rec_arrays(MyObject * obj,GPtrArray * in,GPtrArray ** ret,GError ** error)460 my_object_rec_arrays (MyObject *obj, GPtrArray *in, GPtrArray **ret, GError **error)
461 {
462   char **strs;
463   GArray *ints;
464   guint v_UINT;
465 
466   if (in->len != 2)
467     {
468       g_set_error (error,
469 		   MY_OBJECT_ERROR,
470 		   MY_OBJECT_ERROR_FOO,
471 		   "invalid array len");
472       return FALSE;
473     }
474 
475   strs = g_ptr_array_index (in, 0);
476   if (!*strs || strcmp (*strs, "foo"))
477     {
478       g_set_error (error,
479 		   MY_OBJECT_ERROR,
480 		   MY_OBJECT_ERROR_FOO,
481 		   "invalid string 0");
482       return FALSE;
483     }
484   strs++;
485   if (!*strs || strcmp (*strs, "bar"))
486     {
487       g_set_error (error,
488 		   MY_OBJECT_ERROR,
489 		   MY_OBJECT_ERROR_FOO,
490 		   "invalid string 1");
491       return FALSE;
492     }
493   strs++;
494   if (*strs)
495     {
496       g_set_error (error,
497 		   MY_OBJECT_ERROR,
498 		   MY_OBJECT_ERROR_FOO,
499 		   "invalid string array len in pos 0");
500       return FALSE;
501     }
502   strs = g_ptr_array_index (in, 1);
503   if (!*strs || strcmp (*strs, "baz"))
504     {
505       g_set_error (error,
506 		   MY_OBJECT_ERROR,
507 		   MY_OBJECT_ERROR_FOO,
508 		   "invalid string 0");
509       return FALSE;
510     }
511   strs++;
512   if (!*strs || strcmp (*strs, "whee"))
513     {
514       g_set_error (error,
515 		   MY_OBJECT_ERROR,
516 		   MY_OBJECT_ERROR_FOO,
517 		   "invalid string 1");
518       return FALSE;
519     }
520   strs++;
521   if (!*strs || strcmp (*strs, "moo"))
522     {
523       g_set_error (error,
524 		   MY_OBJECT_ERROR,
525 		   MY_OBJECT_ERROR_FOO,
526 		   "invalid string 2");
527       return FALSE;
528     }
529   strs++;
530   if (*strs)
531     {
532       g_set_error (error,
533 		   MY_OBJECT_ERROR,
534 		   MY_OBJECT_ERROR_FOO,
535 		   "invalid string array len in pos 1");
536       return FALSE;
537     }
538 
539   *ret = g_ptr_array_new ();
540 
541   ints = g_array_new (TRUE, TRUE, sizeof (guint));
542   v_UINT = 10;
543   g_array_append_val (ints, v_UINT);
544   v_UINT = 42;
545   g_array_append_val (ints, v_UINT);
546   v_UINT = 27;
547   g_array_append_val (ints, v_UINT);
548   g_ptr_array_add (*ret, ints);
549 
550   ints = g_array_new (TRUE, TRUE, sizeof (guint));
551   v_UINT = 30;
552   g_array_append_val (ints, v_UINT);
553   g_ptr_array_add (*ret, ints);
554   return TRUE;
555 }
556 
557 gboolean
my_object_objpath(MyObject * obj,const char * incoming,const char ** outgoing,GError ** error)558 my_object_objpath (MyObject *obj, const char *incoming, const char **outgoing, GError **error)
559 {
560   if (strcmp (incoming, "/org/freedesktop/DBus/GLib/Tests/MyTestObject"))
561     {
562       g_set_error (error,
563 		   MY_OBJECT_ERROR,
564 		   MY_OBJECT_ERROR_FOO,
565 		   "invalid incoming object");
566       return FALSE;
567     }
568   *outgoing = "/org/freedesktop/DBus/GLib/Tests/MyTestObject2";
569   return TRUE;
570 }
571 
572 gboolean
my_object_get_objs(MyObject * obj,GPtrArray ** objs,GError ** error)573 my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error)
574 {
575   *objs = g_ptr_array_new ();
576 
577   g_ptr_array_add (*objs, g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject"));
578   g_ptr_array_add (*objs, g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject2"));
579 
580   return TRUE;
581 }
582 
583 static void
hash_foreach(gpointer key,gpointer val,gpointer user_data)584 hash_foreach (gpointer key, gpointer val, gpointer user_data)
585 {
586   const char *keystr = key;
587   const char *valstr = val;
588   guint *count = user_data;
589 
590   *count += (strlen (keystr) + strlen (valstr));
591   g_print ("%s -> %s\n", keystr, valstr);
592 }
593 
594 gboolean
my_object_str_hash_len(MyObject * obj,GHashTable * table,guint * len,GError ** error)595 my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **error)
596 {
597   *len = 0;
598   g_hash_table_foreach (table, hash_foreach, len);
599   return TRUE;
600 }
601 
602 gboolean
my_object_send_car(MyObject * obj,GValueArray * invals,GValueArray ** outvals,GError ** error)603 my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error)
604 {
605   if (invals->n_values != 3
606       || G_VALUE_TYPE (g_value_array_get_nth (invals, 0)) != G_TYPE_STRING
607       || G_VALUE_TYPE (g_value_array_get_nth (invals, 1)) != G_TYPE_UINT
608       || G_VALUE_TYPE (g_value_array_get_nth (invals, 2)) != G_TYPE_VALUE)
609     {
610       g_set_error (error,
611 		   MY_OBJECT_ERROR,
612 		   MY_OBJECT_ERROR_FOO,
613 		   "invalid incoming values");
614       return FALSE;
615     }
616   *outvals = g_value_array_new (2);
617   g_value_array_append (*outvals, NULL);
618   g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), G_TYPE_UINT);
619   g_value_set_uint (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
620 		    g_value_get_uint (g_value_array_get_nth (invals, 1)) + 1);
621   g_value_array_append (*outvals, NULL);
622   g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), DBUS_TYPE_G_OBJECT_PATH);
623   g_value_set_boxed (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
624 		     g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject2"));
625   return TRUE;
626 }
627 
628 gboolean
my_object_get_hash(MyObject * obj,GHashTable ** ret,GError ** error)629 my_object_get_hash (MyObject *obj, GHashTable **ret, GError **error)
630 {
631   GHashTable *table;
632 
633   table = g_hash_table_new (g_str_hash, g_str_equal);
634   g_hash_table_insert (table, "foo", "bar");
635   g_hash_table_insert (table, "baz", "whee");
636   g_hash_table_insert (table, "cow", "crack");
637   *ret = table;
638   return TRUE;
639 }
640 
641 gboolean
my_object_increment_val(MyObject * obj,GError ** error)642 my_object_increment_val (MyObject *obj, GError **error)
643 {
644   obj->val++;
645   return TRUE;
646 }
647 
648 gboolean
my_object_get_val(MyObject * obj,guint * ret,GError ** error)649 my_object_get_val (MyObject *obj, guint *ret, GError **error)
650 {
651   *ret = obj->val;
652   return TRUE;
653 }
654 
655 gboolean
my_object_get_value(MyObject * obj,guint * ret,GError ** error)656 my_object_get_value (MyObject *obj, guint *ret, GError **error)
657 {
658   *ret = obj->val;
659   return TRUE;
660 }
661 
662 gboolean
my_object_echo_variant(MyObject * obj,GValue * variant,GValue * ret,GError ** error)663 my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error)
664 {
665     GType t;
666 
667     obj->echo_variant_called++;
668 
669     t = G_VALUE_TYPE(variant);
670     g_value_init (ret, t);
671     g_value_copy (variant, ret);
672 
673     return TRUE;
674 }
675 
676 gboolean
my_object_echo_signature(MyObject * obj,const gchar * in,gchar ** out,GError ** error)677 my_object_echo_signature (MyObject *obj, const gchar *in, gchar **out, GError **error)
678 {
679   *out = g_strdup (in);
680   return TRUE;
681 }
682 
683 gboolean
my_object_process_variant_of_array_of_ints123(MyObject * obj,GValue * variant,GError ** error)684 my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error)
685 {
686   GArray *array;
687   int i;
688   int j;
689 
690   j = 0;
691 
692   array = (GArray *)g_value_get_boxed (variant);
693 
694   for (i = 0; i <= 2; i++)
695     {
696       j = g_array_index (array, int, i);
697       if (j != i + 1)
698         goto error;
699     }
700 
701   return TRUE;
702 
703 error:
704   *error = g_error_new (MY_OBJECT_ERROR,
705 		       MY_OBJECT_ERROR_FOO,
706 		       "Error decoding a variant of type ai (i + 1 = %i, j = %i)",
707 		       i, j + 1);
708   return FALSE;
709 }
710 
711 
712 typedef struct _HashAndString HashAndString;
713 
714 struct _HashAndString
715 {
716   GHashTable *hash;
717   gchar* string;
718 };
719 
720 static void
hash_foreach_prepend_string(gpointer key,gpointer val,gpointer user_data)721 hash_foreach_prepend_string (gpointer key, gpointer val, gpointer user_data)
722 {
723   HashAndString *data = (HashAndString*) user_data;
724   gchar *in = (gchar*) val;
725   g_hash_table_insert (data->hash, g_strdup ((gchar*) key),
726                        g_strjoin (" ", data->string, in, NULL));
727 }
728 
729 
730 static void
hash_foreach_mangle_dict_of_strings(gpointer key,gpointer val,gpointer user_data)731 hash_foreach_mangle_dict_of_strings (gpointer key, gpointer val, gpointer user_data)
732 {
733   GHashTable *out = (GHashTable*) user_data;
734   GHashTable *in_dict = (GHashTable *) val;
735   HashAndString *data = g_new0 (HashAndString, 1);
736 
737   data->string = (gchar*) key;
738   data->hash = g_hash_table_new_full (g_str_hash, g_str_equal,
739                                             g_free, g_free);
740   g_hash_table_foreach (in_dict, hash_foreach_prepend_string, data);
741 
742   g_hash_table_insert(out, g_strdup ((gchar*) key), data->hash);
743 }
744 
745 gboolean
my_object_dict_of_dicts(MyObject * obj,GHashTable * in,GHashTable ** out,GError ** error)746 my_object_dict_of_dicts (MyObject *obj, GHashTable *in,
747                                 GHashTable **out, GError **error)
748 {
749   *out = g_hash_table_new_full (g_str_hash, g_str_equal,
750 				(GDestroyNotify) g_free,
751                                 (GDestroyNotify) g_hash_table_destroy);
752   g_hash_table_foreach (in, hash_foreach_mangle_dict_of_strings, *out);
753   return TRUE;
754 }
755 
756 void
my_object_dict_of_sigs(MyObject * obj,GHashTable * dict,DBusGMethodInvocation * context)757 my_object_dict_of_sigs (MyObject *obj,
758                         GHashTable *dict,
759                         DBusGMethodInvocation *context)
760 {
761   dbus_g_method_return (context, dict);
762 }
763 
764 void
my_object_dict_of_objs(MyObject * obj,GHashTable * dict,DBusGMethodInvocation * context)765 my_object_dict_of_objs (MyObject *obj,
766                         GHashTable *dict,
767                         DBusGMethodInvocation *context)
768 {
769   dbus_g_method_return (context, dict);
770 }
771 
772 gboolean
my_object_emit_frobnicate(MyObject * obj,GError ** error)773 my_object_emit_frobnicate (MyObject *obj, GError **error)
774 {
775   g_signal_emit (obj, signals[FROBNICATE], 0, 42);
776   return TRUE;
777 }
778 
779 gboolean
my_object_emit_signals(MyObject * obj,GError ** error)780 my_object_emit_signals (MyObject *obj, GError **error)
781 {
782   GValue val = {0, };
783 
784   g_signal_emit (obj, signals[SIG0], 0, "foo", 22, "moo");
785 
786   g_value_init (&val, G_TYPE_STRING);
787   g_value_set_string (&val, "bar");
788   g_signal_emit (obj, signals[SIG1], 0, "baz", &val);
789   g_value_unset (&val);
790 
791   return TRUE;
792 }
793 
794 gboolean
my_object_emit_signal2(MyObject * obj,GError ** error)795 my_object_emit_signal2 (MyObject *obj, GError **error)
796 {
797   GHashTable *table;
798 
799   table = g_hash_table_new (g_str_hash, g_str_equal);
800   g_hash_table_insert (table, "baz", "cow");
801   g_hash_table_insert (table, "bar", "foo");
802   g_signal_emit (obj, signals[SIG2], 0, table);
803   g_hash_table_destroy (table);
804   return TRUE;
805 }
806 
807 typedef struct {
808   gint32 x;
809   DBusGMethodInvocation *context;
810 } IncrementData;
811 
812 static gboolean
do_async_increment(IncrementData * data)813 do_async_increment (IncrementData *data)
814 {
815   gint32 newx = data->x + 1;
816   dbus_g_method_return (data->context, newx);
817   g_free (data);
818   return FALSE;
819 }
820 
821 void
my_object_async_increment(MyObject * obj,gint32 x,DBusGMethodInvocation * context)822 my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context)
823 {
824   IncrementData *data = g_new0 (IncrementData, 1);
825   data->x = x;
826   data->context = context;
827   g_idle_add ((GSourceFunc)do_async_increment, data);
828 }
829 
830 typedef struct {
831   GError *error;
832   DBusGMethodInvocation *context;
833 } ErrorData;
834 
835 static gboolean
do_async_error(ErrorData * data)836 do_async_error (ErrorData *data)
837 {
838   dbus_g_method_return_error (data->context, data->error);
839   g_error_free (data->error);
840   g_free (data);
841   return FALSE;
842 }
843 
844 void
my_object_async_throw_error(MyObject * obj,DBusGMethodInvocation * context)845 my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context)
846 {
847   ErrorData *data = g_new0 (ErrorData, 1);
848 
849   data->error = g_error_copy (obj->saved_error);
850   data->context = context;
851   g_idle_add ((GSourceFunc) do_async_error,  data);
852 }
853 
854 gboolean
my_object_unsafe_disable_legacy_property_access(MyObject * obj,GError ** error)855 my_object_unsafe_disable_legacy_property_access (MyObject *obj,
856     GError **error)
857 {
858   dbus_glib_global_set_disable_legacy_property_access ();
859   return TRUE;
860 }
861 
862 extern GMainLoop *loop;
863 
864 gboolean
my_object_terminate(MyObject * obj,GError ** error)865 my_object_terminate (MyObject *obj, GError **error)
866 {
867   g_main_loop_quit (loop);
868   return TRUE;
869 }
870 
871 void
my_object_emit_objectified(MyObject * obj,GObject * other)872 my_object_emit_objectified (MyObject *obj,
873     GObject *other)
874 {
875   g_signal_emit (obj, signals[OBJECTIFIED], 0, other);
876 }
877