/*
* call-seq:
* array.fill(obj) -> array
* array.fill(obj, start [, length]) -> array
* array.fill(obj, range ) -> array
* array.fill {|index| block } -> array
* array.fill(start [, length] ) {|index| block } -> array
* array.fill(range) {|index| block } -> array
*
* The first three forms set the selected elements of <i>self</i> (which
* may be the entire array) to <i>obj</i>. A <i>start</i> of
* <code>nil</code> is equivalent to zero. A <i>length</i> of
* <code>nil</code> is equivalent to <i>self.length</i>. The last three
* forms fill the array with the value of the block. The block is
* passed the absolute index of each element to be filled.
*
* a = [ "a", "b", "c", "d" ]
* a.fill("x")
* a.fill("z", 2, 2)
* a.fill("y", 0..1)
* a.fill {|i| i*i}
* a.fill(-2) {|i| i*i*i}
*/
static VALUE
rb_ary_fill(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
VALUE item, arg1, arg2;
long beg = 0, end = 0, len = 0;
VALUE *p, *pend;
int block_p = Qfalse;
if (rb_block_given_p()) {
block_p = Qtrue;
rb_scan_args(argc, argv, "02", &arg1, &arg2);
argc += 1; /* hackish */
}
else {
rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
}
switch (argc) {
case 1:
beg = 0;
len = RARRAY(ary)->len;
break;
case 2:
if (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 1)) {
break;
}
/* fall through */
case 3:
beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
if (beg < 0) {
beg = RARRAY(ary)->len + beg;
if (beg < 0) beg = 0;
}
len = NIL_P(arg2) ? RARRAY(ary)->len - beg : NUM2LONG(arg2);
break;
}
rb_ary_modify(ary);
if (len < 0) {
return ary;
}
if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
rb_raise(rb_eArgError, "argument too big");
}
end = beg + len;
if (end > RARRAY(ary)->len) {
if (end >= RARRAY(ary)->aux.capa) {
REALLOC_N(RARRAY(ary)->ptr, VALUE, end);
RARRAY(ary)->aux.capa = end;
}
rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len, end - RARRAY(ary)->len);
RARRAY(ary)->len = end;
}
if (block_p) {
VALUE v;
long i;
for (i=beg; i<end; i++) {
v = rb_yield(LONG2NUM(i));
if (i>=RARRAY(ary)->len) break;
RARRAY(ary)->ptr[i] = v;
}
}
else {
p = RARRAY(ary)->ptr + beg;
pend = p + len;
while (p < pend) {
*p++ = item;
}
}
return ary;
}