From: EGUCHI Osamu Date: 1999-10-14T00:53:18+09:00 Subject: [ruby-dev:8015] [patch] Array modify check (Re: [patch] Array#delete_at w/ minus value) えぐち@エスアンドイー です。 >>> In message [ruby-dev:7985] [patch] Array#delete_at w/ minus value On Tue, 12 Oct 1999 13:00:39 +0900, EGUCHI Osamu said: eguchi> えぐち@エスアンドイーです。 eguchi> eguchi> 負のインデックスを Array の delete_at の引数に eguchi> 使えるようにしてみました。 rb_ary_delete_at() の rb_ary_modify() の位置がまずかったです。 これだと、(インデクスが範囲外が理由の)変更未遂を 見逃してしまいます。 frozen, sort 中の lock それに taint は、 *変更を行わない場合* も検査すべきと解釈しました。 ...合ってますか? そういう目で見ると、 * Array#sort! で length <= 1 の時にも検査必要? * Array#concat にも ? ? Array#clear には ??? あと、 * Array#sort が length == 0 の場合に限り、 dup した新しい配列を返さないで self を返している。 * 再帰の抑止、 rb_ary_plus() と rb_ary_concat() というのに気がつきました。 # いま Ruby で、ある種のアセンブラのオプティマイザ書いてますが、 Ruby の配列って欲しい機能が完備してるので、サクサク作れて快適☆ そのおかげで、このオプティマイザは Ruby の配列クラスの テストプログラムと化してます(笑)。 えぐち Index: array.c =================================================================== RCS file: /usr/home/eguchi/cvs.netlab.co.jp//ruby/array.c,v retrieving revision 1.3 diff -d -u -r1.3 array.c --- array.c 1999/10/13 06:44:40 1.3 +++ array.c 1999/10/13 15:29:50 @@ -914,9 +914,9 @@ rb_ary_sort_bang(ary) VALUE ary; { + rb_ary_modify(ary); if (RARRAY(ary)->len <= 1) return ary; - rb_ary_modify(ary); FL_SET(ary, ARY_TMPLOCK); /* prohibit modification during sort */ rb_ensure(sort_internal, ary, sort_unlock, ary); return ary; @@ -926,8 +926,9 @@ rb_ary_sort(ary) VALUE ary; { + ary = rb_ary_dup(ary); if (RARRAY(ary)->len == 0) return ary; - return rb_ary_sort_bang(rb_ary_dup(ary)); + return rb_ary_sort_bang(ary); } VALUE @@ -966,11 +967,11 @@ long i, pos = NUM2LONG(at), len = RARRAY(ary)->len; VALUE del = Qnil; + rb_ary_modify(ary); if (pos >= len) return Qnil; if (pos < 0) pos += len; if (pos < 0) return Qnil; - rb_ary_modify(ary); del = RARRAY(ary)->ptr[pos]; for (i = pos + 1; i < len; i++, pos++) { RARRAY(ary)->ptr[pos] = RARRAY(ary)->ptr[i]; @@ -1090,7 +1091,7 @@ VALUE z; if (TYPE(y) != T_ARRAY) { - return rb_ary_plus(x, rb_Array(y)); + y = rb_Array(y); } z = rb_ary_new2(RARRAY(x)->len + RARRAY(y)->len); @@ -1106,8 +1107,9 @@ { VALUE *p, *pend; + rb_ary_modify(x); if (TYPE(y) != T_ARRAY) { - return rb_ary_concat(x, rb_Array(y)); + y = rb_Array(y); } p = RARRAY(y)->ptr;