Nobuyoshi Nakada wrote:
> At Fri, 16 Nov 2007 18:47:50 +0900,
> murphy wrote in [ruby-core:13597]:
>> +VALUE
>> +rb_ary_split_at(int argc, VALUE *argv, VALUE ary)
>> +{
>> + return Qnil;
>
> What's this?
debugging artifacts, makes me look stupid. I misinterpreted the output
of "make test". sorry.
>> + long pos, len;
>> + len = 1; /* default */
>
>> + VALUE left = ary_shared_array(rb_cArray, ary);
>> + VALUE right = ary_shared_array(rb_cArray, ary);
>
> These need C99.
you mean, declare them at the top of the function? okay.
>
>> + RARRAY(left)->len = pos;
>> + RARRAY(right)->ptr += pos + len;
>> + RARRAY(right)->len += RARRAY_LEN(ary) - (pos + len);
>
> The last assignment shouldn't be:
> + RARRAY(right)->len -= pos + len;
> or
> + RARRAY(right)->len = RARRAY_LEN(ary) - (pos + len);
> ?
>
I found another bug and rewrote this section. thank you.
the tests should now run for real.
[murphy]
Index: array.c
===================================================================
--- array.c (revision 13948)
+++ array.c (working copy)
@@ -781,6 +781,75 @@
return rb_ary_entry(ary, NUM2LONG(pos));
}
+/*
+ * call-seq:
+ * array.split_at(index) -> [left_array, right_array]
+ * array.split_at(start, length) -> [left_array, right_array]
+ *
+ * Splits an array into two parts, with the first one containing
+ * all elements before the given range, and the second one containing
+ * all elements after it.
+ *
+ * a = [ "a", "b", "c", "d", "e" ]
+ * a.split_at(0) #=> [[], ["b", "c", "d", "e"]]
+ * a.split_at(2) #=> [["a", "b"], ["d", "e"]]
+ * a.split_at(-1) #=> [["a", "b", "c", "d"], []]
+ * a.split_at(1, 2) #=> [["a"], ["d", "e"]]
+ * a.split_at(1, 0) #=> [["a"], ["b", "c", "d", "e"]]
+ *
+ */
+
+VALUE
+rb_ary_split_at(int argc, VALUE *argv, VALUE ary)
+{
+ long pos, len;
+ VALUE left, right;
+ len = 1; /* default */
+
+ switch (argc) {
+ case 2:
+ len = NUM2LONG(argv[1]);
+ /* fall through */
+ case 1:
+ pos = NUM2LONG(argv[0]);
+ break;
+ default:
+ rb_scan_args(argc, argv, "11", 0, 0);
+ }
+
+ if (RARRAY_LEN(ary) == 0) {
+ return rb_assoc_new(rb_ary_new2(0), rb_ary_new2(0));
+ }
+
+ if (pos < 0) {
+ pos += RARRAY_LEN(ary);
+ }
+
+ /* pos out of bounds? */
+ if (pos < 0) {
+ return rb_assoc_new(rb_ary_new2(0), ary_shared_array(rb_cArray, ary));
+ }
+
+ /* Array#slice doesn't fail on negative lengths, so we copy */
+ if (len < 0) {
+ len = 0;
+ }
+
+ left = ary_shared_array(rb_cArray, ary);
+ RARRAY(left)->len = pos;
+
+ /* pos+len out of bounds? */
+ if (pos + len > RARRAY_LEN(ary)) {
+ return rb_assoc_new(left, rb_ary_new2(0));
+ }
+
+ right = ary_shared_array(rb_cArray, ary);
+ RARRAY(right)->ptr += pos + len;
+ RARRAY(right)->len -= pos + len;
+
+ return rb_assoc_new(left, right);
+}
+
/*
* call-seq:
* array.first -> obj or nil
@@ -2557,7 +2626,7 @@
hash = ary_make_hash(ary2, 0);
if (RHASH_EMPTY_P(hash))
- return ary3;
+ return ary3;
for (i=0; i<RARRAY_LEN(ary1); i++) {
v = vv = rb_ary_elt(ary1, i);
@@ -3288,6 +3357,7 @@
rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
+ rb_define_method(rb_cArray, "split_at", rb_ary_split_at, -1);
rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);