[macruby-changes] [3438] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sat Feb 6 20:51:46 PST 2010
Revision: 3438
http://trac.macosforge.org/projects/ruby/changeset/3438
Author: lsansonetti at apple.com
Date: 2010-02-06 20:51:44 -0800 (Sat, 06 Feb 2010)
Log Message:
-----------
completed Array refactoring, cleaned out a few things
Modified Paths:
--------------
MacRuby/trunk/NSDictionary.m
MacRuby/trunk/array.c
MacRuby/trunk/compiler.cpp
MacRuby/trunk/dispatcher.cpp
MacRuby/trunk/hash.c
MacRuby/trunk/include/ruby/intern.h
MacRuby/trunk/include/ruby/ruby.h
MacRuby/trunk/object.c
MacRuby/trunk/rakelib/builder/builder.rb
MacRuby/trunk/range.c
MacRuby/trunk/re.c
Added Paths:
-----------
MacRuby/trunk/NSArray.m
MacRuby/trunk/array.h
MacRuby/trunk/hash.h
MacRuby/trunk/spec/macruby/tags/macruby/core/array_tags.txt
Added: MacRuby/trunk/NSArray.m
===================================================================
--- MacRuby/trunk/NSArray.m (rev 0)
+++ MacRuby/trunk/NSArray.m 2010-02-07 04:51:44 UTC (rev 3438)
@@ -0,0 +1,1510 @@
+/*
+ * MacRuby extensions to NSArray.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2010, Apple Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+#include "ruby/ruby.h"
+#include "ruby/node.h"
+#include "objc.h"
+#include "vm.h"
+#include "array.h"
+
+VALUE rb_cArray;
+VALUE rb_cNSArray;
+VALUE rb_cNSMutableArray;
+static VALUE rb_cCFArray;
+
+static id
+nsary_dup(id rcv, SEL sel)
+{
+ id dup = [rcv mutableCopy];
+ if (OBJ_TAINTED(rcv)) {
+ OBJ_TAINT(dup);
+ }
+ return dup;
+}
+
+static id
+nsary_clone(id rcv, SEL sel)
+{
+ id clone = nsary_dup(rcv, 0);
+ if (OBJ_FROZEN(rcv)) {
+ OBJ_FREEZE(clone);
+ }
+ return clone;
+}
+
+static id
+nsary_clear(id rcv, SEL sel)
+{
+ [rcv removeAllObjects];
+ return rcv;
+}
+
+static id
+nsary_inspect(id rcv, SEL sel)
+{
+ NSMutableString *str = [NSMutableString new];
+ [str appendString:@"["];
+ for (id item in rcv) {
+ if ([str length] > 1) {
+ [str appendString:@", "];
+ }
+ [str appendString:(NSString *)rb_inspect(OC2RB(item))];
+ }
+ [str appendString:@"]"];
+ return str;
+}
+
+static id
+nsary_to_a(id rcv, SEL sel)
+{
+ return rcv;
+}
+
+static VALUE
+nsary_equal(id rcv, SEL sel, id other)
+{
+ return [rcv isEqualToArray:other] ? Qtrue : Qfalse;
+}
+
+static VALUE
+nsary_subseq(id rcv, long beg, long len)
+{
+ if (beg < 0 || len < 0) {
+ return Qnil;
+ }
+ const long n = [rcv count];
+ if (beg > n) {
+ return Qnil;
+ }
+ if (n < len || n < beg + len) {
+ len = n - beg;
+ }
+ return (VALUE)[[rcv subarrayWithRange:NSMakeRange(beg, len)] mutableCopy];
+}
+
+static VALUE
+nsary_entry(id rcv, long offset)
+{
+ const long n = [rcv count];
+ if (n == 0) {
+ return Qnil;
+ }
+ if (offset < 0) {
+ offset += n;
+ }
+ if (offset < 0 || n <= offset) {
+ return Qnil;
+ }
+ return OC2RB([rcv objectAtIndex:offset]);
+}
+
+static VALUE
+nsary_aref(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ long beg, len;
+ if (argc == 2) {
+ beg = NUM2LONG(argv[0]);
+ len = NUM2LONG(argv[1]);
+ if (beg < 0) {
+ beg += [rcv count];
+ }
+ return nsary_subseq(rcv, beg, len);
+ }
+ if (argc != 1) {
+ rb_scan_args(argc, argv, "11", 0, 0);
+ }
+ VALUE arg = argv[0];
+ if (FIXNUM_P(arg)) {
+ return nsary_entry(rcv, FIX2LONG(arg));
+ }
+ // Check if Range.
+ switch (rb_range_beg_len(arg, &beg, &len, [rcv count], 0)) {
+ case Qfalse:
+ break;
+ case Qnil:
+ return Qnil;
+ default:
+ return nsary_subseq(rcv, beg, len);
+ }
+ return nsary_entry(rcv, NUM2LONG(arg));
+}
+
+static void
+nsary_splice(id ary, long beg, long len, VALUE rpl)
+{
+ const long n = [ary count];
+ if (len < 0) {
+ rb_raise(rb_eIndexError, "negative length (%ld)", len);
+ }
+ if (beg < 0) {
+ beg += n;
+ if (beg < 0) {
+ beg -= n;
+ rb_raise(rb_eIndexError, "index %ld out of array", beg);
+ }
+ }
+ if (n < len || n < beg + len) {
+ len = n - beg;
+ }
+
+ long rlen = 0;
+ if (rpl != Qundef) {
+ rpl = rb_ary_to_ary(rpl);
+ rlen = RARRAY_LEN(rpl);
+ }
+
+ if (beg >= n) {
+ for (long i = n; i < beg; i++) {
+ [ary addObject:[NSNull null]];
+ }
+ if (rlen > 0 && rpl != Qundef) {
+ [ary addObjectsFromArray:(id)rpl];
+ }
+ }
+ else {
+ if (rlen > 0 && rpl != Qundef) {
+ [ary replaceObjectsInRange:NSMakeRange(beg, len)
+ withObjectsFromArray:(id)rpl];
+ }
+ else {
+ [ary removeObjectsInRange:NSMakeRange(beg, len)];
+ }
+ }
+}
+
+static void
+nsary_store(id ary, long idx, VALUE val)
+{
+ const long len = [ary count];
+ if (idx < 0) {
+ idx += len;
+ if (idx < 0) {
+ rb_raise(rb_eIndexError, "index %ld out of array",
+ idx - len);
+ }
+ }
+ if (len <= idx) {
+ for (long i = len; i <= idx; i++) {
+ [ary addObject:[NSNull null]];
+ }
+ }
+ [ary replaceObjectAtIndex:idx withObject:RB2OC(val)];
+}
+
+static VALUE
+nsary_aset(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ if (argc == 3) {
+ nsary_splice(rcv, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
+ return argv[2];
+ }
+ if (argc != 2) {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
+ }
+
+ long offset;
+ if (FIXNUM_P(argv[0])) {
+ offset = FIX2LONG(argv[0]);
+ }
+ else {
+ long beg, len;
+ if (rb_range_beg_len(argv[0], &beg, &len, [rcv count], 1)) {
+ // Check if Range.
+ nsary_splice(rcv, beg, len, argv[1]);
+ return argv[1];
+ }
+ offset = NUM2LONG(argv[0]);
+ }
+ nsary_store(rcv, offset, argv[1]);
+ return argv[1];
+}
+
+static VALUE
+nsary_at(id rcv, SEL sel, VALUE pos)
+{
+ return nsary_entry(rcv, NUM2LONG(pos));
+}
+
+static VALUE
+nsary_fetch(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ VALUE pos, ifnone;
+ rb_scan_args(argc, argv, "11", &pos, &ifnone);
+
+ const bool block_given = rb_block_given_p();
+ if (block_given && argc == 2) {
+ rb_warn("block supersedes default value argument");
+ }
+
+ const long len = [rcv count];
+ long idx = NUM2LONG(pos);
+ if (idx < 0) {
+ idx += len;
+ }
+ if (idx < 0 || len <= idx) {
+ if (block_given) {
+ return rb_yield(pos);
+ }
+ if (argc == 1) {
+ rb_raise(rb_eIndexError, "index %ld out of array", idx);
+ }
+ return ifnone;
+ }
+ return OC2RB([rcv objectAtIndex:idx]);
+}
+
+static VALUE
+nsary_shared_first(int argc, VALUE *argv, id ary, bool last, bool remove)
+{
+ VALUE nv;
+ rb_scan_args(argc, argv, "1", &nv);
+ long n = NUM2LONG(nv);
+
+ const long ary_len = [ary count];
+ if (n > ary_len) {
+ n = ary_len;
+ }
+ else if (n < 0) {
+ rb_raise(rb_eArgError, "negative array size");
+ }
+
+ long offset = 0;
+ if (last) {
+ offset = ary_len - n;
+ }
+ id result = [NSMutableArray new];
+
+ for (long i = 0; i < n; i++) {
+ id item = [ary objectAtIndex:i + offset];
+ [result addObject:item];
+ }
+
+ if (remove) {
+ for (long i = 0; i < n; i++) {
+ [ary removeObjectAtIndex:offset];
+ }
+ }
+
+ return (VALUE)result;
+}
+
+static VALUE
+nsary_first(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ if (argc == 0) {
+ return [rcv count] == 0 ? Qnil : OC2RB([rcv objectAtIndex:0]);
+ }
+ return nsary_shared_first(argc, argv, rcv, false, false);
+
+}
+
+static VALUE
+nsary_last(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ if (argc == 0) {
+ const long len = [rcv count];
+ return len == 0 ? Qnil : OC2RB([rcv objectAtIndex:len - 1]);
+ }
+ return nsary_shared_first(argc, argv, rcv, true, false);
+}
+
+static id
+nsary_concat(id rcv, SEL sel, VALUE ary)
+{
+ ary = to_ary(ary);
+ [rcv addObjectsFromArray:(id)ary];
+ return rcv;
+}
+
+static id
+nsary_push(id rcv, SEL sel, VALUE elem)
+{
+ [rcv addObject:RB2OC(elem)];
+ return rcv;
+}
+
+static id
+nsary_push_m(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ for (int i = 0; i < argc; i++) {
+ nsary_push(rcv, 0, argv[i]);
+ }
+ return rcv;
+}
+
+static VALUE
+nsary_pop(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ if (argc == 0) {
+ const long len = [rcv count];
+ if (len > 0) {
+ id elem = [rcv objectAtIndex:len - 1];
+ [rcv removeObjectAtIndex:len - 1];
+ return OC2RB(elem);
+ }
+ return Qnil;
+ }
+ return nsary_shared_first(argc, argv, rcv, true, true);
+}
+
+static VALUE
+nsary_shift(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ if (argc == 0) {
+ const long len = [rcv count];
+ if (len > 0) {
+ id elem = [rcv objectAtIndex:0];
+ [rcv removeObjectAtIndex:0];
+ return OC2RB(elem);
+ }
+ return Qnil;
+ }
+ return nsary_shared_first(argc, argv, rcv, false, true);
+}
+
+static id
+nsary_unshift(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ for (int i = argc - 1; i >= 0; i--) {
+ [rcv insertObject:RB2OC(argv[i]) atIndex:0];
+ }
+ return rcv;
+}
+
+static void
+nsary_insert(id rcv, long idx, VALUE elem)
+{
+ const long len = [rcv count];
+ if (idx < 0) {
+ idx += len;
+ if (idx < 0) {
+ rb_raise(rb_eIndexError, "index %ld out of array", idx - len);
+ }
+ }
+ if (idx > len) {
+ for (long i = len; i < idx; i++) {
+ [rcv addObject:[NSNull null]];
+ }
+ }
+ [rcv insertObject:RB2OC(elem) atIndex:idx];
+}
+
+static id
+nsary_insert_m(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ if (argc < 1) {
+ rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
+ }
+ if (argc > 1) {
+ long pos = NUM2LONG(argv[0]);
+ if (pos == -1) {
+ pos = [rcv count];
+ }
+ if (pos < 0) {
+ pos++;
+ }
+ if (argc == 2) {
+ nsary_insert(rcv, pos, argv[1]);
+ }
+ else {
+ argc--;
+ argv++;
+ NSMutableArray *rpl = [NSMutableArray new];
+ for (int i = 0; i < argc; i++) {
+ [rpl addObject:RB2OC(argv[i])];
+ }
+ nsary_splice(rcv, pos, 0, (VALUE)rpl);
+ }
+ }
+ return rcv;
+}
+
+static VALUE
+nsary_each(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ for (id item in rcv) {
+ rb_yield(OC2RB(item));
+ RETURN_IF_BROKEN();
+ }
+ return (VALUE)rcv;
+}
+
+static VALUE
+nsary_each_index(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ for (long i = 0, count = [rcv count]; i < count; i++) {
+ rb_yield(LONG2NUM(i));
+ RETURN_IF_BROKEN();
+ }
+ return (VALUE)rcv;
+}
+
+static VALUE
+nsary_reverse_each(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ long len = [rcv count];
+ while (len--) {
+ rb_yield(OC2RB([rcv objectAtIndex:len]));
+ RETURN_IF_BROKEN();
+ const long n = [rcv count];
+ if (n < len) {
+ // Array was modified.
+ len = n;
+ }
+ }
+ return (VALUE)rcv;
+
+}
+
+static VALUE
+nsary_length(id rcv, SEL sel)
+{
+ return LONG2NUM([rcv count]);
+}
+
+static VALUE
+nsary_empty(id rcv, SEL sel)
+{
+ return [rcv count] == 0 ? Qtrue : Qfalse;
+}
+
+static VALUE
+nsary_index(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ const long len = [rcv count];
+
+ if (argc == 0) {
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ for (long i = 0; i < len; i++) {
+ VALUE test = rb_yield(OC2RB([rcv objectAtIndex:i]));
+ RETURN_IF_BROKEN();
+ if (RTEST(test)) {
+ return LONG2NUM(i);
+ }
+ }
+ }
+ else {
+ VALUE val;
+ rb_scan_args(argc, argv, "01", &val);
+ if (len > 0) {
+ NSUInteger index = [rcv indexOfObject:RB2OC(val)
+ inRange:NSMakeRange(0, len)];
+ if (index != NSNotFound) {
+ return LONG2NUM(index);
+ }
+ }
+ }
+ return Qnil;
+}
+
+static VALUE
+nsary_rindex(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ const long len = [rcv count];
+
+ if (argc == 0) {
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ long i = len;
+ while (i-- >= 0) {
+ VALUE test = rb_yield(OC2RB([rcv objectAtIndex:i]));
+ RETURN_IF_BROKEN();
+ if (RTEST(test)) {
+ return LONG2NUM(i);
+ }
+ }
+ }
+ else {
+ VALUE val;
+ rb_scan_args(argc, argv, "01", &val);
+ id ocval = RB2OC(val);
+ for (long i = len - 1; i >= 0; i--) {
+ id item = [rcv objectAtIndex:i];
+ if ([ocval isEqual:item]) {
+ return LONG2NUM(i);
+ }
+ }
+ }
+ return Qnil;
+}
+
+static id
+nsary_reverse_bang(id rcv, SEL sel)
+{
+ for (long i = 0, count = [rcv count]; i < (count / 2); i++) {
+ [rcv exchangeObjectAtIndex:i withObjectAtIndex:count - i - 1];
+ }
+ return rcv;
+}
+
+static id
+nsary_reverse(id rcv, SEL sel)
+{
+ return nsary_reverse_bang([rcv mutableCopy], 0);
+}
+
+static NSInteger
+sort_block(id x, id y, void *context)
+{
+ VALUE rbx = OC2RB(x);
+ VALUE rby = OC2RB(y);
+ VALUE ret = rb_yield_values(2, rbx, rby);
+ return rb_cmpint(ret, rbx, rby);
+}
+
+static id
+nsary_sort_bang(id rcv, SEL sel)
+{
+ if ([rcv count] > 1) {
+ if (rb_block_given_p()) {
+ [rcv sortUsingFunction:sort_block context:NULL];
+ }
+ else {
+ [rcv sortUsingSelector:@selector(compare:)];
+ }
+ }
+ return rcv;
+}
+
+static id
+nsary_sort(id rcv, SEL sel)
+{
+ return nsary_sort_bang([rcv mutableCopy], 0);
+}
+
+static VALUE
+collect(id rcv)
+{
+ for (long i = 0, count = [rcv count]; i < count; i++) {
+ id elem = [rcv objectAtIndex:i];
+ id newval = RB2OC(rb_yield(OC2RB(elem)));
+ RETURN_IF_BROKEN();
+ [rcv replaceObjectAtIndex:i withObject:newval];
+ }
+ return (VALUE)rcv;
+}
+
+static VALUE
+nsary_collect_bang(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ return collect(rcv);
+}
+
+static VALUE
+nsary_collect(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ return collect([rcv mutableCopy]);
+}
+
+static VALUE
+nsary_select(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ NSMutableArray *result = [NSMutableArray new];
+ for (id elem in rcv) {
+ VALUE test = rb_yield(OC2RB(elem));
+ RETURN_IF_BROKEN();
+ if (RTEST(test)) {
+ [result addObject:elem];
+ }
+ }
+ return (VALUE)result;
+}
+
+static id
+nsary_values_at(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ const long rcvlen = [rcv count];
+ NSMutableArray *result = [NSMutableArray new];
+ for (long i = 0; i < argc; i++) {
+ long beg, len;
+ switch (rb_range_beg_len(argv[i], &beg, &len, rcvlen, 0)) {
+ // Check if Range.
+ case Qfalse:
+ break;
+ case Qnil:
+ continue;
+ default:
+ for (long j = 0; j < len; j++) {
+ [result addObject:[rcv objectAtIndex:j + beg]];
+ }
+ continue;
+ }
+ [result addObject:[rcv objectAtIndex:NUM2LONG(argv[i])]];
+ }
+ return result;
+}
+
+static bool
+nsary_delete_element(id rcv, VALUE elem)
+{
+ id ocelem = RB2OC(elem);
+ long len = [rcv count];
+ NSRange range = NSMakeRange(0, len);
+ NSUInteger index;
+ bool changed = false;
+ while ((index = [rcv indexOfObject:ocelem inRange:range]) != NSNotFound) {
+ [rcv removeObjectAtIndex:index];
+ range.location = index;
+ range.length = --len - index;
+ changed = true;
+ }
+ return changed;
+}
+
+static VALUE
+nsary_delete(id rcv, SEL sel, VALUE elem)
+{
+ if (!nsary_delete_element(rcv, elem)) {
+ if (rb_block_given_p()) {
+ return rb_yield(elem);
+ }
+ return Qnil;
+ }
+ return elem;
+}
+
+static VALUE
+nsary_delete_at(id rcv, SEL sel, VALUE pos)
+{
+ long index = NUM2LONG(pos);
+ const long len = [rcv count];
+ if (index >= len) {
+ return Qnil;
+ }
+ if (index < 0) {
+ index += len;
+ if (index < 0) {
+ return Qnil;
+ }
+ }
+ VALUE elem = OC2RB([rcv objectAtIndex:index]);
+ [rcv removeObjectAtIndex:index];
+ return elem;
+}
+
+static VALUE
+reject(id rcv)
+{
+ bool changed = false;
+ for (long i = 0, n = [rcv count]; i < n; i++) {
+ VALUE elem = OC2RB([rcv objectAtIndex:i]);
+ VALUE test = rb_yield(elem);
+ RETURN_IF_BROKEN();
+ if (RTEST(test)) {
+ [rcv removeObjectAtIndex:i];
+ n--;
+ i--;
+ changed = true;
+ }
+ }
+ return changed ? (VALUE)rcv : Qnil;
+}
+
+static VALUE
+nsary_delete_if(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ return reject(rcv);
+}
+
+static VALUE
+nsary_reject(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ return reject([rcv mutableCopy]);
+}
+
+static VALUE
+nsary_reject_bang(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ return reject(rcv);
+}
+
+static id
+nsary_replace(id rcv, SEL sel, VALUE other)
+{
+ other = to_ary(other);
+ [rcv setArray:(id)other];
+ return rcv;
+}
+
+static VALUE
+nsary_includes(id rcv, SEL sel, VALUE obj)
+{
+ id elem = RB2OC(obj);
+ return [rcv containsObject:elem] ? Qtrue : Qfalse;
+}
+
+static VALUE
+nsary_slice_bang(id rcv, SEL sel, int argc, VALUE *argv)
+{
+ const long rcvlen = [rcv count];
+ VALUE arg1, arg2;
+ long pos, len;
+
+ if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
+ pos = NUM2LONG(arg1);
+ len = NUM2LONG(arg2);
+delete_pos_len:
+ if (pos < 0) {
+ pos = rcvlen + pos;
+ if (pos < 0) {
+ return Qnil;
+ }
+ }
+ if (rcvlen < len || rcvlen < pos + len) {
+ len = rcvlen - pos;
+ }
+ VALUE result = nsary_subseq(rcv, pos, len);
+ nsary_splice(rcv, pos, len, Qundef);
+ return result;
+ }
+
+ if (!FIXNUM_P(arg1)) {
+ switch (rb_range_beg_len(arg1, &pos, &len, rcvlen, 0)) {
+ case Qtrue:
+ // Valid range.
+ goto delete_pos_len;
+ case Qnil:
+ // invalid range.
+ return Qnil;
+ default:
+ // Not a range.
+ break;
+ }
+ }
+
+ return nsary_delete_at(rcv, 0, arg1);
+}
+
+static id
+nsary_plus(id rcv, SEL sel, VALUE other)
+{
+ other = to_ary(other);
+ NSMutableArray *ary = [NSMutableArray new];
+ [ary addObjectsFromArray:rcv];
+ [ary addObjectsFromArray:(id)other];
+ return ary;
+}
+
+static id
+nsary_times(id rcv, SEL sel, VALUE times)
+{
+ VALUE tmp = rb_check_string_type(times);
+ if (!NIL_P(tmp)) {
+ return (id)rb_ary_join((VALUE)rcv, tmp);
+ }
+
+ const long len = NUM2LONG(times);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative argument");
+ }
+
+ NSMutableArray *result = [NSMutableArray new];
+ if (len > 0) {
+ const long n = [rcv count];
+ if (LONG_MAX/len < n) {
+ rb_raise(rb_eArgError, "argument too big");
+ }
+ for (long i = 0; i < len; i++) {
+ [result addObjectsFromArray:rcv];
+ }
+ }
+ return result;
+}
+
+static VALUE
+nsary_uniq_bang(id rcv, SEL sel)
+{
+ long len = [rcv count];
+ bool changed = false;
+ for (long i = 0; i < len; i++) {
+ id elem = [rcv objectAtIndex:i];
+ NSRange range = NSMakeRange(i + 1, len - i - 1);
+ NSUInteger index;
+ while ((index = [rcv indexOfObject:elem inRange:range]) != NSNotFound) {
+ [rcv removeObjectAtIndex:index];
+ range.location = index;
+ range.length = --len - index;
+ changed = true;
+ }
+ }
+ return changed ? (VALUE)rcv : Qnil;
+}
+
+static id
+nsary_uniq(id rcv, SEL sel)
+{
+ id result = [rcv mutableCopy];
+ nsary_uniq_bang(result, 0);
+ return result;
+}
+
+static VALUE
+nsary_compact_bang(id rcv, SEL sel)
+{
+ return nsary_delete_element(rcv, Qnil) ? (VALUE)rcv : Qnil;
+}
+
+static id
+nsary_compact(id rcv, SEL sel)
+{
+ id result = [rcv mutableCopy];
+ nsary_compact_bang(result, 0);
+ return result;
+}
+
+static VALUE
+nsary_drop(id rcv, SEL sel, VALUE n)
+{
+ const long pos = NUM2LONG(n);
+ if (pos < 0) {
+ rb_raise(rb_eArgError, "attempt to drop negative size");
+ }
+ return nsary_subseq(rcv, pos, [rcv count]);
+}
+
+static VALUE
+nsary_drop_while(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ long i = 0;
+ for (long count = [rcv count]; i < count; i++) {
+ VALUE v = rb_yield(OC2RB([rcv objectAtIndex:i]));
+ RETURN_IF_BROKEN();
+ if (!RTEST(v)) {
+ break;
+ }
+ }
+ return nsary_drop(rcv, 0, LONG2FIX(i));
+}
+
+static VALUE
+nsary_take(id rcv, SEL sel, VALUE n)
+{
+ const long len = NUM2LONG(n);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "attempt to take negative size");
+ }
+ return nsary_subseq(rcv, 0, len);
+}
+
+static VALUE
+nsary_take_while(id rcv, SEL sel)
+{
+ RETURN_ENUMERATOR(rcv, 0, 0);
+ long i = 0;
+ for (long count = [rcv count]; i < count; i++) {
+ VALUE v = rb_yield(OC2RB([rcv objectAtIndex:i]));
+ RETURN_IF_BROKEN();
+ if (!RTEST(v)) {
+ break;
+ }
+ }
+ return nsary_take(rcv, 0, LONG2FIX(i));
+}
+
+static id
+nsary_shuffle_bang(id rcv, SEL sel)
+{
+ long i = [rcv count];
+ while (i > 0) {
+ const long j = rb_genrand_real() * i--;
+ [rcv exchangeObjectAtIndex:i withObjectAtIndex:j];
+ }
+ return rcv;
+}
+
+static id
+nsary_shuffle(id rcv, SEL sel)
+{
+ id result = [rcv mutableCopy];
+ nsary_shuffle_bang(result, 0);
+ return result;
+}
+
+void
+Init_NSArray(void)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
+ rb_cCFArray = (VALUE)objc_getClass("NSCFArray");
+#else
+ rb_cCFArray = (VALUE)objc_getClass("__NSCFArray");
+#endif
+ assert(rb_cCFArray != 0);
+ rb_cNSArray = (VALUE)objc_getClass("NSArray");
+ assert(rb_cNSArray != 0);
+ rb_cArray = rb_cNSArray;
+ rb_cNSMutableArray = (VALUE)objc_getClass("NSMutableArray");
+ assert(rb_cNSMutableArray != 0);
+
+ rb_include_module(rb_cArray, rb_mEnumerable);
+
+ rb_objc_define_method(rb_cArray, "dup", nsary_dup, 0);
+ rb_objc_define_method(rb_cArray, "clone", nsary_clone, 0);
+ rb_objc_define_method(rb_cArray, "clear", nsary_clear, 0);
+ rb_objc_define_method(rb_cArray, "to_s", nsary_inspect, 0);
+ rb_objc_define_method(rb_cArray, "inspect", nsary_inspect, 0);
+ rb_objc_define_method(rb_cArray, "to_a", nsary_to_a, 0);
+ rb_objc_define_method(rb_cArray, "to_ary", nsary_to_a, 0);
+ rb_objc_define_method(rb_cArray, "==", nsary_equal, 1);
+ rb_objc_define_method(rb_cArray, "eql?", nsary_equal, 1);
+ rb_objc_define_method(rb_cArray, "[]", nsary_aref, -1);
+ rb_objc_define_method(rb_cArray, "[]=", nsary_aset, -1);
+ rb_objc_define_method(rb_cArray, "at", nsary_at, 1);
+ rb_objc_define_method(rb_cArray, "fetch", nsary_fetch, -1);
+ rb_objc_define_method(rb_cArray, "first", nsary_first, -1);
+ rb_objc_define_method(rb_cArray, "last", nsary_last, -1);
+ rb_objc_define_method(rb_cArray, "concat", nsary_concat, 1);
+ rb_objc_define_method(rb_cArray, "<<", nsary_push, 1);
+ rb_objc_define_method(rb_cArray, "push", nsary_push_m, -1);
+ rb_objc_define_method(rb_cArray, "pop", nsary_pop, -1);
+ rb_objc_define_method(rb_cArray, "shift", nsary_shift, -1);
+ rb_objc_define_method(rb_cArray, "unshift", nsary_unshift, -1);
+ rb_objc_define_method(rb_cArray, "insert", nsary_insert_m, -1);
+ rb_objc_define_method(rb_cArray, "each", nsary_each, 0);
+ rb_objc_define_method(rb_cArray, "each_index", nsary_each_index, 0);
+ rb_objc_define_method(rb_cArray, "reverse_each", nsary_reverse_each, 0);
+ rb_objc_define_method(rb_cArray, "length", nsary_length, 0);
+ rb_objc_define_method(rb_cArray, "size", nsary_length, 0);
+ rb_objc_define_method(rb_cArray, "empty?", nsary_empty, 0);
+ rb_objc_define_method(rb_cArray, "find_index", nsary_index, -1);
+ rb_objc_define_method(rb_cArray, "index", nsary_index, -1);
+ rb_objc_define_method(rb_cArray, "rindex", nsary_rindex, -1);
+ rb_objc_define_method(rb_cArray, "reverse", nsary_reverse, 0);
+ rb_objc_define_method(rb_cArray, "reverse!", nsary_reverse_bang, 0);
+ rb_objc_define_method(rb_cArray, "sort", nsary_sort, 0);
+ rb_objc_define_method(rb_cArray, "sort!", nsary_sort_bang, 0);
+ rb_objc_define_method(rb_cArray, "collect", nsary_collect, 0);
+ rb_objc_define_method(rb_cArray, "collect!", nsary_collect_bang, 0);
+ rb_objc_define_method(rb_cArray, "map", nsary_collect, 0);
+ rb_objc_define_method(rb_cArray, "map!", nsary_collect_bang, 0);
+ rb_objc_define_method(rb_cArray, "select", nsary_select, 0);
+ rb_objc_define_method(rb_cArray, "values_at", nsary_values_at, -1);
+ rb_objc_define_method(rb_cArray, "delete", nsary_delete, 1);
+ rb_objc_define_method(rb_cArray, "delete_at", nsary_delete_at, 1);
+ rb_objc_define_method(rb_cArray, "delete_if", nsary_delete_if, 0);
+ rb_objc_define_method(rb_cArray, "reject", nsary_reject, 0);
+ rb_objc_define_method(rb_cArray, "reject!", nsary_reject_bang, 0);
+ rb_objc_define_method(rb_cArray, "replace", nsary_replace, 1);
+ rb_objc_define_method(rb_cArray, "include?", nsary_includes, 1);
+ rb_objc_define_method(rb_cArray, "slice", nsary_aref, -1);
+ rb_objc_define_method(rb_cArray, "slice!", nsary_slice_bang, -1);
+ rb_objc_define_method(rb_cArray, "+", nsary_plus, 1);
+ rb_objc_define_method(rb_cArray, "*", nsary_times, 1);
+ rb_objc_define_method(rb_cArray, "uniq", nsary_uniq, 0);
+ rb_objc_define_method(rb_cArray, "uniq!", nsary_uniq_bang, 0);
+ rb_objc_define_method(rb_cArray, "compact", nsary_compact, 0);
+ rb_objc_define_method(rb_cArray, "compact!", nsary_compact_bang, 0);
+ rb_objc_define_method(rb_cArray, "shuffle!", nsary_shuffle_bang, 0);
+ rb_objc_define_method(rb_cArray, "shuffle", nsary_shuffle, 0);
+ rb_objc_define_method(rb_cArray, "take", nsary_take, 1);
+ rb_objc_define_method(rb_cArray, "take_while", nsary_take_while, 0);
+ rb_objc_define_method(rb_cArray, "drop", nsary_drop, 1);
+ rb_objc_define_method(rb_cArray, "drop_while", nsary_drop_while, 0);
+
+ // Implementation shared with RubyArray (and defined in array.c).
+ rb_objc_define_method(rb_cArray, "-", rary_diff, 1);
+ rb_objc_define_method(rb_cArray, "&", rary_and, 1);
+ rb_objc_define_method(rb_cArray, "|", rary_or, 1);
+ rb_objc_define_method(rb_cArray, "join", rary_join, -1);
+ rb_objc_define_method(rb_cArray, "zip", rary_zip, -1);
+ rb_objc_define_method(rb_cArray, "transpose", rary_transpose, 0);
+ rb_objc_define_method(rb_cArray, "fill", rary_fill, -1);
+ rb_objc_define_method(rb_cArray, "<=>", rary_cmp, 1);
+ rb_objc_define_method(rb_cArray, "assoc", rary_assoc, 1);
+ rb_objc_define_method(rb_cArray, "rassoc", rary_rassoc, 1);
+ rb_objc_define_method(rb_cArray, "flatten", rary_flatten, -1);
+ rb_objc_define_method(rb_cArray, "flatten!", rary_flatten_bang, -1);
+ rb_objc_define_method(rb_cArray, "product", rary_product, -1);
+ rb_objc_define_method(rb_cArray, "combination", rary_combination, 1);
+ rb_objc_define_method(rb_cArray, "permutation", rary_permutation, -1);
+ rb_objc_define_method(rb_cArray, "cycle", rary_cycle, -1);
+ rb_objc_define_method(rb_cArray, "sample", rary_sample, -1);
+}
+
+#define PREPARE_RCV(x) \
+ Class old = *(Class *)x; \
+ *(Class *)x = (Class)rb_cCFArray;
+
+#define RESTORE_RCV(x) \
+ *(Class *)x = old;
+
+static long
+imp_rb_array_count(id rcv, SEL sel)
+{
+ PREPARE_RCV(rcv);
+ const long count = [rcv count];
+ RESTORE_RCV(rcv);
+ return count;
+}
+
+static id
+imp_rb_array_objectAtIndex(id rcv, SEL sel, long idx)
+{
+ PREPARE_RCV(rcv);
+ id obj = [rcv objectAtIndex:idx];
+ RESTORE_RCV(rcv);
+ return obj;
+}
+
+static void
+imp_rb_array_insertObjectAtIndex(id rcv, SEL sel, id obj, long idx)
+{
+ PREPARE_RCV(rcv);
+ [rcv insertObject:obj atIndex:idx];
+ RESTORE_RCV(rcv);
+}
+
+static void
+imp_rb_array_removeObjectAtIndex(id rcv, SEL sel, long idx)
+{
+ PREPARE_RCV(rcv);
+ [rcv removeObjectAtIndex:idx];
+ RESTORE_RCV(rcv);
+}
+
+static void
+imp_rb_array_replaceObjectAtIndexWithObject(id rcv, SEL sel, long idx, id obj)
+{
+ PREPARE_RCV(rcv);
+ [rcv replaceObjectAtIndex:idx withObject:obj];
+ RESTORE_RCV(rcv);
+}
+
+static void
+imp_rb_array_addObject(id rcv, SEL sel, id obj)
+{
+ PREPARE_RCV(rcv);
+ [rcv addObject:obj];
+ RESTORE_RCV(rcv);
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
+// This is to work around a bug where CF will try to call an non-existing
+// method.
+static CFIndex
+imp_rb_array_cfindexOfObjectInRange(void *rcv, SEL sel, void *obj,
+ CFRange range)
+{
+ CFIndex i;
+ PREPARE_RCV(rcv);
+ i = CFArrayGetFirstIndexOfValue((CFArrayRef)rcv, range, obj);
+ RESTORE_RCV(rcv);
+ return i;
+}
+#endif
+
+void
+rb_objc_install_array_primitives(Class klass)
+{
+ rb_objc_install_method2(klass, "count", (IMP)imp_rb_array_count);
+ rb_objc_install_method2(klass, "objectAtIndex:",
+ (IMP)imp_rb_array_objectAtIndex);
+
+ const bool is_mutable = class_getSuperclass(klass)
+ == (Class)rb_cNSMutableArray;
+
+ if (is_mutable) {
+ rb_objc_install_method2(klass, "insertObject:atIndex:",
+ (IMP)imp_rb_array_insertObjectAtIndex);
+ rb_objc_install_method2(klass, "removeObjectAtIndex:",
+ (IMP)imp_rb_array_removeObjectAtIndex);
+ rb_objc_install_method2(klass, "replaceObjectAtIndex:withObject:",
+ (IMP)imp_rb_array_replaceObjectAtIndexWithObject);
+ rb_objc_install_method2(klass, "addObject:",
+ (IMP)imp_rb_array_addObject);
+ }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
+ // This is to work around a bug where CF will try to call an non-existing
+ // method.
+ rb_objc_install_method2(klass, "_cfindexOfObject:range:",
+ (IMP)imp_rb_array_cfindexOfObjectInRange);
+ Method m = class_getInstanceMethod(klass,
+ sel_registerName("_cfindexOfObject:range:"));
+ class_addMethod(klass, sel_registerName("_cfindexOfObject:inRange:"),
+ method_getImplementation(m), method_getTypeEncoding(m));
+#endif
+
+ //rb_objc_define_method(*(VALUE *)klass, "alloc", ary_alloc, 0);
+}
+
+// MRI compatibility API.
+
+VALUE
+rb_ary_freeze(VALUE ary)
+{
+ return OBJ_FREEZE(ary);
+}
+
+VALUE
+rb_ary_frozen_p(VALUE ary)
+{
+ return OBJ_FROZEN(ary) ? Qtrue : Qfalse;
+}
+
+long
+rb_ary_len(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return RARY(ary)->len;
+ }
+ else {
+ return [(id)ary count];
+ }
+}
+
+VALUE
+rb_ary_elt(VALUE ary, long offset)
+{
+ if (offset >= 0) {
+ if (IS_RARY(ary)) {
+ if (offset < RARY(ary)->len) {
+ return rary_elt(ary, offset);
+ }
+ }
+ else {
+ if (offset < [(id)ary count]) {
+ return OC2RB([(id)ary objectAtIndex:offset]);
+ }
+ }
+ }
+ return Qnil;
+}
+
+VALUE
+rb_ary_replace(VALUE rcv, VALUE other)
+{
+ other = to_ary(other);
+ rb_ary_clear(rcv);
+ for (long i = 0, count = RARRAY_LEN(other); i < count; i++) {
+ rb_ary_push(rcv, RARRAY_AT(other, i));
+ }
+ return rcv;
+}
+
+VALUE
+rb_ary_clear(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_clear(ary, 0);
+ }
+ else {
+ return (VALUE)nsary_clear((id)ary, 0);
+ }
+}
+
+static VALUE
+recursive_join(VALUE ary, VALUE argp, int recur)
+{
+ VALUE *arg = (VALUE *)argp;
+ if (recur) {
+ return rb_usascii_str_new2("[...]");
+ }
+ return rb_ary_join(arg[0], arg[1]);
+}
+
+VALUE
+rb_ary_join(VALUE ary, VALUE sep)
+{
+ if (RARRAY_LEN(ary) == 0) {
+ return rb_str_new(0, 0);
+ }
+
+ bool taint = false;
+ if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) {
+ taint = true;
+ }
+ bool untrust = false;
+ if (OBJ_UNTRUSTED(ary) || OBJ_UNTRUSTED(sep)) {
+ untrust = true;
+ }
+
+ VALUE result = rb_str_new(0, 0);
+
+ for (long i = 0, count = RARRAY_LEN(ary); i < count; i++) {
+ VALUE tmp = RARRAY_AT(ary, i);
+ switch (TYPE(tmp)) {
+ case T_STRING:
+ break;
+ case T_ARRAY:
+ {
+ VALUE args[2];
+
+ args[0] = tmp;
+ args[1] = sep;
+ tmp = rb_exec_recursive(recursive_join, ary, (VALUE)args);
+ }
+ break;
+ default:
+ tmp = rb_obj_as_string(tmp);
+ }
+ if (i > 0 && !NIL_P(sep)) {
+ rb_str_buf_append(result, sep);
+ }
+ rb_str_buf_append(result, tmp);
+
+ if (OBJ_TAINTED(tmp)) {
+ taint = true;
+ }
+ if (OBJ_UNTRUSTED(tmp)) {
+ untrust = true;
+ }
+ }
+
+ if (taint) {
+ OBJ_TAINT(result);
+ }
+ if (untrust) {
+ OBJ_UNTRUST(result);
+ }
+ return result;
+}
+
+VALUE
+rb_ary_dup(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_dup(ary, 0);
+ }
+ else {
+ return (VALUE)nsary_dup((id)ary, 0);
+ }
+}
+
+VALUE
+rb_ary_reverse(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_reverse_bang(ary, 0);
+ }
+ else {
+ return (VALUE)nsary_reverse_bang((id)ary, 0);
+ }
+}
+
+VALUE
+rb_ary_includes(VALUE ary, VALUE item)
+{
+ if (IS_RARY(ary)) {
+ return rary_includes(ary, 0, item);
+ }
+ else {
+ return nsary_includes((id)ary, 0, item);
+ }
+}
+
+VALUE
+rb_ary_delete(VALUE ary, VALUE item)
+{
+ if (IS_RARY(ary)) {
+ return rary_delete(ary, 0, item);
+ }
+ else {
+ return nsary_delete((id)ary, 0, item);
+ }
+}
+
+VALUE
+rb_ary_delete_at(VALUE ary, long pos)
+{
+ if (IS_RARY(ary)) {
+ return rary_delete_at(ary, 0, LONG2NUM(pos));
+ }
+ else {
+ return nsary_delete_at((id)ary, 0, LONG2NUM(pos));
+ }
+}
+
+VALUE
+rb_ary_pop(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_pop(ary, 0, 0, NULL);
+ }
+ else {
+ return nsary_pop((id)ary, 0, 0, NULL);
+ }
+}
+
+VALUE
+rb_ary_shift(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_shift(ary, 0, 0, NULL);
+ }
+ else {
+ return nsary_shift((id)ary, 0, 0, NULL);
+ }
+}
+
+VALUE
+rb_ary_subseq(VALUE ary, long beg, long len)
+{
+ if (IS_RARY(ary)) {
+ return rary_subseq(ary, beg, len);
+ }
+ else {
+ return nsary_subseq((id)ary, beg, len);
+ }
+}
+
+VALUE
+rb_ary_entry(VALUE ary, long offset)
+{
+ if (IS_RARY(ary)) {
+ return rary_entry(ary, offset);
+ }
+ else {
+ return nsary_entry((id)ary, offset);
+ }
+}
+
+VALUE
+rb_ary_aref(VALUE ary, SEL sel, int argc, VALUE *argv)
+{
+ if (IS_RARY(ary)) {
+ return rary_aref(ary, 0, argc, argv);
+ }
+ else {
+ return nsary_aref((id)ary, 0, argc, argv);
+ }
+}
+
+void
+rb_ary_store(VALUE ary, long idx, VALUE val)
+{
+ if (IS_RARY(ary)) {
+ rary_store(ary, idx, val);
+ }
+ else {
+ nsary_store((id)ary, idx, val);
+ }
+}
+
+void
+rb_ary_insert(VALUE ary, long idx, VALUE val)
+{
+ if (IS_RARY(ary)) {
+ rary_insert(ary, idx, val);
+ }
+ else {
+ nsary_insert((id)ary, idx, val);
+ }
+}
+
+VALUE
+rb_ary_concat(VALUE x, VALUE y)
+{
+ if (IS_RARY(x)) {
+ return rary_concat_m(x, 0, y);
+ }
+ else {
+ return (VALUE)nsary_concat((id)x, 0, y);
+ }
+}
+
+VALUE
+rb_ary_push(VALUE ary, VALUE item)
+{
+ if (IS_RARY(ary)) {
+ return rary_push_m(ary, 0, item);
+ }
+ else {
+ return (VALUE)nsary_push((id)ary, 0, item);
+ }
+}
+
+VALUE
+rb_ary_plus(VALUE x, VALUE y)
+{
+ if (IS_RARY(x)) {
+ return rary_plus(x, 0, y);
+ }
+ else {
+ return (VALUE)nsary_plus((id)x, 0, y);
+ }
+}
+
+VALUE
+rb_ary_unshift(VALUE ary, VALUE item)
+{
+ if (IS_RARY(ary)) {
+ return rary_unshift(ary, 0, 1, &item);
+ }
+ else {
+ return (VALUE)nsary_unshift((id)ary, 0, 1, &item);
+ }
+}
+
+VALUE
+rb_ary_each(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_each(ary, 0);
+ }
+ else {
+ return nsary_each((id)ary, 0);
+ }
+}
+
+VALUE
+rb_ary_sort(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_sort(ary, 0);
+ }
+ else {
+ return (VALUE)nsary_sort((id)ary, 0);
+ }
+}
+
+VALUE
+rb_ary_sort_bang(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_sort_bang(ary, 0);
+ }
+ else {
+ return (VALUE)nsary_sort_bang((id)ary, 0);
+ }
+}
+
+static void *nsary_cptr_key = NULL;
+
+const VALUE *
+rb_ary_ptr(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ return rary_ptr(ary);
+ }
+
+ id nsary = (id)ary;
+ const long len = [nsary count];
+ if (len == 0) {
+ return NULL;
+ }
+
+ VALUE *values = (VALUE *)xmalloc(sizeof(VALUE) * len);
+ for (long i = 0; i < len; i++) {
+ values[i] = OC2RB([nsary objectAtIndex:i]);
+ }
+
+ rb_objc_set_associative_ref((void *)nsary, &nsary_cptr_key, values);
+
+ return values;
+}
Modified: MacRuby/trunk/NSDictionary.m
===================================================================
--- MacRuby/trunk/NSDictionary.m 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/NSDictionary.m 2010-02-07 04:51:44 UTC (rev 3438)
@@ -12,6 +12,7 @@
#include "ruby/node.h"
#include "objc.h"
#include "vm.h"
+#include "hash.h"
VALUE rb_cHash;
VALUE rb_cNSHash;
@@ -98,10 +99,16 @@
return [rcv isEqualToDictionary:other] ? Qtrue : Qfalse;
}
+static inline VALUE
+nshash_lookup(id rcv, VALUE key)
+{
+ return OC2RB([rcv objectForKey:RB2OC(key)]);
+}
+
static VALUE
nshash_aref(id rcv, SEL sel, VALUE key)
{
- return OC2RB([rcv objectForKey:RB2OC(key)]);
+ return nshash_lookup(rcv, key);
}
static VALUE
@@ -191,6 +198,7 @@
RETURN_ENUMERATOR(rcv, 0, 0);
for (id key in rcv) {
rb_yield(OC2RB([rcv objectForKey:key]));
+ RETURN_IF_BROKEN();
}
return (VALUE)rcv;
}
@@ -201,6 +209,7 @@
RETURN_ENUMERATOR(rcv, 0, 0);
for (id key in rcv) {
rb_yield(OC2RB(key));
+ RETURN_IF_BROKEN();
}
return (VALUE)rcv;
}
@@ -212,6 +221,7 @@
for (id key in rcv) {
id value = [rcv objectForKey:key];
rb_yield(rb_assoc_new(OC2RB(key), OC2RB(value)));
+ RETURN_IF_BROKEN();
}
return (VALUE)rcv;
}
@@ -277,6 +287,7 @@
if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
[ary addObject:key];
}
+ RETURN_IF_BROKEN();
}
[rcv removeObjectsForKeys:ary];
return (VALUE)rcv;
@@ -292,6 +303,7 @@
if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
[dict setObject:value forKey:key];
}
+ RETURN_IF_BROKEN();
}
return (VALUE)dict;
}
@@ -608,3 +620,138 @@
//rb_objc_define_method(*(VALUE *)klass, "alloc", hash_alloc, 0);
}
+
+// MRI compatibility API.
+
+VALUE
+rb_hash_dup(VALUE rcv)
+{
+ if (IS_RHASH(rcv)) {
+ return rhash_dup(rcv, 0);
+ }
+ else {
+ return (VALUE)nshash_dup((id)rcv, 0);
+ }
+}
+
+void
+rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
+{
+ if (IS_RHASH(hash)) {
+ rhash_foreach(hash, func, farg);
+ }
+ else {
+ for (id key in (id)hash) {
+ id value = [(id)hash objectForKey:key];
+ if ((*func)(OC2RB(key), OC2RB(value), farg) == ST_STOP) {
+ break;
+ }
+ }
+ }
+}
+
+VALUE
+rb_hash_lookup(VALUE hash, VALUE key)
+{
+ if (IS_RHASH(hash)) {
+ VALUE val = rhash_lookup(hash, key);
+ return val == Qundef ? Qnil : val;
+ }
+ else {
+ return nshash_lookup((id)hash, key);
+ }
+}
+
+VALUE
+rb_hash_aref(VALUE hash, VALUE key)
+{
+ if (IS_RHASH(hash)) {
+ return rhash_aref(hash, 0, key);
+ }
+ else {
+ return nshash_lookup((id)hash, key);
+ }
+}
+
+VALUE
+rb_hash_delete_key(VALUE hash, VALUE key)
+{
+ if (IS_RHASH(hash)) {
+ rhash_modify(hash);
+ return rhash_delete_key(hash, key);
+ }
+ else {
+ id ockey = RB2OC(key);
+ id value = [(id)hash objectForKey:ockey];
+ if (value != nil) {
+ [(id)hash removeObjectForKey:ockey];
+ return OC2RB(value);
+ }
+ return Qundef;
+ }
+}
+
+VALUE
+rb_hash_delete(VALUE hash, VALUE key)
+{
+ VALUE val = rb_hash_delete_key(hash, key);
+ if (val != Qundef) {
+ return val;
+ }
+ return Qnil;
+}
+
+VALUE
+rb_hash_aset(VALUE hash, VALUE key, VALUE val)
+{
+ if (IS_RHASH(hash)) {
+ return rhash_aset(hash, 0, key, val);
+ }
+ else {
+ return nshash_aset((id)hash, 0, key, val);
+ }
+}
+
+long
+rb_hash_size(VALUE hash)
+{
+ if (IS_RHASH(hash)) {
+ return rhash_len(hash);
+ }
+ else {
+ return [(id)hash count];
+ }
+}
+
+VALUE
+rb_hash_keys(VALUE hash)
+{
+ if (IS_RHASH(hash)) {
+ return rhash_keys(hash, 0);
+ }
+ else {
+ return (VALUE)nshash_keys((id)hash, 0);
+ }
+}
+
+VALUE
+rb_hash_has_key(VALUE hash, VALUE key)
+{
+ if (IS_RHASH(hash)) {
+ return rhash_has_key(hash, 0, key);
+ }
+ else {
+ return nshash_has_key((id)hash, 0, key);
+ }
+}
+
+VALUE
+rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
+{
+ if (IS_RHASH(hash)) {
+ return rhash_set_default(hash, 0, ifnone);
+ }
+ else {
+ return nshash_set_default((id)hash, 0, ifnone);
+ }
+}
Modified: MacRuby/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/array.c 2010-02-07 04:51:44 UTC (rev 3438)
@@ -16,186 +16,135 @@
#include "objc.h"
#include "ruby/node.h"
#include "vm.h"
+#include "array.h"
-VALUE rb_cArray;
-VALUE rb_cCFArray;
-VALUE rb_cNSArray;
-VALUE rb_cNSMutableArray;
VALUE rb_cRubyArray;
#define ARY_DEFAULT_SIZE 16
-typedef struct {
- struct RBasic basic;
- size_t beg;
- size_t len;
- size_t cap;
- VALUE *elements;
-} rb_ary_t;
-
// RubyArray primitives.
-static VALUE
-rary_elt(rb_ary_t *ary, size_t idx)
+void
+rary_reserve(VALUE ary, size_t newlen)
{
-// assert(idx < ary->len);
- return ary->elements[ary->beg + idx];
-}
-
-static void
-rary_replace(rb_ary_t *ary, size_t idx, VALUE item)
-{
-// assert(idx < ary->len);
- GC_WB(&ary->elements[ary->beg + idx], item);
-}
-
-static VALUE *
-rary_ptr(rb_ary_t *ary)
-{
- return &ary->elements[ary->beg];
-}
-
-static void
-rary_reserve(rb_ary_t *ary, size_t newlen)
-{
- if (ary->beg + newlen > ary->cap) {
- if (ary->beg > 0) {
- if (ary->beg > newlen) {
+ rb_ary_t *rary = RARY(ary);
+ if (rary->beg + newlen > rary->cap) {
+ if (rary->beg > 0) {
+ if (rary->beg > newlen) {
newlen = 0;
}
else {
- newlen -= ary->beg;
+ newlen -= rary->beg;
}
- for (size_t i = 0; i < ary->len; i++) {
- GC_WB(&ary->elements[i], ary->elements[ary->beg + i]);
+ for (size_t i = 0; i < rary->len; i++) {
+ GC_WB(&rary->elements[i], rary->elements[rary->beg + i]);
}
- ary->beg = 0;
+ rary->beg = 0;
}
- if (newlen > ary->cap) {
- if (ary->cap > 0) {
+ if (newlen > rary->cap) {
+ if (rary->cap > 0) {
newlen *= 2;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
VALUE *new_elements = (VALUE *)xmalloc(sizeof(VALUE) * newlen);
- for (size_t i = 0; i < ary->len; i++) {
- GC_WB(&new_elements[i], ary->elements[i]);
+ for (size_t i = 0; i < rary->len; i++) {
+ GC_WB(&new_elements[i], rary->elements[i]);
}
GC_WB(&ary->elements, new_elements);
#else
-//printf("xrealloc %p (%ld -> %ld)\n", ary, ary->cap, newlen);
- VALUE *new_elements = xrealloc(ary->elements, sizeof(VALUE) * newlen);
- if (new_elements != ary->elements) {
- GC_WB(&ary->elements, new_elements);
+ VALUE *new_elements = xrealloc(rary->elements,
+ sizeof(VALUE) * newlen);
+ if (new_elements != rary->elements) {
+ GC_WB(&rary->elements, new_elements);
}
#endif
- ary->cap = newlen;
+ rary->cap = newlen;
}
}
}
-static void
-rary_append(rb_ary_t *ary, VALUE item)
-{
- rary_reserve(ary, ary->len + 1);
- rary_replace(ary, ary->len, item);
- ary->len++;
-}
-
-static void
-rary_insert(rb_ary_t *ary, size_t idx, VALUE item)
-{
- assert(idx <= ary->len);
- if (idx < ary->len) {
- rary_reserve(ary, ary->len + 1);
- for (size_t i = ary->len; i > idx; i--) {
- rary_replace(ary, i, rary_elt(ary, i - 1));
- }
- rary_replace(ary, idx, item);
- ary->len++;
- }
- else {
- rary_append(ary, item);
- }
-}
-
static VALUE
-rary_erase(rb_ary_t *ary, size_t idx, size_t len)
+rary_erase(VALUE ary, size_t idx, size_t len)
{
- assert(idx + len <= ary->len);
+ assert(idx + len <= RARY(ary)->len);
VALUE item = rary_elt(ary, idx);
if (idx == 0) {
for (size_t i = 0; i < len; i++) {
- rary_replace(ary, i, Qnil);
+ rary_elt_set(ary, i, Qnil);
}
- if (len < ary->len) {
- ary->beg += len;
+ if (len < RARY(ary)->len) {
+ RARY(ary)->beg += len;
}
else {
- ary->beg = 0;
+ RARY(ary)->beg = 0;
}
}
else {
- for (size_t i = idx; i < ary->len - len; i++) {
- rary_replace(ary, i, rary_elt(ary, i + len));
+ for (size_t i = idx; i < RARY(ary)->len - len; i++) {
+ rary_elt_set(ary, i, rary_elt(ary, i + len));
}
for (size_t i = 0; i < len; i++) {
- rary_replace(ary, ary->len - i - 1, Qnil);
+ rary_elt_set(ary, RARY(ary)->len - i - 1, Qnil);
}
}
- ary->len -= len;
+ RARY(ary)->len -= len;
return item;
}
-static void
-rary_store(rb_ary_t *ary, size_t idx, VALUE item)
+void
+rary_store(VALUE ary, long idx, VALUE item)
{
- if (idx >= ary->len) {
+ if (idx < 0) {
+ const long len = RARY(ary)->len;
+ idx += len;
+ if (idx < 0) {
+ rb_raise(rb_eIndexError, "index %ld out of array",
+ idx - len);
+ }
+ }
+ if (idx >= RARY(ary)->len) {
rary_reserve(ary, idx + 1);
- for (size_t i = ary->len; i < idx + 1; i++) {
- rary_replace(ary, i, Qnil);
+ for (size_t i = RARY(ary)->len; i < idx + 1; i++) {
+ rary_elt_set(ary, i, Qnil);
}
- ary->len = idx + 1;
+ RARY(ary)->len = idx + 1;
}
- rary_replace(ary, idx, item);
+ rary_elt_set(ary, idx, item);
}
static void
-rary_resize(rb_ary_t *ary, size_t newlen)
+rary_resize(VALUE ary, size_t newlen)
{
- if (newlen > ary->cap) {
+ if (newlen > RARY(ary)->cap) {
rary_reserve(ary, newlen);
}
- for (size_t i = ary->len; i < newlen; i++) {
- rary_replace(ary, i, Qnil);
+ for (size_t i = RARY(ary)->len; i < newlen; i++) {
+ rary_elt_set(ary, i, Qnil);
}
- ary->len = newlen;
+ RARY(ary)->len = newlen;
}
static void
-rary_concat(rb_ary_t *ary, rb_ary_t *other, size_t beg, size_t len)
+rary_concat(VALUE ary, VALUE other, size_t beg, size_t len)
{
- rary_reserve(ary, ary->len + len);
- for (size_t i = 0; i < len; i++) {
- rary_replace(ary, i + ary->len, rary_elt(other, beg + i));
+ rary_reserve(ary, RARY(ary)->len + len);
+ if (IS_RARY(other)) {
+ for (size_t i = 0; i < len; i++) {
+ rary_elt_set(ary, i + RARY(ary)->len,
+ rary_elt(other, beg + i));
+ }
}
- ary->len += len;
-}
-
-static void
-rary_reverse(rb_ary_t *ary)
-{
- if (ary->len > 1) {
- for (size_t i = 0; i < ary->len / 2; i++) {
- const size_t j = ary->len - i - 1;
- VALUE elem = rary_elt(ary, i);
- rary_replace(ary, i, rary_elt(ary, j));
- rary_replace(ary, j, elem);
+ else {
+ for (size_t i = 0; i < len; i++) {
+ rary_elt_set(ary, i + RARY(ary)->len,
+ rb_ary_elt(other, beg + i));
}
}
+ RARY(ary)->len += len;
}
static void
-rary_clear(rb_ary_t *ary)
+rary_remove_all(rb_ary_t *ary)
{
memset(ary->elements, 0, sizeof(VALUE) * ary->len);
ary->len = 0;
@@ -216,47 +165,6 @@
return rb_equal(x, y);
}
-#define NOT_FOUND LONG_MAX
-
-static size_t
-rary_index_of_item(rb_ary_t *ary, size_t origin, VALUE item)
-{
- assert(origin < ary->len);
- for (size_t i = origin; i < ary->len; i++) {
- VALUE item2 = rary_elt(ary, i);
- if (rb_equal_fast(item, item2) == Qtrue) {
- return i;
- }
- }
- return NOT_FOUND;
-}
-
-//#define IS_RARY(x) (*(VALUE *)x == rb_cRubyArray)
-// XXX temporary
-#define IS_RARY(x) __is_rary(*(VALUE *)x)
-#define RARY(x) ((rb_ary_t *)x)
-
-static force_inline bool
-__is_rary(VALUE k)
-{
- while (k != 0) {
- if (k == rb_cRubyArray) {
- return true;
- }
- if (k == rb_cCFArray) {
- return false;
- }
- k = RCLASS_SUPER(k);
- }
- return false;
-}
-
-bool
-rb_klass_is_rary(VALUE klass)
-{
- return __is_rary(klass);
-}
-
void
rb_mem_clear(register VALUE *mem, register long size)
{
@@ -265,123 +173,18 @@
}
}
-bool _CFArrayIsMutable(void *);
-
-static inline void
-__rb_ary_modify(VALUE ary)
-{
- long mask;
- if (IS_RARY(ary)) {
- mask = RBASIC(ary)->flags;
- }
- else {
- mask = rb_objc_flag_get_mask((void *)ary);
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
- // XXX we shouldn't need to do that and follow the new hash refactoring
- if (!_CFArrayIsMutable((void *)ary)) {
- mask |= FL_FREEZE;
- }
-#endif
- }
- if ((mask & FL_FREEZE) == FL_FREEZE) {
- rb_raise(rb_eRuntimeError, "can't modify frozen/immutable array");
- }
- if ((mask & FL_TAINT) == FL_TAINT && rb_safe_level() >= 4) {
- rb_raise(rb_eSecurityError, "Insecure: can't modify array");
- }
-}
-
-#define rb_ary_modify(ary) \
- do { \
- if (!IS_RARY(ary) || RBASIC(ary)->flags != 0) { \
- __rb_ary_modify(ary); \
- } \
- } \
- while (0)
-
-extern void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap);
-
-static inline void
-rb_ary_set_capacity(VALUE ary, long len)
-{
- if (RARRAY_LEN(ary) < len) {
- if (IS_RARY(ary)) {
- rary_reserve(RARY(ary), len);
- }
- else {
- _CFArraySetCapacity((CFMutableArrayRef)ary, len);
- }
- }
-}
-
-VALUE
-rb_ary_freeze(VALUE ary)
-{
- return rb_obj_freeze(ary);
-}
-
-/*
- * call-seq:
- * array.frozen? -> true or false
- *
- * Return <code>true</code> if this array is frozen (or temporarily frozen
- * while being sorted).
- */
-
-VALUE
-rb_ary_frozen_p(VALUE ary)
-{
- return OBJ_FROZEN(ary) ? Qtrue : Qfalse;
-}
-
-static VALUE
-rb_ary_frozen_imp(VALUE ary, SEL sel)
-{
- return rb_ary_frozen_p(ary);
-}
-
-void rb_ary_insert(VALUE ary, long idx, VALUE val);
-
static inline VALUE
-ary_alloc(VALUE klass)
+rary_alloc(VALUE klass, SEL sel)
{
- if (rb_cRubyArray != 0 && (klass == 0 || __is_rary(klass))) {
- NEWOBJ(ary, rb_ary_t);
- ary->basic.flags = 0;
- ary->basic.klass = klass == 0 ? rb_cRubyArray : klass;
- ary->beg = ary->len = ary->cap = 0;
- ary->elements = NULL;
- return (VALUE)ary;
- }
- else {
- CFMutableArrayRef ary = CFArrayCreateMutable(NULL, 0,
- &kCFTypeArrayCallBacks);
- if (klass != 0 && klass != rb_cNSArray && klass != rb_cNSMutableArray) {
- *(Class *)ary = (Class)klass;
- }
- CFMakeCollectable(ary);
- return (VALUE)ary;
- }
-}
+ assert(klass != 0);
+ assert(rb_klass_is_rary(klass));
-VALUE
-rb_ary_new_fast(int argc, ...)
-{
- VALUE ary = ary_alloc(0);
-
- if (argc > 0) {
- va_list ar;
-
- rary_reserve(RARY(ary), argc);
- va_start(ar, argc);
- for (int i = 0; i < argc; i++) {
- VALUE item = va_arg(ar, VALUE);
- rary_append(RARY(ary), item);
- }
- va_end(ar);
- }
-
- return ary;
+ NEWOBJ(ary, rb_ary_t);
+ ary->basic.flags = 0;
+ ary->basic.klass = klass;
+ ary->beg = ary->len = ary->cap = 0;
+ ary->elements = NULL;
+ return (VALUE)ary;
}
static inline void
@@ -395,31 +198,31 @@
}
}
-static VALUE
-ary_new(VALUE klass, long len)
+VALUE
+rb_ary_new2(long len)
{
assert_ary_len(len);
- VALUE ary = ary_alloc(klass);
- if (IS_RARY(ary)) {
- rary_reserve(RARY(ary), len);
+ VALUE ary;
+ if (rb_cRubyArray != 0) {
+ ary = rary_alloc(rb_cRubyArray, 0);
+ rary_reserve(ary, len);
}
+ else {
+ // RubyArray does not exist yet... fallback on an CFArray.
+ ary = (VALUE)CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ CFMakeCollectable((void *)ary);
+ }
return ary;
}
VALUE
-rb_ary_new2(long len)
-{
- return ary_new(0, len);
-}
-
-VALUE
rb_ary_new(void)
{
return rb_ary_new2(ARY_DEFAULT_SIZE);
}
-#include <stdarg.h>
+static void rary_push(VALUE ary, VALUE item);
VALUE
rb_ary_new3(long n, ...)
@@ -429,9 +232,9 @@
if (n > 0) {
va_list ar;
va_start(ar, n);
- rary_reserve(RARY(ary), n);
+ rary_reserve(ary, n);
for (long i = 0; i < n; i++) {
- rary_append(RARY(ary), va_arg(ar, VALUE));
+ rary_push(ary, va_arg(ar, VALUE));
}
va_end(ar);
}
@@ -442,26 +245,12 @@
VALUE
rb_ary_new4(long n, const VALUE *elts)
{
- VALUE ary;
-
- ary = rb_ary_new2(n);
+ VALUE ary = rb_ary_new2(n);
if (n > 0 && elts != NULL) {
- if (IS_RARY(ary)) {
- for (long i = 0; i < n; i++) {
- rary_append(RARY(ary), elts[i]);
- }
+ for (long i = 0; i < n; i++) {
+ rary_push(ary, elts[i]);
}
- else {
- void **vals = (void **)alloca(n * sizeof(void *));
-
- for (long i = 0; i < n; i++) {
- vals[i] = RB2OC(elts[i]);
- }
- CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0),
- (const void **)vals, n);
- }
}
-
return ary;
}
@@ -471,101 +260,12 @@
return rb_ary_new3(2, car, cdr);
}
-static VALUE
-to_ary(VALUE ary)
-{
- return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
-}
-
VALUE
rb_check_array_type(VALUE ary)
{
return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
}
-long
-rb_ary_len(VALUE ary)
-{
- if (IS_RARY(ary)) {
- return RARY(ary)->len;
- }
- else {
- return CFArrayGetCount((CFArrayRef)ary);
- }
-}
-
-VALUE
-rb_ary_elt(VALUE ary, long offset)
-{
- if (IS_RARY(ary)) {
- if (offset < RARY(ary)->len) {
- return rary_elt(RARY(ary), offset);
- }
- }
- else {
- if (offset < CFArrayGetCount((CFArrayRef)ary)) {
- return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
- }
- }
- return Qnil;
-}
-
-VALUE
-rb_ary_erase(VALUE ary, long offset)
-{
- if (IS_RARY(ary)) {
- return rary_erase(RARY(ary), offset, 1);
- }
- else {
- VALUE item = OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
- CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, offset);
- return item;
- }
-}
-
-VALUE
-rb_ary_push(VALUE ary, VALUE item)
-{
- rb_ary_modify(ary);
- if (IS_RARY(ary)) {
- rary_append(RARY(ary), item);
- }
- else {
- CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)RB2OC(item));
- }
- return ary;
-}
-
-inline static void
-rb_ary_append(VALUE ary, int argc, VALUE *argv)
-{
- rb_ary_modify(ary);
- if (IS_RARY(ary)) {
- rary_reserve(RARY(ary), argc);
- for (int i = 0; i < argc; i++) {
- rary_append(RARY(ary), argv[i]);
- }
- }
- else {
- for (int i = 0; i < argc; i++) {
- CFArrayAppendValue((CFMutableArrayRef)ary,
- (const void *)RB2OC(argv[i]));
- }
- }
-}
-
-static inline void
-rb_ary_resize(VALUE ary, long new_len)
-{
- if (IS_RARY(ary)) {
- rary_resize(RARY(ary), new_len);
- }
- else {
- // TODO
- abort();
- }
-}
-
/*
* call-seq:
* Array.try_convert(obj) -> array or nil
@@ -587,7 +287,7 @@
*/
static VALUE
-rb_ary_s_try_convert(VALUE dummy, SEL sel, VALUE ary)
+rary_s_try_convert(VALUE dummy, SEL sel, VALUE ary)
{
return rb_check_array_type(ary);
}
@@ -630,16 +330,18 @@
* copy = Array.new(squares)
*/
+static VALUE rary_replace(VALUE rcv, SEL sel, VALUE other);
+
static VALUE
-rb_ary_initialize(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_initialize(VALUE ary, SEL sel, int argc, VALUE *argv)
{
- //ary = (VALUE)objc_msgSend((id)ary, selInit);
+ rary_modify(ary);
if (argc == 0) {
if (rb_block_given_p()) {
rb_warning("given block not used");
}
- rb_ary_clear(ary);
+ rary_remove_all(RARY(ary));
return ary;
}
@@ -648,31 +350,28 @@
if (argc == 1 && !FIXNUM_P(size)) {
val = rb_check_array_type(size);
if (!NIL_P(val)) {
- rb_ary_replace(ary, val);
+ rary_replace(ary, 0, val);
return ary;
}
}
- long len = NUM2LONG(size);
+ const long len = NUM2LONG(size);
assert_ary_len(len);
-
- rb_ary_modify(ary);
-
if (rb_block_given_p()) {
if (argc == 2) {
rb_warn("block supersedes default value argument");
}
- rb_ary_clear(ary);
+ rary_remove_all(RARY(ary));
for (long i = 0; i < len; i++) {
VALUE v = rb_yield(LONG2NUM(i));
RETURN_IF_BROKEN();
- rb_ary_push(ary, v);
+ rary_push(ary, v);
}
}
else {
- rb_ary_resize(ary, len);
+ rary_resize(ary, len);
for (long i = 0; i < len; i++) {
- rb_ary_store(ary, i, val);
+ rary_store(ary, i, val);
}
}
return ary;
@@ -687,62 +386,43 @@
*/
static VALUE
-rb_ary_s_create(VALUE klass, SEL sel, int argc, VALUE *argv)
+rary_s_create(VALUE klass, SEL sel, int argc, VALUE *argv)
{
- VALUE ary = ary_alloc(klass);
-
+ VALUE ary = rary_alloc(klass, 0);
if (argc < 0) {
rb_raise(rb_eArgError, "negative array size");
}
-
- rb_ary_append(ary, argc, argv);
-
+ rary_reserve(ary, argc);
+ for (int i = 0; i < argc; i++) {
+ rary_push(ary, argv[i]);
+ }
return ary;
}
void
-rb_ary_insert(VALUE ary, long idx, VALUE val)
+rary_insert(VALUE ary, long idx, VALUE val)
{
if (idx < 0) {
- idx += RARRAY_LEN(ary);
+ idx += RARY(ary)->len;
if (idx < 0) {
rb_raise(rb_eIndexError, "index %ld out of array",
- idx - RARRAY_LEN(ary));
+ idx - RARY(ary)->len);
}
}
-
- if (IS_RARY(ary)) {
- if (idx > RARY(ary)->len) {
- rary_resize(RARY(ary), idx + 1);
- rary_store(RARY(ary), idx, val);
- }
- else {
- rary_insert(RARY(ary), idx, val);
- }
+ if (idx > RARY(ary)->len) {
+ rary_resize(ary, idx + 1);
+ rary_store(ary, idx, val);
}
- else {
- CFArrayInsertValueAtIndex((CFMutableArrayRef)ary, idx,
- (const void *)RB2OC(val));
- }
-}
-
-void
-rb_ary_store(VALUE ary, long idx, VALUE val)
-{
- if (idx < 0) {
- const long len = RARRAY_LEN(ary);
- idx += len;
- if (idx < 0) {
- rb_raise(rb_eIndexError, "index %ld out of array",
- idx - len);
+ else if (idx < RARY(ary)->len) {
+ rary_reserve(ary, RARY(ary)->len + 1);
+ for (size_t i = RARY(ary)->len; i > idx; i--) {
+ rary_elt_set(ary, i, rary_elt(ary, i - 1));
}
+ rary_elt_set(ary, idx, val);
+ RARY(ary)->len++;
}
- if (IS_RARY(ary)) {
- rary_store(RARY(ary), idx, val);
- }
else {
- CFArraySetValueAtIndex((CFMutableArrayRef)ary, idx,
- (const void *)RB2OC(val));
+ rary_push(ary, val);
}
}
@@ -753,7 +433,7 @@
rb_scan_args(argc, argv, "1", &nv);
long n = NUM2LONG(nv);
- const long ary_len = RARRAY_LEN(ary);
+ const long ary_len = RARY(ary)->len;
if (n > ary_len) {
n = ary_len;
}
@@ -765,19 +445,17 @@
if (last) {
offset = ary_len - n;
}
- VALUE result = rb_ary_new();
+ VALUE result = rb_ary_new();
for (long i = 0; i < n; i++) {
- VALUE item = rb_ary_elt(ary, i + offset);
- rary_append(RARY(result), item);
+ VALUE item = rary_elt(ary, i + offset);
+ rary_push(result, item);
}
-
if (remove) {
for (long i = 0; i < n; i++) {
- rb_ary_erase(ary, offset);
+ rary_erase(ary, offset, 1);
}
}
-
return result;
}
@@ -794,10 +472,12 @@
*
*/
-static VALUE
-rb_ary_push_imp(VALUE ary, SEL sel, VALUE item)
+VALUE
+rary_push_m(VALUE ary, SEL sel, VALUE item)
{
- return rb_ary_push(ary, item);
+ rary_modify(ary);
+ rary_push(ary, item);
+ return ary;
}
/*
@@ -813,31 +493,22 @@
* #=> ["a", "b", "c", "d", "e", "f"]
*/
-static VALUE
-rb_ary_push_m(VALUE ary, SEL sel, int argc, VALUE *argv)
+static void
+rary_push(VALUE ary, VALUE item)
{
- if (argc == 0) {
- // Even if there is nothing to push, we still need to check if the
- // receiver can be modified, to conform to RubySpec.
- rb_ary_modify(ary);
- }
- else {
- while (argc--) {
- rb_ary_push(ary, *argv++);
- }
- }
- return ary;
+ rary_reserve(ary, RARY(ary)->len + 1);
+ rary_elt_set(ary, RARY(ary)->len, item);
+ RARY(ary)->len++;
}
-VALUE
-rb_ary_pop(VALUE ary)
+static VALUE
+rary_push_m2(VALUE ary, SEL sel, int argc, VALUE *argv)
{
- rb_ary_modify(ary);
- const long n = RARRAY_LEN(ary);
- if (n == 0) {
- return Qnil;
+ rary_modify(ary);
+ while (argc-- > 0) {
+ rary_push(ary, *argv++);
}
- return rb_ary_erase(ary, n - 1);
+ return ary;
}
/*
@@ -857,28 +528,20 @@
* a #=> ["a"]
*/
-static VALUE
-rb_ary_pop_m(VALUE ary, SEL sel, int argc, VALUE *argv)
+VALUE
+rary_pop(VALUE ary, SEL sel, int argc, VALUE *argv)
{
+ rary_modify(ary);
if (argc == 0) {
- return rb_ary_pop(ary);
+ const long n = RARY(ary)->len;
+ if (n == 0) {
+ return Qnil;
+ }
+ return rary_erase(ary, n - 1, 1);
}
-
- rb_ary_modify(ary);
return ary_shared_first(argc, argv, ary, true, true);
}
-VALUE
-rb_ary_shift(VALUE ary)
-{
- rb_ary_modify(ary);
- if (RARRAY_LEN(ary) == 0) {
- return Qnil;
- }
-
- return rb_ary_erase(ary, 0);
-}
-
/*
* call-seq:
* array.shift -> obj or nil
@@ -900,14 +563,16 @@
* args #=> ["filename"]
*/
-static VALUE
-rb_ary_shift_m(VALUE ary, SEL sel, int argc, VALUE *argv)
+VALUE
+rary_shift(VALUE ary, SEL sel, int argc, VALUE *argv)
{
+ rary_modify(ary);
if (argc == 0) {
- return rb_ary_shift(ary);
+ if (RARY(ary)->len == 0) {
+ return Qnil;
+ }
+ return rary_erase(ary, 0, 1);
}
-
- rb_ary_modify(ary);
return ary_shared_first(argc, argv, ary, false, true);
}
@@ -923,108 +588,16 @@
* a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]
*/
-static VALUE
-rb_ary_unshift_m(VALUE ary, SEL sel, int argc, VALUE *argv)
+VALUE
+rary_unshift(VALUE ary, SEL sel, int argc, VALUE *argv)
{
- rb_ary_modify(ary);
-
+ rary_modify(ary);
for (int i = argc - 1; i >= 0; i--) {
- rb_ary_insert(ary, 0, argv[i]);
+ rary_insert(ary, 0, argv[i]);
}
-
return ary;
}
-VALUE
-rb_ary_unshift(VALUE ary, VALUE item)
-{
- return rb_ary_unshift_m(ary, 0, 1, &item);
-}
-
-static void *rb_objc_ary_cptr_assoc_key = NULL;
-
-const VALUE *
-rb_ary_ptr(VALUE ary)
-{
- if (IS_RARY(ary)) {
- return rary_ptr(RARY(ary));
- }
-
- const long len = RARRAY_LEN(ary);
- if (len == 0) {
- return NULL;
- }
-
- VALUE *values = (VALUE *)xmalloc(sizeof(VALUE) * len);
- CFArrayGetValues((CFArrayRef)ary, CFRangeMake(0, len),
- (const void **)values);
-
- for (long i = 0; i < len; i++) {
- values[i] = OC2RB(values[i]);
- }
- rb_objc_set_associative_ref((void *)ary, &rb_objc_ary_cptr_assoc_key,
- values);
-
- return values;
-}
-
-VALUE
-rb_ary_entry(VALUE ary, long offset)
-{
- const long n = RARRAY_LEN(ary);
- if (n == 0) {
- return Qnil;
- }
- if (offset < 0) {
- offset += n;
- }
- if (offset < 0 || n <= offset) {
- return Qnil;
- }
- return rb_ary_elt(ary, offset);
-}
-
-VALUE
-rb_ary_subseq(VALUE ary, long beg, long len)
-{
- if (beg < 0 || len < 0) {
- return Qnil;
- }
-
- const long n = RARRAY_LEN(ary);
- if (beg > n) {
- return Qnil;
- }
-
- if (n < len || n < beg + len) {
- len = n - beg;
- }
-
- VALUE newary = ary_alloc(rb_obj_class(ary));
- if (len > 0) {
- if (IS_RARY(newary)) {
- if (IS_RARY(ary)) {
- rary_concat(RARY(newary), RARY(ary), beg, len);
- }
- else {
- rary_reserve(RARY(newary), len);
- for (long i = 0; i < len; i++) {
- VALUE item = rb_ary_elt(ary, beg + i);
- rary_append(RARY(newary), item);
- }
- }
- }
- else {
- void **values = (void **)alloca(sizeof(void *) * len);
- CFArrayGetValues((CFArrayRef)ary, CFRangeMake(beg, len),
- (const void **)values);
- CFArrayReplaceValues((CFMutableArrayRef)newary, CFRangeMake(0, 0),
- (const void **)values, len);
- }
- }
- return newary;
-}
-
/*
* call-seq:
* array[index] -> obj or nil
@@ -1058,8 +631,28 @@
*/
VALUE
-rb_ary_aref(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_subseq(VALUE ary, long beg, long len)
{
+ if (beg < 0 || len < 0) {
+ return Qnil;
+ }
+ const long n = RARY(ary)->len;
+ if (beg > n) {
+ return Qnil;
+ }
+ if (n < len || n < beg + len) {
+ len = n - beg;
+ }
+ VALUE newary = rary_alloc(rb_obj_class(ary), 0);
+ if (len > 0) {
+ rary_concat(newary, ary, beg, len);
+ }
+ return newary;
+}
+
+VALUE
+rary_aref(VALUE ary, SEL sel, int argc, VALUE *argv)
+{
long beg, len;
if (argc == 2) {
@@ -1068,7 +661,7 @@
if (beg < 0) {
beg += RARRAY_LEN(ary);
}
- return rb_ary_subseq(ary, beg, len);
+ return rary_subseq(ary, beg, len);
}
if (argc != 1) {
rb_scan_args(argc, argv, "11", 0, 0);
@@ -1076,7 +669,7 @@
VALUE arg = argv[0];
/* special case - speeding up */
if (FIXNUM_P(arg)) {
- return rb_ary_entry(ary, FIX2LONG(arg));
+ return rary_entry(ary, FIX2LONG(arg));
}
/* check if idx is Range */
switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
@@ -1085,9 +678,9 @@
case Qnil:
return Qnil;
default:
- return rb_ary_subseq(ary, beg, len);
+ return rary_subseq(ary, beg, len);
}
- return rb_ary_entry(ary, NUM2LONG(arg));
+ return rary_entry(ary, NUM2LONG(arg));
}
/*
@@ -1104,9 +697,9 @@
*/
static VALUE
-rb_ary_at(VALUE ary, SEL sel, VALUE pos)
+rary_at(VALUE ary, SEL sel, VALUE pos)
{
- return rb_ary_entry(ary, NUM2LONG(pos));
+ return rary_entry(ary, NUM2LONG(pos));
}
/*
@@ -1124,17 +717,15 @@
*/
static VALUE
-rb_ary_first(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_first(VALUE ary, SEL sel, int argc, VALUE *argv)
{
if (argc == 0) {
- if (RARRAY_LEN(ary) == 0) {
+ if (RARY(ary)->len == 0) {
return Qnil;
}
- return RARRAY_AT(ary, 0);
+ return rary_elt(ary, 0);
}
- else {
- return ary_shared_first(argc, argv, ary, false, false);
- }
+ return ary_shared_first(argc, argv, ary, false, false);
}
/*
@@ -1151,18 +742,16 @@
*/
VALUE
-rb_ary_last(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_last(VALUE ary, SEL sel, int argc, VALUE *argv)
{
if (argc == 0) {
- const long n = RARRAY_LEN(ary);
+ const long n = RARY(ary)->len;
if (n == 0) {
return Qnil;
}
- return RARRAY_AT(ary, n - 1);
+ return rary_elt(ary, n - 1);
}
- else {
- return ary_shared_first(argc, argv, ary, true, false);
- }
+ return ary_shared_first(argc, argv, ary, true, false);
}
/*
@@ -1186,7 +775,7 @@
*/
static VALUE
-rb_ary_fetch(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_fetch(VALUE ary, SEL sel, int argc, VALUE *argv)
{
VALUE pos, ifnone;
@@ -1198,9 +787,9 @@
long idx = NUM2LONG(pos);
if (idx < 0) {
- idx += RARRAY_LEN(ary);
+ idx += RARY(ary)->len;
}
- if (idx < 0 || RARRAY_LEN(ary) <= idx) {
+ if (idx < 0 || RARY(ary)->len <= idx) {
if (block_given) {
return rb_yield(pos);
}
@@ -1209,7 +798,7 @@
}
return ifnone;
}
- return RARRAY_AT(ary, idx);
+ return rary_elt(ary, idx);
}
/*
@@ -1230,36 +819,41 @@
* This is an alias of <code>#find_index</code>.
*/
+#define NOT_FOUND LONG_MAX
+
+static size_t
+rary_index_of_item(VALUE ary, size_t origin, VALUE item)
+{
+ assert(origin < RARY(ary)->len);
+ for (size_t i = origin; i < RARY(ary)->len; i++) {
+ VALUE item2 = rary_elt(ary, i);
+ if (rb_equal_fast(item, item2) == Qtrue) {
+ return i;
+ }
+ }
+ return NOT_FOUND;
+}
+
static VALUE
-rb_ary_index(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_index(VALUE ary, SEL sel, int argc, VALUE *argv)
{
VALUE val;
-
- const long n = RARRAY_LEN(ary);
if (rb_scan_args(argc, argv, "01", &val) == 0) {
RETURN_ENUMERATOR(ary, 0, 0);
- for (long i = 0; i < n; i++) {
- VALUE v = rb_yield(RARRAY_AT(ary, i));
+ for (long i = 0; i < RARY(ary)->len; i++) {
+ VALUE elem = rary_elt(ary, i);
+ VALUE test = rb_yield(elem);
RETURN_IF_BROKEN();
- if (RTEST(v)) {
+ if (RTEST(test)) {
return LONG2NUM(i);
}
}
}
- else if (n > 0) {
- if (IS_RARY(ary)) {
- size_t pos = rary_index_of_item(RARY(ary), 0, val);
- if (pos != NOT_FOUND) {
- return LONG2NUM(pos);
- }
+ else if (RARY(ary)->len > 0) {
+ size_t pos = rary_index_of_item(ary, 0, val);
+ if (pos != NOT_FOUND) {
+ return LONG2NUM(pos);
}
- else {
- CFIndex idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary,
- CFRangeMake(0, n), (const void *)RB2OC(val));
- if (idx != -1) {
- return LONG2NUM(idx);
- }
- }
}
return Qnil;
}
@@ -1279,22 +873,34 @@
* a.rindex{|x|x=="b"} #=> 3
*/
-static VALUE
-rb_ary_rindex(VALUE ary, SEL sel, int argc, VALUE *argv)
+static size_t
+rary_rindex_of_item(VALUE ary, long origin, VALUE item)
{
- const long n = RARRAY_LEN(ary);
- long i = n;
+ assert(origin < RARY(ary)->len);
+ for (long i = origin; i >= 0; i--) {
+ VALUE item2 = rary_elt(ary, i);
+ if (rb_equal_fast(item, item2) == Qtrue) {
+ return i;
+ }
+ }
+ return NOT_FOUND;
+}
+static VALUE
+rary_rindex(VALUE ary, SEL sel, int argc, VALUE *argv)
+{
if (argc == 0) {
RETURN_ENUMERATOR(ary, 0, 0);
- while (i--) {
- VALUE v = rb_yield(RARRAY_AT(ary, i));
+ long i = RARY(ary)->len;
+ while (i-- > 0) {
+ VALUE elem = rary_elt(ary, i);
+ VALUE test = rb_yield(elem);
RETURN_IF_BROKEN();
- if (RTEST(v)) {
+ if (RTEST(test)) {
return LONG2NUM(i);
}
- if (i > n) {
- i = n;
+ if (i > RARY(ary)->len) {
+ i = RARY(ary)->len;
}
}
}
@@ -1302,11 +908,9 @@
VALUE val;
rb_scan_args(argc, argv, "01", &val);
- // TODO: optimize for RARY
- i = CFArrayGetLastIndexOfValue((CFArrayRef)ary, CFRangeMake(0, n),
- (const void *)RB2OC(val));
- if (i != -1) {
- return LONG2NUM(i);
+ size_t pos = rary_rindex_of_item(ary, RARY(ary)->len - 1, val);
+ if (pos != NOT_FOUND) {
+ return LONG2NUM(pos);
}
}
return Qnil;
@@ -1325,7 +929,7 @@
}
static void
-rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
+rary_splice(VALUE ary, long beg, long len, VALUE rpl)
{
const long n = RARRAY_LEN(ary);
if (len < 0) {
@@ -1351,57 +955,29 @@
rlen = RARRAY_LEN(rpl);
}
- rb_ary_modify(ary);
- if (IS_RARY(ary) && (rpl == Qundef || IS_RARY(rpl))) {
- if (ary == rpl) {
- rpl = rb_ary_dup(rpl);
+ rary_modify(ary);
+
+ if (ary == rpl) {
+ rpl = rb_ary_dup(rpl);
+ }
+ if (beg >= n) {
+ for (long i = n; i < beg; i++) {
+ rary_push(ary, Qnil);
}
- if (beg >= n) {
- for (long i = n; i < beg; i++) {
- rary_append(RARY(ary), Qnil);
- }
- if (rlen > 0) {
- rary_concat(RARY(ary), RARY(rpl), 0, rlen);
- }
+ if (rlen > 0) {
+ rary_concat(ary, rpl, 0, rlen);
}
- else if (len == rlen) {
- for (long i = 0; i < len; i++) {
- rary_replace(RARY(ary), beg + i, rary_elt(RARY(rpl), i));
- }
- }
- else {
- rary_erase(RARY(ary), beg, len);
- for (long i = 0; i < rlen; i++) {
- rary_insert(RARY(ary), beg + i, rary_elt(RARY(rpl), i));
- }
- }
}
+ else if (len == rlen) {
+ for (long i = 0; i < len; i++) {
+ rary_elt_set(ary, beg + i, rb_ary_elt(rpl, i));
+ }
+ }
else {
- if (beg >= n) {
- for (long i = n; i < beg; i++) {
- CFArrayAppendValue((CFMutableArrayRef)ary,
- (const void *)kCFNull);
- }
- if (rlen > 0) {
- CFArrayAppendArray((CFMutableArrayRef)ary, (CFArrayRef)rpl,
- CFRangeMake(0, rlen));
- }
+ rary_erase(ary, beg, len);
+ for (long i = 0; i < rlen; i++) {
+ rary_insert(ary, beg + i, rb_ary_elt(rpl, i));
}
- else {
- void **values;
- if (rlen > 0) {
- values = (void **)alloca(sizeof(void *) * rlen);
- CFArrayGetValues((CFArrayRef)rpl, CFRangeMake(0, rlen),
- (const void **)values);
- }
- else {
- values = NULL;
- }
- CFArrayReplaceValues((CFMutableArrayRef)ary,
- CFRangeMake(beg, len),
- (const void **)values,
- rlen);
- }
}
}
@@ -1434,12 +1010,12 @@
*/
static VALUE
-rb_ary_aset(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_aset(VALUE ary, SEL sel, int argc, VALUE *argv)
{
long offset, beg, len;
if (argc == 3) {
- rb_ary_splice(ary, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
+ rary_splice(ary, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
return argv[2];
}
if (argc != 2) {
@@ -1447,17 +1023,16 @@
}
if (FIXNUM_P(argv[0])) {
offset = FIX2LONG(argv[0]);
- goto fixnum;
}
- if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
- /* check if idx is Range */
- rb_ary_splice(ary, beg, len, argv[1]);
- return argv[1];
+ else {
+ if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
+ // Check if Range.
+ rary_splice(ary, beg, len, argv[1]);
+ return argv[1];
+ }
+ offset = NUM2LONG(argv[0]);
}
-
- offset = NUM2LONG(argv[0]);
-fixnum:
- rb_ary_store(ary, offset, argv[1]);
+ rary_store(ary, offset, argv[1]);
return argv[1];
}
@@ -1474,10 +1049,10 @@
*/
static VALUE
-rb_ary_insert_m(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_insert_m(VALUE ary, SEL sel, int argc, VALUE *argv)
{
+ rary_modify(ary);
if (argc == 1) {
- rb_ary_modify(ary);
return ary;
}
if (argc < 1) {
@@ -1490,12 +1065,11 @@
if (pos < 0) {
pos++;
}
- rb_ary_modify(ary);
if (argc == 2) {
- rb_ary_insert(ary, pos, argv[1]);
+ rary_insert(ary, pos, argv[1]);
}
else {
- rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
+ rary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
}
return ary;
}
@@ -1515,23 +1089,18 @@
* a -- b -- c --
*/
-static VALUE
-rb_ary_each_imp(VALUE ary, SEL sel)
+VALUE
+rary_each(VALUE ary, SEL sel)
{
RETURN_ENUMERATOR(ary, 0, 0);
- for (long i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(RARRAY_AT(ary, i));
+ for (long i = 0; i < RARY(ary)->len; i++) {
+ VALUE elem = rary_elt(ary, i);
+ rb_yield(elem);
RETURN_IF_BROKEN();
}
return ary;
}
-VALUE
-rb_ary_each(VALUE ary)
-{
- return rb_ary_each_imp(ary, 0);
-}
-
/*
* call-seq:
* array.each_index {|index| block } -> array
@@ -1548,11 +1117,10 @@
*/
static VALUE
-rb_ary_each_index(VALUE ary, SEL sel)
+rary_each_index(VALUE ary, SEL sel)
{
RETURN_ENUMERATOR(ary, 0, 0);
-
- for (long i = 0, n = RARRAY_LEN(ary); i < n; i++) {
+ for (long i = 0; i < RARY(ary)->len; i++) {
rb_yield(LONG2NUM(i));
RETURN_IF_BROKEN();
}
@@ -1575,17 +1143,17 @@
*/
static VALUE
-rb_ary_reverse_each(VALUE ary, SEL sel)
+rary_reverse_each(VALUE ary, SEL sel)
{
RETURN_ENUMERATOR(ary, 0, 0);
- long len = RARRAY_LEN(ary);
- while (len--) {
- rb_yield(RARRAY_AT(ary, len));
+ long len = RARY(ary)->len;
+ while (len-- > 0) {
+ VALUE elem = rary_elt(ary, len);
+ rb_yield(elem);
RETURN_IF_BROKEN();
- const long n = RARRAY_LEN(ary);
- if (n < len) {
- len = n;
+ if (len > RARY(ary)->len) {
+ len = RARY(ary)->len;
}
}
return ary;
@@ -1601,9 +1169,9 @@
*/
static VALUE
-rb_ary_length(VALUE ary, SEL sel)
+rary_length(VALUE ary, SEL sel)
{
- return LONG2NUM(RARRAY_LEN(ary));
+ return LONG2NUM(RARY(ary)->len);
}
/*
@@ -1616,125 +1184,36 @@
*/
static VALUE
-rb_ary_empty_p(VALUE ary, SEL sel)
+rary_empty(VALUE ary, SEL sel)
{
- return RARRAY_LEN(ary) == 0 ? Qtrue : Qfalse;
+ return RARY(ary)->len == 0 ? Qtrue : Qfalse;
}
VALUE
-rb_ary_dup(VALUE ary)
+rary_dup(VALUE ary, SEL sel)
{
- VALUE dup;
-
- if (IS_RARY(ary)) {
- dup = rb_ary_new();
- rary_concat(RARY(dup), RARY(ary), 0, RARY(ary)->len);
- *(VALUE *)dup = *(VALUE *)ary;
- }
- else {
- dup = (VALUE)CFArrayCreateMutableCopy(NULL, 0, (CFArrayRef)ary);
- CFMakeCollectable((CFMutableArrayRef)dup);
- }
-
+ VALUE dup = rary_alloc(rb_cRubyArray, 0);
+ rary_concat(dup, ary, 0, RARY(ary)->len);
+ *(VALUE *)dup = *(VALUE *)ary;
if (OBJ_TAINTED(ary)) {
OBJ_TAINT(dup);
}
-
if (OBJ_UNTRUSTED(ary)) {
OBJ_UNTRUST(dup);
}
-
return dup;
}
static VALUE
-rb_ary_dup_imp(VALUE ary, SEL sel)
+rary_clone(VALUE ary, SEL sel)
{
- return rb_ary_dup(ary);
-}
-
-static VALUE
-rb_ary_clone(VALUE ary, SEL sel)
-{
- VALUE clone = rb_ary_dup(ary);
+ VALUE clone = rary_dup(ary, 0);
if (OBJ_FROZEN(ary)) {
OBJ_FREEZE(clone);
}
- if (OBJ_UNTRUSTED(ary)) {
- OBJ_UNTRUST(clone);
- }
return clone;
}
-extern VALUE rb_output_fs;
-
-static VALUE
-recursive_join(VALUE ary, VALUE argp, int recur)
-{
- VALUE *arg = (VALUE *)argp;
- if (recur) {
- return rb_usascii_str_new2("[...]");
- }
- return rb_ary_join(arg[0], arg[1]);
-}
-
-VALUE
-rb_ary_join(VALUE ary, VALUE sep)
-{
- long i, count;
- int taint = Qfalse;
- int untrust = Qfalse;
- VALUE result, tmp;
-
- if (RARRAY_LEN(ary) == 0) {
- return rb_str_new(0, 0);
- }
- if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) {
- taint = Qtrue;
- }
- if (OBJ_UNTRUSTED(ary) || OBJ_UNTRUSTED(sep)) {
- untrust = Qtrue;
- }
- result = rb_str_new(0, 0);
-
- for (i = 0, count = RARRAY_LEN(ary); i < count; i++) {
- tmp = RARRAY_AT(ary, i);
- switch (TYPE(tmp)) {
- case T_STRING:
- break;
- case T_ARRAY:
- {
- VALUE args[2];
-
- args[0] = tmp;
- args[1] = sep;
- tmp = rb_exec_recursive(recursive_join, ary, (VALUE)args);
- }
- break;
- default:
- tmp = rb_obj_as_string(tmp);
- }
- if (i > 0 && !NIL_P(sep)) {
- rb_str_buf_append(result, sep);
- }
- rb_str_buf_append(result, tmp);
- if (OBJ_TAINTED(tmp)) {
- taint = Qtrue;
- }
- if (OBJ_UNTRUSTED(tmp)) {
- untrust = Qtrue;
- }
- }
-
- if (taint) {
- OBJ_TAINT(result);
- }
- if (untrust) {
- OBJ_UNTRUST(result);
- }
- return result;
-}
-
/*
* call-seq:
* array.join(sep=$,) -> str
@@ -1746,19 +1225,26 @@
* [ "a", "b", "c" ].join("-") #=> "a-b-c"
*/
-static VALUE
-rb_ary_join_m(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_join(VALUE ary, SEL sel, int argc, VALUE *argv)
{
VALUE sep;
-
rb_scan_args(argc, argv, "01", &sep);
if (NIL_P(sep)) {
sep = rb_output_fs;
}
-
return rb_ary_join(ary, sep);
}
+/*
+ * call-seq:
+ * array.to_s -> string
+ * array.inspect -> string
+ *
+ * Create a printable version of <i>array</i>.
+ */
+
static VALUE
inspect_ary(VALUE ary, VALUE dummy, int recur)
{
@@ -1786,16 +1272,8 @@
return str;
}
-/*
- * call-seq:
- * array.to_s -> string
- * array.inspect -> string
- *
- * Create a printable version of <i>array</i>.
- */
-
static VALUE
-rb_ary_inspect(VALUE ary, SEL sel)
+rary_inspect(VALUE ary, SEL sel)
{
if (RARRAY_LEN(ary) == 0) {
return rb_usascii_str_new2("[]");
@@ -1803,73 +1281,8 @@
return rb_exec_recursive(inspect_ary, ary, 0);
}
-VALUE
-rb_ary_to_s(VALUE ary)
-{
- return rb_ary_inspect(ary, 0);
-}
-
/*
* call-seq:
- * array.to_a -> array
- *
- * Returns _self_. If called on a subclass of Array, converts
- * the receiver to an Array object.
- */
-
-static VALUE
-rb_ary_to_a(VALUE ary, SEL sel)
-{
- if (!rb_objc_ary_is_pure(ary)) {
- VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
- rb_ary_replace(dup, ary);
- return dup;
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array.to_ary -> array
- *
- * Returns _self_.
- */
-
-static VALUE
-rb_ary_to_ary_m(VALUE ary, SEL sel)
-{
- return ary;
-}
-
-VALUE
-rb_ary_reverse(VALUE ary)
-{
- rb_ary_modify(ary);
- if (IS_RARY(ary)) {
- rary_reverse(RARY(ary));
- }
- else {
- const long n = RARRAY_LEN(ary);
- if (n > 0) {
- void **values = (void **)alloca(sizeof(void *) * n);
- CFRange range = CFRangeMake(0, n);
- CFArrayGetValues((CFArrayRef)ary, range, (const void **)values);
-
- long i;
- for (i = 0; i < (n / 2); i++) {
- void *v = values[i];
- values[i] = values[n - i - 1];
- values[n - i - 1] = v;
- }
- CFArrayReplaceValues((CFMutableArrayRef)ary, range,
- (const void **)values, n);
- }
- }
- return ary;
-}
-
-/*
- * call-seq:
* array.reverse! -> array
*
* Reverses _self_ in place.
@@ -1879,10 +1292,19 @@
* a #=> ["c", "b", "a"]
*/
-static VALUE
-rb_ary_reverse_bang(VALUE ary, SEL sel)
+VALUE
+rary_reverse_bang(VALUE ary, SEL sel)
{
- return rb_ary_reverse(ary);
+ rary_modify(ary);
+ if (RARY(ary)->len > 1) {
+ for (size_t i = 0; i < RARY(ary)->len / 2; i++) {
+ const size_t j = RARY(ary)->len - i - 1;
+ VALUE elem = rary_elt(ary, i);
+ rary_elt_set(ary, i, rary_elt(ary, j));
+ rary_elt_set(ary, j, elem);
+ }
+ }
+ return ary;
}
/*
@@ -1896,9 +1318,9 @@
*/
static VALUE
-rb_ary_reverse_m(VALUE ary, SEL sel)
+rary_reverse(VALUE ary, SEL sel)
{
- return rb_ary_reverse(rb_ary_dup(ary));
+ return rary_reverse_bang(rary_dup(ary, 0), 0);
}
static int
@@ -1961,22 +1383,6 @@
return rb_cmpint(retval, a, b);
}
-static int
-cf_sort_1(const void *a, const void *b, void *dummy)
-{
- VALUE ra = OC2RB(a);
- VALUE rb = OC2RB(b);
- return sort_1(dummy, &ra, &rb);
-}
-
-static int
-cf_sort_2(const void *a, const void *b, void *dummy)
-{
- VALUE ra = OC2RB(a);
- VALUE rb = OC2RB(b);
- return sort_2(dummy, &ra, &rb);
-}
-
/*
* call-seq:
* array.sort! -> array
@@ -1994,24 +1400,15 @@
*/
static VALUE
-rb_ary_sort_bang1(VALUE ary, bool is_dup)
+sort_bang(VALUE ary, bool is_dup)
{
- const long n = RARRAY_LEN(ary);
- if (n > 1) {
+ if (RARY(ary)->len > 1) {
if (rb_block_given_p()) {
VALUE tmp = is_dup ? ary : rb_ary_dup(ary);
VALUE break_val = 0;
- if (IS_RARY(ary)) {
- qsort_r(rary_ptr(RARY(tmp)), n, sizeof(VALUE), &break_val,
- sort_1);
- }
- else {
- CFArraySortValues((CFMutableArrayRef)tmp,
- CFRangeMake(0, n),
- (CFComparatorFunction)cf_sort_1,
- &break_val);
- }
+ qsort_r(rary_ptr(tmp), RARY(ary)->len, sizeof(VALUE), &break_val,
+ sort_1);
if (break_val != 0) {
return break_val;
@@ -2021,31 +1418,18 @@
}
}
else {
- if (IS_RARY(ary)) {
- qsort_r(rary_ptr(RARY(ary)), n, sizeof(VALUE), NULL, sort_2);
- }
- else {
- CFArraySortValues((CFMutableArrayRef)ary,
- CFRangeMake(0, n),
- (CFComparatorFunction)cf_sort_2,
- NULL);
- }
+ qsort_r(rary_ptr(ary), RARY(ary)->len, sizeof(VALUE), NULL,
+ sort_2);
}
}
return ary;
}
-static VALUE
-rb_ary_sort_bang_imp(VALUE ary, SEL sel)
-{
- rb_ary_modify(ary);
- return rb_ary_sort_bang1(ary, false);
-}
-
VALUE
-rb_ary_sort_bang(VALUE ary)
+rary_sort_bang(VALUE ary, SEL sel)
{
- return rb_ary_sort_bang_imp(ary, 0);
+ rary_modify(ary);
+ return sort_bang(ary, false);
}
/*
@@ -2064,52 +1448,13 @@
* a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
*/
-static VALUE
-rb_ary_sort_imp(VALUE ary, SEL sel)
-{
- ary = rb_ary_dup(ary);
- return rb_ary_sort_bang1(ary, true);
-}
-
VALUE
-rb_ary_sort(VALUE ary)
+rary_sort(VALUE ary, SEL sel)
{
- return rb_ary_sort_imp(ary, 0);
+ ary = rary_dup(ary, 0);
+ return sort_bang(ary, true);
}
-
-/*
- * call-seq:
- * array.collect {|item| block } -> an_array
- * array.map {|item| block } -> an_array
- *
- * Invokes <i>block</i> once for each element of <i>self</i>. Creates a
- * new array containing the values returned by the block.
- * See also <code>Enumerable#collect</code>.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.collect {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"]
- * a #=> ["a", "b", "c", "d"]
- */
-
-static VALUE
-rb_ary_collect(VALUE ary, SEL sel)
-{
- long i;
- VALUE collect;
-
- RETURN_ENUMERATOR(ary, 0, 0);
- collect = rb_ary_new();
- rb_ary_set_capacity(collect, RARRAY_LEN(ary));
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- VALUE v = rb_yield(RARRAY_AT(ary, i));
- RETURN_IF_BROKEN();
- rb_ary_push(collect, v);
- }
- return collect;
-}
-
-
/*
* call-seq:
* array.collect! {|item| block } -> array
@@ -2125,48 +1470,49 @@
*/
static VALUE
-rb_ary_collect_bang(VALUE ary, SEL sel)
+collect_bang(VALUE source, VALUE dest)
{
- long i;
-
- RETURN_ENUMERATOR(ary, 0, 0);
- rb_ary_modify(ary);
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- VALUE v = rb_yield(RARRAY_AT(ary, i));
+ for (long i = 0; i < RARY(source)->len; i++) {
+ VALUE elem = rary_elt(source, i);
+ VALUE new_elem = rb_yield(elem);
RETURN_IF_BROKEN();
- rb_ary_store(ary, i, v);
+ rary_store(dest, i, new_elem);
}
- return ary;
+ return dest;
}
-VALUE
-rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE (*func) (VALUE, long))
+static VALUE
+rary_collect_bang(VALUE ary, SEL sel)
{
- VALUE result = rb_ary_new2(argc);
- long beg, len, i, j;
+ RETURN_ENUMERATOR(ary, 0, 0);
- for (i=0; i<argc; i++) {
- if (FIXNUM_P(argv[i])) {
- rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
- continue;
- }
- /* check if idx is Range */
- switch (rb_range_beg_len(argv[i], &beg, &len, olen, 0)) {
- case Qfalse:
- break;
- case Qnil:
- continue;
- default:
- for (j=0; j<len; j++) {
- rb_ary_push(result, (*func)(obj, j+beg));
- }
- continue;
- }
- rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
- }
- return result;
+ rary_modify(ary);
+ return collect_bang(ary, ary);
}
+/*
+ * call-seq:
+ * array.collect {|item| block } -> an_array
+ * array.map {|item| block } -> an_array
+ *
+ * Invokes <i>block</i> once for each element of <i>self</i>. Creates a
+ * new array containing the values returned by the block.
+ * See also <code>Enumerable#collect</code>.
+ *
+ * a = [ "a", "b", "c", "d" ]
+ * a.collect {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"]
+ * a #=> ["a", "b", "c", "d"]
+ */
+
+static VALUE
+rary_collect(VALUE ary, SEL sel)
+{
+ RETURN_ENUMERATOR(ary, 0, 0);
+
+ VALUE result = rb_ary_new2(RARY(ary)->len);
+ return collect_bang(ary, result);
+}
+
/*
* call-seq:
* array.values_at(selector,... ) -> an_array
@@ -2183,13 +1529,40 @@
* a.values_at(1..3, 2...5)
*/
+VALUE
+rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv,
+ VALUE (*func) (VALUE, long))
+{
+ VALUE result = rb_ary_new2(argc);
+ for (long i = 0; i < argc; i++) {
+ if (FIXNUM_P(argv[i])) {
+ rary_push(result, (*func)(obj, FIX2LONG(argv[i])));
+ continue;
+ }
+ // Check if Range.
+ long beg, len;
+ switch (rb_range_beg_len(argv[i], &beg, &len, olen, 0)) {
+ case Qfalse:
+ break;
+ case Qnil:
+ continue;
+ default:
+ for (long j = 0; j < len; j++) {
+ rary_push(result, (*func)(obj, j+beg));
+ }
+ continue;
+ }
+ rary_push(result, (*func)(obj, NUM2LONG(argv[i])));
+ }
+ return result;
+}
+
static VALUE
-rb_ary_values_at(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_values_at(VALUE ary, SEL sel, int argc, VALUE *argv)
{
- return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
+ return rb_get_values_at(ary, RARY(ary)->len, argc, argv, rary_entry);
}
-
/*
* call-seq:
* array.select {|item| block } -> an_array
@@ -2203,20 +1576,17 @@
*/
static VALUE
-rb_ary_select(VALUE ary, SEL sel)
+rary_select(VALUE ary, SEL sel)
{
- VALUE result;
- long n, i;
-
RETURN_ENUMERATOR(ary, 0, 0);
- n = RARRAY_LEN(ary);
- result = rb_ary_new2(n);
- for (i = 0; i < n; i++) {
- VALUE v = RARRAY_AT(ary, i);
- VALUE v2 = rb_yield(v);
+
+ VALUE result = rb_ary_new2(RARY(ary)->len);
+ for (long i = 0; i < RARY(ary)->len; i++) {
+ VALUE elem = rary_elt(ary, i);
+ VALUE test = rb_yield(elem);
RETURN_IF_BROKEN();
- if (RTEST(v2)) {
- rb_ary_push(result, v);
+ if (RTEST(test)) {
+ rary_push(result, elem);
}
}
return result;
@@ -2239,42 +1609,25 @@
* a.delete("z") { "not found" } #=> "not found"
*/
-static inline bool
-rb_ary_delete0(VALUE ary, VALUE item)
+static bool
+rary_delete_element(VALUE ary, VALUE item)
{
- rb_ary_modify(ary);
-
+ rary_modify(ary);
bool changed = false;
- if (IS_RARY(ary)) {
- size_t pos = 0;
- while (pos < RARY(ary)->len
- && (pos = rary_index_of_item(RARY(ary), pos, item))
- != NOT_FOUND) {
- rary_erase(RARY(ary), pos, 1);
- changed = true;
- }
+ size_t pos = 0;
+ while (pos < RARY(ary)->len
+ && (pos = rary_index_of_item(ary, pos, item))
+ != NOT_FOUND) {
+ rary_erase(ary, pos, 1);
+ changed = true;
}
- else {
- const void *ocitem = (const void *)RB2OC(item);
- long n = RARRAY_LEN(ary);
- CFRange r = CFRangeMake(0, n);
- long i = 0;
- while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, r, ocitem))
- != -1) {
- CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i);
- r.location = i;
- r.length = --n - i;
- changed = true;
- }
- }
-
return changed;
}
-static VALUE
-rb_ary_delete_imp(VALUE ary, SEL sel, VALUE item)
+VALUE
+rary_delete(VALUE ary, SEL sel, VALUE item)
{
- const bool changed = rb_ary_delete0(ary, item);
+ const bool changed = rary_delete_element(ary, item);
if (!changed) {
if (rb_block_given_p()) {
return rb_yield(item);
@@ -2284,37 +1637,6 @@
return item;
}
-VALUE
-rb_ary_delete(VALUE ary, VALUE item)
-{
- return rb_ary_delete0(ary, item) ? item : Qnil;
-}
-
-VALUE
-rb_ary_delete_at(VALUE ary, long pos)
-{
- const long len = RARRAY_LEN(ary);
- if (pos >= len) {
- return Qnil;
- }
- if (pos < 0) {
- pos += len;
- if (pos < 0) {
- return Qnil;
- }
- }
-
- rb_ary_modify(ary);
- if (IS_RARY(ary)) {
- return rary_erase(RARY(ary), pos, 1);
- }
- else {
- VALUE del = RARRAY_AT(ary, pos);
- CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, pos);
- return del;
- }
-}
-
/*
* call-seq:
* array.delete_at(index) -> obj or nil
@@ -2329,10 +1651,21 @@
* a.delete_at(99) #=> nil
*/
-static VALUE
-rb_ary_delete_at_m(VALUE ary, SEL sel, VALUE pos)
+VALUE
+rary_delete_at(VALUE ary, SEL sel, VALUE pos)
{
- return rb_ary_delete_at(ary, NUM2LONG(pos));
+ long index = NUM2LONG(pos);
+ if (index < 0) {
+ index += RARY(ary)->len;
+ if (index < 0) {
+ return Qnil;
+ }
+ }
+ if (index >= RARY(ary)->len) {
+ return Qnil;
+ }
+ rary_modify(ary);
+ return rary_erase(ary, index, 1);
}
/*
@@ -2355,13 +1688,13 @@
*/
static VALUE
-rb_ary_slice_bang(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_slice_bang(VALUE ary, SEL sel, int argc, VALUE *argv)
{
- VALUE arg1, arg2;
+ const long alen = RARY(ary)->len;
long pos, len;
- rb_ary_modify(ary);
- const long alen = RARRAY_LEN(ary);
+ rary_modify(ary);
+ VALUE arg1, arg2;
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
pos = NUM2LONG(arg1);
len = NUM2LONG(arg2);
@@ -2375,26 +1708,25 @@
if (alen < len || alen < pos + len) {
len = alen - pos;
}
- arg2 = rb_ary_subseq(ary, pos, len);
- rb_ary_splice(ary, pos, len, Qundef); /* Qnil/rb_ary_new2(0) */
+ arg2 = rary_subseq(ary, pos, len);
+ rary_splice(ary, pos, len, Qundef);
return arg2;
}
if (!FIXNUM_P(arg1)) {
- switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
+ switch (rb_range_beg_len(arg1, &pos, &len, alen, 0)) {
case Qtrue:
- /* valid range */
+ // Valid range.
goto delete_pos_len;
case Qnil:
- /* invalid range */
+ // Invalid range.
return Qnil;
default:
- /* not a range */
+ // Not a range.
break;
}
}
-
- return rb_ary_delete_at(ary, NUM2LONG(arg1));
+ return rary_delete_at(ary, 0, arg1);
}
/*
@@ -2408,31 +1740,24 @@
*/
static VALUE
-rb_ary_reject_bang(VALUE ary, SEL sel)
+rary_reject_bang(VALUE ary, SEL sel)
{
RETURN_ENUMERATOR(ary, 0, 0);
- rb_ary_modify(ary);
-
- long n = RARRAY_LEN(ary);
- const long orign = n;
- long i1, i2;
- for (i1 = i2 = 0; i1 < n; i1++) {
- VALUE v = RARRAY_AT(ary, i1);
- VALUE v2 = rb_yield(v);
+ rary_modify(ary);
+ bool changed = false;
+ for (long i = 0, n = RARY(ary)->len; i < n; i++) {
+ VALUE elem = rary_elt(ary, i);
+ VALUE test = rb_yield(elem);
RETURN_IF_BROKEN();
- if (!RTEST(v2)) {
- continue;
+ if (RTEST(test)) {
+ rary_erase(ary, i, 1);
+ n--;
+ i--;
+ changed = true;
}
- rb_ary_erase(ary, i1);
- n--;
- i1--;
}
-
- if (n == orign) {
- return Qnil;
- }
- return ary;
+ return changed ? ary : Qnil;
}
/*
@@ -2444,11 +1769,11 @@
*/
static VALUE
-rb_ary_reject(VALUE ary, SEL sel)
+rary_reject(VALUE ary, SEL sel)
{
RETURN_ENUMERATOR(ary, 0, 0);
- ary = rb_ary_dup(ary);
- rb_ary_reject_bang(ary, 0);
+ ary = rary_dup(ary, 0);
+ rary_reject_bang(ary, 0);
return ary;
}
@@ -2464,13 +1789,34 @@
*/
static VALUE
-rb_ary_delete_if(VALUE ary, SEL sel)
+rary_delete_if(VALUE ary, SEL sel)
{
RETURN_ENUMERATOR(ary, 0, 0);
- rb_ary_reject_bang(ary, 0);
+ rary_reject_bang(ary, 0);
return ary;
}
+/*
+ * call-seq:
+ * array.zip(arg, ...) -> an_array
+ * array.zip(arg, ...) {| arr | block } -> nil
+ *
+ * Converts any arguments to arrays, then merges elements of
+ * <i>self</i> with corresponding elements from each argument. This
+ * generates a sequence of <code>self.size</code> <em>n</em>-element
+ * arrays, where <em>n</em> is one more that the count of arguments. If
+ * the size of any argument is less than <code>enumObj.size</code>,
+ * <code>nil</code> values are supplied. If a block given, it is
+ * invoked for each output array, otherwise an array of arrays is
+ * returned.
+ *
+ * a = [ 4, 5, 6 ]
+ * b = [ 7, 8, 9 ]
+ * [1,2,3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
+ * [1,2].zip(a,b) #=> [[1, 4, 7], [2, 5, 8]]
+ * a.zip([1,2],[8]) #=> [[4,1,8], [5,2,nil], [6,nil,nil]]
+ */
+
static VALUE
take_i(VALUE val, VALUE *args, int argc, VALUE *argv)
{
@@ -2503,29 +1849,9 @@
return result;
}
-/*
- * call-seq:
- * array.zip(arg, ...) -> an_array
- * array.zip(arg, ...) {| arr | block } -> nil
- *
- * Converts any arguments to arrays, then merges elements of
- * <i>self</i> with corresponding elements from each argument. This
- * generates a sequence of <code>self.size</code> <em>n</em>-element
- * arrays, where <em>n</em> is one more that the count of arguments. If
- * the size of any argument is less than <code>enumObj.size</code>,
- * <code>nil</code> values are supplied. If a block given, it is
- * invoked for each output array, otherwise an array of arrays is
- * returned.
- *
- * a = [ 4, 5, 6 ]
- * b = [ 7, 8, 9 ]
- * [1,2,3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
- * [1,2].zip(a,b) #=> [[1, 4, 7], [2, 5, 8]]
- * a.zip([1,2],[8]) #=> [[4,1,8], [5,2,nil], [6,nil,nil]]
- */
-
-static VALUE
-rb_ary_zip(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_zip(VALUE ary, SEL sel, int argc, VALUE *argv)
{
const long len = RARRAY_LEN(ary);
for (int i = 0; i < argc; i++) {
@@ -2566,8 +1892,9 @@
* a.transpose #=> [[1, 3, 5], [2, 4, 6]]
*/
-static VALUE
-rb_ary_transpose(VALUE ary, SEL sel)
+// Defined on NSArray.
+VALUE
+rary_transpose(VALUE ary, SEL sel)
{
const long alen = RARRAY_LEN(ary);
if (alen == 0) {
@@ -2608,33 +1935,14 @@
* a #=> ["x", "y", "z"]
*/
-VALUE
-rb_ary_replace(VALUE copy, VALUE orig)
-{
- orig = to_ary(orig);
- rb_ary_modify(copy);
- if (copy == orig) {
- return copy;
- }
-
- if (IS_RARY(copy) && IS_RARY(orig)) {
- rary_clear(RARY(copy));
- rary_concat(RARY(copy), RARY(orig), 0, RARY(orig)->len);
- }
- else {
- CFArrayRemoveAllValues((CFMutableArrayRef)copy);
- CFArrayAppendArray((CFMutableArrayRef)copy,
- (CFArrayRef)orig,
- CFRangeMake(0, RARRAY_LEN(orig)));
- }
-
- return copy;
-}
-
static VALUE
-rb_ary_replace_imp(VALUE copy, SEL sel, VALUE orig)
+rary_replace(VALUE rcv, SEL sel, VALUE other)
{
- return rb_ary_replace(copy, orig);
+ other = to_ary(other);
+ rary_modify(rcv);
+ rary_remove_all(RARY(rcv));
+ rary_concat(rcv, other, 0, RARRAY_LEN(other));
+ return rcv;
}
/*
@@ -2647,25 +1955,14 @@
* a.clear #=> [ ]
*/
-static VALUE
-rb_ary_clear_imp(VALUE ary, SEL sel)
+VALUE
+rary_clear(VALUE ary, SEL sel)
{
- rb_ary_modify(ary);
- if (IS_RARY(ary)) {
- rary_clear(RARY(ary));
- }
- else {
- CFArrayRemoveAllValues((CFMutableArrayRef)ary);
- }
+ rary_modify(ary);
+ rary_remove_all(RARY(ary));
return ary;
}
-VALUE
-rb_ary_clear(VALUE ary)
-{
- return rb_ary_clear_imp(ary, 0);
-}
-
/*
* call-seq:
* array.fill(obj) -> array
@@ -2690,8 +1987,9 @@
* a.fill(-2) {|i| i*i*i} #=> [0, 1, 8, 27]
*/
-static VALUE
-rb_ary_fill(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_fill(VALUE ary, SEL sel, int argc, VALUE *argv)
{
VALUE item, arg1, arg2;
const long n = RARRAY_LEN(ary);
@@ -2754,66 +2052,41 @@
/*
* call-seq:
- * array + other_array -> an_array
+ * array.concat(other_array) -> array
*
- * Concatenation---Returns a new array built by concatenating the
- * two arrays together to produce a third array.
- *
- * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
+ * Appends the elements in other_array to _self_.
+ *
+ * [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
*/
VALUE
-rb_ary_concat(VALUE x, VALUE y)
+rary_concat_m(VALUE x, SEL sel, VALUE y)
{
- if (IS_RARY(x) && IS_RARY(y)) {
- rary_concat(RARY(x), RARY(y), 0, RARY(y)->len);
- }
- else {
- const size_t len = RARRAY_LEN(y);
- CFArrayAppendArray((CFMutableArrayRef)x, (CFArrayRef)y,
- CFRangeMake(0, len));
- }
+ rary_modify(x);
+ y = to_ary(y);
+ rary_concat(x, y, 0, RARRAY_LEN(y));
return x;
}
-static VALUE
-rb_ary_plus_imp(VALUE x, SEL sel, VALUE y)
-{
- VALUE z;
-
- y = to_ary(y);
- z = rb_ary_new2(0);
-
- rary_reserve(RARY(z), RARRAY_LEN(x) + RARRAY_LEN(y));
-
- rb_ary_concat(z, x);
- rb_ary_concat(z, y);
-
- return z;
-}
-
-VALUE
-rb_ary_plus(VALUE x, VALUE y)
-{
- return rb_ary_plus_imp(x, 0, y);
-}
-
/*
* call-seq:
- * array.concat(other_array) -> array
+ * array + other_array -> an_array
*
- * Appends the elements in other_array to _self_.
- *
- * [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
+ * Concatenation---Returns a new array built by concatenating the
+ * two arrays together to produce a third array.
+ *
+ * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
*/
-static VALUE
-rb_ary_concat_imp(VALUE x, SEL sel, VALUE y)
+VALUE
+rary_plus(VALUE x, SEL sel, VALUE y)
{
- rb_ary_modify(x);
y = to_ary(y);
- rb_ary_concat(x, y);
- return x;
+ VALUE z = rb_ary_new2(0);
+ rary_reserve(z, RARY(x)->len + RARRAY_LEN(y));
+ rary_concat_m(z, 0, x);
+ rary_concat_m(z, 0, y);
+ return z;
}
/*
@@ -2832,7 +2105,7 @@
*/
static VALUE
-rb_ary_times(VALUE ary, SEL sel, VALUE times)
+rary_times(VALUE ary, SEL sel, VALUE times)
{
VALUE tmp = rb_check_string_type(times);
if (!NIL_P(tmp)) {
@@ -2843,26 +2116,23 @@
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
- VALUE ary2 = ary_new(rb_obj_class(ary), 0);
+ VALUE ary2 = rary_alloc(rb_obj_class(ary), 0);
if (len > 0) {
- const long n = RARRAY_LEN(ary);
+ const long n = RARY(ary)->len;
if (LONG_MAX/len < n) {
rb_raise(rb_eArgError, "argument too big");
}
-
for (long i = 0; i < len; i++) {
- rb_ary_concat(ary2, ary);
+ rary_concat(ary2, ary, 0, n);
}
}
if (OBJ_TAINTED(ary)) {
OBJ_TAINT(ary2);
}
-
if (OBJ_UNTRUSTED(ary)) {
OBJ_UNTRUST(ary2);
}
-
return ary2;
}
@@ -2886,8 +2156,9 @@
* a.assoc("foo") #=> nil
*/
-static VALUE
-rb_ary_assoc(VALUE ary, SEL sel, VALUE key)
+// Defined on NSArray.
+VALUE
+rary_assoc(VALUE ary, SEL sel, VALUE key)
{
for (long i = 0; i < RARRAY_LEN(ary); ++i) {
VALUE v = rb_check_array_type(RARRAY_AT(ary, i));
@@ -2912,8 +2183,9 @@
* a.rassoc("four") #=> nil
*/
-static VALUE
-rb_ary_rassoc(VALUE ary, SEL sel, VALUE value)
+// Defined on NSArray.
+VALUE
+rary_rassoc(VALUE ary, SEL sel, VALUE value)
{
for (long i = 0; i < RARRAY_LEN(ary); ++i) {
VALUE v = RARRAY_AT(ary, i);
@@ -2947,8 +2219,8 @@
return Qfalse;
}
for (size_t i = 0; i < RARY(ary1)->len; i++) {
- VALUE item1 = rary_elt(RARY(ary1), i);
- VALUE item2 = rary_elt(RARY(ary2), i);
+ VALUE item1 = rary_elt(ary1, i);
+ VALUE item2 = rary_elt(ary2, i);
if ((FIXFLOAT_P(item1) && isnan(FIXFLOAT2DBL(item1)))
|| FIXFLOAT_P(item2) && isnan(FIXFLOAT2DBL(item2))) {
@@ -2965,7 +2237,7 @@
}
static VALUE
-rb_ary_equal_imp(VALUE ary1, SEL sel, VALUE ary2)
+rary_equal(VALUE ary1, SEL sel, VALUE ary2)
{
if (ary1 == ary2) {
return Qtrue;
@@ -2979,29 +2251,30 @@
return rb_ary_equal(ary1, ary2);
}
+/*
+ * call-seq:
+ * array.eql?(other) -> true or false
+ *
+ * Returns <code>true</code> if _array_ and _other_ are the same object,
+ * or are both arrays with the same content.
+ */
+
static VALUE
recursive_eql(VALUE ary1, VALUE ary2, int recur)
{
if (recur) {
return Qfalse;
}
- for (long i = 0; i < RARRAY_LEN(ary1); i++) {
- if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+ for (long i = 0; i < RARY(ary1)->len; i++) {
+ if (!rb_eql(rary_elt(ary1, i), rb_ary_elt(ary2, i))) {
return Qfalse;
+ }
}
return Qtrue;
}
-/*
- * call-seq:
- * array.eql?(other) -> true or false
- *
- * Returns <code>true</code> if _array_ and _other_ are the same object,
- * or are both arrays with the same content.
- */
-
static VALUE
-rb_ary_eql(VALUE ary1, SEL sel, VALUE ary2)
+rary_eql(VALUE ary1, SEL sel, VALUE ary2)
{
if (ary1 == ary2) {
return Qtrue;
@@ -3009,7 +2282,7 @@
if (TYPE(ary2) != T_ARRAY) {
return Qfalse;
}
- if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) {
+ if (RARY(ary1)->len != RARRAY_LEN(ary2)) {
return Qfalse;
}
return rb_exec_recursive(recursive_eql, ary1, ary2);
@@ -3028,49 +2301,14 @@
* a.include?("z") #=> false
*/
-static VALUE
-rb_ary_includes_imp(VALUE ary, SEL sel, VALUE item)
-{
- if (IS_RARY(ary)) {
- if (RARY(ary)->len == 0) {
- return Qfalse;
- }
- return rary_index_of_item(RARY(ary), 0, item) != NOT_FOUND
- ? Qtrue : Qfalse;
- }
- else {
- const long len = RARRAY_LEN(ary);
- const void *ocitem = RB2OC(item);
- return CFArrayContainsValue((CFArrayRef)ary, CFRangeMake(0, len),
- ocitem) ? Qtrue : Qfalse;
- }
-}
-
VALUE
-rb_ary_includes(VALUE ary, VALUE item)
+rary_includes(VALUE ary, SEL sel, VALUE item)
{
- return rb_ary_includes_imp(ary, 0, item);
-}
-
-static VALUE
-recursive_cmp(VALUE ary1, VALUE ary2, int recur)
-{
- if (recur) {
- return Qnil;
+ if (RARY(ary)->len == 0) {
+ return Qfalse;
}
-
- long len = RARRAY_LEN(ary1);
- if (len > RARRAY_LEN(ary2)) {
- len = RARRAY_LEN(ary2);
- }
-
- for (long i = 0; i < len; i++) {
- VALUE v = rb_objs_cmp(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i));
- if (v != INT2FIX(0)) {
- return v;
- }
- }
- return Qundef;
+ return rary_index_of_item(ary, 0, item) != NOT_FOUND
+ ? Qtrue : Qfalse;
}
/*
@@ -3094,8 +2332,30 @@
*/
static VALUE
-rb_ary_cmp(VALUE ary1, SEL sel, VALUE ary2)
+recursive_cmp(VALUE ary1, VALUE ary2, int recur)
{
+ if (recur) {
+ return Qnil;
+ }
+
+ long len = RARRAY_LEN(ary1);
+ if (len > RARRAY_LEN(ary2)) {
+ len = RARRAY_LEN(ary2);
+ }
+
+ for (long i = 0; i < len; i++) {
+ VALUE v = rb_objs_cmp(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i));
+ if (v != INT2FIX(0)) {
+ return v;
+ }
+ }
+ return Qundef;
+}
+
+// Defined on NSArray.
+VALUE
+rary_cmp(VALUE ary1, SEL sel, VALUE ary2)
+{
ary2 = to_ary(ary2);
if (ary1 == ary2) {
return INT2FIX(0);
@@ -3110,6 +2370,18 @@
return len == 0 ? INT2FIX(0) : len > 0 ? INT2FIX(1) : INT2FIX(-1);
}
+/*
+ * call-seq:
+ * array - other_array -> an_array
+ *
+ * Array Difference---Returns a new array that is a copy of
+ * the original array, removing any items that also appear in
+ * other_array. (If you need set-like behavior, see the
+ * library class Set.)
+ *
+ * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
+ */
+
static VALUE
ary_make_hash(VALUE ary1, VALUE ary2)
{
@@ -3125,20 +2397,9 @@
return hash;
}
-/*
- * call-seq:
- * array - other_array -> an_array
- *
- * Array Difference---Returns a new array that is a copy of
- * the original array, removing any items that also appear in
- * other_array. (If you need set-like behavior, see the
- * library class Set.)
- *
- * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
- */
-
-static VALUE
-rb_ary_diff(VALUE ary1, SEL sel, VALUE ary2)
+// Defined on NSArray.
+VALUE
+rary_diff(VALUE ary1, SEL sel, VALUE ary2)
{
ary2 = to_ary(ary2);
const long ary1_len = RARRAY_LEN(ary1);
@@ -3151,26 +2412,13 @@
return ary3;
}
- rary_reserve(RARY(ary3), ary1_len);
-
- if (ary1_len < 100 && ary2_len < 100 && IS_RARY(ary1) && IS_RARY(ary2)) {
- for (long i = 0; i < ary1_len; i++) {
- VALUE elem = rary_elt(RARY(ary1), i);
- if (rary_index_of_item(RARY(ary2), 0, elem) == NOT_FOUND) {
- rary_append(RARY(ary3), elem);
- }
+ VALUE hash = ary_make_hash(ary2, 0);
+ for (long i = 0; i < ary1_len; i++) {
+ VALUE v = RARRAY_AT(ary1, i);
+ if (rb_hash_has_key(hash, v) == Qfalse) {
+ rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
}
- else {
- VALUE hash = ary_make_hash(ary2, 0);
-
- for (long i = 0; i < ary1_len; i++) {
- VALUE v = RARRAY_AT(ary1, i);
- if (rb_hash_has_key(hash, v) == Qfalse) {
- rb_ary_push(ary3, rb_ary_elt(ary1, i));
- }
- }
- }
return ary3;
}
@@ -3195,8 +2443,9 @@
}
}
-static VALUE
-rb_ary_and(VALUE ary1, SEL sel, VALUE ary2)
+// Defined on NSArray.
+VALUE
+rary_and(VALUE ary1, SEL sel, VALUE ary2)
{
ary2 = to_ary(ary2);
VALUE ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
@@ -3220,13 +2469,13 @@
* #=> [ "a", "b", "c", "d" ]
*/
-static VALUE
-rb_ary_or(VALUE ary1, SEL sel, VALUE ary2)
+// Defined on NSArray.
+VALUE
+rary_or(VALUE ary1, SEL sel, VALUE ary2)
{
ary2 = to_ary(ary2);
VALUE ary3 = rb_ary_new2(RARRAY_LEN(ary1) + RARRAY_LEN(ary2));
VALUE hash = ary_make_hash(ary1, ary2);
-
filter_diff(ary1, ary3, hash);
filter_diff(ary2, ary3, hash);
return ary3;
@@ -3247,38 +2496,22 @@
*/
static VALUE
-rb_ary_uniq_bang(VALUE ary, SEL sel)
+rary_uniq_bang(VALUE ary, SEL sel)
{
- rb_ary_modify(ary);
- long n = RARRAY_LEN(ary);
+ rary_modify(ary);
+ long n = RARY(ary)->len;
bool changed = false;
- if (IS_RARY(ary)) {
- for (size_t i = 0; i < n; i++) {
- VALUE item = rary_elt(RARY(ary), i);
- size_t pos = i + 1;
- while (pos < n && (pos = rary_index_of_item(RARY(ary), pos, item))
- != NOT_FOUND) {
- rary_erase(RARY(ary), pos, 1);
- n--;
- changed = true;
- }
+ for (size_t i = 0; i < n; i++) {
+ VALUE item = rary_elt(ary, i);
+ size_t pos = i + 1;
+ while (pos < n && (pos = rary_index_of_item(ary, pos, item))
+ != NOT_FOUND) {
+ rary_erase(ary, pos, 1);
+ n--;
+ changed = true;
}
}
- else {
- for (long i = 0; i < n; i++) {
- const void *ocval = RB2OC(RARRAY_AT(ary, i));
- CFRange r = CFRangeMake(i + 1, n - i - 1);
- long idx = 0;
- while ((idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary,
- r, ocval)) != -1) {
- CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, idx);
- r.location = idx;
- r.length = --n - idx;
- changed = true;
- }
- }
- }
if (!changed) {
return Qnil;
@@ -3297,10 +2530,10 @@
*/
static VALUE
-rb_ary_uniq(VALUE ary, SEL sel)
+rary_uniq(VALUE ary, SEL sel)
{
- ary = rb_ary_dup(ary);
- rb_ary_uniq_bang(ary, 0);
+ ary = rary_dup(ary, 0);
+ rary_uniq_bang(ary, 0);
return ary;
}
@@ -3316,11 +2549,9 @@
*/
static VALUE
-rb_ary_compact_bang(VALUE ary, SEL sel)
+rary_compact_bang(VALUE ary, SEL sel)
{
- const long n = RARRAY_LEN(ary);
- rb_ary_delete(ary, Qnil);
- return RARRAY_LEN(ary) == n ? Qnil : ary;
+ return rary_delete_element(ary, Qnil) ? ary : Qnil;
}
/*
@@ -3334,10 +2565,10 @@
*/
static VALUE
-rb_ary_compact(VALUE ary, SEL sel)
+rary_compact(VALUE ary, SEL sel)
{
- ary = rb_ary_dup(ary);
- rb_ary_compact_bang(ary, 0);
+ ary = rary_dup(ary, 0);
+ rary_compact_bang(ary, 0);
return ary;
}
@@ -3359,47 +2590,38 @@
*/
static VALUE
-rb_ary_count(VALUE ary, SEL sel, int argc, VALUE *argv)
+rary_count(VALUE ary, SEL sel, int argc, VALUE *argv)
{
long n = 0;
if (argc == 0) {
- long count = RARRAY_LEN(ary);
-
if (!rb_block_given_p())
- return LONG2NUM(count);
+ return LONG2NUM(RARY(ary)->len);
- for (long i = 0; i < count; i++) {
- VALUE v = rb_yield(RARRAY_AT(ary, i));
+ for (long i = 0; i < RARY(ary)->len; i++) {
+ VALUE elem = rary_elt(ary, i);
+ VALUE test = rb_yield(elem);
RETURN_IF_BROKEN();
- if (RTEST(v)) {
+ if (RTEST(test)) {
n++;
}
}
}
else {
VALUE obj;
- const long count = RARRAY_LEN(ary);
-
rb_scan_args(argc, argv, "1", &obj);
if (rb_block_given_p()) {
rb_warn("given block not used");
}
- if (IS_RARY(ary)) {
- size_t pos = 0;
- while ((pos = rary_index_of_item(RARY(ary), pos, obj))
- != NOT_FOUND) {
- ++n;
- if (++pos == count) {
- break;
- }
+ size_t pos = 0;
+ while ((pos = rary_index_of_item(ary, pos, obj))
+ != NOT_FOUND) {
+ n++;
+ if (++pos == RARY(ary)->len) {
+ break;
}
}
- else {
- n = CFArrayGetCountOfValue((CFArrayRef)ary, CFRangeMake(0, count),
- RB2OC(obj));
- }
}
return LONG2NUM(n);
@@ -3414,12 +2636,13 @@
st_data_t id;
stack = rb_ary_new();
- result = ary_new(rb_class_of(ary), RARRAY_LEN(ary));
+ result = rary_alloc(rb_class_of(ary), 0);
+ rary_reserve(result, RARRAY_LEN(ary));
memo = st_init_numtable();
st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
*modified = 0;
- while (1) {
+ while (true) {
while (i < RARRAY_LEN(ary)) {
elt = RARRAY_AT(ary, i++);
tmp = rb_check_array_type(elt);
@@ -3473,8 +2696,9 @@
* a.flatten!(1) #=> [1, 2, 3, [4, 5]]
*/
-static VALUE
-rb_ary_flatten_bang(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_flatten_bang(VALUE ary, SEL sel, int argc, VALUE *argv)
{
int mod = 0, level = -1;
VALUE result, lv;
@@ -3515,8 +2739,9 @@
* a.flatten(1) #=> [1, 2, 3, [4, 5]]
*/
-static VALUE
-rb_ary_flatten(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_flatten(VALUE ary, SEL sel, int argc, VALUE *argv)
{
int mod = 0, level = -1;
VALUE result, lv;
@@ -3545,16 +2770,16 @@
*/
static VALUE
-rb_ary_shuffle_bang(VALUE ary, SEL sel)
+rary_shuffle_bang(VALUE ary, SEL sel)
{
- long i = RARRAY_LEN(ary);
+ rary_modify(ary);
- rb_ary_modify(ary);
- while (i) {
+ long i = RARY(ary)->len;
+ while (i > 0) {
const long j = rb_genrand_real() * i;
VALUE elem = rb_ary_elt(ary, --i);
- rb_ary_store(ary, i, rb_ary_elt(ary, j));
- rb_ary_store(ary, j, elem);
+ rary_store(ary, i, rb_ary_elt(ary, j));
+ rary_store(ary, j, elem);
}
return ary;
}
@@ -3570,10 +2795,10 @@
*/
static VALUE
-rb_ary_shuffle(VALUE ary, SEL sel)
+rary_shuffle(VALUE ary, SEL sel)
{
- ary = rb_ary_dup(ary);
- rb_ary_shuffle_bang(ary, 0);
+ ary = rary_dup(ary, 0);
+ rary_shuffle_bang(ary, 0);
return ary;
}
@@ -3587,8 +2812,9 @@
* second form returns an empty array.
*/
-static VALUE
-rb_ary_sample(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_sample(VALUE ary, SEL sel, int argc, VALUE *argv)
{
VALUE nv, result;
long n, len, i, j, k, idx[10];
@@ -3689,8 +2915,9 @@
*
*/
-static VALUE
-rb_ary_cycle(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_cycle(VALUE ary, SEL sel, int argc, VALUE *argv)
{
VALUE nv = Qnil;
rb_scan_args(argc, argv, "01", &nv);
@@ -3782,8 +3009,9 @@
* a.permutation(4).to_a #=> [] # no permutations of length 4
*/
-static VALUE
-rb_ary_permutation(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_permutation(VALUE ary, SEL sel, int argc, VALUE *argv)
{
VALUE num;
long r, n, i;
@@ -3846,7 +3074,7 @@
* of elements from <i>ary</i> and then returns <i>ary</i> itself.
* The implementation makes no guarantees about the order in which
* the combinations are yielded.
- *
+ *
* When invoked without a block, returns an enumerator object instead.
*
* Examples:
@@ -3861,8 +3089,9 @@
*
*/
-static VALUE
-rb_ary_combination(VALUE ary, SEL sel, VALUE num)
+// Defined on NSArray.
+VALUE
+rary_combination(VALUE ary, SEL sel, VALUE num)
{
long n, i, len;
@@ -3921,8 +3150,9 @@
* [1,2].product([]) # => []
*/
-static VALUE
-rb_ary_product(VALUE ary, SEL sel, int argc, VALUE *argv)
+// Defined on NSArray.
+VALUE
+rary_product(VALUE ary, SEL sel, int argc, VALUE *argv)
{
int n = argc+1; /* How many arrays we're operating on */
VALUE *arrays = (VALUE *)alloca(n * sizeof(VALUE));; /* The arrays we're computing the product of */
@@ -3989,13 +3219,13 @@
*/
static VALUE
-rb_ary_take(VALUE obj, SEL sel, VALUE n)
+rary_take(VALUE obj, SEL sel, VALUE n)
{
const long len = NUM2LONG(n);
if (len < 0) {
rb_raise(rb_eArgError, "attempt to take negative size");
}
- return rb_ary_subseq(obj, 0, len);
+ return rary_subseq(obj, 0, len);
}
/*
@@ -4011,18 +3241,21 @@
*/
static VALUE
-rb_ary_take_while(VALUE ary, SEL sel)
+rary_take_while(VALUE ary, SEL sel)
{
RETURN_ENUMERATOR(ary, 0, 0);
+
long i = 0;
- for (; i < RARRAY_LEN(ary); i++) {
- VALUE v = rb_yield(RARRAY_AT(ary, i));
+ while (i < RARY(ary)->len) {
+ VALUE elem = rary_elt(ary, i);
+ VALUE test = rb_yield(elem);
RETURN_IF_BROKEN();
- if (!RTEST(v)) {
+ if (!RTEST(test)) {
break;
}
+ i++;
}
- return rb_ary_take(ary, 0, LONG2FIX(i));
+ return rary_take(ary, 0, LONG2FIX(i));
}
/*
@@ -4038,14 +3271,14 @@
*/
static VALUE
-rb_ary_drop(VALUE ary, SEL sel, VALUE n)
+rary_drop(VALUE ary, SEL sel, VALUE n)
{
const long pos = NUM2LONG(n);
if (pos < 0) {
rb_raise(rb_eArgError, "attempt to drop negative size");
}
- VALUE result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
+ VALUE result = rary_subseq(ary, pos, RARY(ary)->len);
if (result == Qnil) {
result = rb_ary_new();
}
@@ -4066,150 +3299,24 @@
*/
static VALUE
-rb_ary_drop_while(VALUE ary, SEL sel)
+rary_drop_while(VALUE ary, SEL sel)
{
RETURN_ENUMERATOR(ary, 0, 0);
+
long i = 0;
- for (; i < RARRAY_LEN(ary); i++) {
- VALUE v = rb_yield(RARRAY_AT(ary, i));
+ while (i < RARY(ary)->len) {
+ VALUE elem = rary_elt(ary, i);
+ VALUE test = rb_yield(elem);
RETURN_IF_BROKEN();
- if (!RTEST(v)) {
+ if (!RTEST(test)) {
break;
}
+ i++;
}
- return rb_ary_drop(ary, 0, LONG2FIX(i));
+ return rary_drop(ary, 0, LONG2FIX(i));
}
-#define PREPARE_RCV(x) \
- Class old = *(Class *)x; \
- *(Class *)x = (Class)rb_cCFArray;
-
-#define RESTORE_RCV(x) \
- *(Class *)x = old;
-
-bool
-rb_objc_ary_is_pure(VALUE ary)
-{
- return *(Class *)ary == (Class)rb_cRubyArray;
-}
-
static CFIndex
-imp_rb_array_count(void *rcv, SEL sel)
-{
- CFIndex count;
- PREPARE_RCV(rcv);
- count = CFArrayGetCount((CFArrayRef)rcv);
- RESTORE_RCV(rcv);
- return count;
-}
-
-static const void *
-imp_rb_array_objectAtIndex(void *rcv, SEL sel, CFIndex idx)
-{
- const void *obj;
- PREPARE_RCV(rcv);
- obj = CFArrayGetValueAtIndex((CFArrayRef)rcv, idx);
- RESTORE_RCV(rcv);
- return obj;
-}
-
-static void
-imp_rb_array_insertObjectAtIndex(void *rcv, SEL sel, void *obj, CFIndex idx)
-{
- PREPARE_RCV(rcv);
- CFArrayInsertValueAtIndex((CFMutableArrayRef)rcv, idx, obj);
- RESTORE_RCV(rcv);
-}
-
-static void
-imp_rb_array_removeObjectAtIndex(void *rcv, SEL sel, CFIndex idx)
-{
- PREPARE_RCV(rcv);
- CFArrayRemoveValueAtIndex((CFMutableArrayRef)rcv, idx);
- RESTORE_RCV(rcv);
-}
-
-static void
-imp_rb_array_replaceObjectAtIndexWithObject(void *rcv, SEL sel, CFIndex idx,
- void *obj)
-{
- PREPARE_RCV(rcv);
- CFArraySetValueAtIndex((CFMutableArrayRef)rcv, idx, obj);
- RESTORE_RCV(rcv);
-}
-
-static void
-imp_rb_array_replaceObjectsInRangeWithObjectsCount(void *rcv, SEL sel,
- CFRange range, const void **objects, CFIndex count)
-{
- PREPARE_RCV(rcv);
- CFArrayReplaceValues((CFMutableArrayRef)rcv, range, objects, count);
- RESTORE_RCV(rcv);
-}
-
-static void
-imp_rb_array_addObject(void *rcv, SEL sel, void *obj)
-{
- PREPARE_RCV(rcv);
- CFArrayAppendValue((CFMutableArrayRef)rcv, obj);
- RESTORE_RCV(rcv);
-}
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
-// This is to work around a bug where CF will try to call an non-existing
-// method.
-static CFIndex
-imp_rb_array_cfindexOfObjectInRange(void *rcv, SEL sel, void *obj,
- CFRange range)
-{
- CFIndex i;
- PREPARE_RCV(rcv);
- i = CFArrayGetFirstIndexOfValue((CFArrayRef)rcv, range, obj);
- RESTORE_RCV(rcv);
- return i;
-}
-#endif
-
-void
-rb_objc_install_array_primitives(Class klass)
-{
- rb_objc_install_method2(klass, "count", (IMP)imp_rb_array_count);
- rb_objc_install_method2(klass, "objectAtIndex:",
- (IMP)imp_rb_array_objectAtIndex);
-
- const bool is_mutable = class_getSuperclass(klass)
- == (Class)rb_cNSMutableArray;
-
- if (is_mutable) {
- rb_objc_install_method2(klass, "insertObject:atIndex:",
- (IMP)imp_rb_array_insertObjectAtIndex);
- rb_objc_install_method2(klass, "removeObjectAtIndex:",
- (IMP)imp_rb_array_removeObjectAtIndex);
- rb_objc_install_method2(klass, "replaceObjectAtIndex:withObject:",
- (IMP)imp_rb_array_replaceObjectAtIndexWithObject);
- rb_objc_install_method2(klass,
- "replaceObjectsInRange:withObjects:count:",
- (IMP)imp_rb_array_replaceObjectsInRangeWithObjectsCount);
- rb_objc_install_method2(klass, "addObject:",
- (IMP)imp_rb_array_addObject);
- }
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
- /* This is to work around a bug where CF will try to call an non-existing
- * method.
- */
- rb_objc_install_method2(klass, "_cfindexOfObject:range:",
- (IMP)imp_rb_array_cfindexOfObjectInRange);
- Method m = class_getInstanceMethod(klass,
- sel_registerName("_cfindexOfObject:range:"));
- class_addMethod(klass, sel_registerName("_cfindexOfObject:inRange:"),
- method_getImplementation(m), method_getTypeEncoding(m));
-#endif
-
- rb_objc_define_method(*(VALUE *)klass, "alloc", ary_alloc, 0);
-}
-
-static CFIndex
imp_rary_count(void *rcv, SEL sel)
{
return RARY(rcv)->len;
@@ -4219,32 +3326,32 @@
imp_rary_objectAtIndex(void *rcv, SEL sel, CFIndex idx)
{
assert(idx < RARY(rcv)->len);
- return RB2OC(rary_elt(RARY(rcv), idx));
+ return RB2OC(rary_elt((VALUE)rcv, idx));
}
static void
imp_rary_insertObjectAtIndex(void *rcv, SEL sel, void *obj, CFIndex idx)
{
- rary_insert(RARY(rcv), idx, OC2RB(obj));
+ rary_insert((VALUE)rcv, idx, OC2RB(obj));
}
static void
imp_rary_removeObjectAtIndex(void *rcv, SEL sel, CFIndex idx)
{
- rary_erase(RARY(rcv), idx, 1);
+ rary_erase((VALUE)rcv, idx, 1);
}
static void
imp_rary_replaceObjectAtIndexWithObject(void *rcv, SEL sel, CFIndex idx,
void *obj)
{
- rary_store(RARY(rcv), idx, OC2RB(obj));
+ rary_store((VALUE)rcv, idx, OC2RB(obj));
}
static void
imp_rary_addObject(void *rcv, SEL sel, void *obj)
{
- rary_append(RARY(rcv), OC2RB(obj));
+ rary_push((VALUE)rcv, OC2RB(obj));
}
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
@@ -4256,7 +3363,7 @@
assert(range.location + range.length <= RARY(rcv)->len);
VALUE item = OC2RB(obj);
for (size_t i = range.location; i < range.location + range.length; i++) {
- VALUE item2 = rary_elt(RARY(rcv), i);
+ VALUE item2 = rary_elt((VALUE)rcv, i);
if (rb_equal_fast(item, item2) == Qtrue) {
return i;
}
@@ -4265,6 +3372,25 @@
}
#endif
+bool
+rb_objc_ary_is_pure(VALUE ary)
+{
+ VALUE k = *(VALUE *)ary;
+ while (RCLASS_SINGLETON(k)) {
+ k = RCLASS_SUPER(k);
+ }
+ if (k == rb_cRubyArray) {
+ return true;
+ }
+ while (k != 0) {
+ if (k == rb_cRubyArray) {
+ return false;
+ }
+ k = RCLASS_SUPER(k);
+ }
+ return true;
+}
+
/* Arrays are ordered, integer-indexed collections of any object.
* Array indexing starts at 0, as in C or Java. A negative index is
* assumed to be relative to the end of the array---that is, an index of -1
@@ -4272,130 +3398,85 @@
* element in the array, and so on.
*/
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
-# define NSCFARRAY_CNAME "NSCFArray"
-#else
-# define NSCFARRAY_CNAME "__NSCFArray"
-#endif
+void Init_NSArray(void);
void
Init_Array(void)
{
- rb_cCFArray = (VALUE)objc_getClass(NSCFARRAY_CNAME);
- assert(rb_cCFArray != 0);
- rb_const_set(rb_cObject, rb_intern("NSCFArray"), rb_cCFArray);
- rb_cArray = rb_cNSArray = (VALUE)objc_getClass("NSArray");
- rb_cNSMutableArray = (VALUE)objc_getClass("NSMutableArray");
+ Init_NSArray();
- rb_include_module(rb_cArray, rb_mEnumerable);
-
- rb_objc_define_method(*(VALUE *)rb_cArray, "[]", rb_ary_s_create, -1);
- rb_objc_define_method(*(VALUE *)rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
- rb_objc_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
- rb_objc_define_method(rb_cArray, "initialize_copy", rb_ary_replace_imp, 1);
-
- rb_objc_define_method(rb_cArray, "to_s", rb_ary_inspect, 0);
- rb_objc_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
- rb_objc_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
- rb_objc_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
- rb_objc_define_method(rb_cArray, "frozen?", rb_ary_frozen_imp, 0);
-
- rb_objc_define_method(rb_cArray, "==", rb_ary_equal_imp, 1);
- rb_objc_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
-
- rb_objc_define_method(rb_cArray, "[]", rb_ary_aref, -1);
- rb_objc_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
- rb_objc_define_method(rb_cArray, "at", rb_ary_at, 1);
- rb_objc_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
- rb_objc_define_method(rb_cArray, "first", rb_ary_first, -1);
- rb_objc_define_method(rb_cArray, "last", rb_ary_last, -1);
- rb_objc_define_method(rb_cArray, "concat", rb_ary_concat_imp, 1);
- rb_objc_define_method(rb_cArray, "<<", rb_ary_push_imp, 1);
- rb_objc_define_method(rb_cArray, "push", rb_ary_push_m, -1);
- rb_objc_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
- rb_objc_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
- rb_objc_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
- rb_objc_define_method(rb_cArray, "insert", rb_ary_insert_m, -1);
- rb_objc_define_method(rb_cArray, "each", rb_ary_each_imp, 0);
- rb_objc_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
- rb_objc_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
- rb_objc_define_method(rb_cArray, "length", rb_ary_length, 0);
- rb_objc_define_method(rb_cArray, "size", rb_ary_length, 0);
- rb_objc_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
- rb_objc_define_method(rb_cArray, "find_index", rb_ary_index, -1);
- rb_objc_define_method(rb_cArray, "index", rb_ary_index, -1);
- rb_objc_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
- rb_objc_define_method(rb_cArray, "join", rb_ary_join_m, -1);
- rb_objc_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
- rb_objc_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
- rb_objc_define_method(rb_cArray, "sort", rb_ary_sort_imp, 0);
- rb_objc_define_method(rb_cArray, "sort!", rb_ary_sort_bang_imp, 0);
- rb_objc_define_method(rb_cArray, "collect", rb_ary_collect, 0);
- rb_objc_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
- rb_objc_define_method(rb_cArray, "map", rb_ary_collect, 0);
- rb_objc_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
- rb_objc_define_method(rb_cArray, "select", rb_ary_select, 0);
- rb_objc_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
- rb_objc_define_method(rb_cArray, "delete", rb_ary_delete_imp, 1);
- rb_objc_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
- rb_objc_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
- rb_objc_define_method(rb_cArray, "reject", rb_ary_reject, 0);
- rb_objc_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
- rb_objc_define_method(rb_cArray, "zip", rb_ary_zip, -1);
- rb_objc_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
- rb_objc_define_method(rb_cArray, "replace", rb_ary_replace_imp, 1);
- rb_objc_define_method(rb_cArray, "clear", rb_ary_clear_imp, 0);
- rb_objc_define_method(rb_cArray, "fill", rb_ary_fill, -1);
- rb_objc_define_method(rb_cArray, "include?", rb_ary_includes_imp, 1);
- rb_objc_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
-
- rb_objc_define_method(rb_cArray, "slice", rb_ary_aref, -1);
- rb_objc_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
-
- rb_objc_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
- rb_objc_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
-
- rb_objc_define_method(rb_cArray, "+", rb_ary_plus_imp, 1);
- rb_objc_define_method(rb_cArray, "*", rb_ary_times, 1);
-
- rb_objc_define_method(rb_cArray, "-", rb_ary_diff, 1);
- rb_objc_define_method(rb_cArray, "&", rb_ary_and, 1);
- rb_objc_define_method(rb_cArray, "|", rb_ary_or, 1);
-
- rb_objc_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
- rb_objc_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
- rb_objc_define_method(rb_cArray, "compact", rb_ary_compact, 0);
- rb_objc_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
- rb_objc_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
- rb_objc_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
- rb_objc_define_method(rb_cArray, "_count", rb_ary_count, -1);
-
- /* to maintain backwards compatibility with our /etc/irbrc file
- * TODO: fix /etc/irbrc to use #count, and remove this method.
- */
- rb_objc_define_method(rb_cArray, "nitems", rb_ary_count, -1);
-
- rb_objc_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, 0);
- rb_objc_define_method(rb_cArray, "shuffle", rb_ary_shuffle, 0);
- rb_objc_define_method(rb_cArray, "sample", rb_ary_sample, -1);
- rb_objc_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
- rb_objc_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
- rb_objc_define_method(rb_cArray, "combination", rb_ary_combination, 1);
- rb_objc_define_method(rb_cArray, "product", rb_ary_product, -1);
-
- rb_objc_define_method(rb_cArray, "take", rb_ary_take, 1);
- rb_objc_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
- rb_objc_define_method(rb_cArray, "drop", rb_ary_drop, 1);
- rb_objc_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
-
- /* to return mutable copies */
- rb_objc_define_method(rb_cArray, "dup", rb_ary_dup_imp, 0);
- rb_objc_define_method(rb_cArray, "clone", rb_ary_clone, 0);
-
rb_cRubyArray = rb_define_class("Array", rb_cNSMutableArray);
rb_objc_define_method(*(VALUE *)rb_cRubyArray, "new",
rb_class_new_instance_imp, -1);
- rb_objc_define_method(*(VALUE *)rb_cRubyArray, "alloc", ary_alloc, 0);
+ rb_objc_define_method(*(VALUE *)rb_cRubyArray, "alloc", rary_alloc, 0);
+ rb_objc_define_method(*(VALUE *)rb_cRubyArray, "[]", rary_s_create, -1);
+ rb_objc_define_method(*(VALUE *)rb_cRubyArray, "try_convert",
+ rary_s_try_convert, 1);
+ rb_objc_define_method(rb_cRubyArray, "initialize", rary_initialize, -1);
+ rb_objc_define_method(rb_cRubyArray, "initialize_copy", rary_replace, 1);
+ rb_objc_define_method(rb_cRubyArray, "dup", rary_dup, 0);
+ rb_objc_define_method(rb_cRubyArray, "clone", rary_clone, 0);
+ rb_objc_define_method(rb_cRubyArray, "to_s", rary_inspect, 0);
+ rb_objc_define_method(rb_cRubyArray, "inspect", rary_inspect, 0);
+ rb_objc_define_method(rb_cRubyArray, "==", rary_equal, 1);
+ rb_objc_define_method(rb_cRubyArray, "eql?", rary_eql, 1);
+ rb_objc_define_method(rb_cRubyArray, "[]", rary_aref, -1);
+ rb_objc_define_method(rb_cRubyArray, "[]=", rary_aset, -1);
+ rb_objc_define_method(rb_cRubyArray, "at", rary_at, 1);
+ rb_objc_define_method(rb_cRubyArray, "fetch", rary_fetch, -1);
+ rb_objc_define_method(rb_cRubyArray, "first", rary_first, -1);
+ rb_objc_define_method(rb_cRubyArray, "last", rary_last, -1);
+ rb_objc_define_method(rb_cRubyArray, "concat", rary_concat_m, 1);
+ rb_objc_define_method(rb_cRubyArray, "<<", rary_push_m, 1);
+ rb_objc_define_method(rb_cRubyArray, "push", rary_push_m2, -1);
+ rb_objc_define_method(rb_cRubyArray, "pop", rary_pop, -1);
+ rb_objc_define_method(rb_cRubyArray, "shift", rary_shift, -1);
+ rb_objc_define_method(rb_cRubyArray, "unshift", rary_unshift, -1);
+ rb_objc_define_method(rb_cRubyArray, "insert", rary_insert_m, -1);
+ rb_objc_define_method(rb_cRubyArray, "each", rary_each, 0);
+ rb_objc_define_method(rb_cRubyArray, "each_index", rary_each_index, 0);
+ rb_objc_define_method(rb_cRubyArray, "reverse_each", rary_reverse_each, 0);
+ rb_objc_define_method(rb_cRubyArray, "length", rary_length, 0);
+ rb_objc_define_method(rb_cRubyArray, "size", rary_length, 0);
+ rb_objc_define_method(rb_cRubyArray, "empty?", rary_empty, 0);
+ rb_objc_define_method(rb_cRubyArray, "find_index", rary_index, -1);
+ rb_objc_define_method(rb_cRubyArray, "index", rary_index, -1);
+ rb_objc_define_method(rb_cRubyArray, "rindex", rary_rindex, -1);
+ rb_objc_define_method(rb_cRubyArray, "reverse", rary_reverse, 0);
+ rb_objc_define_method(rb_cRubyArray, "reverse!", rary_reverse_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "sort", rary_sort, 0);
+ rb_objc_define_method(rb_cRubyArray, "sort!", rary_sort_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "collect", rary_collect, 0);
+ rb_objc_define_method(rb_cRubyArray, "collect!", rary_collect_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "map", rary_collect, 0);
+ rb_objc_define_method(rb_cRubyArray, "map!", rary_collect_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "select", rary_select, 0);
+ rb_objc_define_method(rb_cRubyArray, "values_at", rary_values_at, -1);
+ rb_objc_define_method(rb_cRubyArray, "delete", rary_delete, 1);
+ rb_objc_define_method(rb_cRubyArray, "delete_at", rary_delete_at, 1);
+ rb_objc_define_method(rb_cRubyArray, "delete_if", rary_delete_if, 0);
+ rb_objc_define_method(rb_cRubyArray, "reject", rary_reject, 0);
+ rb_objc_define_method(rb_cRubyArray, "reject!", rary_reject_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "replace", rary_replace, 1);
+ rb_objc_define_method(rb_cRubyArray, "clear", rary_clear, 0);
+ rb_objc_define_method(rb_cRubyArray, "include?", rary_includes, 1);
+ rb_objc_define_method(rb_cRubyArray, "slice", rary_aref, -1);
+ rb_objc_define_method(rb_cRubyArray, "slice!", rary_slice_bang, -1);
+ rb_objc_define_method(rb_cRubyArray, "+", rary_plus, 1);
+ rb_objc_define_method(rb_cRubyArray, "*", rary_times, 1);
+ rb_objc_define_method(rb_cRubyArray, "uniq", rary_uniq, 0);
+ rb_objc_define_method(rb_cRubyArray, "uniq!", rary_uniq_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "compact", rary_compact, 0);
+ rb_objc_define_method(rb_cRubyArray, "compact!", rary_compact_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "count", rary_count, -1);
+ rb_objc_define_method(rb_cRubyArray, "nitems", rary_count, -1);
+ rb_objc_define_method(rb_cRubyArray, "shuffle!", rary_shuffle_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "shuffle", rary_shuffle, 0);
+ rb_objc_define_method(rb_cRubyArray, "take", rary_take, 1);
+ rb_objc_define_method(rb_cRubyArray, "take_while", rary_take_while, 0);
+ rb_objc_define_method(rb_cRubyArray, "drop", rary_drop, 1);
+ rb_objc_define_method(rb_cRubyArray, "drop_while", rary_drop_while, 0);
+
rb_objc_install_method2((Class)rb_cRubyArray, "count", (IMP)imp_rary_count);
rb_objc_install_method2((Class)rb_cRubyArray, "objectAtIndex:",
(IMP)imp_rary_objectAtIndex);
Added: MacRuby/trunk/array.h
===================================================================
--- MacRuby/trunk/array.h (rev 0)
+++ MacRuby/trunk/array.h 2010-02-07 04:51:44 UTC (rev 3438)
@@ -0,0 +1,150 @@
+/*
+ * MacRuby Hash.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2010, Apple Inc. All rights reserved.
+ */
+
+#ifndef __ARRAY_H_
+#define __ARRAY_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct {
+ struct RBasic basic;
+ size_t beg;
+ size_t len;
+ size_t cap;
+ VALUE *elements;
+} rb_ary_t;
+
+#define RARY(x) ((rb_ary_t *)x)
+
+static inline bool
+rb_klass_is_rary(VALUE klass)
+{
+ do {
+ if (klass == rb_cRubyArray) {
+ return true;
+ }
+ if (klass == rb_cNSArray) {
+ return false;
+ }
+ klass = RCLASS_SUPER(klass);
+ }
+ while (klass != 0);
+ return false;
+}
+
+#define IS_RARY(x) (rb_klass_is_rary(*(VALUE *)x))
+
+static inline void
+rary_modify(VALUE ary)
+{
+ const long mask = RBASIC(ary)->flags;
+ if ((mask & FL_FREEZE) == FL_FREEZE) {
+ rb_raise(rb_eRuntimeError, "can't modify frozen/immutable array");
+ }
+ if ((mask & FL_TAINT) == FL_TAINT && rb_safe_level() >= 4) {
+ rb_raise(rb_eSecurityError, "Insecure: can't modify array");
+ }
+}
+
+static inline VALUE
+rary_elt(VALUE ary, size_t idx)
+{
+ //assert(idx < RARY(ary)->len);
+ return RARY(ary)->elements[RARY(ary)->beg + idx];
+}
+
+static inline void
+rary_elt_set(VALUE ary, size_t idx, VALUE item)
+{
+ //assert(idx < ary->len);
+ GC_WB(&RARY(ary)->elements[RARY(ary)->beg + idx], item);
+}
+
+static inline VALUE *
+rary_ptr(VALUE ary)
+{
+ return &RARY(ary)->elements[RARY(ary)->beg];
+}
+
+static inline VALUE
+rary_entry(VALUE ary, long offset)
+{
+ const long n = RARY(ary)->len;
+ if (n == 0) {
+ return Qnil;
+ }
+ if (offset < 0) {
+ offset += n;
+ }
+ if (offset < 0 || n <= offset) {
+ return Qnil;
+ }
+ return rary_elt(ary, offset);
+}
+
+static inline void
+rb_ary_modify(VALUE ary)
+{
+ if (IS_RARY(ary)) {
+ rary_modify(ary);
+ }
+}
+
+static inline VALUE
+to_ary(VALUE ary)
+{
+ return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
+}
+
+VALUE rary_dup(VALUE ary, SEL sel);
+VALUE rary_clear(VALUE ary, SEL sel);
+VALUE rary_reverse_bang(VALUE ary, SEL sel);
+VALUE rary_includes(VALUE ary, SEL sel, VALUE item);
+VALUE rary_delete(VALUE ary, SEL sel, VALUE item);
+VALUE rary_delete_at(VALUE ary, SEL sel, VALUE pos);
+VALUE rary_pop(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_shift(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_aref(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_plus(VALUE x, SEL sel, VALUE y);
+VALUE rary_push_m(VALUE ary, SEL sel, VALUE item);
+VALUE rary_concat_m(VALUE x, SEL sel, VALUE y);
+VALUE rary_last(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_unshift(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_each(VALUE ary, SEL sel);
+VALUE rary_sort(VALUE ary, SEL sel);
+VALUE rary_sort_bang(VALUE ary, SEL sel);
+void rary_store(VALUE ary, long idx, VALUE item);
+VALUE rary_subseq(VALUE ary, long beg, long len);
+void rary_insert(VALUE ary, long idx, VALUE val);
+
+// Shared implementations.
+VALUE rary_join(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_zip(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_transpose(VALUE ary, SEL sel);
+VALUE rary_fill(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_cmp(VALUE ary1, SEL sel, VALUE ary2);
+VALUE rary_assoc(VALUE ary, SEL sel, VALUE key);
+VALUE rary_rassoc(VALUE ary, SEL sel, VALUE value);
+VALUE rary_flatten(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_flatten_bang(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_product(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_combination(VALUE ary, SEL sel, VALUE num);
+VALUE rary_permutation(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_cycle(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_sample(VALUE ary, SEL sel, int argc, VALUE *argv);
+VALUE rary_diff(VALUE ary1, SEL sel, VALUE ary2);
+VALUE rary_and(VALUE ary1, SEL sel, VALUE ary2);
+VALUE rary_or(VALUE ary1, SEL sel, VALUE ary2);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif // __ARRAY_H_
Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/compiler.cpp 2010-02-07 04:51:44 UTC (rev 3438)
@@ -4440,11 +4440,12 @@
case NODE_VALUES:
{
if (newArrayFunc == NULL) {
- // VALUE rb_ary_new_fast(int argc, ...);
+ // VALUE rb_ary_new3(int argc, ...);
std::vector<const Type *> types;
types.push_back(Int32Ty);
FunctionType *ft = FunctionType::get(RubyObjTy, types, true);
- newArrayFunc = cast<Function>(module->getOrInsertFunction("rb_ary_new_fast", ft));
+ newArrayFunc = cast<Function>(module->getOrInsertFunction(
+ "rb_ary_new3", ft));
}
std::vector<Value *> params;
Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/dispatcher.cpp 2010-02-07 04:51:44 UTC (rev 3438)
@@ -1,5 +1,5 @@
/*
- * MacRuby VM.
+ * MacRuby Dispatcher.
*
* This file is covered by the Ruby license. See COPYING for more details.
*
@@ -14,6 +14,8 @@
#include "compiler.h"
#include "objc.h"
#include "dtrace.h"
+#include "array.h"
+#include "hash.h"
#include <execinfo.h>
#include <dlfcn.h>
@@ -1318,8 +1320,7 @@
switch (TYPE(obj)) {
case T_ARRAY:
if (*(VALUE *)obj == rb_cRubyArray) {
- rb_ary_push(obj, other);
- return obj;
+ return rary_push_m(obj, 0, other);
}
break;
@@ -1344,16 +1345,13 @@
switch (TYPE(obj)) {
case T_ARRAY:
if (*(VALUE *)obj == rb_cRubyArray) {
- if (TYPE(other) == T_FIXNUM) {
- return rb_ary_entry(obj, FIX2LONG(other));
- }
- return rb_ary_aref(obj, 0, 1, &other);
+ return rary_aref(obj, 0, 1, &other);
}
break;
case T_HASH:
if (*(VALUE *)obj == rb_cRubyHash) {
- return rb_hash_aref(obj, other);
+ return rhash_aref(obj, 0, other);
}
break;
}
@@ -1371,7 +1369,7 @@
case T_ARRAY:
if (*(VALUE *)obj == rb_cRubyArray) {
if (TYPE(other1) == T_FIXNUM) {
- rb_ary_store(obj, FIX2LONG(other1), other2);
+ rary_store(obj, FIX2LONG(other1), other2);
return other2;
}
}
@@ -1379,7 +1377,7 @@
case T_HASH:
if (*(VALUE *)obj == rb_cRubyHash) {
- return rb_hash_aset(obj, other1, other2);
+ return rhash_aset(obj, 0, other1, other2);
}
break;
}
Modified: MacRuby/trunk/hash.c
===================================================================
--- MacRuby/trunk/hash.c 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/hash.c 2010-02-07 04:51:44 UTC (rev 3438)
@@ -17,6 +17,7 @@
#include "id.h"
#include "objc.h"
#include "vm.h"
+#include "hash.h"
static VALUE rhash_try_convert(VALUE, SEL, VALUE);
@@ -28,37 +29,6 @@
VALUE rb_cRubyHash;
-typedef struct {
- struct RBasic basic;
- st_table *tbl;
- VALUE ifnone;
- bool has_proc_default;
-} rb_hash_t;
-
-#define IS_RHASH(x) __klass_is_rhash(*(VALUE *)x)
-#define RHASH(x) ((rb_hash_t *)x)
-
-static inline bool
-__klass_is_rhash(VALUE k)
-{
- while (k != 0) {
- if (k == rb_cRubyHash) {
- return true;
- }
- if (k == rb_cNSHash) {
- return false;
- }
- k = RCLASS_SUPER(k);
- }
- return false;
-}
-
-bool
-rb_klass_is_rhash(VALUE klass)
-{
- return __klass_is_rhash(klass);
-}
-
static ID id_yield;
static void *defaultCache = NULL;
@@ -67,12 +37,6 @@
static SEL selDefault = 0;
static SEL selHash = 0;
-static inline long
-rhash_len(VALUE hash)
-{
- return RHASH(hash)->tbl->num_entries;
-}
-
VALUE
rb_hash(VALUE obj)
{
@@ -121,63 +85,6 @@
st_foreach(table, foreach_safe_i, (st_data_t)&arg);
}
-static void
-rhash_iterate(VALUE hash, int (*func)(ANYARGS), VALUE farg)
-{
- st_foreach_safe(RHASH(hash)->tbl, func, (st_data_t)farg);
-}
-
-#define rhash_foreach rhash_iterate
-
-void
-rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
-{
- if (IS_RHASH(hash)) {
- rhash_foreach(hash, func, farg);
- }
- else {
- CFIndex count = CFDictionaryGetCount((CFDictionaryRef)hash);
- if (count != 0) {
- const void **keys = (const void **)alloca(sizeof(void *) * count);
- const void **vals = (const void **)alloca(sizeof(void *) * count);
- CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, vals);
- for (CFIndex i = 0; i < count; i++) {
- if ((*func)(OC2RB(keys[i]), OC2RB(vals[i]), farg)
- != ST_CONTINUE) {
- break;
- }
- }
- }
- }
-}
-
-struct rb_cfhash_iterate_context {
- int (*func)(ANYARGS);
- VALUE farg;
-};
-
-static void
-rb_cfhash_iterate_i(const void *key, const void *value, void *context)
-{
- struct rb_cfhash_iterate_context *ctx =
- (struct rb_cfhash_iterate_context *)context;
-
- (*ctx->func)(OC2RB(key), OC2RB(value), ctx->farg);
-}
-
-void
-rb_hash_iterate(VALUE hash, int (*func)(ANYARGS), VALUE farg)
-{
- if (IS_RHASH(hash)) {
- rhash_iterate(hash, func, farg);
- }
- else {
- struct rb_cfhash_iterate_context ctx = {func, farg};
- CFDictionaryApplyFunction((CFDictionaryRef)hash, rb_cfhash_iterate_i,
- &ctx);
- }
-}
-
static int
rb_any_cmp(VALUE a, VALUE b)
{
@@ -227,6 +134,9 @@
static VALUE
rhash_alloc(VALUE klass, SEL sel)
{
+ assert(klass != 0);
+ assert(rb_klass_is_rhash(klass));
+
NEWOBJ(hash, rb_hash_t);
hash->basic.flags = 0;
hash->basic.klass = klass;
@@ -236,7 +146,7 @@
return (VALUE)hash;
}
-static VALUE
+VALUE
rhash_dup(VALUE rcv, SEL sel)
{
NEWOBJ(dup, rb_hash_t);
@@ -262,27 +172,11 @@
}
VALUE
-rb_hash_dup(VALUE rcv)
-{
- if (IS_RHASH(rcv)) {
- return rhash_dup(rcv, 0);
- }
- else {
- VALUE dup = (VALUE)CFDictionaryCreateMutableCopy(NULL, 0,
- (CFDictionaryRef)rcv);
- CFMakeCollectable((CFTypeRef)dup);
- return dup;
- }
-}
-
-VALUE
rb_hash_new(void)
{
return rhash_alloc(rb_cRubyHash, 0);
}
-static VALUE rhash_aset(VALUE hash, SEL sel, VALUE key, VALUE val);
-
VALUE
rb_hash_new_fast(int argc, ...)
{
@@ -302,18 +196,6 @@
return hash;
}
-static inline void
-rhash_modify(VALUE hash)
-{
- const long mask = RBASIC(hash)->flags;
- if ((mask & FL_FREEZE) == FL_FREEZE) {
- rb_raise(rb_eRuntimeError, "can't modify frozen/immutable hash");
- }
- if ((mask & FL_TAINT) == FL_TAINT && rb_safe_level() >= 4) {
- rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
- }
-}
-
/*
* call-seq:
* Hash.new => hash
@@ -416,29 +298,17 @@
VALUE tmp = rhash_try_convert(Qnil, 0, argv[0]);
if (!NIL_P(tmp)) {
VALUE hash = rhash_alloc(klass, 0);
- if (IS_RHASH(hash) && IS_RHASH(tmp)) {
+ if (IS_RHASH(tmp)) {
GC_WB(&RHASH(hash)->tbl, st_copy(RHASH(tmp)->tbl));
}
else {
- CFIndex count = CFDictionaryGetCount((CFDictionaryRef)tmp);
- if (count == 0) {
- return hash;
+ VALUE keys = rb_hash_keys(tmp);
+ for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) {
+ VALUE key = RARRAY_AT(keys, i);
+ VALUE val = rb_hash_lookup(tmp, key);
+ rhash_aset(hash, 0, key, val);
}
-
- const void **keys = (const void **)alloca(sizeof(void *)
- * count);
- const void **values = (const void **)alloca(sizeof(void *)
- * count);
-
- CFDictionaryGetKeysAndValues((CFDictionaryRef)tmp, keys,
- values);
-
- for (int i = 0; i < count; i++) {
- CFDictionarySetValue((CFMutableDictionaryRef)hash,
- RB2OC(keys[i]), RB2OC(values[i]));
- }
}
-
return hash;
}
@@ -454,7 +324,7 @@
if (len < 1 || 2 < len) {
continue;
}
- rb_hash_aset(hash, RARRAY_AT(v, 0), RARRAY_AT(v, 1));
+ rhash_aset(hash, 0, RARRAY_AT(v, 0), RARRAY_AT(v, 1));
}
return hash;
}
@@ -533,33 +403,8 @@
*
*/
-static inline VALUE
-rhash_lookup(VALUE hash, VALUE key)
-{
- VALUE val;
- if (st_lookup(RHASH(hash)->tbl, key, &val)) {
- return val;
- }
- return Qundef;
-}
VALUE
-rb_hash_lookup(VALUE hash, VALUE key)
-{
- VALUE val;
- if (IS_RHASH(hash)) {
- val = rhash_lookup(hash, key);
- }
- else {
- if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
- (const void *)RB2OC(key), (const void **)&val)) {
- val = Qundef;
- }
- }
- return val == Qundef ? Qnil : val;
-}
-
-static VALUE
rhash_aref(VALUE hash, SEL sel, VALUE key)
{
VALUE val = rhash_lookup(hash, key);
@@ -574,22 +419,6 @@
return val;
}
-VALUE
-rb_hash_aref(VALUE hash, VALUE key)
-{
- if (IS_RHASH(hash)) {
- return rhash_aref(hash, 0, key);
- }
- else {
- VALUE val;
- if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
- (const void *)RB2OC(key), (const void **)&val)) {
- return Qnil;
- }
- return OC2RB(val);
- }
-}
-
/*
* call-seq:
* hsh.fetch(key [, default] ) => obj
@@ -699,7 +528,7 @@
* h["cat"] #=> #<Proc:0x401b3948 at -:6>
*/
-static VALUE
+VALUE
rhash_set_default(VALUE hash, SEL sel, VALUE ifnone)
{
rhash_modify(hash);
@@ -708,15 +537,6 @@
return ifnone;
}
-VALUE
-rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
-{
- if (IS_RHASH(hash)) {
- rhash_set_default(hash, 0, ifnone);
- }
- return ifnone;
-}
-
/*
* call-seq:
* hsh.default_proc -> anObject
@@ -763,7 +583,7 @@
rhash_key(VALUE hash, SEL sel, VALUE value)
{
VALUE args[2] = {value, Qnil};
- rhash_iterate(hash, key_i, (st_data_t)args);
+ rhash_foreach(hash, key_i, (st_data_t)args);
return args[1];
}
@@ -793,46 +613,6 @@
*
*/
-static inline VALUE
-rhash_delete_key(VALUE hash, VALUE key)
-{
- VALUE val;
- if (st_delete(RHASH(hash)->tbl, &key, &val)) {
- return val;
- }
- return Qundef;
-}
-
-VALUE
-rb_hash_delete_key(VALUE hash, VALUE key)
-{
- if (IS_RHASH(hash)) {
- rhash_modify(hash);
- return rhash_delete_key(hash, key);
- }
- else {
- VALUE val;
- id ockey = RB2OC(key);
- if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
- (const void *)ockey, (const void **)&val)) {
- CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
- (const void *)ockey);
- return OC2RB(val);
- }
- return Qundef;
- }
-}
-
-VALUE
-rb_hash_delete(VALUE hash, VALUE key)
-{
- VALUE val = rb_hash_delete_key(hash, key);
- if (val != Qundef) {
- return val;
- }
- return Qnil;
-}
-
static VALUE
rhash_delete(VALUE hash, SEL sel, VALUE key)
{
@@ -876,7 +656,7 @@
rhash_shift(VALUE hash, SEL sel)
{
VALUE args[2] = {0, 0};
- rhash_iterate(hash, shift_i, (st_data_t)args);
+ rhash_foreach(hash, shift_i, (st_data_t)args);
if (args[0] != 0 && args[1] != 0) {
rhash_modify(hash);
rhash_delete_key(hash, args[0]);
@@ -1011,7 +791,7 @@
{
RETURN_ENUMERATOR(hash, 0, 0);
VALUE result = rb_hash_new();
- rhash_iterate(hash, select_i, result);
+ rhash_foreach(hash, select_i, result);
return result;
}
@@ -1052,7 +832,7 @@
*
*/
-static VALUE
+VALUE
rhash_aset(VALUE hash, SEL sel, VALUE key, VALUE val)
{
rhash_modify(hash);
@@ -1060,20 +840,6 @@
return val;
}
-VALUE
-rb_hash_aset(VALUE hash, VALUE key, VALUE val)
-{
- if (IS_RHASH(hash)) {
- rhash_aset(hash, 0, key, val);
- }
- else {
- CFDictionarySetValue((CFMutableDictionaryRef)hash,
- (const void *)RB2OC(key),
- (const void *)RB2OC(val));
- }
- return val;
-}
-
static int
replace_i(VALUE key, VALUE val, VALUE hash)
{
@@ -1133,15 +899,6 @@
return LONG2NUM(rhash_len(hash));
}
-long
-rb_hash_size(VALUE hash)
-{
- if (IS_RHASH(hash)) {
- return rhash_len(hash);
- }
- return CFDictionaryGetCount((CFDictionaryRef)hash);
-}
-
/*
* call-seq:
* hsh.empty? => true or false
@@ -1187,7 +944,7 @@
rhash_each_value(VALUE hash, SEL sel)
{
RETURN_ENUMERATOR(hash, 0, 0);
- rhash_iterate(hash, each_value_i, 0);
+ rhash_foreach(hash, each_value_i, 0);
return hash;
}
@@ -1220,7 +977,7 @@
rhash_each_key(VALUE hash, SEL sel)
{
RETURN_ENUMERATOR(hash, 0, 0);
- rhash_iterate(hash, each_key_i, 0);
+ rhash_foreach(hash, each_key_i, 0);
return hash;
}
@@ -1255,7 +1012,7 @@
rhash_each_pair(VALUE hash, SEL sel)
{
RETURN_ENUMERATOR(hash, 0, 0);
- rhash_iterate(hash, each_pair_i, 0);
+ rhash_foreach(hash, each_pair_i, 0);
return hash;
}
@@ -1283,7 +1040,7 @@
rhash_to_a(VALUE hash, SEL sel)
{
VALUE ary = rb_ary_new();
- rhash_iterate(hash, to_a_i, ary);
+ rhash_foreach(hash, to_a_i, ary);
if (OBJ_TAINTED(hash)) {
OBJ_TAINT(ary);
}
@@ -1324,7 +1081,7 @@
return rb_usascii_str_new2("{...}");
}
VALUE str = rb_str_buf_new2("{");
- rhash_iterate(hash, inspect_i, str);
+ rhash_foreach(hash, inspect_i, str);
rb_str_buf_cat2(str, "}");
OBJ_INFECT(str, hash);
return str;
@@ -1373,22 +1130,14 @@
return ST_CONTINUE;
}
-static VALUE
+VALUE
rhash_keys(VALUE hash, SEL sel)
{
VALUE ary = rb_ary_new();
- rhash_iterate(hash, keys_i, ary);
+ rhash_foreach(hash, keys_i, ary);
return ary;
}
-VALUE
-rb_hash_keys(VALUE hash)
-{
- VALUE ary = rb_ary_new();
- rb_hash_iterate(hash, keys_i, ary);
- return ary;
-}
-
/*
* call-seq:
* hsh.values => array
@@ -1414,7 +1163,7 @@
rhash_values(VALUE hash, SEL sel)
{
VALUE ary = rb_ary_new();
- rhash_iterate(hash, values_i, ary);
+ rhash_foreach(hash, values_i, ary);
return ary;
}
@@ -1433,24 +1182,12 @@
*
*/
-static VALUE
+VALUE
rhash_has_key(VALUE hash, SEL sel, VALUE key)
{
return st_lookup(RHASH(hash)->tbl, key, 0) ? Qtrue : Qfalse;
}
-VALUE
-rb_hash_has_key(VALUE hash, VALUE key)
-{
- if (IS_RHASH(hash)) {
- return rhash_has_key(hash, 0, key);
- }
- else {
- return CFDictionaryContainsKey((CFDictionaryRef)hash,
- (const void *)RB2OC(key)) ? Qtrue : Qfalse;
- }
-}
-
/*
* call-seq:
* hsh.has_value?(value) => true or false
Added: MacRuby/trunk/hash.h
===================================================================
--- MacRuby/trunk/hash.h (rev 0)
+++ MacRuby/trunk/hash.h 2010-02-07 04:51:44 UTC (rev 3438)
@@ -0,0 +1,96 @@
+/*
+ * MacRuby Hash.
+ *
+ * Copyright (C) 2010, Apple Inc. All rights reserved.
+ */
+
+#ifndef __HASH_H_
+#define __HASH_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct {
+ struct RBasic basic;
+ st_table *tbl;
+ VALUE ifnone;
+ bool has_proc_default;
+} rb_hash_t;
+
+#define RHASH(x) ((rb_hash_t *)x)
+
+static inline bool
+rb_klass_is_rhash(VALUE klass)
+{
+ do {
+ if (klass == rb_cRubyHash) {
+ return true;
+ }
+ if (klass == rb_cNSHash) {
+ return false;
+ }
+ klass = RCLASS_SUPER(klass);
+ }
+ while (klass != 0);
+ return false;
+}
+
+#define IS_RHASH(x) (rb_klass_is_rhash(*(VALUE *)x))
+
+static inline void
+rhash_modify(VALUE hash)
+{
+ const long mask = RBASIC(hash)->flags;
+ if ((mask & FL_FREEZE) == FL_FREEZE) {
+ rb_raise(rb_eRuntimeError, "can't modify frozen/immutable hash");
+ }
+ if ((mask & FL_TAINT) == FL_TAINT && rb_safe_level() >= 4) {
+ rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
+ }
+}
+
+static inline long
+rhash_len(VALUE hash)
+{
+ return RHASH(hash)->tbl->num_entries;
+}
+
+static inline void
+rhash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
+{
+ st_foreach_safe(RHASH(hash)->tbl, func, (st_data_t)farg);
+}
+
+static inline VALUE
+rhash_lookup(VALUE hash, VALUE key)
+{
+ VALUE val;
+ if (st_lookup(RHASH(hash)->tbl, key, &val)) {
+ return val;
+ }
+ return Qundef;
+}
+
+static inline VALUE
+rhash_delete_key(VALUE hash, VALUE key)
+{
+ VALUE val;
+ if (st_delete(RHASH(hash)->tbl, &key, &val)) {
+ return val;
+ }
+ return Qundef;
+}
+
+VALUE rhash_dup(VALUE rcv, SEL sel);
+VALUE rhash_aref(VALUE hash, SEL sel, VALUE key);
+VALUE rhash_aset(VALUE hash, SEL sel, VALUE key, VALUE val);
+VALUE rhash_keys(VALUE hash, SEL sel);
+VALUE rhash_has_key(VALUE hash, SEL sel, VALUE key);
+VALUE rhash_set_default(VALUE hash, SEL sel, VALUE ifnone);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif // __HASH_H_
Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/include/ruby/intern.h 2010-02-07 04:51:44 UTC (rev 3438)
@@ -53,7 +53,6 @@
void rb_ary_store(VALUE, long, VALUE);
VALUE rb_ary_dup(VALUE);
VALUE rb_ary_to_ary(VALUE);
-VALUE rb_ary_to_s(VALUE);
VALUE rb_ary_push(VALUE, VALUE);
VALUE rb_ary_pop(VALUE);
VALUE rb_ary_shift(VALUE);
Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/include/ruby/ruby.h 2010-02-07 04:51:44 UTC (rev 3438)
@@ -1134,7 +1134,6 @@
RUBY_EXTERN VALUE rb_cCFString;
RUBY_EXTERN VALUE rb_cNSString;
RUBY_EXTERN VALUE rb_cNSMutableString;
-RUBY_EXTERN VALUE rb_cCFArray;
RUBY_EXTERN VALUE rb_cNSArray;
RUBY_EXTERN VALUE rb_cNSMutableArray;
RUBY_EXTERN VALUE rb_cRubyArray;
Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/object.c 2010-02-07 04:51:44 UTC (rev 3438)
@@ -21,6 +21,8 @@
#include <float.h>
#include "objc.h"
#include "vm.h"
+#include "array.h"
+#include "hash.h"
VALUE rb_cBasicObject;
VALUE rb_mKernel;
@@ -797,9 +799,6 @@
* Returns <code>true</code> if the object is tainted.
*/
-bool rb_klass_is_rary(VALUE klass);
-bool rb_klass_is_rhash(VALUE klass);
-
static VALUE
rb_obj_tainted_p(VALUE obj, SEL sel)
{
Modified: MacRuby/trunk/rakelib/builder/builder.rb
===================================================================
--- MacRuby/trunk/rakelib/builder/builder.rb 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/rakelib/builder/builder.rb 2010-02-07 04:51:44 UTC (rev 3438)
@@ -11,7 +11,7 @@
ruby signal sprintf st string struct time transcode util variable version
thread id objc bs encoding main dln dmyext marshal gcd
vm_eval prelude miniprelude gc-stub bridgesupport compiler dispatcher vm
- debugger MacRuby MacRubyDebuggerConnector NSDictionary
+ debugger MacRuby MacRubyDebuggerConnector NSArray NSDictionary
}
EXTENSIONS = %w{
Modified: MacRuby/trunk/range.c
===================================================================
--- MacRuby/trunk/range.c 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/range.c 2010-02-07 04:51:44 UTC (rev 3438)
@@ -14,6 +14,7 @@
#include "ruby/node.h"
#include "vm.h"
#include "id.h"
+#include "array.h"
VALUE rb_cRange;
static SEL selUpto, selBeg, selEnd, selExcludeEnd, selInclude;
@@ -531,10 +532,10 @@
static VALUE
range_last(VALUE range, SEL sel, int argc, VALUE *argv)
{
- VALUE rb_ary_last(int, VALUE *, VALUE);
-
- if (argc == 0) return RANGE_END(range);
- return rb_ary_last(argc, argv, rb_Array(range));
+ if (argc == 0) {
+ return RANGE_END(range);
+ }
+ return rary_last(rb_Array(range), 0, argc, argv);
}
Modified: MacRuby/trunk/re.c
===================================================================
--- MacRuby/trunk/re.c 2010-02-06 01:19:30 UTC (rev 3437)
+++ MacRuby/trunk/re.c 2010-02-07 04:51:44 UTC (rev 3438)
@@ -1908,7 +1908,6 @@
}
}
- extern VALUE rb_ary_aref(VALUE recv, SEL sel, int argc, VALUE *argv);
return rb_ary_aref(match_to_a(match, 0), 0, argc, argv);
}
Added: MacRuby/trunk/spec/macruby/tags/macruby/core/array_tags.txt
===================================================================
--- MacRuby/trunk/spec/macruby/tags/macruby/core/array_tags.txt (rev 0)
+++ MacRuby/trunk/spec/macruby/tags/macruby/core/array_tags.txt 2010-02-07 04:51:44 UTC (rev 3438)
@@ -0,0 +1 @@
+fails:An NSArray object is immutable
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100206/eadfa696/attachment-0001.html>
More information about the macruby-changes
mailing list