[glib/wip/enum-types-reloc: 1/2] Allow copying the enumeration values when registering types



commit 2b07c124af7f94259b57ba5659d60600e81c998f
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Jul 19 18:32:54 2017 +0100

    Allow copying the enumeration values when registering types
    
    The existing API for registering enumeration types requires that the
    GEnumValue and GFlagsValue arrays that describe the enumeration values
    is located in static storage. This causes unnecessary relocations, and
    does not save that much memory, compared to the rest of GType.
    
    We can provide a new API, to be used by developers, to copy the
    enumeration values, and thus drop the ones they have from static
    storage.

 gobject/genums.c |  122 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gobject/genums.h |    8 ++++
 2 files changed, 128 insertions(+), 2 deletions(-)
---
diff --git a/gobject/genums.c b/gobject/genums.c
index 8212dd9..0763820 100644
--- a/gobject/genums.c
+++ b/gobject/genums.c
@@ -69,8 +69,12 @@
 /* --- prototypes --- */
 static void    g_enum_class_init               (GEnumClass     *class,
                                                 gpointer        class_data);
+static void     g_enum_class_finalize           (GEnumClass     *class,
+                                                 gpointer        class_data);
 static void    g_flags_class_init              (GFlagsClass    *class,
                                                 gpointer        class_data);
+static void     g_flags_class_finalize          (GFlagsClass    *class,
+                                                 gpointer        class_data);
 static void    value_flags_enum_init           (GValue         *value);
 static void    value_flags_enum_copy_value     (const GValue   *src_value,
                                                 GValue         *dest_value);
@@ -218,6 +222,56 @@ g_enum_register_static (const gchar         *name,
 }
 
 /**
+ * g_enum_type_register_static:
+ * @name: A nul-terminated string used as the name of the new type.
+ * @values: An array of #GEnumValue structs for the possible
+ *  enumeration values. The array is terminated by a struct with all
+ *  members being 0. GObject will copy the data.
+ *
+ * Registers a new static enumeration type with the name @name.
+ *
+ * It is normally more convenient to let [glib-mkenums][glib-mkenums],
+ * generate a my_enum_get_type() function from a usual C enumeration
+ * definition  than to write one yourself using g_enum_register_static().
+ *
+ * Returns: The new type identifier.
+ *
+ * Since: 2.54
+ */
+GType
+g_enum_type_register_static (const gchar      *name,
+                             const GEnumValue *values)
+{
+  GTypeInfo enum_type_info = {
+    sizeof (GEnumClass), /* class_size */
+    NULL,                /* base_init */
+    NULL,                /* base_finalize */
+    (GClassInitFunc) g_enum_class_init,
+    (GClassFinalizeFunc) g_enum_class_finalize,
+    NULL,                /* class_data */
+    0,                   /* instance_size */
+    0,                   /* n_preallocs */
+    NULL,                /* instance_init */
+    NULL,               /* value_table */
+  };
+  const GEnumValue *iter;
+  guint n_values = 0;
+  GType type;
+
+  g_return_val_if_fail (name != NULL, 0);
+  g_return_val_if_fail (values != NULL, 0);
+
+  for (iter = values; iter->value_name; iter++)
+    n_values += 1;
+
+  enum_type_info.class_data = g_memdup (values, n_values * sizeof (GEnumValues));
+
+  type = g_type_register_static (G_TYPE_ENUM, name, &enum_type_info, 0);
+
+  return type;
+}
+
+/**
  * g_flags_register_static:
  * @name: A nul-terminated string used as the name of the new type.
  * @const_static_values: An array of #GFlagsValue structs for the possible
@@ -248,15 +302,65 @@ g_flags_register_static (const gchar         *name,
     NULL,                 /* instance_init */
     NULL,                /* value_table */
   };
+  const GEnumValue *iter;
+  guint n_values = 0;
   GType type;
   
   g_return_val_if_fail (name != NULL, 0);
   g_return_val_if_fail (const_static_values != NULL, 0);
-  
-  flags_type_info.class_data = const_static_values;
+
+  for (iter = values; iter->value_name; iter++)
+    n_values += 1;
+
+  flags_type_info.class_data = g_memdup (values, n_values * sizeof (GEnumValues));
   
   type = g_type_register_static (G_TYPE_FLAGS, name, &flags_type_info, 0);
+
+  return type;
+}
+
+/**
+ * g_flags_type_register_static:
+ * @name: A nul-terminated string used as the name of the new type.
+ * @values: An array of #GFlagsValue structs for the possible flags
+ *   values. The array is terminated by a struct with all members
+ *   being 0. GObject copies the data
+ *
+ * Registers a new static flags type with the name @name.
+ *
+ * It is normally more convenient to let [glib-mkenums][glib-mkenums]
+ * generate a my_flags_get_type() function from a usual C enumeration
+ * definition than to write one yourself using g_flags_register_static().
+ *
+ * Returns: The new type identifier.
+ *
+ * Since: 2.54
+ */
+GType
+g_flags_type_register_static (const gchar      *name,
+                              const GFlagsValue *values)
+{
+  GTypeInfo flags_type_info = {
+    sizeof (GFlagsClass), /* class_size */
+    NULL,                 /* base_init */
+    NULL,                 /* base_finalize */
+    (GClassInitFunc) g_flags_class_init,
+    (GClassFinalizeFunc) g_flags_class_finalize,
+    NULL,                 /* class_data */
+    0,                    /* instance_size */
+    0,                    /* n_preallocs */
+    NULL,                 /* instance_init */
+    NULL,                /* value_table */
+  };
+  GType type;
   
+  g_return_val_if_fail (name != NULL, 0);
+  g_return_val_if_fail (values != NULL, 0);
+
+  flags_type_info.class_data = const_static_values;
+
+  type = g_type_register_static (G_TYPE_FLAGS, name, &flags_type_info, 0);
+
   return type;
 }
 
@@ -362,6 +466,13 @@ g_enum_class_init (GEnumClass *class,
 }
 
 static void
+g_enum_class_finalize (GEnumClass *class,
+                       gpointer    class_data)
+{
+  g_free (class->values);
+}
+
+static void
 g_flags_class_init (GFlagsClass *class,
                    gpointer     class_data)
 {
@@ -383,6 +494,13 @@ g_flags_class_init (GFlagsClass *class,
     }
 }
 
+static void
+g_flags_class_finalize (GFlagsClass *class,
+                        gpointer     class_data)
+{
+  g_free (class->values);
+}
+
 /**
  * g_enum_get_value_by_name:
  * @enum_class: a #GEnumClass
diff --git a/gobject/genums.h b/gobject/genums.h
index c66ce45..4eb377f 100644
--- a/gobject/genums.h
+++ b/gobject/genums.h
@@ -262,6 +262,14 @@ GType      g_enum_register_static     (const gchar       *name,
 GLIB_AVAILABLE_IN_ALL
 GType  g_flags_register_static    (const gchar       *name,
                                    const GFlagsValue *const_static_values);
+
+GLIB_AVAILABLE_IN_2_54
+GType   g_enum_type_register_static     (const gchar       *name,
+                                         const GEnumValue  *values);
+GLIB_AVAILABLE_IN_2_54
+GType   g_flags_type_register_static    (const gchar       *name,
+                                         const GFlagsValue *values);
+
 /* functions to complete the type information
  * for enums/flags implemented by plugins
  */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]