summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-09-21 03:08:33 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-09-21 03:08:33 +0000
commitbfabc05a4375b84fa128af89337b1195248bd6da (patch)
treeae0c8f703dca2b6ae94a5b5518c736d373bca377 /array.c
parent90ae99b0f0505f66a6fc1dfb7d7c631bf4bf76cc (diff)
* enum.c (enum_sort_by): do not use qsort directly. use
rb_ary_sort_bang() instead. [ruby-dev:24291] * enum.c (enum_sort_by): pedantic type check added. [ruby-dev:24291] * hash.c (rb_hash_foreach_iter): check iter_lev after each iteration. [ruby-dev:24289] * array.c (rb_ary_and): element size might change during comparison. [ruby-dev:24290] * array.c (rb_ary_or): ditto. [ruby-dev:24292] * array.c (rb_ary_equal): wrong fix. [ruby-dev:24286] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6939 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'array.c')
-rw-r--r--array.c94
1 files changed, 66 insertions, 28 deletions
diff --git a/array.c b/array.c
index 8bb6a067ec..8e6385d588 100644
--- a/array.c
+++ b/array.c
@@ -393,7 +393,7 @@ rb_ary_initialize(argc, argv, ary)
rb_warn("block supersedes default value argument");
}
for (i=0; i<len; i++) {
- RARRAY(ary)->ptr[i] = rb_yield(LONG2NUM(i));
+ rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
RARRAY(ary)->len = i + 1;
}
}
@@ -715,23 +715,30 @@ rb_ary_unshift_m(argc, argv, ary)
return ary;
}
-VALUE
-rb_ary_entry(ary, offset)
+/* faster version - use this if you don't need to treat negative offset */
+static inline VALUE
+rb_ary_elt(ary, offset)
VALUE ary;
long offset;
{
if (RARRAY(ary)->len == 0) return Qnil;
-
- if (offset < 0) {
- offset += RARRAY(ary)->len;
- }
if (offset < 0 || RARRAY(ary)->len <= offset) {
return Qnil;
}
-
return RARRAY(ary)->ptr[offset];
}
+VALUE
+rb_ary_entry(ary, offset)
+ VALUE ary;
+ long offset;
+{
+ if (offset < 0) {
+ offset += RARRAY(ary)->len;
+ }
+ return rb_ary_elt(ary, offset);
+}
+
static VALUE
rb_ary_subseq(ary, beg, len)
VALUE ary;
@@ -1011,6 +1018,10 @@ rb_ary_rindex(ary, val)
long i = RARRAY(ary)->len;
while (i--) {
+ if (i > RARRAY(ary)->len) {
+ i = RARRAY(ary)->len;
+ continue;
+ }
if (rb_equal(RARRAY(ary)->ptr[i], val))
return LONG2NUM(i);
}
@@ -1641,17 +1652,36 @@ rb_ary_reverse_m(ary)
return rb_ary_reverse(rb_ary_dup(ary));
}
+struct ary_sort_data {
+ VALUE ary;
+ VALUE *ptr;
+ long len;
+};
+
+static void
+ary_sort_check(data)
+ struct ary_sort_data *data;
+{
+ if (RARRAY(data->ary)->ptr != data->ptr || RARRAY(data->ary)->len != data->len) {
+ rb_raise(rb_eArgError, "array modified during sort");
+ }
+}
+
static int
-sort_1(a, b)
+sort_1(a, b, data)
VALUE *a, *b;
+ struct ary_sort_data *data;
{
VALUE retval = rb_yield_values(2, *a, *b);
+
+ ary_sort_check(data);
return rb_cmpint(retval, *a, *b);
}
static int
-sort_2(ap, bp)
+sort_2(ap, bp, data)
VALUE *ap, *bp;
+ struct ary_sort_data *data;
{
VALUE retval;
long a = (long)*ap, b = (long)*bp;
@@ -1666,6 +1696,7 @@ sort_2(ap, bp)
}
retval = rb_funcall(a, id_cmp, 1, b);
+ ary_sort_check(data);
return rb_cmpint(retval, a, b);
}
@@ -1673,8 +1704,12 @@ static VALUE
sort_internal(ary)
VALUE ary;
{
+ struct ary_sort_data data;
+
+ data.ary = ary;
+ data.ptr = RARRAY(ary)->ptr; data.len = RARRAY(ary)->len;
qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
- rb_block_given_p()?sort_1:sort_2);
+ rb_block_given_p()?sort_1:sort_2, &data);
return ary;
}
@@ -1878,7 +1913,7 @@ rb_ary_select(ary)
result = rb_ary_new2(RARRAY(ary)->len);
for (i = 0; i < RARRAY(ary)->len; i++) {
if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
- rb_ary_push(result, RARRAY(ary)->ptr[i]);
+ rb_ary_push(result, rb_ary_elt(ary, i));
}
}
return result;
@@ -1910,9 +1945,12 @@ rb_ary_delete(ary, item)
rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
- if (rb_equal(RARRAY(ary)->ptr[i1], item)) continue;
+ VALUE e = RARRAY(ary)->ptr[i1];
+
+ if (rb_equal(e, item)) continue;
if (i1 != i2) {
- RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1];
+ if (RARRAY(ary)->len < i2) break;
+ RARRAY(ary)->ptr[i2] = e;
}
i2++;
}
@@ -2138,9 +2176,9 @@ rb_ary_zip(argc, argv, ary)
for (i=0; i<RARRAY(ary)->len; i++) {
VALUE tmp = rb_ary_new2(argc+1);
- rb_ary_push(tmp, rb_ary_entry(ary, i));
+ rb_ary_push(tmp, rb_ary_elt(ary, i));
for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_entry(argv[j], i));
+ rb_ary_push(tmp, rb_ary_elt(argv[j], i));
}
rb_yield(tmp);
}
@@ -2151,9 +2189,9 @@ rb_ary_zip(argc, argv, ary)
for (i=0; i<len; i++) {
VALUE tmp = rb_ary_new2(argc+1);
- rb_ary_push(tmp, rb_ary_entry(ary, i));
+ rb_ary_push(tmp, rb_ary_elt(ary, i));
for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_entry(argv[j], i));
+ rb_ary_push(tmp, rb_ary_elt(argv[j], i));
}
rb_ary_push(result, tmp);
}
@@ -2181,7 +2219,7 @@ rb_ary_transpose(ary)
alen = RARRAY(ary)->len;
if (alen == 0) return rb_ary_dup(ary);
for (i=0; i<alen; i++) {
- tmp = to_ary(RARRAY(ary)->ptr[i]);
+ tmp = to_ary(rb_ary_elt(ary, i));
if (elen < 0) { /* first element */
elen = RARRAY(tmp)->len;
result = rb_ary_new2(elen);
@@ -2194,7 +2232,7 @@ rb_ary_transpose(ary)
RARRAY(tmp)->len, elen);
}
for (j=0; j<elen; j++) {
- rb_ary_store(RARRAY(result)->ptr[j], i, RARRAY(tmp)->ptr[j]);
+ rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
}
}
return result;
@@ -2541,7 +2579,7 @@ rb_ary_equal(ary1, ary2)
}
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!rb_equal(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i]))
+ if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
return Qfalse;
}
return Qtrue;
@@ -2709,7 +2747,7 @@ rb_ary_diff(ary1, ary2)
for (i=0; i<RARRAY(ary1)->len; i++) {
if (st_lookup(RHASH(hash)->tbl, RARRAY(ary1)->ptr[i], 0)) continue;
- rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
return ary3;
}
@@ -2738,9 +2776,9 @@ rb_ary_and(ary1, ary2)
hash = ary_make_hash(ary2, 0);
for (i=0; i<RARRAY(ary1)->len; i++) {
- VALUE v = RARRAY(ary1)->ptr[i];
+ VALUE v = rb_ary_elt(ary1, i);
if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ rb_ary_push(ary3, v);
}
}
@@ -2771,15 +2809,15 @@ rb_ary_or(ary1, ary2)
hash = ary_make_hash(ary1, ary2);
for (i=0; i<RARRAY(ary1)->len; i++) {
- v = RARRAY(ary1)->ptr[i];
+ v = rb_ary_elt(ary1, i);
if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ rb_ary_push(ary3, v);
}
}
for (i=0; i<RARRAY(ary2)->len; i++) {
- v = RARRAY(ary2)->ptr[i];
+ v = rb_ary_elt(ary2, i);
if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- rb_ary_push(ary3, RARRAY(ary2)->ptr[i]);
+ rb_ary_push(ary3, v);
}
}
return ary3;