• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 /*
21  * MT safe
22  */
23 
24 #include "config.h"
25 
26 #include <string.h>
27 
28 #include "genums.h"
29 #include "gvalue.h"
30 #include "gvaluecollector.h"
31 #include "gobjectalias.h"
32 
33 
34 /**
35  * SECTION:enumerations_flags
36  * @short_description: Enumeration and flags types
37  * @see_also:#GParamSpecEnum, #GParamSpecFlags, g_param_spec_enum(),
38  * g_param_spec_flags(),
39  *
40  * <link linkend="glib-mkenums">glib-mkenums</link>
41  * @title: Enumeration and Flag Types
42  *
43  * The GLib type system provides fundamental types for enumeration and
44  * flags types. (Flags types are like enumerations, but allow their
45  * values to be combined by bitwise or). A registered enumeration or
46  * flags type associates a name and a nickname with each allowed
47  * value, and the methods g_enum_get_value_by_name(),
48  * g_enum_get_value_by_nick(), g_flags_get_value_by_name() and
49  * g_flags_get_value_by_nick() can look up values by their name or
50  * nickname.  When an enumeration or flags type is registered with the
51  * GLib type system, it can be used as value type for object
52  * properties, using g_param_spec_enum() or g_param_spec_flags().
53  *
54  * GObject ships with a utility called <link
55  * linkend="glib-mkenums">glib-mkenums</link> that can construct
56  * suitable type registration functions from C enumeration
57  * definitions.
58  */
59 
60 
61 /* --- prototypes --- */
62 static void	g_enum_class_init		(GEnumClass	*class,
63 						 gpointer	 class_data);
64 static void	g_flags_class_init		(GFlagsClass	*class,
65 						 gpointer	 class_data);
66 static void	value_flags_enum_init		(GValue		*value);
67 static void	value_flags_enum_copy_value	(const GValue	*src_value,
68 						 GValue		*dest_value);
69 static gchar*	value_flags_enum_collect_value  (GValue		*value,
70 						 guint           n_collect_values,
71 						 GTypeCValue    *collect_values,
72 						 guint           collect_flags);
73 static gchar*	value_flags_enum_lcopy_value	(const GValue	*value,
74 						 guint           n_collect_values,
75 						 GTypeCValue    *collect_values,
76 						 guint           collect_flags);
77 
78 /* --- functions --- */
79 void
g_enum_types_init(void)80 g_enum_types_init (void)
81 {
82   static gboolean initialized = FALSE;
83   static const GTypeValueTable flags_enum_value_table = {
84     value_flags_enum_init,	    /* value_init */
85     NULL,			    /* value_free */
86     value_flags_enum_copy_value,    /* value_copy */
87     NULL,			    /* value_peek_pointer */
88     "i",			    /* collect_format */
89     value_flags_enum_collect_value, /* collect_value */
90     "p",			    /* lcopy_format */
91     value_flags_enum_lcopy_value,   /* lcopy_value */
92   };
93   static GTypeInfo info = {
94     0,                          /* class_size */
95     NULL,                       /* base_init */
96     NULL,                       /* base_destroy */
97     NULL,                       /* class_init */
98     NULL,                       /* class_destroy */
99     NULL,                       /* class_data */
100     0,                          /* instance_size */
101     0,                          /* n_preallocs */
102     NULL,                       /* instance_init */
103     &flags_enum_value_table,    /* value_table */
104   };
105   static const GTypeFundamentalInfo finfo = {
106     G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE,
107   };
108   GType type;
109 
110   g_return_if_fail (initialized == FALSE);
111   initialized = TRUE;
112 
113   /* G_TYPE_ENUM
114    */
115   info.class_size = sizeof (GEnumClass);
116   type = g_type_register_fundamental (G_TYPE_ENUM, g_intern_static_string ("GEnum"), &info, &finfo,
117 				      G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT);
118   g_assert (type == G_TYPE_ENUM);
119 
120   /* G_TYPE_FLAGS
121    */
122   info.class_size = sizeof (GFlagsClass);
123   type = g_type_register_fundamental (G_TYPE_FLAGS, g_intern_static_string ("GFlags"), &info, &finfo,
124 				      G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT);
125   g_assert (type == G_TYPE_FLAGS);
126 }
127 
128 static void
value_flags_enum_init(GValue * value)129 value_flags_enum_init (GValue *value)
130 {
131   value->data[0].v_long = 0;
132 }
133 
134 static void
value_flags_enum_copy_value(const GValue * src_value,GValue * dest_value)135 value_flags_enum_copy_value (const GValue *src_value,
136 			     GValue	  *dest_value)
137 {
138   dest_value->data[0].v_long = src_value->data[0].v_long;
139 }
140 
141 static gchar*
value_flags_enum_collect_value(GValue * value,guint n_collect_values,GTypeCValue * collect_values,guint collect_flags)142 value_flags_enum_collect_value (GValue      *value,
143 				guint        n_collect_values,
144 				GTypeCValue *collect_values,
145 				guint        collect_flags)
146 {
147   value->data[0].v_long = collect_values[0].v_int;
148 
149   return NULL;
150 }
151 
152 static gchar*
value_flags_enum_lcopy_value(const GValue * value,guint n_collect_values,GTypeCValue * collect_values,guint collect_flags)153 value_flags_enum_lcopy_value (const GValue *value,
154 			      guint         n_collect_values,
155 			      GTypeCValue  *collect_values,
156 			      guint         collect_flags)
157 {
158   gint *int_p = collect_values[0].v_pointer;
159 
160   if (!int_p)
161     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
162 
163   *int_p = value->data[0].v_long;
164 
165   return NULL;
166 }
167 
168 /**
169  * g_enum_register_static:
170  * @name: A nul-terminated string used as the name of the new type.
171  * @const_static_values: An array of #GEnumValue structs for the possible
172  *  enumeration values. The array is terminated by a struct with all
173  *  members being 0. GObject keeps a reference to the data, so it cannot
174  *  be stack-allocated.
175  *
176  * Registers a new static enumeration type with the name @name.
177  *
178  * It is normally more convenient to let <link
179  * linkend="glib-mkenums">glib-mkenums</link> generate a
180  * my_enum_get_type() function from a usual C enumeration definition
181  * than to write one yourself using g_enum_register_static().
182  *
183  * Returns: The new type identifier.
184  */
185 GType
g_enum_register_static(const gchar * name,const GEnumValue * const_static_values)186 g_enum_register_static (const gchar	 *name,
187 			const GEnumValue *const_static_values)
188 {
189   GTypeInfo enum_type_info = {
190     sizeof (GEnumClass), /* class_size */
191     NULL,                /* base_init */
192     NULL,                /* base_finalize */
193     (GClassInitFunc) g_enum_class_init,
194     NULL,                /* class_finalize */
195     NULL,                /* class_data */
196     0,                   /* instance_size */
197     0,                   /* n_preallocs */
198     NULL,                /* instance_init */
199     NULL,		 /* value_table */
200   };
201   GType type;
202 
203   g_return_val_if_fail (name != NULL, 0);
204   g_return_val_if_fail (const_static_values != NULL, 0);
205 
206   enum_type_info.class_data = const_static_values;
207 
208   type = g_type_register_static (G_TYPE_ENUM, name, &enum_type_info, 0);
209 
210   return type;
211 }
212 
213 /**
214  * g_flags_register_static:
215  * @name: A nul-terminated string used as the name of the new type.
216  * @const_static_values: An array of #GFlagsValue structs for the possible
217  *  flags values. The array is terminated by a struct with all members being 0.
218  *  GObject keeps a reference to the data, so it cannot be stack-allocated.
219  *
220  * Registers a new static flags type with the name @name.
221  *
222  * It is normally more convenient to let <link
223  * linkend="glib-mkenums">glib-mkenums</link> generate a
224  * my_flags_get_type() function from a usual C enumeration definition
225  * than to write one yourself using g_flags_register_static().
226  *
227  * Returns: The new type identifier.
228  */
229 GType
g_flags_register_static(const gchar * name,const GFlagsValue * const_static_values)230 g_flags_register_static (const gchar	   *name,
231 			 const GFlagsValue *const_static_values)
232 {
233   GTypeInfo flags_type_info = {
234     sizeof (GFlagsClass), /* class_size */
235     NULL,                 /* base_init */
236     NULL,                 /* base_finalize */
237     (GClassInitFunc) g_flags_class_init,
238     NULL,                 /* class_finalize */
239     NULL,                 /* class_data */
240     0,                    /* instance_size */
241     0,                    /* n_preallocs */
242     NULL,                 /* instance_init */
243     NULL,		  /* value_table */
244   };
245   GType type;
246 
247   g_return_val_if_fail (name != NULL, 0);
248   g_return_val_if_fail (const_static_values != NULL, 0);
249 
250   flags_type_info.class_data = const_static_values;
251 
252   type = g_type_register_static (G_TYPE_FLAGS, name, &flags_type_info, 0);
253 
254   return type;
255 }
256 
257 /**
258  * g_enum_complete_type_info:
259  * @g_enum_type: the type identifier of the type being completed
260  * @info: the #GTypeInfo struct to be filled in
261  * @const_values: An array of #GEnumValue structs for the possible
262  *  enumeration values. The array is terminated by a struct with all
263  *  members being 0.
264  *
265  * This function is meant to be called from the complete_type_info()
266  * function of a #GTypePlugin implementation, as in the following
267  * example:
268  *
269  * |[
270  * static void
271  * my_enum_complete_type_info (GTypePlugin     *plugin,
272  *                             GType            g_type,
273  *                             GTypeInfo       *info,
274  *                             GTypeValueTable *value_table)
275  * {
276  *   static const GEnumValue values[] = {
277  *     { MY_ENUM_FOO, "MY_ENUM_FOO", "foo" },
278  *     { MY_ENUM_BAR, "MY_ENUM_BAR", "bar" },
279  *     { 0, NULL, NULL }
280  *   };
281  *
282  *   g_enum_complete_type_info (type, info, values);
283  * }
284  * ]|
285  */
286 void
g_enum_complete_type_info(GType g_enum_type,GTypeInfo * info,const GEnumValue * const_values)287 g_enum_complete_type_info (GType	     g_enum_type,
288 			   GTypeInfo	    *info,
289 			   const GEnumValue *const_values)
290 {
291   g_return_if_fail (G_TYPE_IS_ENUM (g_enum_type));
292   g_return_if_fail (info != NULL);
293   g_return_if_fail (const_values != NULL);
294 
295   info->class_size = sizeof (GEnumClass);
296   info->base_init = NULL;
297   info->base_finalize = NULL;
298   info->class_init = (GClassInitFunc) g_enum_class_init;
299   info->class_finalize = NULL;
300   info->class_data = const_values;
301 }
302 
303 /**
304  * g_flags_complete_type_info:
305  * @g_flags_type: the type identifier of the type being completed
306  * @info: the #GTypeInfo struct to be filled in
307  * @const_values: An array of #GFlagsValue structs for the possible
308  *  enumeration values. The array is terminated by a struct with all
309  *  members being 0.
310  *
311  * This function is meant to be called from the complete_type_info()
312  * function of a #GTypePlugin implementation, see the example for
313  * g_enum_complete_type_info() above.
314  */
315 void
g_flags_complete_type_info(GType g_flags_type,GTypeInfo * info,const GFlagsValue * const_values)316 g_flags_complete_type_info (GType	       g_flags_type,
317 			    GTypeInfo	      *info,
318 			    const GFlagsValue *const_values)
319 {
320   g_return_if_fail (G_TYPE_IS_FLAGS (g_flags_type));
321   g_return_if_fail (info != NULL);
322   g_return_if_fail (const_values != NULL);
323 
324   info->class_size = sizeof (GFlagsClass);
325   info->base_init = NULL;
326   info->base_finalize = NULL;
327   info->class_init = (GClassInitFunc) g_flags_class_init;
328   info->class_finalize = NULL;
329   info->class_data = const_values;
330 }
331 
332 static void
g_enum_class_init(GEnumClass * class,gpointer class_data)333 g_enum_class_init (GEnumClass *class,
334 		   gpointer    class_data)
335 {
336   g_return_if_fail (G_IS_ENUM_CLASS (class));
337 
338   class->minimum = 0;
339   class->maximum = 0;
340   class->n_values = 0;
341   class->values = class_data;
342 
343   if (class->values)
344     {
345       GEnumValue *values;
346 
347       class->minimum = class->values->value;
348       class->maximum = class->values->value;
349       for (values = class->values; values->value_name; values++)
350 	{
351 	  class->minimum = MIN (class->minimum, values->value);
352 	  class->maximum = MAX (class->maximum, values->value);
353 	  class->n_values++;
354 	}
355     }
356 }
357 
358 static void
g_flags_class_init(GFlagsClass * class,gpointer class_data)359 g_flags_class_init (GFlagsClass *class,
360 		    gpointer	 class_data)
361 {
362   g_return_if_fail (G_IS_FLAGS_CLASS (class));
363 
364   class->mask = 0;
365   class->n_values = 0;
366   class->values = class_data;
367 
368   if (class->values)
369     {
370       GFlagsValue *values;
371 
372       for (values = class->values; values->value_name; values++)
373 	{
374 	  class->mask |= values->value;
375 	  class->n_values++;
376 	}
377     }
378 }
379 
380 /**
381  * g_enum_get_value_by_name:
382  * @enum_class: a #GEnumClass
383  * @name: the name to look up
384  *
385  * Looks up a #GEnumValue by name.
386  *
387  * Returns: the #GEnumValue with name @name, or %NULL if the
388  *          enumeration doesn't have a member with that name
389  */
390 GEnumValue*
g_enum_get_value_by_name(GEnumClass * enum_class,const gchar * name)391 g_enum_get_value_by_name (GEnumClass  *enum_class,
392 			  const gchar *name)
393 {
394   g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
395   g_return_val_if_fail (name != NULL, NULL);
396 
397   if (enum_class->n_values)
398     {
399       GEnumValue *enum_value;
400 
401       for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
402 	if (strcmp (name, enum_value->value_name) == 0)
403 	  return enum_value;
404     }
405 
406   return NULL;
407 }
408 
409 /**
410  * g_flags_get_value_by_name:
411  * @flags_class: a #GFlagsClass
412  * @name: the name to look up
413  *
414  * Looks up a #GFlagsValue by name.
415  *
416  * Returns: the #GFlagsValue with name @name, or %NULL if there is no
417  *          flag with that name
418  */
419 GFlagsValue*
g_flags_get_value_by_name(GFlagsClass * flags_class,const gchar * name)420 g_flags_get_value_by_name (GFlagsClass *flags_class,
421 			   const gchar *name)
422 {
423   g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
424   g_return_val_if_fail (name != NULL, NULL);
425 
426   if (flags_class->n_values)
427     {
428       GFlagsValue *flags_value;
429 
430       for (flags_value = flags_class->values; flags_value->value_name; flags_value++)
431 	if (strcmp (name, flags_value->value_name) == 0)
432 	  return flags_value;
433     }
434 
435   return NULL;
436 }
437 
438 /**
439  * g_enum_get_value_by_nick:
440  * @enum_class: a #GEnumClass
441  * @nick: the nickname to look up
442  *
443  * Looks up a #GEnumValue by nickname.
444  *
445  * Returns: the #GEnumValue with nickname @nick, or %NULL if the
446  *          enumeration doesn't have a member with that nickname
447  */
448 GEnumValue*
g_enum_get_value_by_nick(GEnumClass * enum_class,const gchar * nick)449 g_enum_get_value_by_nick (GEnumClass  *enum_class,
450 			  const gchar *nick)
451 {
452   g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
453   g_return_val_if_fail (nick != NULL, NULL);
454 
455   if (enum_class->n_values)
456     {
457       GEnumValue *enum_value;
458 
459       for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
460 	if (enum_value->value_nick && strcmp (nick, enum_value->value_nick) == 0)
461 	  return enum_value;
462     }
463 
464   return NULL;
465 }
466 
467 /**
468  * g_flags_get_value_by_nick:
469  * @flags_class: a #GFlagsClass
470  * @nick: the nickname to look up
471  *
472  * Looks up a #GFlagsValue by nickname.
473  *
474  * Returns: the #GFlagsValue with nickname @nick, or %NULL if there is
475  *          no flag with that nickname
476  */
477 GFlagsValue*
g_flags_get_value_by_nick(GFlagsClass * flags_class,const gchar * nick)478 g_flags_get_value_by_nick (GFlagsClass *flags_class,
479 			   const gchar *nick)
480 {
481   g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
482   g_return_val_if_fail (nick != NULL, NULL);
483 
484   if (flags_class->n_values)
485     {
486       GFlagsValue *flags_value;
487 
488       for (flags_value = flags_class->values; flags_value->value_nick; flags_value++)
489 	if (flags_value->value_nick && strcmp (nick, flags_value->value_nick) == 0)
490 	  return flags_value;
491     }
492 
493   return NULL;
494 }
495 
496 /**
497  * g_enum_get_value:
498  * @enum_class: a #GEnumClass
499  * @value: the value to look up
500  *
501  * Returns the #GEnumValue for a value.
502  *
503  * Returns: the #GEnumValue for @value, or %NULL if @value is not a
504  *          member of the enumeration
505  */
506 GEnumValue*
g_enum_get_value(GEnumClass * enum_class,gint value)507 g_enum_get_value (GEnumClass *enum_class,
508 		  gint	      value)
509 {
510   g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
511 
512   if (enum_class->n_values)
513     {
514       GEnumValue *enum_value;
515 
516       for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
517 	if (enum_value->value == value)
518 	  return enum_value;
519     }
520 
521   return NULL;
522 }
523 
524 /**
525  * g_flags_get_first_value:
526  * @flags_class: a #GFlagsClass
527  * @value: the value
528  *
529  * Returns the first #GFlagsValue which is set in @value.
530  *
531  * Returns: the first #GFlagsValue which is set in @value, or %NULL if
532  *          none is set
533  */
534 GFlagsValue*
g_flags_get_first_value(GFlagsClass * flags_class,guint value)535 g_flags_get_first_value (GFlagsClass *flags_class,
536 			 guint	      value)
537 {
538   g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
539 
540   if (flags_class->n_values)
541     {
542       GFlagsValue *flags_value;
543 
544       if (value == 0)
545         {
546           for (flags_value = flags_class->values; flags_value->value_name; flags_value++)
547             if (flags_value->value == 0)
548               return flags_value;
549         }
550       else
551         {
552           for (flags_value = flags_class->values; flags_value->value_name; flags_value++)
553             if (flags_value->value != 0 && (flags_value->value & value) == flags_value->value)
554               return flags_value;
555         }
556     }
557 
558   return NULL;
559 }
560 
561 /**
562  * g_value_set_enum:
563  * @value: a valid #GValue whose type is derived from %G_TYPE_ENUM
564  * @v_enum: enum value to be set
565  *
566  * Set the contents of a %G_TYPE_ENUM #GValue to @v_enum.
567  */
568 void
g_value_set_enum(GValue * value,gint v_enum)569 g_value_set_enum (GValue *value,
570 		  gint    v_enum)
571 {
572   g_return_if_fail (G_VALUE_HOLDS_ENUM (value));
573 
574   value->data[0].v_long = v_enum;
575 }
576 
577 /**
578  * g_value_get_enum:
579  * @value: a valid #GValue whose type is derived from %G_TYPE_ENUM
580  *
581  * Get the contents of a %G_TYPE_ENUM #GValue.
582  *
583  * Returns: enum contents of @value
584  */
585 gint
g_value_get_enum(const GValue * value)586 g_value_get_enum (const GValue *value)
587 {
588   g_return_val_if_fail (G_VALUE_HOLDS_ENUM (value), 0);
589 
590   return value->data[0].v_long;
591 }
592 
593 /**
594  * g_value_set_flags:
595  * @value: a valid #GValue whose type is derived from %G_TYPE_FLAGS
596  * @v_flags: flags value to be set
597  *
598  * Set the contents of a %G_TYPE_FLAGS #GValue to @v_flags.
599  */
600 void
g_value_set_flags(GValue * value,guint v_flags)601 g_value_set_flags (GValue *value,
602 		   guint   v_flags)
603 {
604   g_return_if_fail (G_VALUE_HOLDS_FLAGS (value));
605 
606   value->data[0].v_ulong = v_flags;
607 }
608 
609 /**
610  * g_value_get_flags:
611  * @value: a valid #GValue whose type is derived from %G_TYPE_FLAGS
612  *
613  * Get the contents of a %G_TYPE_FLAGS #GValue.
614  *
615  * Returns: flags contents of @value
616  */
617 guint
g_value_get_flags(const GValue * value)618 g_value_get_flags (const GValue *value)
619 {
620   g_return_val_if_fail (G_VALUE_HOLDS_FLAGS (value), 0);
621 
622   return value->data[0].v_ulong;
623 }
624 
625 #define __G_ENUMS_C__
626 #include "gobjectaliasdef.c"
627