diff options
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 57 |
1 files changed, 37 insertions, 20 deletions
@@ -459,7 +459,7 @@ rb_ary_pop(ary) return RARRAY(ary)->ptr[--RARRAY(ary)->len]; } -static void +static VALUE ary_make_shared(ary) VALUE ary; { @@ -472,6 +472,11 @@ ary_make_shared(ary) shared->aux.capa = RARRAY(ary)->aux.capa; RARRAY(ary)->aux.shared = (VALUE)shared; FL_SET(ary, ELTS_SHARED); + OBJ_FREEZE(shared); + return (VALUE)shared; + } + else { + return RARRAY(ary)->aux.shared; } } @@ -591,7 +596,8 @@ rb_ary_subseq(ary, beg, len) VALUE ary; long beg, len; { - VALUE klass, ary2; + VALUE klass, ary2, shared; + VALUE *ptr; if (beg > RARRAY(ary)->len) return Qnil; if (beg < 0 || len < 0) return Qnil; @@ -604,11 +610,12 @@ rb_ary_subseq(ary, beg, len) klass = rb_obj_class(ary); if (len == 0) return ary_new(klass, 0); - ary_make_shared(ary); + shared = ary_make_shared(ary); + ptr = RARRAY(ary)->ptr; ary2 = ary_alloc(klass); - RARRAY(ary2)->ptr = RARRAY(ary)->ptr + beg; + RARRAY(ary2)->ptr = ptr + beg; RARRAY(ary2)->len = len; - RARRAY(ary2)->aux.shared = RARRAY(ary)->aux.shared; + RARRAY(ary2)->aux.shared = shared; FL_SET(ary2, ELTS_SHARED); return ary2; @@ -1562,9 +1569,10 @@ sort_1(a, b, data) struct ary_sort_data *data; { VALUE retval = rb_yield_values(2, *a, *b); + int n; - ary_sort_check(data); - return rb_cmpint(retval, *a, *b); + n = rb_cmpint(retval, *a, *b); + return n; } static int @@ -1573,11 +1581,12 @@ sort_2(ap, bp, data) struct ary_sort_data *data; { VALUE retval; - long a = (long)*ap, b = (long)*bp; + VALUE a = *ap, b = *bp; + int n; if (FIXNUM_P(a) && FIXNUM_P(b)) { - if (a > b) return 1; - if (a < b) return -1; + if ((long)a > (long)b) return 1; + if ((long)a < (long)b) return -1; return 0; } if (TYPE(a) == T_STRING && TYPE(b) == T_STRING) { @@ -1585,8 +1594,9 @@ sort_2(ap, bp, data) } retval = rb_funcall(a, id_cmp, 1, b); - ary_sort_check(data); - return rb_cmpint(retval, a, b); + n = rb_cmpint(retval, a, b); + + return n; } static VALUE @@ -2150,15 +2160,17 @@ static VALUE rb_ary_replace(copy, orig) VALUE copy, orig; { + VALUE shared; + rb_ary_modify(copy); orig = to_ary(orig); if (copy == orig) return copy; - ary_make_shared(orig); + shared = ary_make_shared(orig); if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED)) free(RARRAY(copy)->ptr); - RARRAY(copy)->ptr = RARRAY(orig)->ptr; - RARRAY(copy)->len = RARRAY(orig)->len; - RARRAY(copy)->aux.shared = RARRAY(orig)->aux.shared; + RARRAY(copy)->ptr = RARRAY(shared)->ptr; + RARRAY(copy)->len = RARRAY(shared)->len; + RARRAY(copy)->aux.shared = shared; FL_SET(copy, ELTS_SHARED); return copy; @@ -2874,8 +2886,11 @@ flatten(ary, idx, ary2, memo) rb_ary_push(memo, id); rb_ary_update(ary, idx, 1, ary2); while (i < lim) { - if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) { - n = flatten(ary, i, RARRAY(ary)->ptr[i], memo); + VALUE tmp; + + tmp = rb_check_array_type(RARRAY(ary)->ptr[i]); + if (!NIL_P(tmp)) { + n = flatten(ary, i, tmp, memo); i += n; lim += n; } i++; @@ -2910,12 +2925,14 @@ rb_ary_flatten_bang(ary) rb_ary_modify(ary); while (i<RARRAY(ary)->len) { VALUE ary2 = RARRAY(ary)->ptr[i]; + VALUE tmp; - if (TYPE(ary2) == T_ARRAY) { + tmp = rb_check_array_type(ary2); + if (!NIL_P(tmp)) { if (NIL_P(memo)) { memo = rb_ary_new(); } - i += flatten(ary, i, ary2, memo); + i += flatten(ary, i, tmp, memo); mod = 1; } i++; |