Branch data Line data Source code
1 : : /* flags.c
2 : : * Copyright (C) 2018 Arthur Demchenkov
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General
17 : : * Public License along with this library; if not, see
18 : : * <http://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include <glib-object.h>
22 : :
23 : : /* Check that validation of flags works on architectures where
24 : : * #gint and #glong are different sizes, as the flags are cast
25 : : * between types a few times.
26 : : *
27 : : * See: https://gitlab.gnome.org/GNOME/glib/issues/1572
28 : : */
29 : :
30 : : enum {
31 : : PROP_FLAGS = 1
32 : : };
33 : :
34 : : typedef struct _GTest GTest;
35 : : typedef struct _GTestClass GTestClass;
36 : :
37 : : typedef enum {
38 : : NO_FLAG = 0,
39 : : LOWEST_FLAG = 1,
40 : : HIGHEST_FLAG = 1 << 31
41 : : } MyFlagsEnum;
42 : :
43 : : struct _GTest {
44 : : GObject object;
45 : : MyFlagsEnum flags;
46 : : };
47 : :
48 : : struct _GTestClass {
49 : : GObjectClass parent_class;
50 : : };
51 : :
52 : : static GType my_test_get_type (void);
53 : : static GType my_test_flags_get_type (void);
54 : :
55 : : #define G_TYPE_TEST (my_test_get_type())
56 : : #define MY_TEST(test) (G_TYPE_CHECK_INSTANCE_CAST ((test), G_TYPE_TEST, GTest))
57 : 14 : G_DEFINE_TYPE (GTest, my_test, G_TYPE_OBJECT)
58 : :
59 : : static void my_test_class_init (GTestClass * klass);
60 : : static void my_test_init (GTest * test);
61 : : static void my_test_get_property (GObject *object,
62 : : guint prop_id,
63 : : GValue *value,
64 : : GParamSpec *pspec);
65 : : static void my_test_set_property (GObject *object,
66 : : guint prop_id,
67 : : const GValue *value,
68 : : GParamSpec *pspec);
69 : :
70 : : static GType
71 : 1 : my_test_flags_get_type (void)
72 : : {
73 : : static GType flags_type = 0;
74 : :
75 : 1 : if (G_UNLIKELY(flags_type == 0))
76 : : {
77 : : static const GFlagsValue values[] = {
78 : : { LOWEST_FLAG, "LOWEST_FLAG", "lowest" },
79 : : { HIGHEST_FLAG, "HIGHEST_FLAG", "highest" },
80 : : { 0, NULL, NULL }
81 : : };
82 : :
83 : 1 : flags_type = g_flags_register_static (g_intern_static_string ("GTestFlags"), values);
84 : : }
85 : 1 : return flags_type;
86 : : }
87 : :
88 : : static void
89 : 1 : my_test_class_init (GTestClass *klass)
90 : : {
91 : 1 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
92 : :
93 : 1 : gobject_class->get_property = my_test_get_property;
94 : 1 : gobject_class->set_property = my_test_set_property;
95 : :
96 : 1 : g_object_class_install_property (gobject_class, 1,
97 : : g_param_spec_flags ("flags",
98 : : "Flags",
99 : : "Flags test property",
100 : : my_test_flags_get_type(), 0,
101 : : G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
102 : 1 : }
103 : :
104 : 4 : static void my_test_init (GTest *test)
105 : : {
106 : 4 : }
107 : :
108 : : static void
109 : 4 : my_test_get_property (GObject *object,
110 : : guint prop_id,
111 : : GValue *value,
112 : : GParamSpec *pspec)
113 : : {
114 : 4 : GTest *test = MY_TEST (object);
115 : :
116 : 4 : switch (prop_id)
117 : : {
118 : 4 : case PROP_FLAGS:
119 : 4 : g_value_set_flags (value, test->flags);
120 : 4 : break;
121 : 0 : default:
122 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
123 : 0 : break;
124 : : }
125 : 4 : }
126 : :
127 : : static void
128 : 4 : my_test_set_property (GObject *object,
129 : : guint prop_id,
130 : : const GValue *value,
131 : : GParamSpec *pspec)
132 : : {
133 : 4 : GTest *test = MY_TEST (object);
134 : :
135 : 4 : switch (prop_id)
136 : : {
137 : 4 : case PROP_FLAGS:
138 : 4 : test->flags = g_value_get_flags (value);
139 : 4 : break;
140 : 0 : default:
141 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
142 : 0 : break;
143 : : }
144 : 4 : }
145 : :
146 : : static void
147 : 1 : check_flags_validation (void)
148 : : {
149 : 1 : guint test_flags[] = {
150 : : NO_FLAG,
151 : : LOWEST_FLAG,
152 : : HIGHEST_FLAG,
153 : : LOWEST_FLAG | HIGHEST_FLAG
154 : : };
155 : : guint flag_read;
156 : : gsize i;
157 : :
158 : 5 : for (i = 0; i < G_N_ELEMENTS (test_flags); i++)
159 : : {
160 : 4 : guint flag_set = test_flags[i];
161 : 4 : GObject *test = g_object_new (G_TYPE_TEST,
162 : : "flags", flag_set,
163 : : NULL);
164 : :
165 : 4 : g_object_get (test, "flags", &flag_read, NULL);
166 : :
167 : : /* This check will fail in case of gint -> glong conversion
168 : : * in value_flags_enum_collect_value() */
169 : 4 : g_assert_cmpint (flag_read, ==, flag_set);
170 : :
171 : 4 : g_object_unref (test);
172 : : }
173 : 1 : }
174 : :
175 : : int
176 : 1 : main (int argc, char **argv)
177 : : {
178 : 1 : g_test_init (&argc, &argv, NULL);
179 : 1 : g_test_add_func ("/gobject/flags/validate", check_flags_validation);
180 : 1 : return g_test_run ();
181 : : }
|