summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'array.c')
-rw-r--r--array.c158
1 files changed, 119 insertions, 39 deletions
diff --git a/array.c b/array.c
index 741f09b9b1..c1ad9981c1 100644
--- a/array.c
+++ b/array.c
@@ -20,14 +20,43 @@ VALUE rb_to_a();
void
memclear(mem, size)
- VALUE *mem;
- int size;
+ register VALUE *mem;
+ register int size;
{
while (size--) {
*mem++ = Qnil;
}
}
+#define ARY_FREEZE FL_USER1
+
+static void
+ary_modify(ary)
+ VALUE ary;
+{
+ rb_secure(5);
+ if (FL_TEST(ary, ARY_FREEZE)) {
+ TypeError("can't modify frozen array");
+ }
+}
+
+VALUE
+ary_freeze(ary)
+ VALUE ary;
+{
+ FL_SET(ary, ARY_FREEZE);
+ return ary;
+}
+
+static VALUE
+ary_frozen_p(ary)
+ VALUE ary;
+{
+ if (FL_TEST(ary, ARY_FREEZE))
+ return TRUE;
+ return FALSE;
+}
+
VALUE
ary_new2(len)
int len;
@@ -148,12 +177,13 @@ ary_s_create(argc, argv, class)
return (VALUE)ary;
}
-static void
-astore(ary, idx, val)
+void
+ary_store(ary, idx, val)
struct RArray *ary;
int idx;
VALUE val;
{
+ ary_modify(ary);
if (idx < 0) {
IndexError("negative index for array");
}
@@ -177,7 +207,7 @@ ary_push(ary, item)
struct RArray *ary;
VALUE item;
{
- astore(ary, ary->len, item);
+ ary_store(ary, ary->len, item);
return (VALUE)ary;
}
@@ -188,7 +218,7 @@ ary_push_method(argc, argv, ary)
struct RArray *ary;
{
while (argc--) {
- astore(ary, ary->len, *argv++);
+ ary_store(ary, ary->len, *argv++);
}
return (VALUE)ary;
}
@@ -231,6 +261,7 @@ ary_unshift(ary, item)
struct RArray *ary;
int item;
{
+ ary_modify(ary);
if (ary->len >= ary->capa) {
ary->capa+=ARY_DEFAULT_SIZE;
REALLOC_N(ary->ptr, VALUE, ary->capa);
@@ -243,18 +274,6 @@ ary_unshift(ary, item)
return ary->ptr[0] = item;
}
-static VALUE
-ary_unshift_method(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- while (argc--) {
- ary_unshift(ary, argv[argc]);
- }
- return (VALUE)ary;
-}
-
VALUE
ary_entry(ary, offset)
struct RArray *ary;
@@ -402,7 +421,7 @@ ary_indexes(ary, args)
p = args->ptr; pend = p + args->len;
while (p < pend) {
- astore(new_ary, i++, ary_entry(ary, NUM2INT(*p)));
+ ary_store(new_ary, i++, ary_entry(ary, NUM2INT(*p)));
p++;
}
return new_ary;
@@ -413,6 +432,7 @@ ary_replace(ary, beg, len, rpl)
struct RArray *ary, *rpl;
int beg, len;
{
+ ary_modify(ary);
if (TYPE(rpl) != T_ARRAY) {
rpl = (struct RArray*)rb_to_a(rpl);
}
@@ -490,11 +510,11 @@ ary_aset(argc, argv, ary)
if (offset < 0) {
offset = ary->len + offset;
}
- astore(ary, offset, arg2);
+ ary_store(ary, offset, arg2);
return arg2;
}
-static VALUE
+VALUE
ary_each(ary)
struct RArray *ary;
{
@@ -519,6 +539,18 @@ ary_each_index(ary)
}
static VALUE
+ary_reverse_each(ary)
+ struct RArray *ary;
+{
+ int len = ary->len;
+
+ while (len--) {
+ rb_yield(ary->ptr[len]);
+ }
+ return Qnil;
+}
+
+static VALUE
ary_length(ary)
struct RArray *ary;
{
@@ -575,6 +607,7 @@ ary_join(ary, sep)
}
if (!NIL_P(sep)) str_cat(result, sep->ptr, sep->len);
str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len);
+ if (str_tainted(tmp)) str_taint(result);
}
return result;
@@ -590,9 +623,7 @@ ary_join_method(argc, argv, ary)
rb_scan_args(argc, argv, "01", &sep);
if (NIL_P(sep)) sep = OFS;
-
- if (!NIL_P(sep))
- Check_Type(sep, T_STRING);
+ if (!NIL_P(sep)) Check_Type(sep, T_STRING);
return ary_join(ary, sep);
}
@@ -628,7 +659,6 @@ ary_inspect(ary)
{
int i, len;
VALUE s, str;
- char *p;
if (ary->len == 0) return str_new2("[]");
str = str_new2("[");
@@ -707,6 +737,13 @@ sort_2(a, b)
{
VALUE retval;
+ if (FIXNUM_P(*a)) {
+ if (FIXNUM_P(*b)) return *a - *b;
+ }
+ else if (TYPE(*a) == T_STRING) {
+ if (TYPE(*b) == T_STRING) return str_cmp(*a, *b);
+ }
+
retval = rb_funcall(*a, cmp, 1, *b);
return NUM2INT(retval);
}
@@ -715,6 +752,7 @@ VALUE
ary_sort_bang(ary)
struct RArray *ary;
{
+ ary_modify(ary);
qsort(ary->ptr, ary->len, sizeof(VALUE), iterator_p()?sort_1:sort_2);
return (VALUE)ary;
}
@@ -726,13 +764,14 @@ ary_sort(ary)
return ary_sort_bang(ary_clone(ary));
}
-static VALUE
+VALUE
ary_delete(ary, item)
struct RArray *ary;
VALUE item;
{
int i1, i2;
+ ary_modify(ary);
for (i1 = i2 = 0; i1 < ary->len; i1++) {
if (rb_equal(ary->ptr[i1], item)) continue;
if (i1 != i2) {
@@ -741,13 +780,14 @@ ary_delete(ary, item)
i2++;
}
if (ary->len == i2) {
- if (iterator_p()) rb_yield(Qnil);
+ if (iterator_p()) rb_yield(item);
+ return Qnil;
}
else {
ary->len = i2;
}
- return (VALUE)ary;
+ return item;
}
VALUE
@@ -758,6 +798,7 @@ ary_delete_at(ary, at)
int i1, i2, pos;
VALUE del = Qnil;
+ ary_modify(ary);
pos = NUM2INT(at);
for (i1 = i2 = 0; i1 < ary->len; i1++) {
if (i1 == pos) {
@@ -780,6 +821,7 @@ ary_delete_if(ary)
{
int i1, i2;
+ ary_modify(ary);
for (i1 = i2 = 0; i1 < ary->len; i1++) {
if (rb_yield(ary->ptr[i1])) continue;
if (i1 != i2) {
@@ -792,6 +834,21 @@ ary_delete_if(ary)
return (VALUE)ary;
}
+#if 0
+static VALUE
+ary_replace(ary)
+ struct RArray *ary;
+{
+ int i;
+
+ for (i = 0; i < ary->len; i++) {
+ ary->ptr[i] = rb_yield(ary->ptr[i]);
+ }
+
+ return (VALUE)ary;
+}
+#endif
+
static VALUE
ary_clear(ary)
struct RArray *ary;
@@ -871,7 +928,6 @@ VALUE
ary_concat(x, y)
struct RArray *x, *y;
{
- struct RArray *z;
VALUE *p, *pend;
if (TYPE(y) != T_ARRAY) {
@@ -881,7 +937,7 @@ ary_concat(x, y)
p = y->ptr;
pend = p + y->len;
while (p < pend) {
- astore(x, x->len, *p);
+ ary_store(x, x->len, *p);
p++;
}
return (VALUE)x;
@@ -903,6 +959,10 @@ ary_times(ary, times)
ary2 = (struct RArray*)ary_new2(len);
ary2->len = len;
+ if (len < 0) {
+ ArgError("negative argument");
+ }
+
for (i=0; i<len; i+=ary->len) {
MEMCPY(ary2->ptr+i, ary->ptr, VALUE, ary->len);
}
@@ -962,21 +1022,34 @@ ary_equal(ary1, ary2)
}
static VALUE
+ary_eql(ary1, ary2)
+ struct RArray *ary1, *ary2;
+{
+ int i;
+
+ if (TYPE(ary2) != T_ARRAY) return FALSE;
+ if (ary1->len != ary2->len) return FALSE;
+ for (i=0; i<ary1->len; i++) {
+ if (!rb_eql(ary1->ptr[i], ary2->ptr[i]))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static VALUE
ary_hash(ary)
struct RArray *ary;
{
- int i, h;
- ID hash = rb_intern("hash");
+ int h, i;
- h = 0;
+ h = ary->len;
for (i=0; i<ary->len; i++) {
- h ^= rb_funcall(ary->ptr[i], hash, 0);
+ h ^= rb_hash(ary->ptr[i]);
}
- h += ary->len;
return INT2FIX(h);
}
-static VALUE
+VALUE
ary_includes(ary, item)
struct RArray *ary;
VALUE item;
@@ -1055,6 +1128,7 @@ ary_compact_bang(ary)
{
VALUE *p, *t, *end;
+ ary_modify(ary);
p = t = ary->ptr;
end = p + ary->len;
while (t < end) {
@@ -1104,10 +1178,13 @@ Init_Array()
rb_define_method(cArray, "inspect", ary_inspect, 0);
rb_define_method(cArray, "to_a", ary_to_a, 0);
- rb_define_method(cArray, "print_on", ary_print_on, 1);
+ rb_define_method(cArray, "freeze", ary_freeze, 0);
+ rb_define_method(cArray, "frozen?", ary_frozen_p, 0);
rb_define_method(cArray, "==", ary_equal, 1);
+ rb_define_method(cArray, "eql?", ary_eql, 1);
rb_define_method(cArray, "hash", ary_hash, 0);
+
rb_define_method(cArray, "[]", ary_aref, -1);
rb_define_method(cArray, "[]=", ary_aset, -1);
rb_define_method(cArray, "concat", ary_concat, 1);
@@ -1115,9 +1192,10 @@ Init_Array()
rb_define_method(cArray, "push", ary_push_method, -1);
rb_define_method(cArray, "pop", ary_pop, 0);
rb_define_method(cArray, "shift", ary_shift, 0);
- rb_define_method(cArray, "unshift", ary_unshift_method, -1);
+ rb_define_method(cArray, "unshift", ary_unshift, 1);
rb_define_method(cArray, "each", ary_each, 0);
rb_define_method(cArray, "each_index", ary_each_index, 0);
+ rb_define_method(cArray, "reverse_each", ary_reverse_each, 0);
rb_define_method(cArray, "length", ary_length, 0);
rb_define_alias(cArray, "size", "length");
rb_define_method(cArray, "empty?", ary_empty_p, 0);
@@ -1132,10 +1210,12 @@ Init_Array()
rb_define_method(cArray, "delete", ary_delete, 1);
rb_define_method(cArray, "delete_at", ary_delete_at, 1);
rb_define_method(cArray, "delete_if", ary_delete_if, 0);
+#if 0
+ rb_define_method(cArray, "replace", ary_replace, 0);
+#endif
rb_define_method(cArray, "clear", ary_clear, 0);
rb_define_method(cArray, "fill", ary_fill, -1);
rb_define_method(cArray, "include?", ary_includes, 1);
- rb_define_method(cArray, "includes?", ary_includes, 1); /* obsolate */
rb_define_method(cArray, "assoc", ary_assoc, 1);
rb_define_method(cArray, "rassoc", ary_rassoc, 1);