changed collect_format, collect_value() and lcopy_format, lcopy_value() in
authorTim Janik <timj@gtk.org>
Sat, 17 Feb 2001 05:32:00 +0000 (05:32 +0000)
committerTim Janik <timj@src.gnome.org>
Sat, 17 Feb 2001 05:32:00 +0000 (05:32 +0000)
Sat Feb 17 04:55:35 2001  Tim Janik  <timj@gtk.org>

        * gtype.[hc]: changed collect_format, collect_value() and lcopy_format,
        lcopy_value() in the GTypeValueTable. the collect functions are now
        called only once per value, collect_format/lcopy_format are strings
        that enlist all necessary GTypeCValues to be varargs-collected.

        * gvalue.h: ranamed STATIC_TAG to G_VALUE_NOCOPY_CONTENTS to indicate that
        a value shouldn't copy its contents.

        * gvaluecollector.h: changed G_VALUE_COLLECT() and G_VALUE_LCOPY()
        macros to carry an additional argument (flags) that can be used
        to pass G_VALUE_NOCOPY_CONTENTS along to the collection functions.

        * *.c: adapted collect_value() and lcopy_value() functions to the new
        prototypes, support G_VALUE_NOCOPY_CONTENTS where apropriate.

        * gsignal.[hc]: introduced a G_SIGNAL_TYPE_STATIC_SCOPE flag that can
        be passed along (ORed) with the parameter types, indicating that the
        emission arguments are to be considered static for the scope of the
        emission. should be used with care and only if the caller knows that
        a parameter cannot be destroyed/freed from signal handlers connected
        to an emission.

15 files changed:
docs/reference/gobject/tmpl/gobject-unused.sgml
docs/reference/gobject/tmpl/types.sgml
gobject/ChangeLog
gobject/gboxed.c
gobject/genums.c
gobject/gobject.c
gobject/gparam.c
gobject/gsignal.c
gobject/gsignal.h
gobject/gtype.c
gobject/gtype.h
gobject/gvalue.c
gobject/gvalue.h
gobject/gvaluecollector.h
gobject/gvaluetypes.c

index 246632b..596d110 100644 (file)
@@ -1,3 +1,83 @@
+<!-- ##### SECTION ./tmpl/closures.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/closures.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/closures.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/closures.sgml:Title ##### -->
+Closures
+
+
+<!-- ##### SECTION ./tmpl/enumerations_flags.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/enumerations_flags.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/enumerations_flags.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/enumerations_flags.sgml:Title ##### -->
+Enumeration and Flag Types
+
+
+<!-- ##### SECTION ./tmpl/gboxed.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gboxed.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gboxed.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/gboxed.sgml:Title ##### -->
+gboxed
+
+
+<!-- ##### SECTION ./tmpl/generic_values.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/generic_values.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/generic_values.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/generic_values.sgml:Title ##### -->
+Generic values
+
+
 <!-- ##### SECTION ./tmpl/gtypemodule.sgml.sgml:Long_Description ##### -->
 <para>
 
 gtypemodule.sgml
 
 
