/** rb_ary_fill
*
*/
@JRubyMethod(name = "fill", optional = 3, frame = true)
public IRubyObject fill(ThreadContext context, IRubyObject[] args, Block block) {
IRubyObject item = null;
IRubyObject begObj = null;
IRubyObject lenObj = null;
int argc = args.length;
if (block.isGiven()) {
Arity.checkArgumentCount(getRuntime(), args, 0, 2);
item = null;
begObj = argc > 0 ? args[0] : null;
lenObj = argc > 1 ? args[1] : null;
argc++;
} else {
Arity.checkArgumentCount(getRuntime(), args, 1, 3);
item = args[0];
begObj = argc > 1 ? args[1] : null;
lenObj = argc > 2 ? args[2] : null;
}
int beg = 0, end = 0, len = 0;
switch (argc) {
case 1:
beg = 0;
len = realLength;
break;
case 2:
if (begObj instanceof RubyRange) {
long[] beglen = ((RubyRange) begObj).begLen(realLength, 1);
beg = (int) beglen[0];
len = (int) beglen[1];
break;
}
/* fall through */
case 3:
beg = begObj.isNil() ? 0 : RubyNumeric.num2int(begObj);
if (beg < 0) {
beg = realLength + beg;
if (beg < 0) beg = 0;
}
len = (lenObj == null || lenObj.isNil()) ? realLength - beg : RubyNumeric.num2int(lenObj);
// TODO: In MRI 1.9, an explicit check for negative length is
// added here. IndexError is raised when length is negative.
// See [ruby-core:12953] for more details.
//
// New note: This is actually under re-evaluation,
// see [ruby-core:17483].
break;
}
modify();
// See [ruby-core:17483]
if (len < 0) {
return this;
}
if (len > Integer.MAX_VALUE - beg) {
throw getRuntime().newArgumentError("argument too big");
}
end = beg + len;
if (end > realLength) {
if (end >= values.length) realloc(end);
realLength = end;
}
if (block.isGiven()) {
Ruby runtime = getRuntime();
for (int i = beg; i < end; i++) {
IRubyObject v = block.yield(context, runtime.newFixnum(i));
if (i >= realLength) break;
try {
values[i] = v;
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification();