Skip to content

Commit

Permalink
fixing more Array regressions
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@125 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
lrz committed Apr 1, 2008
1 parent 94fe241 commit f849c50
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 13 deletions.
78 changes: 68 additions & 10 deletions array.c
Expand Up @@ -41,8 +41,10 @@ memfill(register VALUE *mem, register long size, register VALUE val)
}

#if WITH_OBJC
/* TODO optimize this */
struct rb_objc_ary_struct {
bool frozen;
bool tainted;
bool named_args;
void *cptr;
};
Expand All @@ -63,13 +65,29 @@ rb_objc_ary_get_struct2(VALUE ary)

s = rb_objc_ary_get_struct(ary);
if (s == NULL) {
s = xmalloc(sizeof(struct rb_objc_ary_struct));
rb_objc_set_associative_ref((void *)ary, &rb_objc_ary_assoc_key, s);
s->frozen = false;
s->named_args = false;
s = xmalloc(sizeof(struct rb_objc_ary_struct));
rb_objc_set_associative_ref((void *)ary, &rb_objc_ary_assoc_key, s);
s->frozen = false;
s->tainted = false;
s->named_args = false;
s->cptr = NULL;
}
return s;
}

static void
rb_objc_ary_copy_struct(VALUE old, VALUE new)
{
struct rb_objc_ary_struct *s;

s = rb_objc_ary_get_struct(old);
if (s != NULL) {
struct rb_objc_ary_struct *n;

n = rb_objc_ary_get_struct2(new);
memcpy(n, s, sizeof(struct rb_objc_ary_struct));
}
}
#else
#define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED)

Expand Down Expand Up @@ -129,6 +147,22 @@ rb_ary_freeze(VALUE ary)
#endif
}

#if WITH_OBJC
VALUE
rb_ary_taint(VALUE ary)
{
rb_objc_ary_get_struct2(ary)->tainted = true;
return ary;
}

VALUE
rb_ary_tainted(VALUE ary)
{
struct rb_objc_ary_struct *s = rb_objc_ary_get_struct(ary);
return s != NULL && s->tainted ? Qtrue : Qfalse;
}
#endif

/*
* call-seq:
* array.frozen? -> true or false
Expand Down Expand Up @@ -273,9 +307,7 @@ rb_ary_new4(long n, const VALUE *elts)
ary = rb_ary_new2(n);
if (n > 0 && elts) {
#if WITH_OBJC
long i;
for (i = 0; i < n; i++)
rb_ary_insert(ary, i, elts[i]);
CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), (const void **)elts, n);
#else
MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
RARRAY(ary)->len = n;
Expand Down Expand Up @@ -1523,10 +1555,10 @@ rb_ary_empty_p(VALUE ary)
return Qfalse;
}

VALUE
rb_ary_dup(VALUE ary)
{
#if WITH_OBJC
static inline VALUE
rb_ary_dup2(VALUE ary)
{
VALUE klass, dup;
long n;

Expand All @@ -1536,6 +1568,24 @@ rb_ary_dup(VALUE ary)
if (n > 0)
CFArrayAppendArray((CFMutableArrayRef)dup, (CFArrayRef)ary,
CFRangeMake(0, n));
return dup;
}

VALUE
rb_ary_clone(VALUE ary)
{
VALUE dup = rb_ary_dup2(ary);
rb_objc_ary_copy_struct(ary, dup);
return dup;
}
#endif

VALUE
rb_ary_dup(VALUE ary)
{
#if WITH_OBJC
VALUE dup = rb_ary_dup2(ary);
/* copy the named_args flag, but not other flags */
if (rb_ary_is_named_args(ary))
rb_ary_set_named_args(dup, true);
#else
Expand Down Expand Up @@ -3692,15 +3742,21 @@ rb_ary_combination(VALUE ary, VALUE num)
volatile VALUE cc = rb_ary_new2(n);
long lev = 0;

#if !WITH_OBJC
RBASIC(cc)->klass = 0;
#endif
MEMZERO(stack, long, n);
stack[0] = -1;
for (i = 0; i < nlen; i++) {
rb_ary_store(cc, lev, RARRAY_AT(ary, stack[lev+1]));
for (lev++; lev < n; lev++) {
rb_ary_store(cc, lev, RARRAY_AT(ary, stack[lev+1] = stack[lev]+1));
}
#if WITH_OBJC
rb_yield(rb_ary_dup(cc));
#else
rb_yield(cc);
#endif
do {
stack[lev--]++;
} while (lev && (stack[lev+1]+n == len+lev+1));
Expand Down Expand Up @@ -3925,6 +3981,8 @@ Init_Array(void)
FL_UNSET(rb_cArrayRuby, RCLASS_OBJC_IMPORTED);
rb_const_set(rb_cObject, rb_intern("Array"), rb_cArrayRuby);
rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
rb_define_method(rb_cArray, "taint", rb_ary_taint, 0);
rb_define_method(rb_cArray, "tainted?", rb_ary_tainted, 0);
#else
rb_cArray = rb_define_class("Array", rb_cObject);
#endif
Expand Down
2 changes: 1 addition & 1 deletion enumerator.c
Expand Up @@ -241,7 +241,7 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv)
else {
ptr->iter = enumerator_each_i;
}
if (argc) ptr->args = rb_ary_new4(argc, argv);
if (argc) GC_WB(&ptr->args, rb_ary_new4(argc, argv));
ptr->fib = 0;
ptr->dst = Qnil;
ptr->no_next = Qfalse;
Expand Down
39 changes: 39 additions & 0 deletions hash.c
Expand Up @@ -260,10 +260,12 @@ rb_cfdictionary_release_cb(CFAllocatorRef allocator, const void *v)
rb_objc_release(v);
}