+<!-- ##### SECTION ./tmpl/gtypemodule.sgml:Long_Description ##### -->
+<para>
+#GTypeModule provides a simple implementation of the #GTypePlugin
+interface. The model of #GTypeModule is a dynamically loaded module
+which implements some number of types and interface
+implementations. When the module is loaded, it registerse its types
+and interfaces using g_type_module_register_type() and
+g_type_module_add_interface().  As long as any instances of these
+types and interface implementations are in use, the module is kept
+loaded. When the types and interfaces are gone, the module may be
+unloaded. If the types and interfaces become used again, the module
+will be reloaded.
+</para>
+<para>
+Keeping track of whether the module should be loaded or not is done by
+using a use count - it starts at zero, and whenever it is greater than
+zero, the module is loaded. The use count is maintained internally by
+the type system, but also can be explicitely controlled by
+g_type_module_use() and g_type_module_unuse(). Typically, when loading
+a module for the first type, g_type_module_use() will be used to load
+it so that it can initialize its types. At some later point, when the
+module no longer needs to be loaded except for the type
+implementations it contains, g_type_module_unuse() is called.
+</para>
+<para>
+#GTypeModule does not actually provide any implementation of module
+loading and unloading. To create a particular module type you must
+derive from #GTypeModule and implement the load and unload functions
+in #GTypeModuleClass.
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gtypemodule.sgml:See_Also ##### -->
+<para>
+<variablelist>
+
+<varlistentry>
+<term>#GTypePlugin</term>
+<listitem><para>The abstract type loader interface.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term>#GModule</term>
+<listitem><para>Portable mechanism for dynamically loaded modules.</para></listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gtypemodule.sgml:Short_Description ##### -->
+Type Loading Modules
+
+
+<!-- ##### SECTION ./tmpl/gtypemodule.sgml:Title ##### -->
+GTypeModule
+
+
+<!-- ##### SECTION ./tmpl/gtypeplugin.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gtypeplugin.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gtypeplugin.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/gtypeplugin.sgml:Title ##### -->
+GTypePlugin
+
+
+<!-- ##### SECTION ./tmpl/objects.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/objects.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/objects.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/objects.sgml:Title ##### -->
+The Base Object Type
+
+
+<!-- ##### SECTION ./tmpl/param_specs.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/param_specs.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/param_specs.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/param_specs.sgml:Title ##### -->
+Parameter Specifications
+
+
+<!-- ##### SECTION ./tmpl/signals.sgml:Long_Description ##### -->
+<para>
+The basic concept of the signal system is that of the <emphasis>emission</emphasis>
+of a signal.
+Signals are introduced per-type and are identified through strings.
+Signals introduced for a parent type are availale in derived types as well,
+so basically they are a per-type facility that is inherited.
+A signal emission mainly involves invocation of a certain set of callbacks in
+precisely defined manner. There are two main categories of such callbacks,
+per-object
+       <footnote><para> Although signals can deal with any kind of type, i'm
+       referring to those types as "object types" in the following, simply
+       because that is the context most users will encounter signals in.
+       </para></footnote>
+ones and user provided ones.
+The per-object callbacks are most often referred to as "object method
+handler" or "default (signal) handler", while user provided callbacks are
+usually just called "signal handler".
+The object method handler is provided at signal creation time (this most
+frequently happens at the end of an object class' creation), while user
+provided handlers are frequently connected and disconnected to/from a certain
+signal on certain object instances.
+</para>
+<para>
+A signal emission consists of five stages, unless prematurely stopped:
+<variablelist>
+  <varlistentry><term></term><listitem><para>
+       1 - Invocation of the object method handler for %G_SIGNAL_RUN_FIRST signals
+  </para></listitem></varlistentry>
+  <varlistentry><term></term><listitem><para>
+       2 - Invocation of normal user-provided signal handlers (<emphasis>after</emphasis> flag %FALSE)
+  </para></listitem></varlistentry>
+  <varlistentry><term></term><listitem><para>
+       3 - Invocation of the object method handler for %G_SIGNAL_RUN_LAST signals
+  </para></listitem></varlistentry>
+  <varlistentry><term></term><listitem><para>
+       4 - Invocation of user provided signal handlers, connected with an <emphasis>after</emphasis> flag of %TRUE
+  </para></listitem></varlistentry>
+  <varlistentry><term></term><listitem><para>
+       5 - Invocation of the object method handler for %G_SIGNAL_RUN_CLEANUP signals
+  </para></listitem></varlistentry>
+</variablelist>
+The user provided signal handlers are called in the order they were
+connected in.
+All handlers may prematurely stop a signal emission, and any number of
+handlers may be connected, disconnected, blocked or unblocked during
+a signal emission.
+There are certain criteria for skipping user handlers in stages 2 and 4
+of a signal emission.
+First, user handlers may be <emphasis>blocked</emphasis>, blocked handlers are omitted
+during callback invocation, to return from the "blocked" state, a
+handler has to get unblocked exactly the same amount of times
+it has been blocked before.
+Second, upon emission of a %G_SIGNAL_DETAILED signal, an additional
+"detail" argument passed in to g_signal_emit() has to match the detail
+argument of the signal handler currently subject to invocation.
+Specification of no detail argument for signal handlers (omission of the
+detail part of the signal specification upon connection) serves as a
+wildcard and matches any detail argument passed in to emission.
+</para>
+
+
+<!-- ##### SECTION ./tmpl/signals.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/signals.sgml:Short_Description ##### -->
+Signals provide a means for customization of object behaviour and are used
+as general purpose notification mechanism.
+
+
+<!-- ##### SECTION ./tmpl/signals.sgml:Title ##### -->
+Signals
+
+
+<!-- ##### SECTION ./tmpl/standard_params.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/standard_params.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/standard_params.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/standard_params.sgml:Title ##### -->
+Standard Parameter Types
+
+
+<!-- ##### SECTION ./tmpl/value_collection.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/value_collection.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/value_collection.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/value_collection.sgml:Title ##### -->
+Varargs Value Collection
+
+
+<!-- ##### SECTION ./tmpl/value_types.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/value_types.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/value_types.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/value_types.sgml:Title ##### -->
+Standard value types
+
+
 <!-- ##### USER_FUNCTION GObjectGetParamFunc ##### -->
 <para>
 
index 23c92a1..4289ca4 100644 (file)
@@ -287,9 +287,9 @@ used specifically for managing interface types.
 @value_free: 
 @value_copy: 
 @value_peek_pointer: 
-@collect_type
+@collect_format
 @collect_value: 
-@lcopy_type
+@lcopy_format
 @lcopy_value: 
 
 <!-- ##### MACRO G_TYPE_FROM_INSTANCE ##### -->
index 70e850a..de5067c 100644 (file)
@@ -1,3 +1,27 @@
+Sat Feb 17 04:55:35 2001  Tim Janik  <timj@gtk.org>
+
+       * gtype.[hc]: changed collect_format, collect_value() and lcopy_format,
+       lcopy_value() in the GTypeValueTable. the collect functions are now
+       called only once per value, collect_format/lcopy_format are strings
+       that enlist all necessary GTypeCValues to be varargs-collected.
+
+       * gvalue.h: ranamed STATIC_TAG to G_VALUE_NOCOPY_CONTENTS to indicate that
+       a value shouldn't copy its contents.
+
+       * gvaluecollector.h: changed G_VALUE_COLLECT() and G_VALUE_LCOPY()
+       macros to carry an additional argument (flags) that can be used
+       to pass G_VALUE_NOCOPY_CONTENTS along to the collection functions.
+
+       * *.c: adapted collect_value() and lcopy_value() functions to the new
+       prototypes, support G_VALUE_NOCOPY_CONTENTS where apropriate.
+
+       * gsignal.[hc]: introduced a G_SIGNAL_TYPE_STATIC_SCOPE flag that can
+       be passed along (ORed) with the parameter types, indicating that the
+       emission arguments are to be considered static for the scope of the
+       emission. should be used with care and only if the caller knows that
+       a parameter cannot be destroyed/freed from signal handlers connected
+       to an emission.
+
 Fri Feb 16 07:10:44 2001  Tim Janik  <timj@gtk.org>
 
        * gclosure.c:
index c3d90de..a2684b3 100644 (file)
@@ -85,7 +85,7 @@ boxed_proxy_value_init (GValue *value)
 static void
 boxed_proxy_value_free (GValue *value)
 {
-  if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_STATIC_TAG))
+  if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
     {
       BoxedNode key, *node;
 
@@ -119,37 +119,53 @@ boxed_proxy_value_peek_pointer (const GValue *value)
 
 static gchar*
 boxed_proxy_collect_value (GValue      *value,
-                          guint        nth_value,
-                          GType       *collect_type,
-                          GTypeCValue *collect_value)
+                          guint        n_collect_values,
+                          GTypeCValue *collect_values,
+                          guint        collect_flags)
 {
-  BoxedNode key, *node;
-
-  key.type = value->g_type;
-  node = g_bsearch_array_lookup (&boxed_bsa, &key);
-  value->data[0].v_pointer = collect_value->v_pointer ? node->copy (collect_value->v_pointer) : NULL;
+  if (!collect_values[0].v_pointer)
+    value->data[0].v_pointer = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    {
+      value->data[0].v_pointer = collect_values[0].v_pointer;
+      value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
+    }
+  else
+    {
+      BoxedNode key, *node;
+      
+      key.type = value->g_type;
+      node = g_bsearch_array_lookup (&boxed_bsa, &key);
+      value->data[0].v_pointer = node->copy (collect_values[0].v_pointer);
+    }
 
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 boxed_proxy_lcopy_value (const GValue *value,
-                        guint         nth_value,
-                        GType        *collect_type,
-                        GTypeCValue  *collect_value)
+                        guint         n_collect_values,
+                        GTypeCValue  *collect_values,
+                        guint         collect_flags)
 {
-  BoxedNode key, *node;
-  gpointer *boxed_p = collect_value->v_pointer;
+  gpointer *boxed_p = collect_values[0].v_pointer;
 
   if (!boxed_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
 
-  key.type = value->g_type;
-  node = g_bsearch_array_lookup (&boxed_bsa, &key);
-  *boxed_p = value->data[0].v_pointer ? node->copy (value->data[0].v_pointer) : NULL;
+  if (!value->data[0].v_pointer)
+    *boxed_p = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    *boxed_p = value->data[0].v_pointer;
+  else
+    {
+      BoxedNode key, *node;
+
+      key.type = value->g_type;
+      node = g_bsearch_array_lookup (&boxed_bsa, &key);
+      *boxed_p = node->copy (value->data[0].v_pointer);
+    }
 
-  *collect_type = 0;
   return NULL;
 }
 
@@ -163,9 +179,9 @@ g_boxed_type_register_static (const gchar   *name,
     boxed_proxy_value_free,
     boxed_proxy_value_copy,
     boxed_proxy_value_peek_pointer,
-    G_VALUE_COLLECT_POINTER,
+    "p",
     boxed_proxy_collect_value,
-    G_VALUE_COLLECT_POINTER,
+    "p",
     boxed_proxy_lcopy_value,
   };
   static const GTypeInfo type_info = {
@@ -293,7 +309,7 @@ g_value_set_boxed (GValue       *value,
   g_return_if_fail (G_IS_VALUE_BOXED (value));
   g_return_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value)));
 
-  if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_STATIC_TAG))
+  if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
     g_boxed_free (G_VALUE_TYPE (value), value->data[0].v_pointer);
   value->data[0].v_pointer = boxed ? g_boxed_copy (G_VALUE_TYPE (value), boxed) : NULL;
   value->data[1].v_uint = 0;
@@ -306,10 +322,10 @@ g_value_set_static_boxed (GValue       *value,
   g_return_if_fail (G_IS_VALUE_BOXED (value));
   g_return_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value)));
 
-  if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_STATIC_TAG))
+  if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
     g_boxed_free (G_VALUE_TYPE (value), value->data[0].v_pointer);
   value->data[0].v_pointer = (gpointer) boxed;
-  value->data[1].v_uint = boxed ? G_VALUE_STATIC_TAG : 0;
+  value->data[1].v_uint = boxed ? G_VALUE_NOCOPY_CONTENTS : 0;
 }
 
 gpointer
