Bug 584453 - Handle char ** correctly (and const variation)
[gnome.gobject-introspection] / gir / everything.c
1 #include <string.h>
2 #include "everything.h"
3
4 /* basic types */
5 gboolean test_boolean (gboolean in)
6 {
7   return in;
8 }
9
10 gint8 test_int8 (gint8 in)
11 {
12   return in;
13 }
14
15 guint8 test_uint8 (guint8 in)
16 {
17   return in;
18 }
19
20 gint16 test_int16 (gint16 in)
21 {
22   return in;
23 }
24
25 guint16 test_uint16 (guint16 in)
26 {
27   return in;
28 }
29
30 gint32 test_int32 (gint32 in)
31 {
32   return in;
33 }
34
35 guint32 test_uint32 (guint32 in)
36 {
37   return in;
38 }
39
40 gint64 test_int64 (gint64 in)
41 {
42   return in;
43 }
44
45 guint64 test_uint64 (guint64 in)
46 {
47   return in;
48 }
49
50 gint test_int (gint in)
51 {
52   return in;
53 }
54
55 guint test_uint (guint in)
56 {
57   return in;
58 }
59
60 glong test_long (glong in)
61 {
62   return in;
63 }
64
65 gulong test_ulong (gulong in)
66 {
67   return in;
68 }
69
70 gssize test_ssize (gssize in)
71 {
72   return in;
73 }
74
75 gsize test_size (gsize in)
76 {
77   return in;
78 }
79
80 gfloat test_float (gfloat in)
81 {
82   return in;
83 }
84
85 gdouble test_double (gdouble in)
86 {
87   return in;
88 }
89
90
91 time_t test_timet (time_t in)
92 {
93   return in;
94 }
95
96 GType test_gtype (GType in)
97 {
98   return in;
99 }
100
101 int test_closure (GClosure *closure)
102 {
103   GValue return_value = {0, };
104   int ret;
105
106   g_value_init (&return_value, G_TYPE_INT);
107
108   g_closure_invoke (closure,
109                     &return_value,
110                     0, NULL,
111                     NULL);
112
113   ret = g_value_get_int (&return_value);
114
115   g_value_unset(&return_value);
116
117   return ret;
118 }
119
120 int test_closure_one_arg (GClosure *closure, int arg)
121 {
122   GValue return_value = {0, };
123   GValue arguments[1];
124   int ret;
125
126   g_value_init (&return_value, G_TYPE_INT);
127
128   memset (&arguments[0], 0, sizeof (arguments));
129   g_value_init (&arguments[0], G_TYPE_INT);
130   g_value_set_int (&arguments[0], arg);
131
132   g_closure_invoke (closure,
133                     &return_value,
134                     1, arguments,
135                     NULL);
136
137   ret = g_value_get_int (&return_value);
138
139   g_value_unset(&return_value);
140   g_value_unset(&arguments[0]);
141
142   return ret;
143 }
144
145 /**
146  * test_value_arg:
147  * @v: (transfer none): a GValue expected to contain an int
148  *
149  * Return value: the int contained in the GValue.
150  */
151 int test_int_value_arg(const GValue *v) {
152   int i;
153
154   i = g_value_get_int (v);
155
156   return i;
157 }
158
159 static GValue value;
160 /**
161  * test_value_return:
162  * @i: an int
163  *
164  * Return value: (transfer none): the int wrapped in a GValue.
165  */
166 const GValue *test_value_return(int i) {
167   memset(&value, '\0', sizeof(GValue));
168
169   g_value_init (&value, G_TYPE_INT);
170   g_value_set_int (&value, i);
171
172   return &value;
173 }
174
175
176 /************************************************************************/
177 /* utf8 */
178 /* insert BLACK HEART SUIT to ensure UTF-8 doesn't get mangled */
179 static const char utf8_const[]    = "const \xe2\x99\xa5 utf8";
180 static const char utf8_nonconst[] = "nonconst \xe2\x99\xa5 utf8";
181
182 /**
183  * test_utf8_const_return:
184  * Return value: <const char*> UTF-8 string
185  */
186 G_CONST_RETURN char *test_utf8_const_return (void)
187 {
188   /* transfer mode none */
189   return utf8_const;
190 }
191
192 /**
193  * test_utf8_nonconst_return:
194  * Return value: <char*> UTF-8 string
195  */
196 char *test_utf8_nonconst_return (void)
197 {
198   /* transfer mode full */
199   return g_strdup (utf8_nonconst);
200 }
201
202 void test_utf8_nonconst_in (char *in)
203 {
204   /* transfer mode full */
205   g_assert (strcmp (in, utf8_nonconst) == 0);
206   g_free(in);
207 }
208
209 void test_utf8_const_in (const char *in)
210 {
211   /* transfer mode none */
212   g_assert (strcmp (in, utf8_const) == 0);
213 }
214
215 /**
216  * test_utf8_out:
217  * @out: (out) (transfer full):
218  */
219 void test_utf8_out (char **out)
220 {
221   /* out parameter, transfer mode full */
222   *out = g_strdup (utf8_nonconst);
223 }
224
225 /**
226  * test_utf8_inout:
227  * @inout: (inout):
228  */
229 void test_utf8_inout (char **inout)
230 {
231   /* inout parameter, transfer mode full */
232   g_assert (strcmp (*inout, utf8_const) == 0);
233   g_free(*inout);
234   *inout = g_strdup (utf8_nonconst);
235 }
236
237 /**
238  * test_filename_return:
239  *
240  * Return value: (element-type filename) (transfer full): list of strings
241  */
242 GSList *test_filename_return (void)
243 {
244   GSList *filenames = NULL;
245   filenames = g_slist_prepend (filenames, g_filename_from_utf8("/etc/fstab", -1, NULL, NULL, NULL));
246   filenames = g_slist_prepend (filenames, g_filename_from_utf8("åäö", -1, NULL, NULL, NULL));
247   return filenames;
248 }
249
250 /* non-basic-types */
251
252 static const char *test_sequence[] = {"1", "2", "3"};
253
254 /* array */
255
256 /**
257  * test_array_int_in:
258  * @n_ints:
259  * @ints: (array length=n_ints): List of ints
260  */
261 int
262 test_array_int_in (int n_ints, int *ints)
263 {
264   int i, sum = 0;
265   for (i = 0; i < n_ints; i++)
266     sum += ints[i];
267   return sum;
268 }
269
270 /**
271  * test_array_gint8_in:
272  * @n_ints:
273  * @ints: (array length=n_ints): List of ints
274  */
275 int
276 test_array_gint8_in (int n_ints, gint8 *ints)
277 {
278   int i, sum = 0;
279   for (i = 0; i < n_ints; i++)
280     sum += ints[i];
281   return sum;
282 }
283
284 /**
285  * test_array_gint16_in:
286  * @n_ints:
287  * @ints: (array length=n_ints): List of ints
288  */
289 int
290 test_array_gint16_in (int n_ints, gint16 *ints)
291 {
292   int i, sum = 0;
293   for (i = 0; i < n_ints; i++)
294     sum += ints[i];
295   return sum;
296 }
297
298 /**
299  * test_array_gint32_in:
300  * @n_ints:
301  * @ints: (array length=n_ints): List of ints
302  */
303 gint32
304 test_array_gint32_in (int n_ints, gint32 *ints)
305 {
306   int i;
307   gint32 sum = 0;
308   for (i = 0; i < n_ints; i++)
309     sum += ints[i];
310   return sum;
311 }
312
313 /**
314  * test_array_gint64_in:
315  * @n_ints:
316  * @ints: (array length=n_ints): List of ints
317  */
318 gint64
319 test_array_gint64_in (int n_ints, gint64 *ints)
320 {
321   int i;
322   gint64 sum = 0;
323   for (i = 0; i < n_ints; i++)
324     sum += ints[i];
325   return sum;
326 }
327
328 /**
329  * test_strv_in:
330  * @arr: (array zero-terminated=1) (transfer none):
331  */
332 gboolean
333 test_strv_in (char **arr)
334 {
335   if (g_strv_length (arr) != 3)
336     return FALSE;
337   if (strcmp (arr[0], "1") != 0)
338     return FALSE;
339   if (strcmp (arr[1], "2") != 0)
340     return FALSE;
341   if (strcmp (arr[2], "3") != 0)
342     return FALSE;
343   return TRUE;
344 }
345
346 /**
347  * test_strv_in_container:
348  * @arr: (array zero-terminated=1) (transfer container):
349  */
350 gboolean
351 test_strv_in_container (char **arr)
352 {
353   gboolean result = test_strv_in (arr);
354   g_free (arr);
355   return result;
356 }
357
358 /**
359  * test_array_gtype_in:
360  * @n_types:
361  * @types: (array length=n_types): List of types
362  * Return value: string representation of provided types
363  * */
364 char *
365 test_array_gtype_in (int n_types, GType *types)
366 {
367   GString *string;
368   int i;
369
370   string = g_string_new ("[");
371   for (i = 0; i < n_types; i++)
372     {
373       g_string_append (string, g_type_name (types[i]));
374       g_string_append_c (string, ',');
375     }
376   g_string_append_c (string, ']');
377   return g_string_free (string, FALSE);
378 }
379
380 /**
381  * test_strv_out:
382  *
383  * No annotations here.  We want the default to Do The Right Thing.
384  */
385 char **
386 test_strv_out (void)
387 {
388   int i = 0;
389   int n = 6;
390   char **ret = g_new (char *, n);
391   ret[i++] = g_strdup ("thanks");
392   ret[i++] = g_strdup ("for");
393   ret[i++] = g_strdup ("all");
394   ret[i++] = g_strdup ("the");
395   ret[i++] = g_strdup ("fish");
396   ret[i++] = NULL;
397   g_assert (i == n);
398   return ret;
399 }
400
401 /**
402  * test_strv_out_container:
403  *
404  * Return value: (array zero-terminated=1) (transfer container):
405  */
406 char **
407 test_strv_out_container (void)
408 {
409   char **ret = g_new (char *, 4);
410   ret[0] = "1";
411   ret[1] = "2";
412   ret[2] = "3";
413   ret[3] = NULL;
414   return ret;
415 }
416
417 /**
418  * test_strv_outarg:
419  * @retp: (array zero-terminated=1) (out) (transfer container):
420  */
421 void
422 test_strv_outarg (char ***retp)
423 {
424   char **ret = g_new (char *, 4);
425   ret[0] = "1";
426   ret[1] = "2";
427   ret[2] = "3";
428   ret[3] = NULL;
429   *retp = ret;
430 }
431
432 /**
433  * test_array_int_in_take:
434  * @n_ints:
435  * @ints: (array length=n_ints) (transfer full): List of ints
436  */
437 int test_array_int_in_take (int n_ints, int *ints)
438 {
439   int i, sum = 0;
440   for (i = 0; i < n_ints; i++)
441     sum += ints[i];
442   g_free (ints);
443   return sum;
444 }
445
446 /**
447  * test_strv_out_c:
448  *
449  * No annotations here.  We want the default to Do The Right Thing.
450  */
451 const char * const*
452 test_strv_out_c (void)
453 {
454   static char **ret = NULL;
455
456   if (ret == NULL)
457     ret = test_strv_out ();
458
459   return (const char * const *) ret;
460 }
461
462 /**
463  * test_array_int_full_out:
464  * @len: length of the returned array.
465  * Returns: (array length=len) (transfer full): a new array of integers.
466  */
467 int *
468 test_array_int_full_out(int *len) {
469   int *result, i;
470   *len = 5;
471   result = g_malloc0(sizeof(*result) * (*len));
472   for (i=1; i < (*len); i++)
473     result[i] = result[i-1] + 1;
474   return result;
475 }
476
477 /**
478  * test_array_int_none_out:
479  * @len: length of the returned array.
480  * Returns: (array length=len) (transfer none): a static array of integers.
481  */
482 int *
483 test_array_int_none_out(int *len) {
484   static int result[5] = { 1, 2, 3, 4, 5 };
485   *len = 5;
486   return result;
487 }
488
489 /* interface */
490
491 /************************************************************************/
492 /* GList */
493
494 static /*const*/ GList *test_sequence_list()
495 {
496     static GList *list = NULL;
497     if (!list) {
498         gsize i;
499         for (i = 0; i < G_N_ELEMENTS(test_sequence); ++i) {
500             list = g_list_prepend (list, (gpointer)test_sequence[i]);
501         }
502         list = g_list_reverse (list);
503     }
504     return list;
505 }
506
507 /**
508  * test_glist_free:
509  * @in: (element-type utf8) (transfer full):
510  */
511 void test_glist_free (GList *in)
512 {
513   g_list_foreach (in, (GFunc)g_free, NULL);
514   g_list_free (in);
515 }
516
517 /**
518  * test_glist_nothing_return:
519  *
520  * Return value: (element-type utf8) (transfer none):
521  */
522 G_CONST_RETURN GList *test_glist_nothing_return (void)
523 {
524   return test_sequence_list ();
525 }
526
527 /**
528  * test_glist_nothing_return2:
529  *
530  * Return value: (element-type utf8) (transfer none):
531  */
532 GList *test_glist_nothing_return2 (void)
533 {
534   return test_sequence_list ();
535 }
536
537 /**
538  * test_glist_container_return:
539  *
540  * Return value: (element-type utf8) (transfer container):
541  */
542 GList *test_glist_container_return (void)
543 {
544   return g_list_copy (test_sequence_list ());
545 }
546
547 /**
548  * test_glist_everything_return:
549  *
550  * Return value: (element-type utf8) (transfer full):
551  */
552 GList *test_glist_everything_return (void)
553 {
554   GList *list;
555   GList *l;
556
557   list = g_list_copy (test_sequence_list ());
558   for (l = list; l != NULL; l = l->next)
559       l->data = g_strdup (l->data);
560   return list;
561 }
562
563 static void assert_test_sequence_list (const GList *in)
564 {
565   const GList *l;
566   gsize i;
567
568   for (i = 0, l = in; l != NULL; ++i, l = l->next) {
569       g_assert (i < G_N_ELEMENTS(test_sequence));
570       g_assert (strcmp (l->data, test_sequence[i]) == 0);
571   }
572   g_assert (i == G_N_ELEMENTS(test_sequence));
573 }
574
575 /**
576  * test_glist_nothing_in:
577  * @in: (element-type utf8):
578  */
579 void test_glist_nothing_in (const GList *in)
580 {
581   assert_test_sequence_list (in);
582 }
583
584 /**
585  * test_glist_nothing_in2:
586  * @in: (element-type utf8):
587  */
588 void test_glist_nothing_in2 (GList *in)
589 {
590   assert_test_sequence_list (in);
591 }
592
593 /**
594  * test_glist_container_in:
595  * @in: (element-type utf8) (transfer container):
596  */
597 void test_glist_container_in (GList *in)
598 {
599   assert_test_sequence_list (in);
600   g_list_free (in);
601 }
602
603 /**
604  * test_glist_everything_in:
605  * @in: (element-type utf8) (transfer full):
606  */
607 void test_glist_everything_in (GList *in)
608 {
609   assert_test_sequence_list (in);
610   test_glist_free (in);
611 }
612
613 /************************************************************************/
614 /* GSList */
615
616 static /*const*/ GSList *test_sequence_slist()
617 {
618     static GSList *list = NULL;
619     if (!list) {
620         gsize i;
621         for (i = 0; i < G_N_ELEMENTS(test_sequence); ++i) {
622             list = g_slist_prepend (list, (gpointer)test_sequence[i]);
623         }
624         list = g_slist_reverse (list);
625     }
626     return list;
627 }
628
629 /**
630  * test_gslist_free:
631  * @in: (element-type utf8) (transfer full):
632  */
633 void test_gslist_free (GSList *in)
634 {
635   g_slist_foreach (in, (GFunc)g_free, NULL);
636   g_slist_free (in);
637 }
638
639 /**
640  * test_gslist_nothing_return:
641  *
642  * Return value: (element-type utf8) (transfer none):
643  */
644 G_CONST_RETURN GSList *test_gslist_nothing_return (void)
645 {
646   return test_sequence_slist ();
647 }
648
649 /**
650  * test_gslist_nothing_return2:
651  *
652  * Return value: (element-type utf8) (transfer none):
653  */
654 GSList *test_gslist_nothing_return2 (void)
655 {
656   return test_sequence_slist ();
657 }
658
659 /**
660  * test_gslist_container_return:
661  *
662  * Return value: (element-type utf8) (transfer container):
663  */
664 GSList *test_gslist_container_return (void)
665 {
666   return g_slist_copy (test_sequence_slist ());
667 }
668
669 /**
670  * test_gslist_everything_return:
671  *
672  * Return value: (element-type utf8) (transfer full):
673  */
674 GSList *test_gslist_everything_return (void)
675 {
676   GSList *list;
677   GSList *l;
678
679   list = g_slist_copy (test_sequence_slist ());
680   for (l = list; l != NULL; l = l->next)
681       l->data = g_strdup (l->data);
682   return list;
683 }
684
685 static void assert_test_sequence_slist (const GSList *in)
686 {
687   const GSList *l;
688   gsize i;
689
690   for (i = 0, l = in; l != NULL; ++i, l = l->next) {
691       g_assert (i < G_N_ELEMENTS(test_sequence));
692       g_assert (strcmp (l->data, test_sequence[i]) == 0);
693   }
694   g_assert (i == G_N_ELEMENTS(test_sequence));
695 }
696
697 /**
698  * test_gslist_nothing_in:
699  * @in: (element-type utf8):
700  */
701 void test_gslist_nothing_in (const GSList *in)
702 {
703   assert_test_sequence_slist (in);
704 }
705
706 /**
707  * test_gslist_nothing_in2:
708  * @in: (element-type utf8):
709  */
710 void test_gslist_nothing_in2 (GSList *in)
711 {
712   assert_test_sequence_slist (in);
713 }
714
715 /**
716  * test_gslist_container_in:
717  * @in: (element-type utf8) (transfer container):
718  */
719 void test_gslist_container_in (GSList *in)
720 {
721   assert_test_sequence_slist (in);
722   g_slist_free (in);
723 }
724
725 /**
726  * test_gslist_everything_in:
727  * @in: (element-type utf8) (transfer full):
728  */
729 void test_gslist_everything_in (GSList *in)
730 {
731   assert_test_sequence_slist (in);
732   test_gslist_free (in);
733 }
734
735 /************************************************************************/
736 /* GHash */
737
738 static char *table_data[3][2] = {
739   { "foo", "bar" }, { "baz", "bat" }, { "qux", "quux" }
740 };
741
742 static GHashTable *test_table_ghash_new_container()
743 {
744   GHashTable *hash;
745   int i;
746   hash = g_hash_table_new(g_str_hash, g_str_equal);
747   for (i=0; i<3; i++)
748     g_hash_table_insert(hash, table_data[i][0], table_data[i][1]);
749   return hash;
750 }
751
752 static GHashTable *test_table_ghash_new_full()
753 {
754   GHashTable *hash;
755   int i;
756   hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
757   for (i=0; i<3; i++)
758     g_hash_table_insert(hash,
759                         g_strdup(table_data[i][0]),
760                         g_strdup(table_data[i][1]));
761   return hash;
762 }
763
764 static /*const*/ GHashTable *test_table_ghash_const()
765 {
766   static GHashTable *hash = NULL;
767   if (!hash) {
768     hash = test_table_ghash_new_container();
769   }
770   return hash;
771 }
772
773 /**
774  * test_ghash_free:
775  * @in: (transfer full) (element-type utf8 utf8)
776  */
777 void test_ghash_free (GHashTable *in)
778 {
779   /* keys and values are deleted iff an appropriate element destroy function
780    * was registered */
781   g_hash_table_unref(in);
782 }
783
784 /**
785  * test_ghash_null_return:
786  *
787  * Return value: (element-type utf8 utf8) (transfer none) (allow-none):
788  */
789 G_CONST_RETURN GHashTable *test_ghash_null_return (void)
790 {
791   return NULL;
792 }
793
794 /**
795  * test_ghash_nothing_return:
796  *
797  * Return value: (element-type utf8 utf8) (transfer none):
798  */
799 G_CONST_RETURN GHashTable *test_ghash_nothing_return (void)
800 {
801   return test_table_ghash_const ();
802 }
803
804 /**
805  * test_ghash_nothing_return2:
806  *
807  * Return value: (element-type utf8 utf8) (transfer none):
808  */
809 GHashTable *test_ghash_nothing_return2 (void)
810 {
811   return test_table_ghash_const ();
812 }
813
814 /**
815  * test_ghash_container_return:
816  *
817  * Return value: (element-type utf8 utf8) (transfer container):
818  */
819 GHashTable *test_ghash_container_return (void)
820 {
821   return test_table_ghash_new_container ();
822 }
823
824 /**
825  * test_ghash_everything_return:
826  *
827  * Return value: (element-type utf8 utf8) (transfer full):
828  */
829 GHashTable *test_ghash_everything_return (void)
830 {
831   return test_table_ghash_new_full ();
832 }
833
834 static void assert_test_table_ghash (const GHashTable *in)
835 {
836   GHashTable *h = test_table_ghash_const();
837   GHashTableIter iter;
838   gpointer key, value;
839
840   g_assert(g_hash_table_size(h) ==
841            g_hash_table_size((GHashTable*)in));
842
843   g_hash_table_iter_init(&iter, (GHashTable*)in);
844   while (g_hash_table_iter_next (&iter, &key, &value))
845     g_assert( strcmp(g_hash_table_lookup(h, (char*)key), (char*)value) == 0);
846 }
847
848 /**
849  * test_ghash_null_in:
850  * @in: (element-type utf8 utf8) (allow-none):
851  */
852 void test_ghash_null_in (const GHashTable *in)
853 {
854   g_assert (in == NULL);
855 }
856
857 /**
858  * test_ghash_nothing_in:
859  * @in: (element-type utf8 utf8):
860  */
861 void test_ghash_nothing_in (const GHashTable *in)
862 {
863   assert_test_table_ghash (in);
864 }
865
866 /**
867  * test_ghash_nothing_in2:
868  * @in: (element-type utf8 utf8):
869  */
870 void test_ghash_nothing_in2 (GHashTable *in)
871 {
872   assert_test_table_ghash (in);
873 }
874
875 /**
876  * test_ghash_container_in:
877  * @in: (transfer container) (element-type utf8 utf8):
878  */
879 void test_ghash_container_in (GHashTable *in)
880 {
881   assert_test_table_ghash (in);
882   /* be careful and explicitly steal all the elements from the ghash before
883    * freeing it. */
884   g_hash_table_steal_all (in);
885   g_hash_table_destroy (in);
886 }
887
888 static gboolean ghash_freer(gpointer key, gpointer value, gpointer user_data) {
889   g_free(key);
890   g_free(value);
891   return TRUE;
892 }
893
894 /**
895  * test_ghash_everything_in:
896  * @in: (transfer full) (element-type utf8 utf8):
897  */
898 void test_ghash_everything_in (GHashTable *in)
899 {
900   assert_test_table_ghash (in);
901   /* free the elements, then free the container.  Don't rely on the
902    * GHashTable's key/value destructor functions. */
903   g_hash_table_foreach_steal (in, ghash_freer, NULL);
904   /* okay, dealloc the hash table. */
905   g_hash_table_destroy (in);
906 }
907
908 /************************************************************************/
909
910 /* error? */
911
912 /* enums / flags */
913
914 GType
915 test_enum_get_type (void)
916 {
917     static GType etype = 0;
918     if (G_UNLIKELY(etype == 0)) {
919         static const GEnumValue values[] = {
920             { TEST_VALUE1, "TEST_VALUE1", "value1" },
921             { TEST_VALUE2, "TEST_VALUE2", "value2" },
922             { TEST_VALUE3, "TEST_VALUE3", "value3" },
923             { 0, NULL, NULL }
924         };
925         etype = g_enum_register_static (g_intern_static_string ("TestEnum"), values);
926     }
927
928     return etype;
929 }
930
931 GType
932 test_flags_get_type (void)
933 {
934     static GType etype = 0;
935     if (G_UNLIKELY(etype == 0)) {
936         static const GFlagsValue values[] = {
937             { TEST_FLAG1, "TEST_FLAG1", "flag1" },
938             { TEST_FLAG2, "TEST_FLAG2", "flag2" },
939             { TEST_FLAG3, "TEST_FLAG3", "flag2" },
940             { 0, NULL, NULL }
941         };
942         etype = g_flags_register_static (g_intern_static_string ("TestFlags"), values);
943     }
944
945     return etype;
946 }
947
948 const gchar *
949 test_enum_param(TestEnum e)
950 {
951   GEnumValue *ev;
952   GEnumClass *ec;
953
954   ec = g_type_class_ref (test_enum_get_type ());
955   ev = g_enum_get_value (ec, e);
956   g_type_class_unref (ec);
957
958   return ev->value_nick;
959 }
960
961 /* structures */
962
963 /**
964  * test_struct_a_clone:
965  * @a: the structure
966  * @a_out: the cloned structure
967  *
968  * Make a copy of a TestStructA
969  */
970 void
971 test_struct_a_clone (TestStructA *a,
972                      TestStructA *a_out)
973 {
974   *a_out = *a;
975 }
976
977 /**
978  * test_struct_b_clone:
979  * @b: the structure
980  * @b_out: the cloned structure
981  *
982  * Make a copy of a TestStructB
983  */
984 void
985 test_struct_b_clone (TestStructB *b,
986                      TestStructB *b_out)
987 {
988   *b_out = *b;
989 }
990
991 /* plain-old-data boxed types */
992
993 TestSimpleBoxedA *
994 test_simple_boxed_a_copy (TestSimpleBoxedA *a)
995 {
996   TestSimpleBoxedA *new_a = g_slice_new (TestSimpleBoxedA);
997
998   *new_a = *a;
999
1000   return new_a;
1001 }
1002
1003 static void
1004 test_simple_boxed_a_free (TestSimpleBoxedA *a)
1005 {
1006   g_slice_free (TestSimpleBoxedA, a);
1007 }
1008
1009 GType
1010 test_simple_boxed_a_get_type (void)
1011 {
1012   static GType our_type = 0;
1013
1014   if (our_type == 0)
1015     our_type = g_boxed_type_register_static (g_intern_static_string ("TestSimpleBoxedA"),
1016                                              (GBoxedCopyFunc)test_simple_boxed_a_copy,
1017                                              (GBoxedFreeFunc)test_simple_boxed_a_free);
1018   return our_type;
1019 }
1020
1021 TestSimpleBoxedB *
1022 test_simple_boxed_b_copy (TestSimpleBoxedB *b)
1023 {
1024   TestSimpleBoxedB *new_b = g_slice_new (TestSimpleBoxedB);
1025
1026   *new_b = *b;
1027
1028   return new_b;
1029 }
1030
1031 gboolean
1032 test_simple_boxed_a_equals (TestSimpleBoxedA *a,
1033                             TestSimpleBoxedA *other_a)
1034 {
1035   return (a->some_int == other_a->some_int &&
1036           a->some_int8 == other_a->some_int8 &&
1037           a->some_double == other_a->some_double);
1038 }
1039
1040 const TestSimpleBoxedA*
1041 test_simple_boxed_a_const_return (void)
1042 {
1043   static TestSimpleBoxedA simple_a = {
1044     5, 6, 7.0
1045   };
1046
1047   return &simple_a;
1048 }
1049
1050 static void
1051 test_simple_boxed_b_free (TestSimpleBoxedB *a)
1052 {
1053   g_slice_free (TestSimpleBoxedB, a);
1054 }
1055
1056 GType
1057 test_simple_boxed_b_get_type (void)
1058 {
1059   static GType our_type = 0;
1060
1061   if (our_type == 0)
1062     our_type = g_boxed_type_register_static (g_intern_static_string ("TestSimpleBoxedB"),
1063                                              (GBoxedCopyFunc)test_simple_boxed_b_copy,
1064                                              (GBoxedFreeFunc)test_simple_boxed_b_free);
1065   return our_type;
1066 }
1067
1068 /* opaque boxed */
1069
1070 struct _TestBoxedPrivate
1071 {
1072   guint magic;
1073 };
1074
1075 TestBoxed *
1076 test_boxed_new (void)
1077 {
1078   TestBoxed *boxed = g_slice_new0(TestBoxed);
1079   boxed->priv = g_slice_new0(TestBoxedPrivate);
1080   boxed->priv->magic = 0xdeadbeef;
1081
1082   return boxed;
1083 }
1084
1085 TestBoxed *
1086 test_boxed_copy (TestBoxed *boxed)
1087 {
1088   TestBoxed *new_boxed = test_boxed_new();
1089   TestBoxedPrivate *save;
1090
1091   save = new_boxed->priv;
1092   *new_boxed = *boxed;
1093   new_boxed->priv = save;
1094
1095   return new_boxed;
1096 }
1097
1098 gboolean
1099 test_boxed_equals (TestBoxed *boxed,
1100                    TestBoxed *other)
1101 {
1102   return (other->some_int8 == boxed->some_int8 &&
1103           test_simple_boxed_a_equals(&other->nested_a, &boxed->nested_a));
1104 }
1105
1106 static void
1107 test_boxed_free (TestBoxed *boxed)
1108 {
1109   g_assert (boxed->priv->magic == 0xdeadbeef);
1110
1111   g_slice_free (TestBoxedPrivate, boxed->priv);
1112   g_slice_free (TestBoxed, boxed);
1113 }
1114
1115 GType
1116 test_boxed_get_type (void)
1117 {
1118   static GType our_type = 0;
1119
1120   if (our_type == 0)
1121     our_type = g_boxed_type_register_static (g_intern_static_string ("TestBoxed"),
1122                                              (GBoxedCopyFunc)test_boxed_copy,
1123                                              (GBoxedFreeFunc)test_boxed_free);
1124   return our_type;
1125 }
1126
1127 G_DEFINE_TYPE(TestObj, test_obj, G_TYPE_OBJECT);
1128
1129 enum
1130 {
1131   PROP_TEST_OBJ_BARE = 1
1132 };
1133
1134 static void
1135 test_obj_set_property (GObject      *object,
1136                        guint         property_id,
1137                        const GValue *value,
1138                        GParamSpec   *pspec)
1139 {
1140   TestObj *self = TEST_OBJECT (object);
1141
1142   switch (property_id)
1143     {
1144     case PROP_TEST_OBJ_BARE:
1145       test_obj_set_bare (self, g_value_get_object (value));
1146       break;
1147
1148     default:
1149       /* We don't have any other property... */
1150       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1151       break;
1152     }
1153 }
1154
1155 static void
1156 test_obj_get_property (GObject    *object,
1157                         guint       property_id,
1158                         GValue     *value,
1159                         GParamSpec *pspec)
1160 {
1161   TestObj *self = TEST_OBJECT (object);
1162
1163   switch (property_id)
1164     {
1165     case PROP_TEST_OBJ_BARE:
1166       g_value_set_object (value, self->bare);
1167       break;
1168
1169     default:
1170       /* We don't have any other property... */
1171       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1172       break;
1173     }
1174 }
1175
1176 static void
1177 test_obj_dispose (GObject *gobject)
1178 {
1179   TestObj *self = TEST_OBJECT (gobject);
1180
1181   if (self->bare)
1182     {
1183       g_object_unref (self->bare);
1184
1185       self->bare = NULL;
1186     }
1187
1188   /* Chain up to the parent class */
1189   G_OBJECT_CLASS (test_obj_parent_class)->dispose (gobject);
1190 }
1191
1192 static int
1193 test_obj_default_matrix (TestObj *obj, const char *somestr)
1194 {
1195   return 42;
1196 }
1197
1198 static void
1199 test_obj_class_init (TestObjClass *klass)
1200 {
1201   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1202   GParamSpec *pspec;
1203   GType param_types[1];
1204
1205   klass->test_signal =
1206     g_signal_newv ("test",
1207                    G_TYPE_FROM_CLASS (gobject_class),
1208                    G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
1209                    NULL /* closure */,
1210                    NULL /* accumulator */,
1211                    NULL /* accumulator data */,
1212                    g_cclosure_marshal_VOID__VOID,
1213                    G_TYPE_NONE /* return_type */,
1214                    0     /* n_params */,
1215                    NULL  /* param_types */);
1216
1217   param_types[0] = test_simple_boxed_a_get_type() | G_SIGNAL_TYPE_STATIC_SCOPE;
1218   klass->test_signal_with_static_scope_arg =
1219     g_signal_newv ("test-with-static-scope-arg",
1220                    G_TYPE_FROM_CLASS (gobject_class),
1221                    G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
1222                    NULL /* closure */,
1223                    NULL /* accumulator */,
1224                    NULL /* accumulator data */,
1225                    g_cclosure_marshal_VOID__BOXED,
1226                    G_TYPE_NONE /* return_type */,
1227                    1     /* n_params */,
1228                    param_types);
1229
1230   gobject_class->set_property = test_obj_set_property;
1231   gobject_class->get_property = test_obj_get_property;
1232   gobject_class->dispose = test_obj_dispose;
1233
1234   pspec = g_param_spec_object ("bare",
1235                                "Bare property",
1236                                "A contained object",
1237                                G_TYPE_OBJECT,
1238                                G_PARAM_READWRITE);
1239   g_object_class_install_property (gobject_class,
1240                                    PROP_TEST_OBJ_BARE,
1241                                    pspec);
1242
1243   klass->matrix = test_obj_default_matrix;
1244 }
1245
1246 static void
1247 test_obj_init (TestObj *obj)
1248 {
1249   obj->bare = NULL;
1250 }
1251
1252 TestObj *
1253 test_obj_new_from_file (const char *x, GError **error)
1254 {
1255   return g_object_new (TEST_TYPE_OBJ, NULL);
1256 }
1257
1258 /**
1259  * test_obj_set_bare:
1260  * @bare: (allow-none):
1261  */
1262 void
1263 test_obj_set_bare (TestObj *obj, GObject *bare)
1264 {
1265   if (obj->bare)
1266     g_object_unref (obj->bare);
1267   obj->bare = bare;
1268   if (obj->bare)
1269     g_object_ref (obj->bare);
1270 }
1271
1272 double
1273 test_obj_static_method (int x)
1274 {
1275   return x;
1276 }
1277
1278 /**
1279  * test_obj_do_matrix:
1280  * @obj: A #TestObj
1281  * @somestr: Meaningless string
1282  *
1283  * This method is virtual.  Notably its name differs from the virtual
1284  * slot name, which makes it useful for testing bindings handle this
1285  * case.
1286  *
1287  * Virtual: matrix
1288  */
1289 int
1290 test_obj_do_matrix (TestObj *obj, const char *somestr)
1291 {
1292   return TEST_OBJ_GET_CLASS (obj)->matrix (obj, somestr);
1293 }
1294
1295 typedef struct _CallbackInfo CallbackInfo;
1296
1297 struct _CallbackInfo
1298 {
1299   TestCallbackUserData callback;
1300   GDestroyNotify notify;
1301   gpointer user_data;
1302 };
1303
1304
1305 /**
1306  * test_callback:
1307  * @callback: (scope call):
1308  *
1309  **/
1310 int
1311 test_callback (TestCallback callback)
1312 {
1313   return callback();
1314 }
1315
1316 /**
1317  * test_callback_user_data:
1318  * @callback: (scope call):
1319  *
1320  * Call - callback parameter persists for the duration of the method
1321  * call and can be released on return.
1322  **/
1323 int
1324 test_callback_user_data (TestCallbackUserData callback,
1325                          gpointer user_data)
1326 {
1327   return callback(user_data);
1328 }
1329
1330 static GSList *notified_callbacks = NULL;
1331
1332 /**
1333  * test_callback_destroy_notify:
1334  * @callback: (scope notified):
1335  *
1336  * Notified - callback persists until a DestroyNotify delegate
1337  * is invoked.
1338  **/
1339 int
1340 test_callback_destroy_notify (TestCallbackUserData callback,
1341                               gpointer user_data,
1342                               GDestroyNotify notify)
1343 {
1344   int retval;
1345   CallbackInfo *info;
1346
1347   retval = callback(user_data);
1348
1349   info = g_new(CallbackInfo, 1);
1350   info->callback = callback;
1351   info->notify = notify;
1352   info->user_data = user_data;
1353
1354   notified_callbacks = g_slist_prepend(notified_callbacks, info);
1355
1356   return retval;
1357 }
1358
1359 /**
1360  * test_callback_thaw_notifications:
1361  *
1362  * Invokes all callbacks installed by #test_callback_destroy_notify(),
1363  * adding up their return values, and removes them, invoking the
1364  * corresponding destroy notfications.
1365  *
1366  * Return value: Sum of the return values of the invoked callbacks.
1367  */
1368 int
1369 test_callback_thaw_notifications (void)
1370 {
1371   int retval = 0;
1372   GSList *node;
1373
1374   for (node = notified_callbacks; node != NULL; node = node->next)
1375     {
1376       CallbackInfo *info = (CallbackInfo *)node->data;
1377       retval += info->callback (info->user_data);
1378       if (info->notify)
1379         info->notify (info->user_data);
1380       g_free (info);
1381     }
1382
1383   g_slist_free (notified_callbacks);
1384   notified_callbacks = NULL;
1385
1386   return retval;
1387 }
1388
1389 /**
1390  * test_callback_infinte:
1391  * @callback: (scope infinte):
1392  *
1393  * Infinite - callback persists forever.
1394  **/
1395
1396 static GSList *infinite_callbacks = NULL;
1397
1398 int
1399 test_callback_infinte (TestCallbackUserData callback,
1400                        gpointer user_data)
1401 {
1402   infinite_callbacks = g_slist_prepend(infinite_callbacks, callback);
1403
1404   return callback(user_data);
1405 }
1406
1407 /* interface */
1408
1409 static void
1410 test_interface_class_init(void *g_iface)
1411 {
1412 }
1413
1414 GType
1415 test_interface_get_type(void)
1416 {
1417     static GType type = 0;
1418     if (type == 0) {
1419         type = g_type_register_static_simple (G_TYPE_INTERFACE,
1420                                               "EverythingTestInterface",
1421                                               sizeof (TestInterfaceIface),
1422                                               (GClassInitFunc) test_interface_class_init,
1423                                               0, NULL, 0);
1424     }
1425
1426     return type;
1427 }
1428
1429 /* gobject with non-standard prefix */
1430 G_DEFINE_TYPE(TestWi8021x, test_wi_802_1x, G_TYPE_OBJECT);
1431
1432 enum
1433 {
1434   PROP_TEST_WI_802_1X_TESTBOOL = 1
1435 };
1436
1437 static void
1438 test_wi_802_1x_set_property (GObject      *object,
1439                              guint         property_id,
1440                              const GValue *value,
1441                              GParamSpec   *pspec)
1442 {
1443   TestWi8021x *self = TEST_WI_802_1X (object);
1444
1445   switch (property_id)
1446     {
1447     case PROP_TEST_WI_802_1X_TESTBOOL:
1448       test_wi_802_1x_set_testbool (self, g_value_get_boolean (value));
1449       break;
1450
1451     default:
1452       /* We don't have any other property... */
1453       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1454       break;
1455     }
1456 }
1457
1458 static void
1459 test_wi_802_1x_get_property (GObject    *object,
1460                         guint       property_id,
1461                         GValue     *value,
1462                         GParamSpec *pspec)
1463 {
1464   TestWi8021x *self = TEST_WI_802_1X (object);
1465
1466   switch (property_id)
1467     {
1468     case PROP_TEST_WI_802_1X_TESTBOOL:
1469       g_value_set_boolean (value, test_wi_802_1x_get_testbool (self));
1470       break;
1471
1472     default:
1473       /* We don't have any other property... */
1474       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1475       break;
1476     }
1477 }
1478
1479 static void
1480 test_wi_802_1x_dispose (GObject *gobject)
1481 {
1482   /* Chain up to the parent class */
1483   G_OBJECT_CLASS (test_wi_802_1x_parent_class)->dispose (gobject);
1484 }
1485
1486 static void
1487 test_wi_802_1x_class_init (TestWi8021xClass *klass)
1488 {
1489   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1490   GParamSpec *pspec;
1491
1492   gobject_class->set_property = test_wi_802_1x_set_property;
1493   gobject_class->get_property = test_wi_802_1x_get_property;
1494   gobject_class->dispose = test_wi_802_1x_dispose;
1495
1496   pspec = g_param_spec_boolean ("testbool",
1497                                 "Nick for testbool",
1498                                 "Blurb for testbool",
1499                                 TRUE,
1500                                 G_PARAM_READWRITE);
1501   g_object_class_install_property (gobject_class,
1502                                    PROP_TEST_WI_802_1X_TESTBOOL,
1503                                    pspec);
1504 }
1505
1506 static void
1507 test_wi_802_1x_init (TestWi8021x *obj)
1508 {
1509   obj->testbool = TRUE;
1510 }
1511
1512 TestWi8021x *
1513 test_wi_802_1x_new (void)
1514 {
1515   return g_object_new (TEST_TYPE_WI_802_1X, NULL);
1516 }
1517
1518 void
1519 test_wi_802_1x_set_testbool (TestWi8021x *obj, gboolean val)
1520 {
1521   obj->testbool = val;
1522 }
1523
1524 gboolean
1525 test_wi_802_1x_get_testbool (TestWi8021x *obj)
1526 {
1527   return obj->testbool;
1528 }
1529
1530 int
1531 test_wi_802_1x_static_method (int x)
1532 {
1533   return 2*x;
1534 }