On Mon, 2005-05-16 at 15:20 +0200, Jim Meyering wrote:
> Yoann Vandoorselaere <[EMAIL PROTECTED]> wrote:
> > This patch fix constness warning in the GnuLib hash module.
> 
> I'm all for avoiding warnings, but not when it detracts from what I
> think of as the correctness of an interface, as it would in this case.
> 
> Those `const void *entry' parameters constitute a promise
> by the hash module that it will not try to write through
> those pointers.  Removing `const' here might make users of
> these functions wonder whether the functions write through
> the void pointers.

Since the interface let the user provide a function for deleting data
(which thus does not use const), you might then as well workaround this
issue using:

union {
        const void *val_ro;
        void *val_rw;
} user_data;

And use the later in order to provide the deletion callback with a not
const pointer.
Proof of concept patch attached.

-- 
Yoann Vandoorselaere | Responsable R&D / CTO | PreludeIDS Technologies
Tel: +33 (0)8 70 70 21 58                  Fax: +33(0)4 78 42 21 58
http://www.prelude-ids.com
Index: lib/hash.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/hash.c,v
retrieving revision 1.38
diff -u -r1.38 hash.c
--- lib/hash.c	14 May 2005 06:03:58 -0000	1.38
+++ lib/hash.c	16 May 2005 13:41:52 -0000
@@ -178,7 +178,7 @@
 
   for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
     {
-      if (bucket->data)
+      if (bucket->user_data.ro_data)
 	{
 	  struct hash_entry const *cursor = bucket;
 	  size_t bucket_length = 1;
@@ -206,7 +206,7 @@
 
   for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
     {
-      if (bucket->data)
+      if (bucket->user_data.ro_data)
 	{
 	  struct hash_entry const *cursor = bucket;
 
@@ -256,12 +256,12 @@
   if (! (bucket < table->bucket_limit))
     abort ();
 
-  if (bucket->data == NULL)
+  if (bucket->user_data.ro_data == NULL)
     return NULL;
 
   for (cursor = bucket; cursor; cursor = cursor->next)
-    if (table->comparator (entry, cursor->data))
-      return cursor->data;
+    if (table->comparator (entry, cursor->user_data.ro_data))
+      return cursor->user_data.rw_data;
 
   return NULL;
 }
@@ -286,8 +286,8 @@
   for (bucket = table->bucket; ; bucket++)
     if (! (bucket < table->bucket_limit))
       abort ();
-    else if (bucket->data)
-      return bucket->data;
+    else if (bucket->user_data.ro_data)
+      return bucket->user_data.rw_data;
 }
 
 /* Return the user data for the entry following ENTRY, where ENTRY has been
@@ -306,13 +306,13 @@
 
   /* Find next entry in the same bucket.  */
   for (cursor = bucket; cursor; cursor = cursor->next)
-    if (cursor->data == entry && cursor->next)
-      return cursor->next->data;
+    if (cursor->user_data.ro_data == entry && cursor->next)
+      return cursor->next->user_data.rw_data;
 
   /* Find first entry in any subsequent bucket.  */
   while (++bucket < table->bucket_limit)
-    if (bucket->data)
-      return bucket->data;
+    if (bucket->user_data.ro_data)
+      return bucket->user_data.rw_data;
 
   /* None found.  */
   return NULL;
@@ -332,13 +332,13 @@
 
   for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
     {
-      if (bucket->data)
+      if (bucket->user_data.ro_data)
 	{
 	  for (cursor = bucket; cursor; cursor = cursor->next)
 	    {
 	      if (counter >= buffer_size)
 		return counter;
-	      buffer[counter++] = cursor->data;
+	      buffer[counter++] = cursor->user_data.rw_data;
 	    }
 	}
     }
@@ -364,11 +364,11 @@
 
   for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
     {
-      if (bucket->data)
+      if (bucket->user_data.ro_data)
 	{
 	  for (cursor = bucket; cursor; cursor = cursor->next)
 	    {
-	      if (!(*processor) (cursor->data, processor_data))
+	      if (!(*processor) (cursor->user_data.rw_data, processor_data))
 		return counter;
 	      counter++;
 	    }
@@ -608,7 +608,7 @@
 
   for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
     {
-      if (bucket->data)
+      if (bucket->user_data.ro_data)
 	{
 	  struct hash_entry *cursor;
 	  struct hash_entry *next;
@@ -617,8 +617,8 @@
 	  for (cursor = bucket->next; cursor; cursor = next)
 	    {
 	      if (table->data_freer)
-		(*table->data_freer) (cursor->data);
-	      cursor->data = NULL;
+		(*table->data_freer) (cursor->user_data.rw_data);
+	      cursor->user_data.ro_data = NULL;
 
 	      next = cursor->next;
 	      /* Relinking is done one entry at a time, as it is to be expected
@@ -629,8 +629,8 @@
 
 	  /* Free the bucket head.  */
 	  if (table->data_freer)
-	    (*table->data_freer) (bucket->data);
-	  bucket->data = NULL;
+	    (*table->data_freer) (bucket->user_data.rw_data);
+	  bucket->user_data.ro_data = NULL;
 	  bucket->next = NULL;
 	}
     }
@@ -656,11 +656,11 @@
     {
       for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
 	{
-	  if (bucket->data)
+	  if (bucket->user_data.ro_data)
 	    {
 	      for (cursor = bucket; cursor; cursor = cursor->next)
 		{
-		  (*table->data_freer) (cursor->data);
+		  (*table->data_freer) (cursor->user_data.rw_data);
 		}
 	    }
 	}
@@ -729,7 +729,7 @@
 static void
 free_entry (Hash_table *table, struct hash_entry *entry)
 {
-  entry->data = NULL;
+  entry->user_data.ro_data = NULL;
   entry->next = table->free_entry_list;
   table->free_entry_list = entry;
 }
@@ -754,13 +754,13 @@
   *bucket_head = bucket;
 
   /* Test for empty bucket.  */
-  if (bucket->data == NULL)
+  if (bucket->user_data.ro_data == NULL)
     return NULL;
 
   /* See if the entry is the first in the bucket.  */
-  if ((*table->comparator) (entry, bucket->data))
+  if ((*table->comparator) (entry, bucket->user_data.ro_data))
     {
-      void *data = bucket->data;
+      void *data = bucket->user_data.rw_data;
 
       if (delete)
 	{
@@ -775,7 +775,7 @@
 	    }
 	  else
 	    {
-	      bucket->data = NULL;
+	      bucket->user_data.ro_data = NULL;
 	    }
 	}
 
@@ -785,9 +785,9 @@
   /* Scan the bucket overflow.  */
   for (cursor = bucket; cursor->next; cursor = cursor->next)
     {
-      if ((*table->comparator) (entry, cursor->next->data))
+      if ((*table->comparator) (entry, cursor->next->user_data.ro_data))
 	{
-	  void *data = cursor->next->data;
+	  void *data = cursor->next->user_data.rw_data;
 
 	  if (delete)
 	    {
@@ -836,10 +836,10 @@
   new_table->free_entry_list = table->free_entry_list;
 
   for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
-    if (bucket->data)
+    if (bucket->user_data.ro_data)
       for (cursor = bucket; cursor; cursor = next)
 	{
-	  void *data = cursor->data;
+	  void *data = cursor->user_data.rw_data;
 	  struct hash_entry *new_bucket
 	    = (new_table->bucket
 	       + new_table->hasher (data, new_table->n_buckets));
@@ -849,7 +849,7 @@
 
 	  next = cursor->next;
 
-	  if (new_bucket->data)
+	  if (new_bucket->user_data.ro_data)
 	    {
 	      if (cursor == bucket)
 		{
@@ -860,7 +860,7 @@
 		  if (new_entry == NULL)
 		    return false;
 
-		  new_entry->data = data;
+		  new_entry->user_data.ro_data = data;
 		  new_entry->next = new_bucket->next;
 		  new_bucket->next = new_entry;
 		}
@@ -878,7 +878,7 @@
 		 overflow into a bucket header.  Also take care of the
 		 simple case of moving from a bucket header into a bucket
 		 header.  */
-	      new_bucket->data = data;
+	      new_bucket->user_data.ro_data = data;
 	      new_table->n_buckets_used++;
 	      if (cursor != bucket)
 		free_entry (new_table, cursor);
@@ -920,7 +920,7 @@
 
   /* ENTRY is not matched, it should be inserted.  */
 
-  if (bucket->data)
+  if (bucket->user_data.ro_data)
     {
       struct hash_entry *new_entry = allocate_entry (table);
 
@@ -929,16 +929,16 @@
 
       /* Add ENTRY in the overflow of the bucket.  */
 
-      new_entry->data = (void *) entry;
+      new_entry->user_data.ro_data = entry;
       new_entry->next = bucket->next;
       bucket->next = new_entry;
       table->n_entries++;
-      return (void *) entry;
+      return new_entry->user_data.rw_data;
     }
 
   /* Add ENTRY right in the bucket head.  */
 
-  bucket->data = (void *) entry;
+  bucket->user_data.ro_data = entry;
   table->n_entries++;
   table->n_buckets_used++;
 
@@ -990,7 +990,7 @@
     return NULL;
 
   table->n_entries--;
-  if (!bucket->data)
+  if (!bucket->user_data.ro_data)
     {
       table->n_buckets_used--;
 
Index: lib/hash.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/hash.h,v
retrieving revision 1.16
diff -u -r1.16 hash.h
--- lib/hash.h	14 May 2005 06:03:58 -0000	1.16
+++ lib/hash.h	16 May 2005 13:41:52 -0000
@@ -34,7 +34,12 @@
 
 struct hash_entry
   {
-    void *data;
+    union 
+    {
+      const void *ro_data;
+      void *rw_data;
+    } user_data;
+          
     struct hash_entry *next;
   };
 
_______________________________________________
bug-gnulib mailing list
bug-gnulib@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-gnulib

Reply via email to