[#11439] comments needed for Random class — "NAKAMURA, Hiroshi" <nakahiro@...>

-----BEGIN PGP SIGNED MESSAGE-----

15 messages 2007/06/12

[#11450] Re: new method dispatch rule (matz' proposal) — David Flanagan <david@...>

This is a late response to the very long thread that started back in

17 messages 2007/06/13

[#11482] Ruby Changes Its Mind About Non-Word Characters — James Edward Gray II <james@...>

Does this look like a bug to anyone else?

10 messages 2007/06/16

[#11505] Question about the patchlevel release cycle — Sylvain Joyeux <sylvain.joyeux@...4x.org>

1.8.6 thread support was broken in bad ways. It stayed for three months

20 messages 2007/06/20
[#11512] Re: Question about the patchlevel release cycle — Urabe Shyouhei <shyouhei@...> 2007/06/20

Hi, I'm the 1.8.6 branch manager.

[#11543] Re: Apple reportedly to ship with ruby 1.8.6-p36 unless informed what to patch — James Edward Gray II <james@...>

On Jun 27, 2007, at 4:47 PM, Bill Kelly wrote:

10 messages 2007/06/27

Re: [BUG] delete_if with destructive methods in block

From: Nobuyoshi Nakada <nobu@...>
Date: 2007-06-29 04:55:08 UTC
List: ruby-core #11561
Hi,

At Fri, 29 Jun 2007 11:10:25 +0900,
Florian Gross wrote in [ruby-core:11556]:
> It outputs the following:
> 
> [5, 6]
> {1=>2, 3=>4}
> 
> [5]
> {3=>4}

The second is outputed from the block called by Hash#delete
used internally.  It seems wrong indeed.

And rb_hash_shift() should consider iter_lev too.


Index: hash.c
===================================================================
--- hash.c	(revision 12654)
+++ hash.c	(working copy)
@@ -591,4 +591,21 @@ index_i(key, value, args)
 }
 
+static VALUE
+rb_hash_delete_key(hash, key)
+    VALUE hash, key;
+{
+    st_data_t ktmp = (st_data_t)key, val;
+
+    if (RHASH(hash)->iter_lev > 0) {
+	if (st_delete_safe(RHASH(hash)->tbl, &ktmp, &val, Qundef)) {
+	    FL_SET(hash, HASH_DELETED);
+	    return (VALUE)val;
+	}
+    }
+    else if (st_delete(RHASH(hash)->tbl, &ktmp, &val))
+	return (VALUE)val;
+    return Qundef;
+}
+
 /*
  *  call-seq:
@@ -670,12 +687,6 @@ rb_hash_delete(hash, key)
 
     rb_hash_modify(hash);
-    if (RHASH(hash)->iter_lev > 0) {
-	if (st_delete_safe(RHASH(hash)->tbl, (st_data_t*)&key, &val, Qundef)) {
-	    FL_SET(hash, HASH_DELETED);
-	    return val;
-	}
-    }
-    else if (st_delete(RHASH(hash)->tbl, (st_data_t*)&key, &val))
-	return val;
+    val = rb_hash_delete_key(hash, key);
+    if (val != Qundef) return val;
     if (rb_block_given_p()) {
 	return rb_yield(key);
@@ -685,5 +696,4 @@ rb_hash_delete(hash, key)
 
 struct shift_var {
-    int stop;
     VALUE key;
     VALUE val;
@@ -696,6 +706,5 @@ shift_i(key, value, var)
 {
     if (key == Qundef) return ST_CONTINUE;
-    if (var->stop) return ST_STOP;
-    var->stop = 1;
+    if (var->key != Qundef) return ST_STOP;
     var->key = key;
     var->val = value;
@@ -703,4 +712,15 @@ shift_i(key, value, var)
 }
 
+static int
+shift_i_safe(key, value, var)
+    VALUE key, value;
+    struct shift_var *var;
+{
+    if (key == Qundef) return ST_CONTINUE;
+    var->key = key;
+    var->val = value;
+    return ST_STOP;
+}
+
 /*
  *  call-seq:
@@ -723,8 +743,19 @@ rb_hash_shift(hash)
 
     rb_hash_modify(hash);
-    var.stop = 0;
-    rb_hash_foreach(hash, shift_i, (st_data_t)&var);
+    var.key = Qundef;
+    if (RHASH(hash)->iter_lev > 0) {
+	rb_hash_foreach(hash, shift_i_safe, (st_data_t)&var);
+	if (var.key != Qundef) {
+	    st_data_t key = var.key;
+	    if (st_delete_safe(RHASH(hash)->tbl, &key, 0, Qundef)) {
+		FL_SET(hash, HASH_DELETED);
+	    }
+	}
+    }
+    else {
+	rb_hash_foreach(hash, shift_i, (st_data_t)&var);
+    }
 
-    if (var.stop) {
+    if (var.key != Qundef) {
 	return rb_assoc_new(var.key, var.val);
     }
@@ -743,5 +774,5 @@ delete_if_i(key, value, hash)
     if (key == Qundef) return ST_CONTINUE;
     if (RTEST(rb_yield_values(2, key, value))) {
-	rb_hash_delete(hash, key);
+	rb_hash_delete_key(hash, key);
     }
     return ST_CONTINUE;


-- 
Nobu Nakada

In This Thread