This is a multi-part message in MIME format. --------------020509020403000302000408 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit 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 ; /* default */ > >> + VALUE left ry_shared_array(rb_cArray, ary); >> + VALUE right ry_shared_array(rb_cArray, ary); > > These need C99. you mean, declare them at the top of the function? okay. > >> + RARRAY(left)->len os; >> + RARRAY(right)->ptr + os + len; >> + RARRAY(right)->len + ARRAY_LEN(ary) - (pos + len); > > The last assignment shouldn't be: > + RARRAY(right)->len - os + len; > or > + RARRAY(right)->len ARRAY_LEN(ary) - (pos + len); > ? > I found another bug and rewrote this section. thank you. the tests should now run for real. [murphy] --------------020509020403000302000408 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name rray_split_at_draft_2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename rray_split_at_draft_2.diff" 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 ; /* default */ + + switch (argc) { + case 2: + len UM2LONG(argv[1]); + /* fall through */ + case 1: + pos UM2LONG(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 + ARRAY_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 ; + } + + left ry_shared_array(rb_cArray, ary); + RARRAY(left)->len os; + + /* pos+len out of bounds? */ + if (pos + len > RARRAY_LEN(ary)) { + return rb_assoc_new(left, rb_ary_new2(0)); + } + + right ry_shared_array(rb_cArray, ary); + RARRAY(right)->ptr + os + len; + RARRAY(right)->len - os + len; + + return rb_assoc_new(left, right); +} + /* * call-seq: * array.first -> obj or nil @@ -2557,7 +2626,7 @@ hash ry_make_hash(ary2, 0); if (RHASH_EMPTY_P(hash)) - return ary3; + return ary3; for (i i<RARRAY_LEN(ary1); i++) { v v b_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); --------------020509020403000302000408--