/* TODO optimize me */
struct rb_objc_hash_struct {
VALUE ifnone;
bool has_proc_default;
bool frozen;
bool tainted;
};

/* This variable will always stay NULL, we only use its address. */
Expand All @@ -287,6 +289,7 @@ rb_objc_hash_get_struct2(VALUE hash)
s->ifnone = Qnil;
s->has_proc_default = false;
s->frozen = false;
s->tainted = false;
}
return s;
}
Expand All @@ -312,6 +315,27 @@ rb_hash_frozen(VALUE hash)
return s != NULL && s->frozen ? Qtrue : Qfalse;
}

VALUE
rb_hash_taint(VALUE hash)
{
struct rb_objc_hash_struct *s;

s = rb_objc_hash_get_struct2(hash);
s->tainted = true;

return hash;
}

VALUE
rb_hash_tainted(VALUE hash)
{
struct rb_objc_hash_struct *s;

s = rb_objc_hash_get_struct(hash);

return s != NULL && s->tainted ? Qtrue : Qfalse;
}

static void
rb_objc_hash_set_struct(VALUE hash, VALUE ifnone, bool has_proc_default)
{
Expand All @@ -322,6 +346,19 @@ rb_objc_hash_set_struct(VALUE hash, VALUE ifnone, bool has_proc_default)
GC_WB(&s->ifnone, ifnone);
s->has_proc_default = has_proc_default;
}

VALUE
rb_hash_clone(VALUE hash)
{
#if 0 // TODO
VALUE klass, dup;
long n;

klass = rb_obj_class(ary);
dup = hash_alloc(klass);
#endif
return Qnil;
}
#endif

static VALUE
Expand Down Expand Up @@ -3046,6 +3083,8 @@ Init_Hash(void)
rb_const_set(rb_cObject, rb_intern("Hash"), rb_cHashRuby);
rb_define_method(rb_cHash, "freeze", rb_hash_freeze, 0);
rb_define_method(rb_cHash, "frozen?", rb_hash_frozen, 0);
rb_define_method(rb_cHash, "taint", rb_hash_taint, 0);
rb_define_method(rb_cHash, "tainted?", rb_hash_tainted, 0);
#else
rb_cHash = rb_define_class("Hash", rb_cObject);
#endif
Expand Down
4 changes: 4 additions & 0 deletions include/ruby/intern.h
Expand Up @@ -81,6 +81,7 @@ VALUE rb_get_values_at(VALUE, long, int, VALUE*, VALUE(*)(VALUE,long));
VALUE rb_ary_elt(VALUE, long);
void rb_ary_set_named_args(VALUE, bool);
bool rb_ary_is_named_args(VALUE);
VALUE rb_ary_clone(VALUE);
#endif
/* bignum.c */
VALUE rb_big_clone(VALUE);
Expand Down Expand Up @@ -361,6 +362,9 @@ VALUE rb_hash_delete(VALUE,VALUE);
struct st_table *rb_hash_tbl(VALUE);
int rb_path_check(const char*);
int rb_env_path_tainted(void);
#if WITH_OBJC
VALUE rb_hash_clone(VALUE);
#endif
/* io.c */
#define rb_defout rb_stdout
RUBY_EXTERN VALUE rb_fs;
Expand Down
16 changes: 16 additions & 0 deletions object.c
Expand Up @@ -157,6 +157,16 @@ rb_obj_class(VALUE obj)
static void
init_copy(VALUE dest, VALUE obj)
{
#if WITH_OBJC
if (rb_objc_is_non_native(obj)) {
int type = TYPE(obj);
if (type == T_ARRAY)
if (rb_ary_tainted(obj)) rb_ary_taint(dest);
else if (type == T_HASH)
if (rb_hash_tainted(obj)) rb_hash_taint(dest);
goto call_init_copy;
}
#endif
if (OBJ_FROZEN(dest)) {
rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
}
Expand Down Expand Up @@ -197,6 +207,7 @@ init_copy(VALUE dest, VALUE obj)
}
break;
}
call_init_copy:
rb_funcall(dest, id_init_copy, 1, obj);
}

Expand Down Expand Up @@ -234,6 +245,11 @@ rb_obj_clone(VALUE obj)
}
#if WITH_OBJC
if (rb_objc_is_non_native(obj)) {
int type = TYPE(obj);
if (type == T_ARRAY)
return rb_ary_clone(obj);
if (type == T_HASH)
return rb_hash_clone(obj);
clone = rb_obj_alloc(rb_obj_class(obj));
init_copy(clone, obj);
return clone;
Expand Down
4 changes: 2 additions & 2 deletions test/ruby/test_array.rb
Expand Up @@ -182,14 +182,14 @@ def setup

def test_00_new
a = @cls.new()
assert_instance_of(@cls, a)
assert_kind_of(@cls, a)
assert_equal(0, a.length)
assert_nil(a[0])
end

def test_01_square_brackets
a = @cls[ 5, 4, 3, 2, 1 ]
assert_instance_of(@cls, a)
assert_kind_of(@cls, a)
assert_equal(5, a.length)
5.times { |i| assert_equal(5-i, a[i]) }
assert_nil(a[6])
Expand Down

0 comments on commit f849c50

Please sign in to comment.