return whether a value got removed.
authorTim Janik <timj@gtk.org>
Wed, 13 Dec 2000 00:44:18 +0000 (00:44 +0000)
committerTim Janik <timj@src.gnome.org>
Wed, 13 Dec 2000 00:44:18 +0000 (00:44 +0000)
Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>

        * ghash.c (g_hash_table_remove): return whether a value
        got removed.

Tue Dec 12 23:38:02 2000  Tim Janik  <timj@gtk.org>

        * Makefile.am: _never_ touch oldest-source-stamp.

        * gobject.[hc]: construct property handling fixes/improvements.
        fixed trailer handling in get/set property.

        * gparam.[hc]: implement param spec pool, got rid of param spec
        hashtable. the most prominent change is that e deal with type
        prefixes here.

18 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
ghash.c
ghash.h
glib/ghash.c
glib/ghash.h
gobject/ChangeLog
gobject/gobject.c
gobject/gobject.h
gobject/gparam.c
gobject/gparam.h
gobject/gtype.c

index 4dcd875..4dca3db 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>
+
+       * ghash.c (g_hash_table_remove): return whether a value
+       got removed.
+
 Tue Dec 12 15:18:10 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.[ch]: Revert unauthorized changes.
index 4dcd875..4dca3db 100644 (file)
@@ -1,3 +1,8 @@
+Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>
+
+       * ghash.c (g_hash_table_remove): return whether a value
+       got removed.
+
 Tue Dec 12 15:18:10 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.[ch]: Revert unauthorized changes.
index 4dcd875..4dca3db 100644 (file)
@@ -1,3 +1,8 @@
+Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>
+
+       * ghash.c (g_hash_table_remove): return whether a value
+       got removed.
+
 Tue Dec 12 15:18:10 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.[ch]: Revert unauthorized changes.
index 4dcd875..4dca3db 100644 (file)
@@ -1,3 +1,8 @@
+Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>
+
+       * ghash.c (g_hash_table_remove): return whether a value
+       got removed.
+
 Tue Dec 12 15:18:10 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.[ch]: Revert unauthorized changes.
index 4dcd875..4dca3db 100644 (file)
@@ -1,3 +1,8 @@
+Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>
+
+       * ghash.c (g_hash_table_remove): return whether a value
+       got removed.
+
 Tue Dec 12 15:18:10 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.[ch]: Revert unauthorized changes.
index 4dcd875..4dca3db 100644 (file)
@@ -1,3 +1,8 @@
+Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>
+
+       * ghash.c (g_hash_table_remove): return whether a value
+       got removed.
+
 Tue Dec 12 15:18:10 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.[ch]: Revert unauthorized changes.
index 4dcd875..4dca3db 100644 (file)
@@ -1,3 +1,8 @@
+Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>
+
+       * ghash.c (g_hash_table_remove): return whether a value
+       got removed.
+
 Tue Dec 12 15:18:10 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.[ch]: Revert unauthorized changes.
index 4dcd875..4dca3db 100644 (file)
@@ -1,3 +1,8 @@
+Tue Dec 12 18:58:22 2000  Tim Janik  <timj@gtk.org>
+
+       * ghash.c (g_hash_table_remove): return whether a value
+       got removed.
+
 Tue Dec 12 15:18:10 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.[ch]: Revert unauthorized changes.
diff --git a/ghash.c b/ghash.c
index d35df18..52427ce 100644 (file)
--- a/ghash.c
+++ b/ghash.c
@@ -169,16 +169,15 @@ g_hash_table_insert (GHashTable *hash_table,
     }
 }
 