index 4ef62d0..6a20024 100644 (file)
@@ -37,14 +37,14 @@ static void g_flags_class_init              (GFlagsClass    *class,
 static void    value_flags_enum_init           (GValue         *value);
 static void    value_flags_enum_copy_value     (const GValue   *src_value,
                                                 GValue         *dest_value);
-static gchar*  value_flags_enum_collect_value (GValue          *value,
-                                               guint            nth_value,
-                                               GType           *collect_type,
-                                               GTypeCValue     *collect_value);
+static gchar*  value_flags_enum_collect_value  (GValue         *value,
+                                                guint           n_collect_values,
+                                                GTypeCValue    *collect_values,
+                                                guint           collect_flags);
 static gchar*  value_flags_enum_lcopy_value    (const GValue   *value,
-                                                guint           nth_value,
-                                                GType          *collect_type,
-                                                GTypeCValue    *collect_value);
+                                                guint           n_collect_values,
+                                                GTypeCValue    *collect_values,
+                                                guint           collect_flags);
 
 
 /* --- functions --- */
@@ -53,13 +53,13 @@ g_enum_types_init (void)    /* sync with gtype.c */
 {
   static gboolean initialized = FALSE;
   static const GTypeValueTable flags_enum_value_table = {
-    value_flags_enum_init,       /* value_init */
-    NULL,                                /* value_free */
+    value_flags_enum_init,         /* value_init */
+    NULL,                          /* value_free */
     value_flags_enum_copy_value,    /* value_copy */
-    NULL,                                /* value_peek_pointer */
-    G_VALUE_COLLECT_INT,                 /* collect_type */
+    NULL,                          /* value_peek_pointer */
+    "i",                           /* collect_format */
     value_flags_enum_collect_value, /* collect_value */
-    G_VALUE_COLLECT_POINTER,     /* lcopy_type */
+    "p",                           /* lcopy_format */
     value_flags_enum_lcopy_value,   /* lcopy_value */
   };
   static GTypeInfo info = {
@@ -110,30 +110,28 @@ value_flags_enum_copy_value (const GValue *src_value,
 
 static gchar*
 value_flags_enum_collect_value (GValue      *value,
-                               guint        nth_value,
-                               GType       *collect_type,
-                               GTypeCValue *collect_value)
+                               guint        n_collect_values,
+                               GTypeCValue *collect_values,
+                               guint        collect_flags)
 {
-  value->data[0].v_long = collect_value->v_int;
-  
-  *collect_type = 0;
+  value->data[0].v_long = collect_values[0].v_int;
+
   return NULL;
 }
 
 static gchar*
 value_flags_enum_lcopy_value (const GValue *value,
-                             guint         nth_value,
-                             GType        *collect_type,
-                             GTypeCValue  *collect_value)
+                             guint         n_collect_values,
+                             GTypeCValue  *collect_values,
+                             guint         collect_flags)
 {
-  gint *int_p = collect_value->v_pointer;
+  gint *int_p = collect_values[0].v_pointer;
   
   if (!int_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
   
   *int_p = value->data[0].v_long;
   
-  *collect_type = 0;
   return NULL;
 }
 
index b105133..a4aed1f 100644 (file)
@@ -88,13 +88,13 @@ static void g_value_object_copy_value               (const GValue   *src_value,
                                                         GValue         *dest_value);
 static gpointer g_value_object_peek_pointer             (const GValue   *value);
 static gchar*  g_value_object_collect_value            (GValue         *value,
-                                                        guint           nth_value,
-                                                        GType          *collect_type,
-                                                        GTypeCValue    *collect_value);
+                                                        guint           n_collect_values,
+                                                        GTypeCValue    *collect_values,
+                                                        guint           collect_flags);
 static gchar*  g_value_object_lcopy_value              (const GValue   *value,
-                                                        guint           nth_value,
-                                                        GType          *collect_type,
-                                                        GTypeCValue    *collect_value);
+                                                        guint           n_collect_values,
+                                                        GTypeCValue    *collect_values,
+                                                        guint           collect_flags);
 static void    g_object_dispatch_properties_changed    (GObject        *object,
                                                         guint           n_pspecs,
                                                         GParamSpec    **pspecs);
@@ -196,9 +196,9 @@ g_object_type_init (void)   /* sync with gtype.c */
     g_value_object_free_value,   /* value_free */
     g_value_object_copy_value,   /* value_copy */
     g_value_object_peek_pointer,  /* value_peek_pointer */
-    G_VALUE_COLLECT_POINTER,     /* collect_type */
+    "p",                         /* collect_format */
     g_value_object_collect_value, /* collect_value */
-    G_VALUE_COLLECT_POINTER,     /* lcopy_type */
+    "p",                         /* lcopy_format */
     g_value_object_lcopy_value,          /* lcopy_value */
   };
   GType type;
