summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-09-21 09:35:29 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-09-21 09:35:29 +0000
commitba19ba779cc232474d75eb190e7420bf667832dc (patch)
treeac9f317f71df73b44ce9a4b0b485f6df646d44bc /array.c
parentde5a85496ac4ae7bd24b5fc7acb8001a5e4d8b7d (diff)
* array.c (rb_ary_uniq_bang): element size might change during
comparison. [ruby-dev:24298] * 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/branches/ruby_1_8@6940 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'array.c')
-rw-r--r--array.c94
1 files changed, 63 insertions, 31 deletions
diff --git a/array.c b/array.c
index 67da6b8e7e..3e22138468 100644
--- a/array.c
+++ b/array.c
@@ -561,23 +561,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;
@@ -857,6 +864,10 @@ rb_ary_index(ary, val)
* array.rindex(obj) -> int or nil
*
* Returns the index of the last object in <i>array</i>
+ if (i > RARRAY(ary)->len) {
+ i = RARRAY(ary)->len;
+ continue;
+ }
* <code>==</code> to <i>obj</i>. Returns <code>nil</code> if
* no match is found.
*
@@ -1533,17 +1544,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;
@@ -1558,6 +1588,7 @@ sort_2(ap, bp)
}
retval = rb_funcall(a, id_cmp, 1, b);
+ ary_sort_check(data);
return rb_cmpint(retval, a, b);
}
@@ -1565,8 +1596,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;
}
@@ -1775,7 +1810,7 @@ rb_ary_select(argc, argv, 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, rb_ary_entry(ary, i));
+ rb_ary_push(result, rb_ary_elt(ary, i));
}
}
return result;
@@ -2038,9 +2073,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);
}
@@ -2051,9 +2086,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);
}
@@ -2081,7 +2116,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(rb_ary_entry(ary, i));
+ tmp = to_ary(rb_ary_elt(ary, i));
if (elen < 0) { /* first element */
elen = RARRAY(tmp)->len;
result = rb_ary_new2(elen);
@@ -2094,7 +2129,7 @@ rb_ary_transpose(ary)
RARRAY(tmp)->len, elen);
}
for (j=0; j<elen; j++) {
- rb_ary_store(rb_ary_entry(result, j), i, rb_ary_entry(tmp, j));
+ rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
}
}
return result;
@@ -2441,7 +2476,7 @@ rb_ary_equal(ary1, ary2)
}
for (i=0; i<RARRAY(ary1)->len; i++) {
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
- 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;
@@ -2640,7 +2675,7 @@ rb_ary_and(ary1, ary2)
for (i=0; i<RARRAY(ary1)->len; i++) {
VALUE v = RARRAY(ary1)->ptr[i];
if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
}
@@ -2671,15 +2706,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;
@@ -2704,7 +2739,7 @@ rb_ary_uniq_bang(ary)
VALUE ary;
{
VALUE hash;
- VALUE *p, *q, *end;
+ long i, j;
rb_ary_modify(ary);
@@ -2713,16 +2748,13 @@ rb_ary_uniq_bang(ary)
if (RARRAY(ary)->len == RHASH(hash)->tbl->num_entries) {
return Qnil;
}
- p = q = RARRAY(ary)->ptr;
- end = p + RARRAY(ary)->len;
- while (p < end) {
- VALUE v = *p;
+ for (i=j=0; i<RARRAY(ary)->len; i++) {
+ VALUE v = rb_ary_elt(ary, i);
if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- *q++ = *p;
+ rb_ary_store(ary, j++, v);
}
- p++;
}
- RARRAY(ary)->len = (q - RARRAY(ary)->ptr);
+ RARRAY(ary)->len = j;
return ary;
}