PageRenderTime 24ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/gobject/testgobject.c

https://github.com/ieei/glib
C | 427 lines | 330 code | 64 blank | 33 comment | 28 complexity | 06dceb71d2e740eb98655a5b8f94d84e MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-3.0
  1. /* GObject - GLib Type, Object, Parameter and Signal Library
  2. * Copyright (C) 2001 Red Hat, Inc.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General
  15. * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <string.h>
  18. #undef G_LOG_DOMAIN
  19. #define G_LOG_DOMAIN "TestObject"
  20. #include <glib-object.h>
  21. /* --- TestIface --- */
  22. #define TEST_TYPE_IFACE (test_iface_get_type ())
  23. #define TEST_IFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_IFACE, TestIface))
  24. #define TEST_IS_IFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_IFACE))
  25. #define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE, TestIfaceClass))
  26. typedef struct _TestIface TestIface;
  27. typedef struct _TestIfaceClass TestIfaceClass;
  28. struct _TestIfaceClass
  29. {
  30. GTypeInterface base_iface;
  31. void (*print_string) (TestIface *tiobj,
  32. const gchar *string);
  33. };
  34. static void iface_base_init (TestIfaceClass *iface);
  35. static void iface_base_finalize (TestIfaceClass *iface);
  36. static void print_foo (TestIface *tiobj,
  37. const gchar *string);
  38. static GType
  39. test_iface_get_type (void)
  40. {
  41. static GType test_iface_type = 0;
  42. if (!test_iface_type)
  43. {
  44. const GTypeInfo test_iface_info =
  45. {
  46. sizeof (TestIfaceClass),
  47. (GBaseInitFunc) iface_base_init, /* base_init */
  48. (GBaseFinalizeFunc) iface_base_finalize, /* base_finalize */
  49. };
  50. test_iface_type = g_type_register_static (G_TYPE_INTERFACE, "TestIface", &test_iface_info, 0);
  51. g_type_interface_add_prerequisite (test_iface_type, G_TYPE_OBJECT);
  52. }
  53. return test_iface_type;
  54. }
  55. static guint iface_base_init_count = 0;
  56. static void
  57. iface_base_init (TestIfaceClass *iface)
  58. {
  59. iface_base_init_count++;
  60. if (iface_base_init_count == 1)
  61. {
  62. /* add signals here */
  63. }
  64. }
  65. static void
  66. iface_base_finalize (TestIfaceClass *iface)
  67. {
  68. iface_base_init_count--;
  69. if (iface_base_init_count == 0)
  70. {
  71. /* destroy signals here */
  72. }
  73. }
  74. static void
  75. print_foo (TestIface *tiobj,
  76. const gchar *string)
  77. {
  78. if (!string)
  79. string = "<NULL>";
  80. g_print ("Iface-FOO: \"%s\" from %p\n", string, tiobj);
  81. }
  82. static void
  83. test_object_test_iface_init (gpointer giface,
  84. gpointer iface_data)
  85. {
  86. TestIfaceClass *iface = giface;
  87. g_assert (iface_data == GUINT_TO_POINTER (42));
  88. g_assert (G_TYPE_FROM_INTERFACE (iface) == TEST_TYPE_IFACE);
  89. /* assert iface_base_init() was already called */
  90. g_assert (iface_base_init_count > 0);
  91. /* initialize stuff */
  92. iface->print_string = print_foo;
  93. }
  94. static void
  95. iface_print_string (TestIface *tiobj,
  96. const gchar *string)
  97. {
  98. TestIfaceClass *iface;
  99. g_return_if_fail (TEST_IS_IFACE (tiobj));
  100. g_return_if_fail (G_IS_OBJECT (tiobj)); /* ensured through prerequisite */
  101. iface = TEST_IFACE_GET_CLASS (tiobj);
  102. g_object_ref (tiobj);
  103. iface->print_string (tiobj, string);
  104. g_object_unref (tiobj);
  105. }
  106. /* --- TestObject --- */
  107. #define TEST_TYPE_OBJECT (test_object_get_type ())
  108. #define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJECT, TestObject))
  109. #define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass))
  110. #define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJECT))
  111. #define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT))
  112. #define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass))
  113. #define TEST_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TEST_TYPE_OBJECT, TestObjectPrivate))
  114. typedef struct _TestObject TestObject;
  115. typedef struct _TestObjectClass TestObjectClass;
  116. typedef struct _TestObjectPrivate TestObjectPrivate;
  117. struct _TestObject
  118. {
  119. GObject parent_instance;
  120. };
  121. struct _TestObjectClass
  122. {
  123. GObjectClass parent_class;
  124. gchar* (*test_signal) (TestObject *tobject,
  125. TestIface *iface_object,
  126. gpointer tdata);
  127. };
  128. struct _TestObjectPrivate
  129. {
  130. int dummy1;
  131. gdouble dummy2;
  132. };
  133. static void test_object_class_init (TestObjectClass *class);
  134. static void test_object_init (TestObject *tobject);
  135. static gboolean test_signal_accumulator (GSignalInvocationHint *ihint,
  136. GValue *return_accu,
  137. const GValue *handler_return,
  138. gpointer data);
  139. static gchar* test_object_test_signal (TestObject *tobject,
  140. TestIface *iface_object,
  141. gpointer tdata);
  142. static GType
  143. test_object_get_type (void)
  144. {
  145. static GType test_object_type = 0;
  146. if (!test_object_type)
  147. {
  148. const GTypeInfo test_object_info =
  149. {
  150. sizeof (TestObjectClass),
  151. NULL, /* base_init */
  152. NULL, /* base_finalize */
  153. (GClassInitFunc) test_object_class_init,
  154. NULL, /* class_finalize */
  155. NULL, /* class_data */
  156. sizeof (TestObject),
  157. 5, /* n_preallocs */
  158. (GInstanceInitFunc) test_object_init,
  159. };
  160. GInterfaceInfo iface_info = { test_object_test_iface_init, NULL, GUINT_TO_POINTER (42) };
  161. test_object_type = g_type_register_static (G_TYPE_OBJECT, "TestObject", &test_object_info, 0);
  162. g_type_add_interface_static (test_object_type, TEST_TYPE_IFACE, &iface_info);
  163. }
  164. return test_object_type;
  165. }
  166. static void
  167. test_object_class_init (TestObjectClass *class)
  168. {
  169. /* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */
  170. class->test_signal = test_object_test_signal;
  171. g_signal_new ("test-signal",
  172. G_OBJECT_CLASS_TYPE (class),
  173. G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
  174. G_STRUCT_OFFSET (TestObjectClass, test_signal),
  175. test_signal_accumulator, NULL,
  176. g_cclosure_marshal_STRING__OBJECT_POINTER,
  177. G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER);
  178. g_type_class_add_private (class, sizeof (TestObjectPrivate));
  179. }
  180. static void
  181. test_object_init (TestObject *tobject)
  182. {
  183. TestObjectPrivate *priv;
  184. priv = TEST_OBJECT_GET_PRIVATE (tobject);
  185. g_assert (priv);
  186. g_assert ((gchar *)priv >= (gchar *)tobject + sizeof (TestObject));
  187. priv->dummy1 = 54321;
  188. }
  189. /* Check to see if private data initialization in the
  190. * instance init function works.
  191. */
  192. static void
  193. test_object_check_private_init (TestObject *tobject)
  194. {
  195. TestObjectPrivate *priv;
  196. priv = TEST_OBJECT_GET_PRIVATE (tobject);
  197. g_print ("private data during initialization: %u == %u\n", priv->dummy1, 54321);
  198. g_assert (priv->dummy1 == 54321);
  199. }
  200. static gboolean
  201. test_signal_accumulator (GSignalInvocationHint *ihint,
  202. GValue *return_accu,
  203. const GValue *handler_return,
  204. gpointer data)
  205. {
  206. const gchar *accu_string = g_value_get_string (return_accu);
  207. const gchar *new_string = g_value_get_string (handler_return);
  208. gchar *result_string;
  209. if (accu_string)
  210. result_string = g_strconcat (accu_string, new_string, NULL);
  211. else if (new_string)
  212. result_string = g_strdup (new_string);
  213. else
  214. result_string = NULL;
  215. g_value_take_string (return_accu, result_string);
  216. return TRUE;
  217. }
  218. static gchar*
  219. test_object_test_signal (TestObject *tobject,
  220. TestIface *iface_object,
  221. gpointer tdata)
  222. {
  223. g_message ("::test_signal default_handler called");
  224. g_return_val_if_fail (TEST_IS_IFACE (iface_object), NULL);
  225. return g_strdup ("<default_handler>");
  226. }
  227. /* --- TestIface for DerivedObject --- */
  228. static void
  229. print_bar (TestIface *tiobj,
  230. const gchar *string)
  231. {
  232. TestIfaceClass *parent_iface;
  233. g_return_if_fail (TEST_IS_IFACE (tiobj));
  234. if (!string)
  235. string = "<NULL>";
  236. g_print ("Iface-BAR: \"%s\" from %p\n", string, tiobj);
  237. g_print ("chaining: ");
  238. parent_iface = g_type_interface_peek_parent (TEST_IFACE_GET_CLASS (tiobj));
  239. parent_iface->print_string (tiobj, string);
  240. g_assert (g_type_interface_peek_parent (parent_iface) == NULL);
  241. }
  242. static void
  243. derived_object_test_iface_init (gpointer giface,
  244. gpointer iface_data)
  245. {
  246. TestIfaceClass *iface = giface;
  247. g_assert (iface_data == GUINT_TO_POINTER (87));
  248. g_assert (G_TYPE_FROM_INTERFACE (iface) == TEST_TYPE_IFACE);
  249. /* assert test_object_test_iface_init() was already called */
  250. g_assert (iface->print_string == print_foo);
  251. /* override stuff */
  252. iface->print_string = print_bar;
  253. }
  254. /* --- DerivedObject --- */
  255. #define DERIVED_TYPE_OBJECT (derived_object_get_type ())
  256. #define DERIVED_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DERIVED_TYPE_OBJECT, DerivedObject))
  257. #define DERIVED_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DERIVED_TYPE_OBJECT, DerivedObjectClass))
  258. #define DERIVED_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), DERIVED_TYPE_OBJECT))
  259. #define DERIVED_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DERIVED_TYPE_OBJECT))
  260. #define DERIVED_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DERIVED_TYPE_OBJECT, DerivedObjectClass))
  261. #define DERIVED_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DERIVED_TYPE_OBJECT, DerivedObjectPrivate))
  262. typedef struct _DerivedObject DerivedObject;
  263. typedef struct _TestObjectClass DerivedObjectClass;
  264. typedef struct _DerivedObjectPrivate DerivedObjectPrivate;
  265. struct _DerivedObject
  266. {
  267. TestObject parent_instance;
  268. int dummy1;
  269. int dummy2;
  270. };
  271. struct _DerivedObjectPrivate
  272. {
  273. char dummy;
  274. };
  275. static void derived_object_class_init (DerivedObjectClass *class);
  276. static void derived_object_init (DerivedObject *dobject);
  277. static GType
  278. derived_object_get_type (void)
  279. {
  280. static GType derived_object_type = 0;
  281. if (!derived_object_type)
  282. {
  283. const GTypeInfo derived_object_info =
  284. {
  285. sizeof (DerivedObjectClass),
  286. NULL, /* base_init */
  287. NULL, /* base_finalize */
  288. (GClassInitFunc) derived_object_class_init,
  289. NULL, /* class_finalize */
  290. NULL, /* class_data */
  291. sizeof (DerivedObject),
  292. 5, /* n_preallocs */
  293. (GInstanceInitFunc) derived_object_init,
  294. };
  295. GInterfaceInfo iface_info = { derived_object_test_iface_init, NULL, GUINT_TO_POINTER (87) };
  296. derived_object_type = g_type_register_static (TEST_TYPE_OBJECT, "DerivedObject", &derived_object_info, 0);
  297. g_type_add_interface_static (derived_object_type, TEST_TYPE_IFACE, &iface_info);
  298. }
  299. return derived_object_type;
  300. }
  301. static void
  302. derived_object_class_init (DerivedObjectClass *class)
  303. {
  304. g_type_class_add_private (class, sizeof (DerivedObjectPrivate));
  305. }
  306. static void
  307. derived_object_init (DerivedObject *dobject)
  308. {
  309. TestObjectPrivate *test_priv;
  310. DerivedObjectPrivate *derived_priv;
  311. derived_priv = DERIVED_OBJECT_GET_PRIVATE (dobject);
  312. g_assert (derived_priv);
  313. g_assert ((gchar *)derived_priv >= (gchar *)TEST_OBJECT_GET_PRIVATE (dobject) + sizeof (TestObjectPrivate));
  314. test_priv = TEST_OBJECT_GET_PRIVATE (dobject);
  315. g_assert (test_priv);
  316. g_assert ((gchar *)test_priv >= (gchar *)dobject + sizeof (TestObject));
  317. }
  318. /* --- main --- */
  319. int
  320. main (int argc,
  321. char *argv[])
  322. {
  323. GTypeInfo info = { 0, };
  324. GTypeFundamentalInfo finfo = { 0, };
  325. GType type;
  326. TestObject *sigarg;
  327. DerivedObject *dobject;
  328. TestObjectPrivate *priv;
  329. gchar *string = NULL;
  330. g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
  331. G_LOG_LEVEL_WARNING |
  332. G_LOG_LEVEL_CRITICAL);
  333. /* test new fundamentals */
  334. g_assert (G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST) == g_type_fundamental_next ());
  335. type = g_type_register_fundamental (g_type_fundamental_next (), "FooShadow1", &info, &finfo, 0);
  336. g_assert (type == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST));
  337. g_assert (G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 1) == g_type_fundamental_next ());
  338. type = g_type_register_fundamental (g_type_fundamental_next (), "FooShadow2", &info, &finfo, 0);
  339. g_assert (type == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 1));
  340. g_assert (G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 2) == g_type_fundamental_next ());
  341. g_assert (g_type_from_name ("FooShadow1") == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST));
  342. g_assert (g_type_from_name ("FooShadow2") == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 1));
  343. /* to test past class initialization interface setups, create the class here */
  344. g_type_class_ref (TEST_TYPE_OBJECT);
  345. dobject = g_object_new (DERIVED_TYPE_OBJECT, NULL);
  346. test_object_check_private_init (TEST_OBJECT (dobject));
  347. sigarg = g_object_new (TEST_TYPE_OBJECT, NULL);
  348. g_print ("MAIN: emit test-signal:\n");
  349. g_signal_emit_by_name (dobject, "test-signal", sigarg, NULL, &string);
  350. g_message ("signal return: \"%s\"", string);
  351. g_assert (strcmp (string, "<default_handler><default_handler>") == 0);
  352. g_free (string);
  353. g_print ("MAIN: call iface print-string on test and derived object:\n");
  354. iface_print_string (TEST_IFACE (sigarg), "iface-string-from-test-type");
  355. iface_print_string (TEST_IFACE (dobject), "iface-string-from-derived-type");
  356. priv = TEST_OBJECT_GET_PRIVATE (dobject);
  357. g_print ("private data after initialization: %u == %u\n", priv->dummy1, 54321);
  358. g_assert (priv->dummy1 == 54321);
  359. g_object_unref (sigarg);
  360. g_object_unref (dobject);
  361. g_message ("%s done", argv[0]);
  362. return 0;
  363. }