@@ -795,7 +795,7 @@ g_object_new_valist (GType    object_type,
       value = g_new (GValue, 1);
       value->g_type = 0;
       g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
-      G_VALUE_COLLECT (value, var_args, &error);
+      G_VALUE_COLLECT (value, var_args, 0, &error);
       if (error)
        {
          g_warning ("%s: %s", G_STRLOC, error);
@@ -1008,7 +1008,7 @@ g_object_set_valist (GObject       *object,
       
       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
       
-      G_VALUE_COLLECT (&value, var_args, &error);
+      G_VALUE_COLLECT (&value, var_args, 0, &error);
       if (error)
        {
          g_warning ("%s: %s", G_STRLOC, error);
@@ -1077,7 +1077,7 @@ g_object_get_valist (GObject       *object,
       
       object_get_property (object, &value, pspec, trailer);
       
-      G_VALUE_LCOPY (&value, var_args, &error);
+      G_VALUE_LCOPY (&value, var_args, 0, &error);
       if (error)
        {
          g_warning ("%s: %s", G_STRLOC, error);
@@ -1393,13 +1393,13 @@ g_value_object_peek_pointer (const GValue *value)
 
 static gchar*
 g_value_object_collect_value (GValue     *value,
-                             guint        nth_value,
-                             GType       *collect_type,
-                             GTypeCValue *collect_value)
+                             guint        n_collect_values,
+                             GTypeCValue *collect_values,
+                             guint        collect_flags)
 {
-  if (collect_value->v_pointer)
+  if (collect_values[0].v_pointer)
     {
-      GObject *object = collect_value->v_pointer;
+      GObject *object = collect_values[0].v_pointer;
       
       if (object->g_type_instance.g_class == NULL)
        return g_strconcat ("invalid unclassed object pointer for value type `",
@@ -1418,24 +1418,27 @@ g_value_object_collect_value (GValue      *value,
   else
     value->data[0].v_pointer = NULL;
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 g_value_object_lcopy_value (const GValue *value,
-                           guint         nth_value,
-                           GType        *collect_type,
-                           GTypeCValue  *collect_value)
+                           guint        n_collect_values,
+                           GTypeCValue *collect_values,
+                           guint        collect_flags)
 {
-  GObject **object_p = collect_value->v_pointer;
+  GObject **object_p = collect_values[0].v_pointer;
   
   if (!object_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+
+  if (!value->data[0].v_pointer)
+    *object_p = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    *object_p = value->data[0].v_pointer;
+  else
+    *object_p = g_object_ref (value->data[0].v_pointer);
   
-  *object_p = value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
-  
-  *collect_type = 0;
   return NULL;
 }
 
index 0c99722..7ead600 100644 (file)
@@ -51,13 +51,13 @@ static void value_param_copy_value          (const GValue   *src_value,
                                                 GValue         *dest_value);
 static gpointer        value_param_peek_pointer        (const GValue   *value);
 static gchar*  value_param_collect_value       (GValue         *value,
-                                                guint           nth_value,
-                                                GType          *collect_type,
-                                                GTypeCValue    *collect_value);
+                                                guint           n_collect_values,
+                                                GTypeCValue    *collect_values,
+                                                guint           collect_flags);
 static gchar*  value_param_lcopy_value         (const GValue   *value,
-                                                guint           nth_value,
-                                                GType          *collect_type,
-                                                GTypeCValue    *collect_value);
+                                                guint           n_collect_values,
+                                                GTypeCValue    *collect_values,
+                                                guint           collect_flags);
 
 
 /* --- variables --- */
@@ -80,9 +80,9 @@ g_param_type_init (void)      /* sync with gtype.c */
     value_param_free_value,     /* value_free */
     value_param_copy_value,     /* value_copy */
     value_param_peek_pointer,   /* value_peek_pointer */
-    G_VALUE_COLLECT_POINTER,    /* collect_type */
+    "p",                       /* collect_format */
     value_param_collect_value,  /* collect_value */
-    G_VALUE_COLLECT_POINTER,    /* lcopy_type */
+    "p",                       /* lcopy_format */
     value_param_lcopy_value,    /* lcopy_value */
   };
   static const GTypeInfo param_spec_info = {
@@ -399,13 +399,13 @@ value_param_peek_pointer (const GValue *value)
 
 static gchar*
 value_param_collect_value (GValue      *value,
-                          guint        nth_value,
-                          GType       *collect_type,
-                          GTypeCValue *collect_value)
+                          guint        n_collect_values,
+                          GTypeCValue *collect_values,
+                          guint        collect_flags)
 {
-  if (collect_value->v_pointer)
+  if (collect_values[0].v_pointer)
     {
-      GParamSpec *param = collect_value->v_pointer;
+      GParamSpec *param = collect_values[0].v_pointer;
 
       if (param->g_type_instance.g_class == NULL)
        return g_strconcat ("invalid unclassed param spec pointer for value type `",
@@ -424,24 +424,27 @@ value_param_collect_value (GValue      *value,
   else
     value->data[0].v_pointer = NULL;
 
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_param_lcopy_value (const GValue *value,
-                        guint         nth_value,
-                        GType        *collect_type,
-                        GTypeCValue  *collect_value)
+                        guint         n_collect_values,
+                        GTypeCValue  *collect_values,
+                        guint         collect_flags)
 {
-  GParamSpec **param_p = collect_value->v_pointer;
+  GParamSpec **param_p = collect_values[0].v_pointer;
 
   if (!param_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
 
-  *param_p = value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
+  if (!value->data[0].v_pointer)
+    *param_p = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    *param_p = value->data[0].v_pointer;
+  else
+    *param_p = g_param_spec_ref (value->data[0].v_pointer);
 
-  *collect_type = 0;
   return NULL;
 }
 
index abdd927..3c91c67 100644 (file)
@@ -158,8 +158,8 @@ struct _SignalNode
   /* reinitializable portion */
   guint              flags : 8;
   guint              n_params : 8;
-  GType                    *param_types;
-  GType                     return_type;
+  GType                    *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
+  GType                     return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
   GClosure          *class_closure;
   GSignalAccumulator accumulator;
   GSignalCMarshaller c_marshaller;
@@ -941,8 +941,7 @@ g_signal_newc (const gchar   *signal_name,
   va_start (args, n_params);
 
   signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
-                                   g_signal_type_cclosure_new (itype,
-                                                               class_offset),
+                                   g_signal_type_cclosure_new (itype, class_offset),
                                    accumulator, c_marshaller,
                                    return_type, n_params, args);
 
@@ -1001,19 +1000,20 @@ g_signal_newv (const gchar       *signal_name,
       return 0;
     }
   for (i = 0; i < n_params; i++)
-    if (!G_TYPE_IS_VALUE (param_types[i]) ||
-       param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
+    if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE) ||
+       (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE) == G_TYPE_ENUM ||
+       (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE) == G_TYPE_FLAGS) /* FIXME: kludge */
       {
        g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
-                  i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
+                  i + 1, g_type_name (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE), g_type_name (itype), name);
        g_free (name);
        G_UNLOCK (g_signal_mutex);
        return 0;
       }
-  if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
+  if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
     {
       g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
-                g_type_name (param_types[i]), g_type_name (itype), name);
+                g_type_name (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE), g_type_name (itype), name);
       g_free (name);
       G_UNLOCK (g_signal_mutex);
       return 0;
@@ -1559,11 +1559,11 @@ g_signal_emitv (const GValue *instance_and_params,
       return;
     }
   for (i = 0; i < node->n_params; i++)
-    if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
+    if (!G_VALUE_HOLDS (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
       {
        g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
                    G_STRLOC,
-                   g_type_name (node->param_types[i]),
+                   g_type_name (node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE),
                    i,
                    node->name,
                    G_VALUE_TYPE_NAME (param_values + i));
@@ -1576,16 +1576,16 @@ g_signal_emitv (const GValue *instance_and_params,
        {
          g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
                      G_STRLOC,
-                     g_type_name (node->return_type),
+                     g_type_name (node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE),
                      node->name);
          G_UNLOCK (g_signal_mutex);
          return;
        }
-      else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
+      else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
        {
          g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
                      G_STRLOC,
-                     g_type_name (node->return_type),
+                     g_type_name (node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE),
                      node->name,
                      G_VALUE_TYPE_NAME (return_value));
          G_UNLOCK (g_signal_mutex);
@@ -1644,8 +1644,11 @@ g_signal_emit_valist (gpointer instance,
       gchar *error;
 
       param_values[i].g_type = 0;
-      g_value_init (param_values + i, node->param_types[i]);
-      G_VALUE_COLLECT (param_values + i, var_args, &error);
+      g_value_init (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+      G_VALUE_COLLECT (param_values + i,
+                      var_args,
+                      node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE ? G_VALUE_NOCOPY_CONTENTS : 0,
+                      &error);
       if (error)
        {
          g_warning ("%s: %s", G_STRLOC, error);
@@ -1672,9 +1675,12 @@ g_signal_emit_valist (gpointer instance,
       GValue return_value = { 0, };
       gchar *error = NULL;
 
-      g_value_init (&return_value, node->return_type);
+      g_value_init (&return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
       if (signal_emit_R (node, detail, instance, &return_value, instance_and_params))
-       G_VALUE_LCOPY (&return_value, var_args, &error);
+       G_VALUE_LCOPY (&return_value,
+                      var_args,
+                      node->return_type & G_SIGNAL_TYPE_STATIC_SCOPE ? G_VALUE_NOCOPY_CONTENTS : 0,
+                      &error);
       if (!error)
        g_value_unset (&return_value);
       else
@@ -1779,7 +1785,7 @@ signal_emit_R (SignalNode   *node,
   ihint.detail = detail;
   accumulator = node->accumulator;
   if (accumulator)
-    g_value_init (&accu, node->return_type);
+    g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
   emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
                 signal_id, detail, instance, &emission_state);
   class_closure = node->class_closure;
@@ -2007,7 +2013,7 @@ signal_emit_R (SignalNode   *node,
        {
          if (!accumulator)
            {
-             g_value_init (&accu, node->return_type);
+             g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
              need_unset = TRUE;
            }
          else if (accu_used)
index 748e072..b81a92a 100644 (file)
@@ -53,8 +53,8 @@ typedef enum
   G_SIGNAL_DETAILED    = 1 << 4,
   G_SIGNAL_ACTION      = 1 << 5,
   G_SIGNAL_NO_HOOKS    = 1 << 6
-#define G_SIGNAL_FLAGS_MASK  0x7f
 } GSignalFlags;
+#define G_SIGNAL_FLAGS_MASK  0x7f
 typedef enum
 {
   G_SIGNAL_MATCH_ID       = 1 << 0,
@@ -63,8 +63,9 @@ typedef enum
   G_SIGNAL_MATCH_FUNC     = 1 << 3,
   G_SIGNAL_MATCH_DATA     = 1 << 4,
   G_SIGNAL_MATCH_UNBLOCKED = 1 << 5
-#define G_SIGNAL_MATCH_MASK  0x3f
 } GSignalMatchType;
+#define G_SIGNAL_MATCH_MASK  0x3f
+#define        G_SIGNAL_TYPE_STATIC_SCOPE (G_TYPE_FLAG_RESERVED_ID_BIT)
 
 
 /* --- signal information --- */
@@ -78,9 +79,9 @@ struct _GSignalQuery
 {
   guint                signal_id;
   const gchar  *signal_name;
-  GType                itype;
+  GType                itype;       /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
   GSignalFlags signal_flags;
-  GType                return_type;
+  GType                return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
   guint                n_params;
   const GType  *param_types;
 };
index dd74828..4e4096f 100644 (file)
  */
 #include       "gtype.h"
 
+/*
+ * MT safe
+ */
+
 #include       "gtypeplugin.h"
+#include       "gvaluecollector.h"
 #include       <string.h>
 
 
@@ -548,6 +553,20 @@ check_derivation_U (GType        parent_type,
 }
 
 static gboolean
+check_collect_format_I (const gchar *collect_format)
+{
+  const gchar *p = collect_format;
+  gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
+                          G_VALUE_COLLECT_DOUBLE, G_VALUE_COLLECT_POINTER,
+                          0 };
+
+  while (*p)
+    if (!strchr (valid_format, *p++))
+      return FALSE;
+  return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
+}
+
+static gboolean
 check_value_table_I (const gchar           *type_name,
                     const GTypeValueTable *value_table)
 {
@@ -557,8 +576,8 @@ check_value_table_I (const gchar           *type_name,
     {
       if (value_table->value_free || value_table->value_copy ||
          value_table->value_peek_pointer ||
-         value_table->collect_type || value_table->collect_value ||
-         value_table->lcopy_type || value_table->lcopy_value)
+         value_table->collect_format || value_table->collect_value ||
+         value_table->lcopy_format || value_table->lcopy_value)
        g_warning ("cannot handle uninitializable values of type `%s'",
                   type_name);
       return FALSE;
@@ -577,17 +596,31 @@ check_value_table_I (const gchar           *type_name,
          g_warning ("missing `value_copy()' for type `%s'", type_name);
          return FALSE;
        }
-      if ((value_table->collect_type || value_table->collect_value) &&
-         (!value_table->collect_type || !value_table->collect_value))
+      if ((value_table->collect_format || value_table->collect_value) &&
+         (!value_table->collect_format || !value_table->collect_value))
+       {
+         g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
+                    type_name);
+         return FALSE;
+       }
+      if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
+       {
+         g_warning ("the `%s' specification for type `%s' is too long or invalid",
+                    "collect_format",
+                    type_name);
+         return FALSE;
+       }
+      if ((value_table->lcopy_format || value_table->lcopy_value) &&
+         (!value_table->lcopy_format || !value_table->lcopy_value))
        {
-         g_warning ("one of `collect_type' and `collect_value()' is unspecified for type `%s'",
+         g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
                     type_name);
          return FALSE;
        }
-      if ((value_table->lcopy_type || value_table->lcopy_value) &&
-         (!value_table->lcopy_type || !value_table->lcopy_value))
+      if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
        {
-         g_warning ("one of `lcopy_type' and `lcopy_value()' is unspecified for type `%s'",
+         g_warning ("the `%s' specification for type `%s' is too long or invalid",
+                    "lcopy_format",
                     type_name);
          return FALSE;
        }
@@ -834,7 +867,11 @@ type_data_make_W (TypeNode              *node,
   node->data->common.ref_count = 1;
   
   if (vtable_size)
-    *vtable = *value_table;
+    {
+      *vtable = *value_table;
+      vtable->collect_format = g_strdup (value_table->collect_format ? value_table->collect_format : "");
+      vtable->lcopy_format = g_strdup (value_table->lcopy_format ? value_table->lcopy_format : "");
+    }
   node->data->common.value_table = vtable;
   
   g_assert (node->data->common.value_table != NULL); /* paranoid */
@@ -1377,7 +1414,12 @@ type_data_last_unref_Wm (GType    type,
        }
       else
        node->data = NULL;
-      
+
+      if (tdata->common.value_table)
+       {
+         g_free (tdata->common.value_table->collect_format);
+         g_free (tdata->common.value_table->lcopy_format);
+       }
       g_free (tdata);
       
       if (ptype)
index 4a29e4c..b0a0c50 100644 (file)
@@ -273,16 +273,16 @@ struct _GTypeValueTable
                                  GValue       *dest_value);
   /* varargs functionality (optional) */
   gpointer (*value_peek_pointer) (const GValue *value);
-  guint      collect_type;
+  gchar            *collect_format;
   gchar*   (*collect_value)      (GValue       *value,
-                                 guint         nth_value,
-                                 GType        *collect_type,
-                                 GTypeCValue  *collect_value);
-  guint      lcopy_type;
+                                 guint         n_collect_values,
+                                 GTypeCValue  *collect_values,
+                                 guint         collect_flags);
+  gchar            *lcopy_format;
   gchar*   (*lcopy_value)        (const GValue *value,
-                                 guint         nth_value,
-                                 GType        *collect_type,
-                                 GTypeCValue  *collect_value);
+                                 guint         n_collect_values,
+                                 GTypeCValue  *collect_values,
+                                 guint         collect_flags);
 };
 GType g_type_register_static       (GType                       parent_type,
                                     const gchar                *type_name,
index b7eaded..b7f6856 100644 (file)
@@ -127,26 +127,14 @@ g_value_set_instance (GValue  *value,
       GType g_type = G_VALUE_TYPE (value);
       GTypeValueTable *value_table = g_type_value_table_peek (g_type);
       GTypeCValue cvalue = { 0, };
-      guint nth_value = 0;
-      guint collect_type = value_table->collect_type;
       gchar *error_msg;
       
       g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
       g_return_if_fail (g_type_is_a (G_TYPE_FROM_INSTANCE (instance), G_VALUE_TYPE (value)));
-      g_return_if_fail (value_table->collect_type == G_VALUE_COLLECT_POINTER);
+      g_return_if_fail (strcmp (value_table->collect_format, "p") == 0);
       
       cvalue.v_pointer = instance;
-      error_msg = value_table->collect_value (value, nth_value++, &collect_type, &cvalue);
-      
-      /* this shouldn't be triggered, instance types should collect just one pointer,
-       * but since we have to follow the calling conventions for collect_value(),
-       * we can attempt to feed them with 0s if they insist on extra args.
-       */
-      while (collect_type && !error_msg)
-       {
-         memset (&cvalue, 0, sizeof (cvalue));
-         error_msg = value_table->collect_value (value, nth_value++, &collect_type, &cvalue);
-       }
+      error_msg = value_table->collect_value (value, 1, &cvalue, 0);
       
       if (error_msg)
        {
index 364e88a..54d6498 100644 (file)
@@ -81,7 +81,8 @@ gboolean g_value_types_exchangable    (GType         value_type1,
 void     g_value_register_exchange_func        (GType         value_type1,
                                         GType         value_type2,
                                         GValueExchange func);
-#define G_VALUE_STATIC_TAG             (1 << 27)
+#define G_VALUE_NOCOPY_CONTENTS                (1 << 27)
+
 
 #ifdef __cplusplus
 }
index d85e8d6..b34a21a 100644 (file)
@@ -34,13 +34,15 @@ extern "C" {
  */
 enum   /*< skip >*/
 {
-  G_VALUE_COLLECT_NONE,
-  G_VALUE_COLLECT_INT,
-  G_VALUE_COLLECT_LONG,
-  G_VALUE_COLLECT_DOUBLE,
-  G_VALUE_COLLECT_POINTER
+  G_VALUE_COLLECT_INT          = 'i',
+  G_VALUE_COLLECT_LONG         = 'l',
+  G_VALUE_COLLECT_DOUBLE       = 'd',
+  G_VALUE_COLLECT_POINTER      = 'p'
 };
 
+
+/* vararg union holding actuall values collected
+ */
 union _GTypeCValue
 {
   gint     v_int;
@@ -60,94 +62,89 @@ union _GTypeCValue
  * __error is a gchar** variable that will be modified to hold a g_new()
  * allocated error messages if something fails.
  */
-#define G_VALUE_COLLECT(value, var_args, __error)                                      \
+#define G_VALUE_COLLECT(value, var_args, flags, __error)                               \
 G_STMT_START {                                                                         \
   GValue *_value = (value);                                                            \
+  guint _flags = (flags);                                                              \
   GTypeValueTable *_vtable = g_type_value_table_peek (G_VALUE_TYPE (_value));          \
-  gchar *_error_msg = NULL;                                                            \
-  guint _collect_type = _vtable->collect_type;                                         \
-  guint _nth_value = 0;                                                                        \
+  gchar *_collect_format = _vtable->collect_format;                                    \
+  GTypeCValue _cvalues[G_VALUE_COLLECT_FORMAT_MAX_LENGTH] = { { 0, }, };               \
+  guint _n_values = 0;                                                                 \
                                                                                         \
   g_value_reset (_value);                                                              \
-  while (_collect_type && !_error_msg)                                                 \
+  while (*_collect_format)                                                             \
     {                                                                                  \
-      GTypeCValue _cvalue = { 0, };                                                    \
+      GTypeCValue *_cvalue = _cvalues + _n_values++;                                   \
                                                                                         \
-      switch (_collect_type)                                                           \
+      switch (*_collect_format++)                                                      \
        {                                                                               \
        case G_VALUE_COLLECT_INT:                                                       \
-         _cvalue.v_int = va_arg ((var_args), gint);                                    \
+         _cvalue->v_int = va_arg ((var_args), gint);                                   \
          break;                                                                        \
        case G_VALUE_COLLECT_LONG:                                                      \
-         _cvalue.v_long = va_arg ((var_args), glong);                                  \
+         _cvalue->v_long = va_arg ((var_args), glong);                                 \
          break;                                                                        \
        case G_VALUE_COLLECT_DOUBLE:                                                    \
-         _cvalue.v_double = va_arg ((var_args), gdouble);                              \
+         _cvalue->v_double = va_arg ((var_args), gdouble);                             \
          break;                                                                        \
        case G_VALUE_COLLECT_POINTER:                                                   \
-         _cvalue.v_pointer = va_arg ((var_args), gpointer);                            \
+         _cvalue->v_pointer = va_arg ((var_args), gpointer);                           \
          break;                                                                        \
        default:                                                                        \
-         _error_msg  = g_strdup_printf ("%s: invalid collect type (%d) used for %s",   \
-                                        G_STRLOC,                                      \
-                                        _collect_type,                                 \
-                                        "G_VALUE_COLLECT()");                          \
-         continue;                                                                     \
+         g_assert_not_reached ();                                                      \
        }                                                                               \
-      _error_msg = _vtable->collect_value (_value,                                     \
-                                          _nth_value++,                                \
-                                          &_collect_type,                              \
-                                          &_cvalue);                                   \
     }                                                                                  \
-  *(__error) = _error_msg;                                                             \
+  *(__error) = _vtable->collect_value (_value,                                         \
+                                      _n_values,                                       \
+                                      _cvalues,                                        \
+                                      _flags);                                         \
 } G_STMT_END
 
 
 /* G_VALUE_LCOPY() collects a value's variable argument
  * locations from a va_list. usage is analogous to G_VALUE_COLLECT().
  */
-#define G_VALUE_LCOPY(value, var_args, __error)                                                \
+#define G_VALUE_LCOPY(value, var_args, flags, __error)                                 \
 G_STMT_START {                                                                         \
   GValue *_value = (value);                                                            \
+  guint _flags = (flags);                                                              \
   GTypeValueTable *_vtable = g_type_value_table_peek (G_VALUE_TYPE (_value));          \
-  gchar *_error_msg = NULL;                                                            \
-  guint _lcopy_type = _vtable->lcopy_type;                                             \
-  guint _nth_value = 0;                                                                        \
+  gchar *_lcopy_format = _vtable->lcopy_format;                                                \
+  GTypeCValue _cvalues[G_VALUE_COLLECT_FORMAT_MAX_LENGTH] = { { 0, }, };               \
+  guint _n_values = 0;                                                                 \
                                                                                         \
-  while (_lcopy_type && !_error_msg)                                                   \
+  while (*_lcopy_format)                                                               \
     {                                                                                  \
-      GTypeCValue _cvalue = { 0, };                                                    \
+      GTypeCValue *_cvalue = _cvalues + _n_values++;                                   \
                                                                                         \
-      switch (_lcopy_type)                                                             \
+      switch (*_lcopy_format++)                                                                \
        {                                                                               \
        case G_VALUE_COLLECT_INT:                                                       \
-         _cvalue.v_int = va_arg ((var_args), gint);                                    \
+         _cvalue->v_int = va_arg ((var_args), gint);                                   \
          break;                                                                        \
        case G_VALUE_COLLECT_LONG:                                                      \
-         _cvalue.v_long = va_arg ((var_args), glong);                                  \
+         _cvalue->v_long = va_arg ((var_args), glong);                                 \
          break;                                                                        \
        case G_VALUE_COLLECT_DOUBLE:                                                    \
-         _cvalue.v_double = va_arg ((var_args), gdouble);                              \
+         _cvalue->v_double = va_arg ((var_args), gdouble);                             \
          break;                                                                        \
        case G_VALUE_COLLECT_POINTER:                                                   \
-         _cvalue.v_pointer = va_arg ((var_args), gpointer);                            \
+         _cvalue->v_pointer = va_arg ((var_args), gpointer);                           \
          break;                                                                        \
        default:                                                                        \
-         _error_msg  = g_strdup_printf ("%s: invalid collect type (%d) used for %s",   \
-                                        G_STRLOC,                                      \
-                                        _lcopy_type,                                   \
-                                        "G_VALUE_LCOPY()");                            \
-         continue;                                                                     \
+         g_assert_not_reached ();                                                      \
        }                                                                               \
-      _error_msg = _vtable->lcopy_value (_value,                                       \
-                                        _nth_value++,                                  \
-                                        &_lcopy_type,                                  \
-                                        &_cvalue);                                     \
     }                                                                                  \
-  *(__error) = _error_msg;                                                             \
+  *(__error) = _vtable->lcopy_value (_value,                                           \
+                                    _n_values,                                         \
+                                    _cvalues,                                          \
+                                    _flags);                                           \
 } G_STMT_END
 
 
+#define        G_VALUE_COLLECT_FORMAT_MAX_LENGTH       (8)
+
+
 
 #ifdef __cplusplus
 }
index 1980e95..42193b2 100644 (file)
@@ -43,93 +43,87 @@ value_long0_copy (const GValue *src_value,
 
 static gchar*
 value_char_lcopy_value (const GValue *value,
-                       guint         nth_value,
-                       GType        *collect_type,
-                       GTypeCValue  *collect_value)
+                       guint         n_collect_values,
+                       GTypeCValue  *collect_values,
+                       guint         collect_flags)
 {
-  gint8 *int8_p = collect_value->v_pointer;
+  gint8 *int8_p = collect_values[0].v_pointer;
   
   if (!int8_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
   
   *int8_p = value->data[0].v_int;
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_boolean_lcopy_value (const GValue *value,
-                          guint         nth_value,
-                          GType        *collect_type,
-                          GTypeCValue  *collect_value)
+                          guint         n_collect_values,
+                          GTypeCValue  *collect_values,
+                          guint         collect_flags)
 {
-  gboolean *bool_p = collect_value->v_pointer;
+  gboolean *bool_p = collect_values[0].v_pointer;
   
   if (!bool_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
   
   *bool_p = value->data[0].v_int;
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_int_collect_value (GValue             *value,
-                        guint        nth_value,
-                        GType       *collect_type,
-                        GTypeCValue *collect_value)
+                        guint        n_collect_values,
+                        GTypeCValue *collect_values,
+                        guint        collect_flags)
 {
-  value->data[0].v_int = collect_value->v_int;
+  value->data[0].v_int = collect_values[0].v_int;
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_int_lcopy_value (const GValue *value,
-                      guint         nth_value,
-                      GType        *collect_type,
-                      GTypeCValue  *collect_value)
+                      guint         n_collect_values,
+                      GTypeCValue  *collect_values,
+                      guint         collect_flags)
 {
-  gint *int_p = collect_value->v_pointer;
+  gint *int_p = collect_values[0].v_pointer;
   
   if (!int_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
   
   *int_p = value->data[0].v_int;
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_long_collect_value (GValue      *value,
-                         guint        nth_value,
-                         GType       *collect_type,
-                         GTypeCValue *collect_value)
+                         guint        n_collect_values,
+                         GTypeCValue *collect_values,
+                         guint        collect_flags)
 {
-  value->data[0].v_long = collect_value->v_long;
+  value->data[0].v_long = collect_values[0].v_long;
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_long_lcopy_value (const GValue *value,
-                       guint         nth_value,
-                       GType        *collect_type,
-                       GTypeCValue  *collect_value)
+                        guint         n_collect_values,
+                       GTypeCValue  *collect_values,
+                       guint         collect_flags)
 {
-  glong *long_p = collect_value->v_pointer;
+  glong *long_p = collect_values[0].v_pointer;
   
   if (!long_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
   
   *long_p = value->data[0].v_long;
   
-  *collect_type = 0;
   return NULL;
 }
 
@@ -148,30 +142,28 @@ value_float_copy (const GValue *src_value,
 
 static gchar*
 value_float_collect_value (GValue      *value,
-                          guint        nth_value,
-                          GType       *collect_type,
-                          GTypeCValue *collect_value)
+                          guint        n_collect_values,
+                          GTypeCValue *collect_values,
+                          guint        collect_flags)
 {
-  value->data[0].v_float = collect_value->v_double;
+  value->data[0].v_float = collect_values[0].v_double;
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_float_lcopy_value (const GValue *value,
-                        guint         nth_value,
-                        GType        *collect_type,
-                        GTypeCValue  *collect_value)
+                        guint         n_collect_values,
+                        GTypeCValue  *collect_values,
+                        guint         collect_flags)
 {
-  gfloat *float_p = collect_value->v_pointer;
+  gfloat *float_p = collect_values[0].v_pointer;
   
   if (!float_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
   
   *float_p = value->data[0].v_float;
   
-  *collect_type = 0;
   return NULL;
 }
 
@@ -190,30 +182,28 @@ value_double_copy (const GValue *src_value,
 
 static gchar*
 value_double_collect_value (GValue     *value,
-                           guint        nth_value,
-                           GType       *collect_type,
-                           GTypeCValue *collect_value)
+                           guint        n_collect_values,
+                           GTypeCValue *collect_values,
+                           guint        collect_flags)
 {
-  value->data[0].v_double = collect_value->v_double;
+  value->data[0].v_double = collect_values[0].v_double;
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_double_lcopy_value (const GValue *value,
-                         guint         nth_value,
-                         GType        *collect_type,
-                         GTypeCValue  *collect_value)
+                         guint         n_collect_values,
+                         GTypeCValue  *collect_values,
+                         guint         collect_flags)
 {
-  gdouble *double_p = collect_value->v_pointer;
+  gdouble *double_p = collect_values[0].v_pointer;
   
   if (!double_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
   
   *double_p = value->data[0].v_double;
   
-  *collect_type = 0;
   return NULL;
 }
 
@@ -226,7 +216,7 @@ value_string_init (GValue *value)
 static void
 value_string_free_value (GValue *value)
 {
-  if (!(value->data[1].v_uint & G_VALUE_STATIC_TAG))
+  if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
     g_free (value->data[0].v_pointer);
 }
 
@@ -239,30 +229,41 @@ value_string_copy_value (const GValue *src_value,
 
 static gchar*
 value_string_collect_value (GValue     *value,
-                           guint        nth_value,
-                           GType       *collect_type,
-                           GTypeCValue *collect_value)
+                           guint        n_collect_values,
+                           GTypeCValue *collect_values,
+                           guint        collect_flags)
 {
-  value->data[0].v_pointer = g_strdup (collect_value->v_pointer);
+  if (!collect_values[0].v_pointer)
+    value->data[0].v_pointer = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    {
+      value->data[0].v_pointer = collect_values[0].v_pointer;
+      value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
+    }
+  else
+    value->data[0].v_pointer = g_strdup (collect_values[0].v_pointer);
   
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_string_lcopy_value (const GValue *value,
-                         guint         nth_value,
-                         GType        *collect_type,
-                         GTypeCValue  *collect_value)
+                          guint         n_collect_values,
+                         GTypeCValue  *collect_values,
+                         guint         collect_flags)
 {
-  gchar **string_p = collect_value->v_pointer;
+  gchar **string_p = collect_values[0].v_pointer;
   
   if (!string_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
   
-  *string_p = g_strdup (value->data[0].v_pointer);
+  if (!value->data[0].v_pointer)
+    *string_p = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    *string_p = value->data[0].v_pointer;
+  else
+    *string_p = g_strdup (value->data[0].v_pointer);
   
-  *collect_type = 0;
   return NULL;
 }
 
@@ -287,30 +288,28 @@ value_pointer_peek_pointer (const GValue *value)
 
 static gchar*
 value_pointer_collect_value (GValue      *value,
-                            guint        nth_value,
-                            GType       *collect_type,
-                            GTypeCValue *collect_value)
+                            guint        n_collect_values,
+                            GTypeCValue *collect_values,
+                            guint        collect_flags)
 {
-  value->data[0].v_pointer = collect_value->v_pointer;
+  value->data[0].v_pointer = collect_values[0].v_pointer;
 
-  *collect_type = 0;
   return NULL;
 }
 
 static gchar*
 value_pointer_lcopy_value (const GValue *value,
-                          guint         nth_value,
-                          GType        *collect_type,
-                          GTypeCValue  *collect_value)
+                          guint         n_collect_values,
+                          GTypeCValue  *collect_values,
+                          guint         collect_flags)
 {
-  gpointer *pointer_p = collect_value->v_pointer;
+  gpointer *pointer_p = collect_values[0].v_pointer;
 
   if (!pointer_p)
     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
 
   *pointer_p = value->data[0].v_pointer;
 
-  *collect_type = 0;
   return NULL;
 }
 
@@ -331,55 +330,38 @@ value_ccallback_copy (const GValue *src_value,
 
 static gchar*
 value_ccallback_collect_value (GValue      *value,
-                              guint        nth_value,
-                              GType       *collect_type,
-                              GTypeCValue *collect_value)
+                              guint        n_collect_values,
+                              GTypeCValue *collect_values,
+                              guint        collect_flags)
 {
   gchar *error = NULL;
 
-  switch (nth_value)
-    {
-    case 0:
-      value->data[0].v_pointer = collect_value->v_pointer;
-      *collect_type = G_VALUE_COLLECT_POINTER;
-      if (!value->data[0].v_pointer)
-       error = g_strconcat ("invalid (NULL) pointer callback function for value type `",
-                            G_VALUE_TYPE_NAME (value),
-                            "'",
-                            NULL);
-      break;
-    case 1:
-      value->data[1].v_pointer = collect_value->v_pointer;
-      *collect_type = 0;
-      break;
-    }
+  if (!collect_values[0].v_pointer)
+    error = g_strconcat ("invalid (NULL) pointer callback function for value type `",
+                        G_VALUE_TYPE_NAME (value),
+                        "'",
+                        NULL);
+  value->data[0].v_pointer = collect_values[0].v_pointer;
+  value->data[1].v_pointer = collect_values[1].v_pointer;
 
   return error;
 }
 
 static gchar*
 value_ccallback_lcopy_value (const GValue *value,
-                            guint         nth_value,
-                            GType        *collect_type,
-                            GTypeCValue  *collect_value)
+                            guint         n_collect_values,
+                            GTypeCValue  *collect_values,
+                            guint         collect_flags)
 {
-  gpointer *pointer_p = collect_value->v_pointer;
+  gpointer *callback_p = collect_values[0].v_pointer;
+  gpointer *data_p = collect_values[1].v_pointer;
 
-  if (!pointer_p)
+  if (!callback_p || !data_p)
     return g_strdup_printf ("%s location for `%s' passed as NULL",
-                           nth_value ? "data" : "callback",
+                           callback_p ? "data" : "callback",
                            G_VALUE_TYPE_NAME (value));
-  switch (nth_value)
-    {
-    case 0:
-      *pointer_p = value->data[0].v_pointer;
-      *collect_type = G_VALUE_COLLECT_POINTER;
-      break;
-    case 1:
-      *pointer_p = value->data[1].v_pointer;
-      *collect_type = 0;
-      break;
-    }
+  *callback_p = value->data[0].v_pointer;
+  *data_p = value->data[1].v_pointer;
 
   return NULL;
 }
@@ -412,9 +394,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       NULL,                    /* value_free */
       value_long0_copy,                /* value_copy */
       NULL,                    /* value_peek_pointer */
-      G_VALUE_COLLECT_INT,     /* collect_type */
+      "i",                     /* collect_format */
       value_int_collect_value, /* collect_value */
-      G_VALUE_COLLECT_POINTER, /* lcopy_type */
+      "p",                     /* lcopy_format */
       value_char_lcopy_value,  /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -432,9 +414,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       NULL,                     /* value_free */
       value_long0_copy,                 /* value_copy */
       NULL,                      /* value_peek_pointer */
-      G_VALUE_COLLECT_INT,      /* collect_type */
+      "i",                      /* collect_format */
       value_int_collect_value,  /* collect_value */
-      G_VALUE_COLLECT_POINTER,  /* lcopy_type */
+      "p",                      /* lcopy_format */
       value_boolean_lcopy_value, /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -450,9 +432,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       NULL,                    /* value_free */
       value_long0_copy,                /* value_copy */
       NULL,                     /* value_peek_pointer */
-      G_VALUE_COLLECT_INT,     /* collect_type */
+      "i",                     /* collect_format */
       value_int_collect_value, /* collect_value */
-      G_VALUE_COLLECT_POINTER, /* lcopy_type */
+      "p",                     /* lcopy_format */
       value_int_lcopy_value,   /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -470,9 +452,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       NULL,                    /* value_free */
       value_long0_copy,                /* value_copy */
       NULL,                     /* value_peek_pointer */
-      G_VALUE_COLLECT_LONG,    /* collect_type */
+      "l",                     /* collect_format */
       value_long_collect_value,        /* collect_value */
-      G_VALUE_COLLECT_POINTER, /* lcopy_type */
+      "p",                     /* lcopy_format */
       value_long_lcopy_value,  /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -490,9 +472,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       NULL,                     /* value_free */
       value_float_copy,                 /* value_copy */
       NULL,                      /* value_peek_pointer */
-      G_VALUE_COLLECT_DOUBLE,   /* collect_type */
+      "d",                      /* collect_format */
       value_float_collect_value, /* collect_value */
-      G_VALUE_COLLECT_POINTER,  /* lcopy_type */
+      "p",                      /* lcopy_format */
       value_float_lcopy_value,  /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -508,9 +490,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       NULL,                      /* value_free */
       value_double_copy,         /* value_copy */
       NULL,                       /* value_peek_pointer */
-      G_VALUE_COLLECT_DOUBLE,    /* collect_type */
+      "d",                       /* collect_format */
       value_double_collect_value, /* collect_value */
-      G_VALUE_COLLECT_POINTER,   /* lcopy_type */
+      "p",                       /* lcopy_format */
       value_double_lcopy_value,          /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -526,9 +508,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       value_string_free_value,   /* value_free */
       value_string_copy_value,   /* value_copy */
       value_pointer_peek_pointer, /* value_peek_pointer */
-      G_VALUE_COLLECT_POINTER,   /* collect_type */
+      "p",                       /* collect_format */
       value_string_collect_value, /* collect_value */
-      G_VALUE_COLLECT_POINTER,   /* lcopy_type */
+      "p",                       /* lcopy_format */
       value_string_lcopy_value,          /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -544,9 +526,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       NULL,                        /* value_free */
       value_pointer_copy,          /* value_copy */
       value_pointer_peek_pointer,  /* value_peek_pointer */
-      G_VALUE_COLLECT_POINTER,     /* collect_type */
+      "p",                        /* collect_format */
       value_pointer_collect_value, /* collect_value */
-      G_VALUE_COLLECT_POINTER,     /* lcopy_type */
+      "p",                        /* lcopy_format */
       value_pointer_lcopy_value,   /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -562,9 +544,9 @@ g_value_types_init (void)  /* sync with gtype.c */
       NULL,                          /* value_free */
       value_ccallback_copy,          /* value_copy */
       NULL,                          /* value_peek_pointer */
-      G_VALUE_COLLECT_POINTER,       /* collect_type */
+      "pp",                         /* collect_format */
       value_ccallback_collect_value, /* collect_value */
-      G_VALUE_COLLECT_POINTER,       /* lcopy_type */
+      "pp",                         /* lcopy_format */
       value_ccallback_lcopy_value,   /* lcopy_value */
     };
     info.value_table = &value_table;
@@ -734,7 +716,7 @@ g_value_set_string (GValue  *value,
 {
   g_return_if_fail (G_IS_VALUE_STRING (value));
   
-  if (value->data[1].v_uint & G_VALUE_STATIC_TAG)
+  if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
     value->data[1].v_uint = 0;
   else
     g_free (value->data[0].v_pointer);
@@ -747,9 +729,9 @@ g_value_set_static_string (GValue      *value,
 {
   g_return_if_fail (G_IS_VALUE_STRING (value));
   
-  if (!(value->data[1].v_uint & G_VALUE_STATIC_TAG))
+  if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
     g_free (value->data[0].v_pointer);
-  value->data[1].v_uint = G_VALUE_STATIC_TAG;
+  value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
   value->data[0].v_pointer = (gchar*) v_string;
 }