1/* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 1998-1999, 2000-2001 Tim Janik and 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.1 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
18/*
19 * MT safe
20 */
21
22#include "config.h"
23
24#include <string.h>
25
26#include "genums.h"
27#include "gtype-private.h"
28#include "gvalue.h"
29#include "gvaluecollector.h"
30
31
32/**
33 * SECTION:enumerations_flags
34 * @short_description: Enumeration and flags types
35 * @title: Enumeration and Flag Types
36 * @see_also:#GParamSpecEnum, #GParamSpecFlags, g_param_spec_enum(),
37 * g_param_spec_flags()
38 *
39 * The GLib type system provides fundamental types for enumeration and
40 * flags types. (Flags types are like enumerations, but allow their
41 * values to be combined by bitwise or). A registered enumeration or
42 * flags type associates a name and a nickname with each allowed
43 * value, and the methods g_enum_get_value_by_name(),
44 * g_enum_get_value_by_nick(), g_flags_get_value_by_name() and
45 * g_flags_get_value_by_nick() can look up values by their name or
46 * nickname. When an enumeration or flags type is registered with the
47 * GLib type system, it can be used as value type for object
48 * properties, using g_param_spec_enum() or g_param_spec_flags().
49 *
50 * GObject ships with a utility called [glib-mkenums][glib-mkenums],
51 * that can construct suitable type registration functions from C enumeration
52 * definitions.
53 *
54 * Example of how to get a string representation of an enum value:
55 * |[<!-- language="C" -->
56 * GEnumClass *enum_class;
57 * GEnumValue *enum_value;
58 *
59 * enum_class = g_type_class_ref (MAMAN_TYPE_MY_ENUM);
60 * enum_value = g_enum_get_value (enum_class, MAMAN_MY_ENUM_FOO);
61 *
62 * g_print ("Name: %s\n", enum_value->value_name);
63 *
64 * g_type_class_unref (enum_class);
65 * ]|
66 */
67
68
69/* --- prototypes --- */
70static void g_enum_class_init (GEnumClass *class,
71 gpointer class_data);
72static void g_flags_class_init (GFlagsClass *class,
73 gpointer class_data);
74static void value_flags_enum_init (GValue *value);
75static void value_flags_enum_copy_value (const GValue *src_value,
76 GValue *dest_value);
77static gchar* value_flags_enum_collect_value (GValue *value,
78 guint n_collect_values,
79 GTypeCValue *collect_values,
80 guint collect_flags);
81static gchar* value_flags_enum_lcopy_value (const GValue *value,
82 guint n_collect_values,
83 GTypeCValue *collect_values,
84 guint collect_flags);
85
86/* --- functions --- */
87void
88_g_enum_types_init (void)
89{
90 static gboolean initialized = FALSE;
91 static const GTypeValueTable flags_enum_value_table = {
92 value_flags_enum_init, /* value_init */
93 NULL, /* value_free */
94 value_flags_enum_copy_value, /* value_copy */
95 NULL, /* value_peek_pointer */
96 "i", /* collect_format */
97 value_flags_enum_collect_value, /* collect_value */
98 "p", /* lcopy_format */
99 value_flags_enum_lcopy_value, /* lcopy_value */
100 };
101 GTypeInfo info = {
102 0, /* class_size */
103 NULL, /* base_init */
104 NULL, /* base_destroy */
105 NULL, /* class_init */
106 NULL, /* class_destroy */
107 NULL, /* class_data */
108 0, /* instance_size */
109 0, /* n_preallocs */
110 NULL, /* instance_init */
111 &flags_enum_value_table, /* value_table */
112 };
113 static const GTypeFundamentalInfo finfo = {
114 G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE,
115 };
116 GType type G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
117
118 g_return_if_fail (initialized == FALSE);
119 initialized = TRUE;
120
121 /* G_TYPE_ENUM
122 */
123 info.class_size = sizeof (GEnumClass);
124 type = g_type_register_fundamental (G_TYPE_ENUM, type_name: g_intern_static_string (string: "GEnum"), info: &info, finfo: &finfo,
125 flags: G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT);
126 g_assert (type == G_TYPE_ENUM);
127
128 /* G_TYPE_FLAGS
129 */
130 info.class_size = sizeof (GFlagsClass);
131 type = g_type_register_fundamental (G_TYPE_FLAGS, type_name: g_intern_static_string (string: "GFlags"), info: &info, finfo: &finfo,
132 flags: G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT);
133 g_assert (type == G_TYPE_FLAGS);
134}
135
136static void
137value_flags_enum_init (GValue *value)
138{
139 value->data[0].v_long = 0;
140}
141
142static void
143value_flags_enum_copy_value (const GValue *src_value,
144 GValue *dest_value)
145{
146 dest_value->data[0].v_long = src_value->data[0].v_long;
147}
148
149static gchar*
150value_flags_enum_collect_value (GValue *value,
151 guint n_collect_values,
152 GTypeCValue *collect_values,
153 guint collect_flags)
154{
155 if (G_VALUE_HOLDS_ENUM (value))
156 value->data[0].v_long = collect_values[0].v_int;
157 else
158 value->data[0].v_ulong = (guint) collect_values[0].v_int;
159
160 return NULL;
161}
162
163static gchar*
164value_flags_enum_lcopy_value (const GValue *value,
165 guint n_collect_values,
166 GTypeCValue *collect_values,
167 guint collect_flags)
168{
169 gint *int_p = collect_values[0].v_pointer;
170
171 g_return_val_if_fail (int_p != NULL, g_strdup_printf ("value location for '%s' passed as NULL", G_VALUE_TYPE_NAME (value)));
172
173 *int_p = value->data[0].v_long;
174
175 return NULL;
176}
177
178/**
179 * g_enum_register_static:
180 * @name: A nul-terminated string used as the name of the new type.
181 * @const_static_values: An array of #GEnumValue structs for the possible
182 * enumeration values. The array is terminated by a struct with all
183 * members being 0. GObject keeps a reference to the data, so it cannot
184 * be stack-allocated.
185 *
186 * Registers a new static enumeration type with the name @name.
187 *
188 * It is normally more convenient to let [glib-mkenums][glib-mkenums],
189 * generate a my_enum_get_type() function from a usual C enumeration
190 * definition than to write one yourself using g_enum_register_static().
191 *
192 * Returns: The new type identifier.
193 */
194GType
195g_enum_register_static (const gchar *name,
196 const GEnumValue *const_static_values)
197{
198 GTypeInfo enum_type_info = {
199 sizeof (GEnumClass), /* class_size */
200 NULL, /* base_init */
201 NULL, /* base_finalize */
202 (GClassInitFunc) g_enum_class_init,
203 NULL, /* class_finalize */
204 NULL, /* class_data */
205 0, /* instance_size */
206 0, /* n_preallocs */
207 NULL, /* instance_init */
208 NULL, /* value_table */
209 };
210 GType type;
211
212 g_return_val_if_fail (name != NULL, 0);
213 g_return_val_if_fail (const_static_values != NULL, 0);
214
215 enum_type_info.class_data = const_static_values;
216
217 type = g_type_register_static (G_TYPE_ENUM, type_name: name, info: &enum_type_info, flags: 0);
218
219 return type;
220}
221
222/**
223 * g_flags_register_static:
224 * @name: A nul-terminated string used as the name of the new type.
225 * @const_static_values: An array of #GFlagsValue structs for the possible
226 * flags values. The array is terminated by a struct with all members being 0.
227 * GObject keeps a reference to the data, so it cannot be stack-allocated.
228 *
229 * Registers a new static flags type with the name @name.
230 *
231 * It is normally more convenient to let [glib-mkenums][glib-mkenums]
232 * generate a my_flags_get_type() function from a usual C enumeration
233 * definition than to write one yourself using g_flags_register_static().
234 *
235 * Returns: The new type identifier.
236 */
237GType
238g_flags_register_static (const gchar *name,
239 const GFlagsValue *const_static_values)
240{
241 GTypeInfo flags_type_info = {
242 sizeof (GFlagsClass), /* class_size */
243 NULL, /* base_init */
244 NULL, /* base_finalize */
245 (GClassInitFunc) g_flags_class_init,
246 NULL, /* class_finalize */
247 NULL, /* class_data */
248 0, /* instance_size */
249 0, /* n_preallocs */
250 NULL, /* instance_init */
251 NULL, /* value_table */
252 };
253 GType type;
254
255 g_return_val_if_fail (name != NULL, 0);
256 g_return_val_if_fail (const_static_values != NULL, 0);
257
258 flags_type_info.class_data = const_static_values;
259
260 type = g_type_register_static (G_TYPE_FLAGS, type_name: name, info: &flags_type_info, flags: 0);
261
262 return type;
263}
264
265/**
266 * g_enum_complete_type_info:
267 * @g_enum_type: the type identifier of the type being completed
268 * @info: (out callee-allocates): the #GTypeInfo struct to be filled in
269 * @const_values: An array of #GEnumValue structs for the possible
270 * enumeration values. The array is terminated by a struct with all
271 * members being 0.
272 *
273 * This function is meant to be called from the `complete_type_info`
274 * function of a #GTypePlugin implementation, as in the following
275 * example:
276 *
277 * |[<!-- language="C" -->
278 * static void
279 * my_enum_complete_type_info (GTypePlugin *plugin,
280 * GType g_type,
281 * GTypeInfo *info,
282 * GTypeValueTable *value_table)
283 * {
284 * static const GEnumValue values[] = {
285 * { MY_ENUM_FOO, "MY_ENUM_FOO", "foo" },
286 * { MY_ENUM_BAR, "MY_ENUM_BAR", "bar" },
287 * { 0, NULL, NULL }
288 * };
289 *
290 * g_enum_complete_type_info (type, info, values);
291 * }
292 * ]|
293 */
294void
295g_enum_complete_type_info (GType g_enum_type,
296 GTypeInfo *info,
297 const GEnumValue *const_values)
298{
299 g_return_if_fail (G_TYPE_IS_ENUM (g_enum_type));
300 g_return_if_fail (info != NULL);
301 g_return_if_fail (const_values != NULL);
302
303 info->class_size = sizeof (GEnumClass);
304 info->base_init = NULL;
305 info->base_finalize = NULL;
306 info->class_init = (GClassInitFunc) g_enum_class_init;
307 info->class_finalize = NULL;
308 info->class_data = const_values;
309}
310
311/**
312 * g_flags_complete_type_info:
313 * @g_flags_type: the type identifier of the type being completed
314 * @info: (out callee-allocates): the #GTypeInfo struct to be filled in
315 * @const_values: An array of #GFlagsValue structs for the possible
316 * enumeration values. The array is terminated by a struct with all
317 * members being 0.
318 *
319 * This function is meant to be called from the complete_type_info()
320 * function of a #GTypePlugin implementation, see the example for
321 * g_enum_complete_type_info() above.
322 */
323void
324g_flags_complete_type_info (GType g_flags_type,
325 GTypeInfo *info,
326 const GFlagsValue *const_values)
327{
328 g_return_if_fail (G_TYPE_IS_FLAGS (g_flags_type));
329 g_return_if_fail (info != NULL);
330 g_return_if_fail (const_values != NULL);
331
332 info->class_size = sizeof (GFlagsClass);
333 info->base_init = NULL;
334 info->base_finalize = NULL;
335 info->class_init = (GClassInitFunc) g_flags_class_init;
336 info->class_finalize = NULL;
337 info->class_data = const_values;
338}
339
340static void
341g_enum_class_init (GEnumClass *class,
342 gpointer class_data)
343{
344 g_return_if_fail (G_IS_ENUM_CLASS (class));
345
346 class->minimum = 0;
347 class->maximum = 0;
348 class->n_values = 0;
349 class->values = class_data;
350
351 if (class->values)
352 {
353 GEnumValue *values;
354
355 class->minimum = class->values->value;
356 class->maximum = class->values->value;
357 for (values = class->values; values->value_name; values++)
358 {
359 class->minimum = MIN (class->minimum, values->value);
360 class->maximum = MAX (class->maximum, values->value);
361 class->n_values++;
362 }
363 }
364}
365
366static void
367g_flags_class_init (GFlagsClass *class,
368 gpointer class_data)
369{
370 g_return_if_fail (G_IS_FLAGS_CLASS (class));
371
372 class->mask = 0;
373 class->n_values = 0;
374 class->values = class_data;
375
376 if (class->values)
377 {
378 GFlagsValue *values;
379
380 for (values = class->values; values->value_name; values++)
381 {
382 class->mask |= values->value;
383 class->n_values++;
384 }
385 }
386}
387
388/**
389 * g_enum_get_value_by_name:
390 * @enum_class: a #GEnumClass
391 * @name: the name to look up
392 *
393 * Looks up a #GEnumValue by name.
394 *
395 * Returns: (transfer none) (nullable): the #GEnumValue with name @name,
396 * or %NULL if the enumeration doesn't have a member
397 * with that name
398 */
399GEnumValue*
400g_enum_get_value_by_name (GEnumClass *enum_class,
401 const gchar *name)
402{
403 g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
404 g_return_val_if_fail (name != NULL, NULL);
405
406 if (enum_class->n_values)
407 {
408 GEnumValue *enum_value;
409
410 for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
411 if (strcmp (s1: name, s2: enum_value->value_name) == 0)
412 return enum_value;
413 }
414
415 return NULL;
416}
417
418/**
419 * g_flags_get_value_by_name:
420 * @flags_class: a #GFlagsClass
421 * @name: the name to look up
422 *
423 * Looks up a #GFlagsValue by name.
424 *
425 * Returns: (transfer none) (nullable): the #GFlagsValue with name @name,
426 * or %NULL if there is no flag with that name
427 */
428GFlagsValue*
429g_flags_get_value_by_name (GFlagsClass *flags_class,
430 const gchar *name)
431{
432 g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
433 g_return_val_if_fail (name != NULL, NULL);
434
435 if (flags_class->n_values)
436 {
437 GFlagsValue *flags_value;
438
439 for (flags_value = flags_class->values; flags_value->value_name; flags_value++)
440 if (strcmp (s1: name, s2: flags_value->value_name) == 0)
441 return flags_value;
442 }
443
444 return NULL;
445}
446
447/**
448 * g_enum_get_value_by_nick:
449 * @enum_class: a #GEnumClass
450 * @nick: the nickname to look up
451 *
452 * Looks up a #GEnumValue by nickname.
453 *
454 * Returns: (transfer none) (nullable): the #GEnumValue with nickname @nick,
455 * or %NULL if the enumeration doesn't have a member
456 * with that nickname
457 */
458GEnumValue*
459g_enum_get_value_by_nick (GEnumClass *enum_class,
460 const gchar *nick)
461{
462 g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
463 g_return_val_if_fail (nick != NULL, NULL);
464
465 if (enum_class->n_values)
466 {
467 GEnumValue *enum_value;
468
469 for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
470 if (enum_value->value_nick && strcmp (s1: nick, s2: enum_value->value_nick) == 0)
471 return enum_value;
472 }
473
474 return NULL;
475}
476
477/**
478 * g_flags_get_value_by_nick:
479 * @flags_class: a #GFlagsClass
480 * @nick: the nickname to look up
481 *
482 * Looks up a #GFlagsValue by nickname.
483 *
484 * Returns: (transfer none) (nullable): the #GFlagsValue with nickname @nick,
485 * or %NULL if there is no flag with that nickname
486 */
487GFlagsValue*
488g_flags_get_value_by_nick (GFlagsClass *flags_class,
489 const gchar *nick)
490{
491 g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
492 g_return_val_if_fail (nick != NULL, NULL);
493
494 if (flags_class->n_values)
495 {
496 GFlagsValue *flags_value;
497
498 for (flags_value = flags_class->values; flags_value->value_nick; flags_value++)
499 if (flags_value->value_nick && strcmp (s1: nick, s2: flags_value->value_nick) == 0)
500 return flags_value;
501 }
502
503 return NULL;
504}
505
506/**
507 * g_enum_get_value:
508 * @enum_class: a #GEnumClass
509 * @value: the value to look up
510 *
511 * Returns the #GEnumValue for a value.
512 *
513 * Returns: (transfer none) (nullable): the #GEnumValue for @value, or %NULL
514 * if @value is not a member of the enumeration
515 */
516GEnumValue*
517g_enum_get_value (GEnumClass *enum_class,
518 gint value)
519{
520 g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
521
522 if (enum_class->n_values)
523 {
524 GEnumValue *enum_value;
525
526 for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
527 if (enum_value->value == value)
528 return enum_value;
529 }
530
531 return NULL;
532}
533
534/**
535 * g_flags_get_first_value:
536 * @flags_class: a #GFlagsClass
537 * @value: the value
538 *
539 * Returns the first #GFlagsValue which is set in @value.
540 *
541 * Returns: (transfer none) (nullable): the first #GFlagsValue which is set in
542 * @value, or %NULL if none is set
543 */
544GFlagsValue*
545g_flags_get_first_value (GFlagsClass *flags_class,
546 guint value)
547{
548 g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
549
550 if (flags_class->n_values)
551 {
552 GFlagsValue *flags_value;
553
554 if (value == 0)
555 {
556 for (flags_value = flags_class->values; flags_value->value_name; flags_value++)
557 if (flags_value->value == 0)
558 return flags_value;
559 }
560 else
561 {
562 for (flags_value = flags_class->values; flags_value->value_name; flags_value++)
563 if (flags_value->value != 0 && (flags_value->value & value) == flags_value->value)
564 return flags_value;
565 }
566 }
567
568 return NULL;
569}
570
571/**
572 * g_enum_to_string:
573 * @g_enum_type: the type identifier of a #GEnumClass type
574 * @value: the value
575 *
576 * Pretty-prints @value in the form of the enum’s name.
577 *
578 * This is intended to be used for debugging purposes. The format of the output
579 * may change in the future.
580 *
581 * Returns: (transfer full): a newly-allocated text string
582 *
583 * Since: 2.54
584 */
585gchar *
586g_enum_to_string (GType g_enum_type,
587 gint value)
588{
589 gchar *result;
590 GEnumClass *enum_class;
591 GEnumValue *enum_value;
592
593 g_return_val_if_fail (G_TYPE_IS_ENUM (g_enum_type), NULL);
594
595 enum_class = g_type_class_ref (type: g_enum_type);
596
597 /* Already warned */
598 if (enum_class == NULL)
599 return g_strdup_printf (format: "%d", value);
600
601 enum_value = g_enum_get_value (enum_class, value);
602
603 if (enum_value == NULL)
604 result = g_strdup_printf (format: "%d", value);
605 else
606 result = g_strdup (str: enum_value->value_name);
607
608 g_type_class_unref (g_class: enum_class);
609 return result;
610}
611
612/*
613 * g_flags_get_value_string:
614 * @flags_class: a #GFlagsClass
615 * @value: the value
616 *
617 * Pretty-prints @value in the form of the flag names separated by ` | ` and
618 * sorted. Any extra bits will be shown at the end as a hexadecimal number.
619 *
620 * This is intended to be used for debugging purposes. The format of the output
621 * may change in the future.
622 *
623 * Returns: (transfer full): a newly-allocated text string
624 *
625 * Since: 2.54
626 */
627static gchar *
628g_flags_get_value_string (GFlagsClass *flags_class,
629 guint value)
630{
631 GString *str;
632 GFlagsValue *flags_value;
633
634 g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
635
636 str = g_string_new (NULL);
637
638 while ((str->len == 0 || value != 0) &&
639 (flags_value = g_flags_get_first_value (flags_class, value)) != NULL)
640 {
641 if (str->len > 0)
642 g_string_append (string: str, val: " | ");
643
644 g_string_append (string: str, val: flags_value->value_name);
645
646 value &= ~flags_value->value;
647 }
648
649 /* Show the extra bits */
650 if (value != 0 || str->len == 0)
651 {
652 if (str->len > 0)
653 g_string_append (string: str, val: " | ");
654
655 g_string_append_printf (string: str, format: "0x%x", value);
656 }
657
658 return g_string_free (string: str, FALSE);
659}
660
661/**
662 * g_flags_to_string:
663 * @flags_type: the type identifier of a #GFlagsClass type
664 * @value: the value
665 *
666 * Pretty-prints @value in the form of the flag names separated by ` | ` and
667 * sorted. Any extra bits will be shown at the end as a hexadecimal number.
668 *
669 * This is intended to be used for debugging purposes. The format of the output
670 * may change in the future.
671 *
672 * Returns: (transfer full): a newly-allocated text string
673 *
674 * Since: 2.54
675 */
676gchar *
677g_flags_to_string (GType flags_type,
678 guint value)
679{
680 gchar *result;
681 GFlagsClass *flags_class;
682
683 g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
684
685 flags_class = g_type_class_ref (type: flags_type);
686
687 /* Already warned */
688 if (flags_class == NULL)
689 return NULL;
690
691 result = g_flags_get_value_string (flags_class, value);
692
693 g_type_class_unref (g_class: flags_class);
694 return result;
695}
696
697
698/**
699 * g_value_set_enum:
700 * @value: a valid #GValue whose type is derived from %G_TYPE_ENUM
701 * @v_enum: enum value to be set
702 *
703 * Set the contents of a %G_TYPE_ENUM #GValue to @v_enum.
704 */
705void
706g_value_set_enum (GValue *value,
707 gint v_enum)
708{
709 g_return_if_fail (G_VALUE_HOLDS_ENUM (value));
710
711 value->data[0].v_long = v_enum;
712}
713
714/**
715 * g_value_get_enum:
716 * @value: a valid #GValue whose type is derived from %G_TYPE_ENUM
717 *
718 * Get the contents of a %G_TYPE_ENUM #GValue.
719 *
720 * Returns: enum contents of @value
721 */
722gint
723g_value_get_enum (const GValue *value)
724{
725 g_return_val_if_fail (G_VALUE_HOLDS_ENUM (value), 0);
726
727 return value->data[0].v_long;
728}
729
730/**
731 * g_value_set_flags:
732 * @value: a valid #GValue whose type is derived from %G_TYPE_FLAGS
733 * @v_flags: flags value to be set
734 *
735 * Set the contents of a %G_TYPE_FLAGS #GValue to @v_flags.
736 */
737void
738g_value_set_flags (GValue *value,
739 guint v_flags)
740{
741 g_return_if_fail (G_VALUE_HOLDS_FLAGS (value));
742
743 value->data[0].v_ulong = v_flags;
744}
745
746/**
747 * g_value_get_flags:
748 * @value: a valid #GValue whose type is derived from %G_TYPE_FLAGS
749 *
750 * Get the contents of a %G_TYPE_FLAGS #GValue.
751 *
752 * Returns: flags contents of @value
753 */
754guint
755g_value_get_flags (const GValue *value)
756{
757 g_return_val_if_fail (G_VALUE_HOLDS_FLAGS (value), 0);
758
759 return value->data[0].v_ulong;
760}
761

source code of gtk/subprojects/glib/gobject/genums.c