-void
-g_hash_table_remove (GHashTable             *hash_table,
-                    gconstpointer    key)
+gboolean
+g_hash_table_remove (GHashTable          *hash_table,
+                    gconstpointer key)
 {
   GHashNode **node, *dest;
   
-  g_return_if_fail (hash_table != NULL);
+  g_return_val_if_fail (hash_table != NULL, FALSE);
   
   node = g_hash_table_lookup_node (hash_table, key);
-
   if (*node)
     {
       dest = *node;
@@ -187,7 +186,11 @@ g_hash_table_remove (GHashTable         *hash_table,
       hash_table->nnodes--;
   
       g_hash_table_resize (hash_table);
+
+      return TRUE;
     }
+
+  return FALSE;
 }
 
 gboolean
diff --git a/ghash.h b/ghash.h
index 2f64131..ce0d1ed 100644 (file)
--- a/ghash.h
+++ b/ghash.h
@@ -45,7 +45,7 @@ void      g_hash_table_destroy        (GHashTable     *hash_table);
 void       g_hash_table_insert         (GHashTable     *hash_table,
                                         gpointer        key,
                                         gpointer        value);
-void       g_hash_table_remove         (GHashTable     *hash_table,
+gboolean    g_hash_table_remove                (GHashTable     *hash_table,
                                         gconstpointer   key);
 gpointer    g_hash_table_lookup                (GHashTable     *hash_table,
                                         gconstpointer   key);
index d35df18..52427ce 100644 (file)
@@ -169,16 +169,15 @@ g_hash_table_insert (GHashTable *hash_table,
     }
 }
 
-void
-g_hash_table_remove (GHashTable             *hash_table,
-                    gconstpointer    key)
+gboolean
+g_hash_table_remove (GHashTable          *hash_table,
+                    gconstpointer key)
 {
   GHashNode **node, *dest;
   
-  g_return_if_fail (hash_table != NULL);
+  g_return_val_if_fail (hash_table != NULL, FALSE);
   
   node = g_hash_table_lookup_node (hash_table, key);
-
   if (*node)
     {
       dest = *node;
@@ -187,7 +186,11 @@ g_hash_table_remove (GHashTable         *hash_table,
       hash_table->nnodes--;
   
       g_hash_table_resize (hash_table);
+
+      return TRUE;
     }
+
+  return FALSE;
 }
 
 gboolean
index 2f64131..ce0d1ed 100644 (file)
@@ -45,7 +45,7 @@ void      g_hash_table_destroy        (GHashTable     *hash_table);
 void       g_hash_table_insert         (GHashTable     *hash_table,
                                         gpointer        key,
                                         gpointer        value);
-void       g_hash_table_remove         (GHashTable     *hash_table,
+gboolean    g_hash_table_remove                (GHashTable     *hash_table,
                                         gconstpointer   key);
 gpointer    g_hash_table_lookup                (GHashTable     *hash_table,
                                         gconstpointer   key);
index ab686b4..928ac3a 100644 (file)
@@ -1,3 +1,14 @@
+Tue Dec 12 23:38:02 2000  Tim Janik  <timj@gtk.org>
+
+       * Makefile.am: _never_ touch oldest-source-stamp.
+       
+       * gobject.[hc]: construct property handling fixes/improvements.
+       fixed trailer handling in get/set property.
+       
+       * gparam.[hc]: implement param spec pool, got rid of param spec
+       hashtable. the most prominent change is that e deal with type
+       prefixes here.
+       
 2000-12-12  Elliot Lee  <sopwith@redhat.com>
 
        * Makefile.am:
index f1be160..50e68a0 100644 (file)
@@ -126,11 +126,11 @@ struct _NotifyQueue
 
 
 /* --- variables --- */
-static GQuark           quark_notify_queue = 0;
-static GQuark           quark_property_id = 0;
-static GQuark           quark_closure_array = 0;
-static GHashTable      *pspec_hash_table = NULL;
-static gulong           gobject_signals[LAST_SIGNAL] = { 0, };
+static GQuark         quark_notify_queue = 0;
+static GQuark         quark_property_id = 0;
+static GQuark         quark_closure_array = 0;
+static GParamSpecPool *pspec_pool = NULL;
+static gulong         gobject_signals[LAST_SIGNAL] = { 0, };
 
 
 /* --- functions --- */
@@ -218,9 +218,12 @@ g_object_type_init (void)  /* sync with gtype.c */
 static void
 g_object_base_class_init (GObjectClass *class)
 {
+  GObjectClass *pclass = g_type_class_peek_parent (class);
+
   /* reset instance specific fields and methods that don't get inherited */
   class->n_property_specs = 0;
   class->property_specs = NULL;
+  class->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL;
   class->get_property = NULL;
   class->set_property = NULL;
 }
@@ -233,12 +236,14 @@ g_object_base_class_finalize (GObjectClass *class)
   g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
 
   _g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
-  
+
+  g_slist_free (class->construct_properties);
+  class->construct_properties = NULL;
   for (i = 0; i < class->n_property_specs; i++)
     {
       GParamSpec *pspec = class->property_specs[i];
       
-      g_param_spec_hash_table_remove (pspec_hash_table, pspec);
+      g_param_spec_pool_remove (pspec_pool, pspec);
       g_param_spec_set_qdata (pspec, quark_property_id, NULL);
       g_param_spec_unref (pspec);
     }
@@ -253,7 +258,7 @@ g_object_do_class_init (GObjectClass *class)
   quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
   quark_property_id = g_quark_from_static_string ("GObject-property-id");
   quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
-  pspec_hash_table = g_param_spec_hash_table_new ();
+  pspec_pool = g_param_spec_pool_new (TRUE);
   
   class->constructor = g_object_constructor;
   class->set_property = g_object_do_set_property;
@@ -332,7 +337,7 @@ g_object_class_install_property (GObjectClass *class,
   g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
   if (pspec->flags & G_PARAM_CONSTRUCT)
     g_return_if_fail ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
-  if (pspec->flags & (G_PARAM_CONSTRUCT || G_PARAM_CONSTRUCT_ONLY))
+  if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
     g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
 
   /* expensive paranoia checks ;( */
@@ -347,7 +352,7 @@ g_object_class_install_property (GObjectClass *class,
                   pspec->name);
        return;
       }
-  if (g_object_class_find_property (class, pspec->name))
+  if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE, NULL))
     {
       g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
                 G_OBJECT_CLASS_NAME (class),
@@ -358,10 +363,19 @@ g_object_class_install_property (GObjectClass *class,
   g_param_spec_ref (pspec);
   g_param_spec_sink (pspec);
   g_param_spec_set_qdata (pspec, quark_property_id, GUINT_TO_POINTER (property_id));
-  g_param_spec_hash_table_insert (pspec_hash_table, pspec, G_OBJECT_CLASS_TYPE (class));
+  g_param_spec_pool_insert (pspec_pool, pspec, G_OBJECT_CLASS_TYPE (class));
   i = class->n_property_specs++;
   class->property_specs = g_renew (GParamSpec*, class->property_specs, class->n_property_specs);
   class->property_specs[i] = pspec;
+  if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
+    class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
+
+  /* for property overrides of construct poperties, we have to get rid
+   * of the overidden inherited construct property
+   */
+  pspec = g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type_parent (G_OBJECT_CLASS_TYPE (class)), TRUE, NULL);
+  if (pspec && pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
+    class->construct_properties = g_slist_remove (class->construct_properties, pspec);
 }
 
 GParamSpec*
@@ -371,10 +385,10 @@ g_object_class_find_property (GObjectClass *class,
   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
   g_return_val_if_fail (property_name != NULL, NULL);
   
-  return g_param_spec_hash_table_lookup (pspec_hash_table,
-                                        property_name,
-                                        G_OBJECT_CLASS_TYPE (class),
-                                        TRUE, NULL);
+  return g_param_spec_pool_lookup (pspec_pool,
+                                  property_name,
+                                  G_OBJECT_CLASS_TYPE (class),
+                                  TRUE, NULL);
 }
 
 static void
@@ -446,9 +460,9 @@ g_object_do_set_property (GObject      *object,
       gboolean swapped, after;
       gpointer callback, data;
     case PROP_DATA:
-      g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+      g_return_if_fail (trailer != NULL);
 
-      g_object_set_data (object, trailer + 2, g_value_get_pointer (value));
+      g_object_set_data (object, trailer, g_value_get_pointer (value));
       break;
     case PROP_SWAPPED_SIGNAL_AFTER:
       i++;
@@ -459,10 +473,10 @@ g_object_do_set_property (GObject      *object,
     case PROP_SIGNAL:
       after = i > 2;
       swapped = i & 1;
-      g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+      g_return_if_fail (trailer != NULL);
 
       g_value_get_ccallback (value, &callback, &data);
-      g_signal_connect_data (object, trailer + 2,
+      g_signal_connect_data (object, trailer,
                             callback, data, NULL,
                             swapped, after);
       break;
@@ -482,9 +496,9 @@ g_object_do_get_property (GObject     *object,
   switch (property_id)
     {
     case PROP_DATA:
-      g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+      g_return_if_fail (trailer != NULL);
 
-      g_value_set_pointer (value, g_object_get_data (object, trailer + 2));
+      g_value_set_pointer (value, g_object_get_data (object, trailer));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -598,9 +612,10 @@ static void
 g_object_notify_property_changed (GObject    *object,
                                  GParamSpec *pspec)
 {
-  g_message ("NOTIFICATION: %s property changed on object `%s'",
-            pspec->name,
-            G_OBJECT_TYPE_NAME (object));
+  if (0) /* FIXME */
+    g_message ("NOTIFICATION: property `%s' changed on object `%s'",
+              pspec->name,
+              G_OBJECT_TYPE_NAME (object));
 }
 
 void
@@ -627,10 +642,10 @@ g_object_notify (GObject     *object,
     return;
   
   g_object_ref (object);
-  pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
-                                         property_name,
-                                         G_OBJECT_TYPE (object),
-                                         TRUE, NULL);
+  pspec = g_param_spec_pool_lookup (pspec_pool,
+                                   property_name,
+                                   G_OBJECT_TYPE (object),
+                                   TRUE, NULL);
   if (!pspec)
     g_warning ("%s: object class `%s' has no property named `%s'",
               G_STRLOC,
@@ -725,9 +740,13 @@ g_object_new_valist (GType   object_type,
   const gchar *name;
   GObjectConstructParam *cparams = NULL, *nparams = NULL;
   guint n_cparams = 0, n_nparams = 0;
+  GSList *clist;
   
   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
 
+  class = g_type_class_ref (object_type);
+  clist = g_slist_copy (class->construct_properties);
+
   /* collect parameters, sort into construction and normal ones */
   name = first_property_name;
   while (name)
@@ -736,12 +755,12 @@ g_object_new_valist (GType          object_type,
       GValue *value;
       GParamSpec *pspec;
       gchar *error = NULL;
-
-      pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
-                                             name,
-                                             object_type,
-                                             TRUE,
-                                             &trailer);
+      
+      pspec = g_param_spec_pool_lookup (pspec_pool,
+                                       name,
+                                       object_type,
+                                       TRUE,
+                                       &trailer);
       if (!pspec)
        {
          g_warning ("%s: object class `%s' has no property named `%s'",
@@ -775,17 +794,24 @@ g_object_new_valist (GType          object_type,
        }
       if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
        {
+         guint i;
+
          if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
-           cparams = g_renew (GObjectConstructParam, cparams, n_cparams + 1);
+           cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
          cparams[n_cparams].pspec = pspec;
          cparams[n_cparams].value = value;
          cparams[n_cparams].trailer = trailer;
+         for (i = 0; i < n_cparams; i++)       /* picky, aren't we? ;) */
+           if (cparams[i].pspec == pspec)
+             g_warning (G_STRLOC ": construct property \"%s\" for object `%s' is being set twice",
+                        pspec->name, g_type_name (object_type));
          n_cparams++;
+         clist = g_slist_remove (clist, pspec);   /* FIXME: unique */
        }
       else
        {
          if (!n_nparams || n_nparams >= PREALLOC_CPARAMS)
-           nparams = g_renew (GObjectConstructParam, nparams, n_nparams + 1);
+           nparams = g_renew (GObjectConstructParam, nparams, MAX (n_nparams + 1, PREALLOC_CPARAMS));
          nparams[n_nparams].pspec = pspec;
          nparams[n_nparams].value = value;
          nparams[n_nparams].trailer = trailer;
@@ -796,9 +822,27 @@ g_object_new_valist (GType   object_type,
     }
 
   /* construct object from construction parameters */
-  class = g_type_class_ref (object_type);
+  while (clist)
+    {
+      GSList *tmp = clist->next;
+      GParamSpec *pspec = clist->data;
+      GValue *value = g_new (GValue, 1);
+
+      value->g_type = 0;
+      g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+      g_param_value_set_default (pspec, value);
+
+      if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
+       cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
+      cparams[n_cparams].pspec = pspec;
+      cparams[n_cparams].value = value;
+      cparams[n_cparams].trailer = NULL;
+      n_cparams++;
+
+      g_slist_free_1 (clist);
+      clist = tmp;
+    }
   object = class->constructor (object_type, n_cparams, cparams);
-  g_type_class_unref (class);
 
   /* free construction values */
   while (n_cparams--)
@@ -807,17 +851,18 @@ g_object_new_valist (GType          object_type,
       g_free (cparams[n_cparams].value);
     }
   g_free (cparams);
-
+  
   /* release g_object_init() notification queue freeze_count */
   nqueue = object_freeze_notifies (object);
   nqueue->freeze_count--;
   
   /* set remaining properties */
+  cparams = nparams;
   while (n_nparams--)
     {
-      GValue *value = nparams[n_nparams].value;
-      GParamSpec *pspec = nparams[n_nparams].pspec;
-      const gchar *trailer = nparams[n_nparams].trailer;
+      GValue *value = nparams->value;
+      GParamSpec *pspec = nparams->pspec;
+      const gchar *trailer = nparams++->trailer;
 
       /* convert if necessary */
       if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
@@ -842,7 +887,9 @@ g_object_new_valist (GType    object_type,
       g_value_unset (value);
       g_free (value);
     }
-  g_free (nparams);
+  g_free (cparams);
+
+  g_type_class_unref (class);
 
   /* release our own freeze count and handle notifications */
   object_thaw_notifies (object, nqueue);
@@ -868,9 +915,9 @@ g_object_constructor (GType                  type,
       /* set construct properties */
       while (n_construct_properties--)
        {
-         GValue *value = construct_params[n_construct_properties].value;
-         GParamSpec *pspec = construct_params[n_construct_properties].pspec;
-         const gchar *trailer = construct_params[n_construct_properties].trailer;
+         GValue *value = construct_params->value;
+         GParamSpec *pspec = construct_params->pspec;
+         const gchar *trailer = construct_params++->trailer;
          
          /* convert if necessary */
          if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
@@ -923,11 +970,11 @@ g_object_set_valist (GObject       *object,
       GParamSpec *pspec;
       gchar *error = NULL;
       
-      pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
-                                             name,
-                                             G_OBJECT_TYPE (object),
-                                             TRUE,
-                                             &trailer);
+      pspec = g_param_spec_pool_lookup (pspec_pool,
+                                       name,
+                                       G_OBJECT_TYPE (object),
+                                       TRUE,
+                                       &trailer);
       if (!pspec)
        {
          g_warning ("%s: object class `%s' has no property named `%s'",
@@ -990,11 +1037,11 @@ g_object_get_valist (GObject      *object,
       GParamSpec *pspec;
       gchar *error;
       
-      pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
-                                             name,
-                                             G_OBJECT_TYPE (object),
-                                             TRUE,
-                                             &trailer);
+      pspec = g_param_spec_pool_lookup (pspec_pool,
+                                       name,
+                                       G_OBJECT_TYPE (object),
+                                       TRUE,
+                                       &trailer);
       if (!pspec)
        {
          g_warning ("%s: object class `%s' has no property named `%s'",
@@ -1037,10 +1084,11 @@ g_object_get_valist (GObject     *object,
 }
 
 void
-g_object_set (GObject    *object,
+g_object_set (gpointer     _object,
              const gchar *first_property_name,
              ...)
 {
+  GObject *object = _object;
   va_list var_args;
   
   g_return_if_fail (G_IS_OBJECT (object));
@@ -1051,10 +1099,11 @@ g_object_set (GObject     *object,
 }
 
 void
-g_object_get (GObject    *object,
+g_object_get (gpointer     _object,
              const gchar *first_property_name,
              ...)
 {
+  GObject *object = _object;
   va_list var_args;
   
   g_return_if_fail (G_IS_OBJECT (object));
@@ -1080,11 +1129,11 @@ g_object_set_property (GObject      *object,
   g_object_ref (object);
   nqueue = object_freeze_notifies (object);
   
-  pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
-                                         property_name,
-                                         G_OBJECT_TYPE (object),
-                                         TRUE,
-                                         &trailer);
+  pspec = g_param_spec_pool_lookup (pspec_pool,
+                                   property_name,
+                                   G_OBJECT_TYPE (object),
+                                   TRUE,
+                                   &trailer);
   if (!pspec)
     g_warning ("%s: object class `%s' has no property named `%s'",
               G_STRLOC,
@@ -1128,11 +1177,11 @@ g_object_get_property (GObject     *object,
   
   g_object_ref (object);
   
-  pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
-                                         property_name,
-                                         G_OBJECT_TYPE (object),
-                                         TRUE,
-                                         &trailer);
+  pspec = g_param_spec_pool_lookup (pspec_pool,
+                                   property_name,
+                                   G_OBJECT_TYPE (object),
+                                   TRUE,
+                                   &trailer);
   if (!pspec)
     g_warning ("%s: object class `%s' has no property named `%s'",
               G_STRLOC,
@@ -1169,9 +1218,11 @@ g_object_get_property (GObject      *object,
   g_object_unref (object);
 }
 
-GObject*
-g_object_ref (GObject *object)
+gpointer
+g_object_ref (gpointer _object)
 {
+  GObject *object = _object;
+
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
   g_return_val_if_fail (object->ref_count > 0, NULL);
   
@@ -1181,8 +1232,10 @@ g_object_ref (GObject *object)
 }
 
 void
-g_object_unref (GObject *object)
+g_object_unref (gpointer _object)
 {
+  GObject *object = _object;
+
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (object->ref_count > 0);
   
index 4625830..2d4bff6 100644 (file)
@@ -74,11 +74,12 @@ struct  _GObjectClass
   /* private, these fields might vanish */
   guint        n_property_specs;
   GParamSpec **property_specs;
+  GSList      *construct_properties;
 
   /* public overridable methods */
   GObject*   (*constructor)     (GType                  type,
                                  guint                  n_construct_properties,
-                                 GObjectConstructParam *construct_params);
+                                 GObjectConstructParam *construct_properties);
   void       (*get_property)            (GObject        *object,
                                          guint           property_id,
                                          GValue         *value,
@@ -124,10 +125,10 @@ gpointer    g_object_new                      (GType           object_type,
 gpointer    g_object_new_valist               (GType           object_type,
                                               const gchar    *first_property_name,
                                               va_list         var_args);
-void        g_object_set                      (GObject        *object,
+void        g_object_set                      (gpointer               object,
                                               const gchar    *first_property_name,
                                               ...);
-void        g_object_get                      (GObject        *object,
+void        g_object_get                      (gpointer        object,
                                               const gchar    *first_property_name,
                                               ...);
 void        g_object_set_valist               (GObject        *object,
@@ -146,8 +147,8 @@ void        g_object_freeze_notify            (GObject        *object);
 void        g_object_notify                   (GObject        *object,
                                               const gchar    *property_name);
 void        g_object_thaw_notify              (GObject        *object);
-GObject*    g_object_ref                      (GObject        *object);
-void        g_object_unref                    (GObject        *object);
+gpointer    g_object_ref                      (gpointer        object);
+void        g_object_unref                    (gpointer        object);
 gpointer    g_object_get_qdata                (GObject        *object,
                                               GQuark          quark);
 void        g_object_set_qdata                (GObject        *object,
index fdb1508..92882b8 100644 (file)
@@ -398,8 +398,16 @@ value_param_lcopy_value (const GValue *value,
   return NULL;
 }
 
+
+/* --- param spec pool --- */
+struct _GParamSpecPool
+{
+  gboolean    type_prefixing;
+  GHashTable *hash_table;
+};
+
 static guint
-param_spec_hash (gconstpointer key_spec)
+param_spec_pool_hash (gconstpointer key_spec)
 {
   const GParamSpec *key = key_spec;
   const gchar *p;
@@ -412,8 +420,8 @@ param_spec_hash (gconstpointer key_spec)
 }
 
 static gboolean
-param_spec_equals (gconstpointer key_spec_1,
-                  gconstpointer key_spec_2)
+param_spec_pool_equals (gconstpointer key_spec_1,
+                       gconstpointer key_spec_2)
 {
   const GParamSpec *key1 = key_spec_1;
   const GParamSpec *key2 = key_spec_2;
@@ -422,88 +430,181 @@ param_spec_equals (gconstpointer key_spec_1,
          strcmp (key1->name, key2->name) == 0);
 }
 
-GHashTable*
-g_param_spec_hash_table_new (void)
+GParamSpecPool*
+g_param_spec_pool_new (gboolean type_prefixing)
 {
-  return g_hash_table_new (param_spec_hash, param_spec_equals);
+  GParamSpecPool *pool = g_new (GParamSpecPool, 1);
+
+  pool->type_prefixing = type_prefixing != FALSE;
+  pool->hash_table = g_hash_table_new (param_spec_pool_hash, param_spec_pool_equals);
+
+  return pool;
 }
 
 void
-g_param_spec_hash_table_insert (GHashTable *hash_table,
-                               GParamSpec *pspec,
-                               GType       owner_type)
+g_param_spec_pool_insert (GParamSpecPool *pool,
+                         GParamSpec     *pspec,
+                         GType           owner_type)
 {
-  g_return_if_fail (hash_table != NULL);
-  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
-  g_return_if_fail (pspec->name != NULL);
-  if (pspec->owner_type != owner_type)
-    g_return_if_fail (pspec->owner_type == 0);
+  gchar *p;
 
-  if (strchr (pspec->name, ':'))
-    g_warning (G_STRLOC ": parameter name `%s' contains field-delimeter",
-              pspec->name);
-  else
+  g_return_if_fail (pool != NULL);
+  g_return_if_fail (pspec);
+  g_return_if_fail (owner_type > 0);
+  g_return_if_fail (pspec->owner_type == 0);
+
+  for (p = pspec->name; *p; p++)
     {
-      pspec->owner_type = owner_type;
-      g_hash_table_insert (hash_table, pspec, pspec);
+      if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
+       {
+         g_warning (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
+         return;
+       }
     }
+
+  pspec->owner_type = owner_type;
+  g_param_spec_ref (pspec);
+  g_hash_table_insert (pool->hash_table, pspec, pspec);
 }
 
 void
-g_param_spec_hash_table_remove (GHashTable *hash_table,
-                               GParamSpec *pspec)
+g_param_spec_pool_remove (GParamSpecPool *pool,
+                         GParamSpec     *pspec)
 {
-  g_return_if_fail (hash_table != NULL);
-  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+  g_return_if_fail (pool != NULL);
+  g_return_if_fail (pspec);
+
+  if (g_hash_table_remove (pool->hash_table, pspec))
+    g_param_spec_unref (pspec);
+  else
+    g_warning (G_STRLOC ": attempt to remove unknown pspec `%s' from pool", pspec->name);
+}
 
-  g_assert (g_param_spec_hash_table_lookup (hash_table, pspec->name, pspec->owner_type, FALSE, NULL) != NULL); /* FIXME: paranoid */
+static inline GParamSpec*
+param_spec_ht_lookup (GHashTable  *hash_table,
+                     const gchar *param_name,
+                     GType        owner_type,
+                     gboolean     walk_ancestors)
+{
+  GParamSpec key, *pspec;
 
-  g_hash_table_remove (hash_table, pspec);
-  g_assert (g_param_spec_hash_table_lookup (hash_table, pspec->name, pspec->owner_type, FALSE, NULL) == NULL); /* FIXME: paranoid */
-  pspec->owner_type = 0;
+  key.owner_type = owner_type;
+  key.name = (gchar*) param_name;
+  if (walk_ancestors)
+    do
+      {
+       pspec = g_hash_table_lookup (hash_table, &key);
+       if (pspec)
+         return pspec;
+       key.owner_type = g_type_parent (key.owner_type);
+      }
+    while (key.owner_type);
+  else
+    pspec = g_hash_table_lookup (hash_table, &key);
+
+  if (!pspec)
+    {
+      /* sigh, try canonicalization */
+      key.name = g_strdup (param_name);
+      key.owner_type = owner_type;
+      
+      g_strcanon (key.name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
+      if (walk_ancestors)
+       do
+         {
+           pspec = g_hash_table_lookup (hash_table, &key);
+           if (pspec)
+             {
+               g_free (key.name);
+               return pspec;
+             }
+           key.owner_type = g_type_parent (key.owner_type);
+         }
+       while (key.owner_type);
+      else
+       pspec = g_hash_table_lookup (hash_table, &key);
+      g_free (key.name);
+    }
+
+  return pspec;
 }
 
 GParamSpec*
-g_param_spec_hash_table_lookup (GHashTable   *hash_table,
-                               const gchar  *param_name,
-                               GType         owner_type,
-                               gboolean      try_ancestors,
-                               const gchar **trailer)
+g_param_spec_pool_lookup (GParamSpecPool *pool,
+                         const gchar    *param_name,
+                         GType           owner_type,
+                         gboolean        walk_ancestors,
+                         const gchar   **trailer_p)
 {
   GParamSpec *pspec;
-  GParamSpec key;
   gchar *delim;
-  
-  g_return_val_if_fail (hash_table != NULL, NULL);
-  g_return_val_if_fail (param_name != NULL, NULL);
-  
-  key.owner_type = owner_type;
+
+  g_return_val_if_fail (pool != NULL, NULL);
+  g_return_val_if_fail (param_name, NULL);
+
   delim = strchr (param_name, ':');
-  if (delim)
-    key.name = g_strndup (param_name, delim - param_name);
-  else
-    key.name = g_strdup (param_name);
-  g_strcanon (key.name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
 
-  if (trailer)
-    *trailer = delim;
-  
-  pspec = g_hash_table_lookup (hash_table, &key);
-  if (!pspec && try_ancestors)
+  /* try quick and away, i.e. no prefix, no trailer */
+  if (!delim)
     {
-      key.owner_type = g_type_parent (key.owner_type);
-      while (key.owner_type)
+      if (trailer_p)
+       *trailer_p = NULL;
+      return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
+    }
+
+  /* strip type prefix */
+  if (pool->type_prefixing && delim[1] == ':')
+    {
+      guint l = delim - param_name;
+      gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
+      GType type;
+      
+      strncpy (buffer, param_name, delim - param_name);
+      buffer[l] = 0;
+      type = g_type_from_name (buffer);
+      if (l >= 32)
+       g_free (buffer);
+      if (type)                /* type==0 isn't a valid type pefix */
        {
-         pspec = g_hash_table_lookup (hash_table, &key);
-         if (pspec)
-           break;
-         key.owner_type = g_type_parent (key.owner_type);
+         /* sanity check, these cases don't make a whole lot of sense */
+         if ((!walk_ancestors && type != owner_type) || !g_type_is_a (owner_type, type))
+           {
+             if (trailer_p)
+               *trailer_p = NULL;
+             return NULL;
+           }
+         owner_type = type;
+         param_name += l + 2;
+         delim = strchr (param_name, ':');
+         if (!delim)           /* good, can still forget about trailer */
+           {
+             if (trailer_p)
+               *trailer_p = NULL;
+             return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
+           }
        }
     }
-  
-  g_free (key.name);
-  
-  return pspec;
+
+  /* ok, no prefix, handle trailer */
+  if (delim[1] == ':')
+    {
+      guint l = delim - param_name;
+      gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
+      
+      strncpy (buffer, param_name, delim - param_name);
+      buffer[l] = 0;
+      pspec = param_spec_ht_lookup (pool->hash_table, buffer, owner_type, walk_ancestors);
+      if (l >= 32)
+       g_free (buffer);
+      if (trailer_p)
+       *trailer_p = pspec ? delim + 2 : NULL;
+      return pspec;
+    }
+
+  /* malformed param_name */
+  if (trailer_p)
+    *trailer_p = NULL;
+  return NULL;
 }
 
 
index ec33fbc..59c942c 100644 (file)
@@ -48,15 +48,17 @@ typedef enum
   G_PARAM_WRITABLE            = 1 << 1,
   G_PARAM_CONSTRUCT          = 1 << 2,
   G_PARAM_CONSTRUCT_ONLY      = 1 << 3,
-#define        G_PARAM_MASK            (0x000f)
-  /* bits in the range 0xfff0 are reserved for 3rd party usage */
-#define        G_PARAM_USER_MASK       (0xfff0)
+  G_PARAM_PRIVATE            = 1 << 4,
+#define        G_PARAM_MASK            (0x000000ff)
+  /* bits in the range 0xffffff00 are reserved for 3rd party usage */
+#define        G_PARAM_USER_MASK       (0xffffff00)
 } GParamFlags;
 
 
 /* --- typedefs & structures --- */
 typedef struct _GParamSpec      GParamSpec;
 typedef struct _GParamSpecClass GParamSpecClass;
+typedef struct _GParamSpecPool  GParamSpecPool;
 struct _GParamSpec
 {
   GTypeInstance  g_type_instance;
@@ -144,23 +146,23 @@ GType     g_param_type_register_static    (const gchar              *name,
                                         const GParamSpecTypeInfo *pspec_info);
 
 
-/* --- private --- */
+/* --- protected --- */
 gpointer       g_param_spec_internal           (GType          param_type,
                                                 const gchar   *name,
                                                 const gchar   *nick,
                                                 const gchar   *blurb,
                                                 GParamFlags    flags);
-GHashTable*    g_param_spec_hash_table_new     (void);
-void           g_param_spec_hash_table_insert  (GHashTable    *hash_table,
-                                                GParamSpec    *pspec,
-                                                GType          owner_type);
-void           g_param_spec_hash_table_remove  (GHashTable    *hash_table,
-                                                GParamSpec    *pspec);
-GParamSpec*    g_param_spec_hash_table_lookup  (GHashTable    *hash_table,
-                                                const gchar   *param_name,
-                                                GType          owner_type,
-                                                gboolean       try_ancestors,
-                                                const gchar  **trailer);
+GParamSpecPool* g_param_spec_pool_new          (gboolean       type_prefixing);
+void           g_param_spec_pool_insert        (GParamSpecPool *pool,
+                                                GParamSpec     *pspec,
+                                                GType           owner_type);
+void           g_param_spec_pool_remove        (GParamSpecPool *pool,
+                                                GParamSpec     *pspec);
+GParamSpec*    g_param_spec_pool_lookup        (GParamSpecPool *pool,
+                                                const gchar    *param_name,
+                                                GType           owner_type,
+                                                gboolean        walk_ancestors,
+                                                const gchar   **trailer_p);
 
 
 /* contracts:
index 42842dd..6f9aed3 100644 (file)
@@ -345,7 +345,7 @@ type_lookup_iface_entry (TypeNode *node,
       guint n_ifaces = node->n_ifaces;
       GType iface_type = NODE_TYPE (iface);
 
-      do               /* FIXME: should optimize iface lookups for <= 4 */
+      do
        {
          guint i;
          IFaceEntry *check;