mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
array.c: implement Array#index and Array#rindex in C
No need to override Array#index in mruby-array-ext. We can call `to_enum` from C implemented methods.
This commit is contained in:
@@ -700,35 +700,6 @@ class Array
|
||||
self.replace(result)
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.index(val) -> int or nil
|
||||
# ary.index {|item| block } -> int or nil
|
||||
#
|
||||
# Returns the _index_ of the first object in +ary+ such that the object is
|
||||
# <code>==</code> to +obj+.
|
||||
#
|
||||
# If a block is given instead of an argument, returns the _index_ of the
|
||||
# first object for which the block returns +true+. Returns +nil+ if no
|
||||
# match is found.
|
||||
#
|
||||
# ISO 15.2.12.5.14
|
||||
def index(val=NONE, &block)
|
||||
return to_enum(:find_index, val) if !block && NONE.equal?(val)
|
||||
|
||||
if block
|
||||
idx = 0
|
||||
len = size
|
||||
while idx < len
|
||||
return idx if block.call self[idx]
|
||||
idx += 1
|
||||
end
|
||||
else
|
||||
return self.__ary_index(val)
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.dig(idx, ...) -> object
|
||||
|
||||
@@ -361,11 +361,6 @@ assert('Array#to_h') do
|
||||
assert_raise(ArgumentError) { [[1]].to_h }
|
||||
end
|
||||
|
||||
assert("Array#index (block)") do
|
||||
assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
||||
assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
||||
end
|
||||
|
||||
assert("Array#dig") do
|
||||
h = [[[1]], 0]
|
||||
assert_equal(1, h.dig(0, 0, 0))
|
||||
|
||||
+62
-10
@@ -1133,31 +1133,84 @@ mrb_ary_last(mrb_state *mrb, mrb_value self)
|
||||
return mrb_ary_new_from_values(mrb, size, ARY_PTR(a) + alen - size);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ary.index(val) -> int or nil
|
||||
* ary.index {|item| block } -> int or nil
|
||||
* array.index -> enumerator
|
||||
*
|
||||
* Returns the _index_ of the first object in +ary+ such that the object is
|
||||
* <code>==</code> to +obj+.
|
||||
*
|
||||
* If a block is given instead of an argument, returns the _index_ of the
|
||||
* first object for which the block returns +true+. Returns +nil+ if no
|
||||
* match is found.
|
||||
*
|
||||
* ISO 15.2.12.5.14
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
mrb_value obj, blk;
|
||||
|
||||
for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
|
||||
if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
|
||||
return mrb_int_value(mrb, i);
|
||||
if (mrb_get_args(mrb, "|o&", &obj, &blk) == 0 && mrb_nil_p(blk)) {
|
||||
return mrb_funcall_id(mrb, self, MRB_SYM(to_enum), 1, mrb_symbol_value(MRB_SYM(index)));
|
||||
}
|
||||
|
||||
if (mrb_nil_p(blk)) {
|
||||
for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
|
||||
if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
|
||||
return mrb_int_value(mrb, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
|
||||
mrb_value eq = mrb_funcall_id(mrb, blk, MRB_SYM(call), 1, RARRAY_PTR(self)[i]);
|
||||
if (mrb_test(eq)) {
|
||||
return mrb_int_value(mrb, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ary.rindex(val) -> int or nil
|
||||
* ary.rindex {|item| block } -> int or nil
|
||||
* array.rindex -> enumerator
|
||||
*
|
||||
* Returns the _index_ of the first object in +ary+ such that the object is
|
||||
* <code>==</code> to +obj+.
|
||||
*
|
||||
* If a block is given instead of an argument, returns the _index_ of the
|
||||
* first object for which the block returns +true+. Returns +nil+ if no
|
||||
* match is found.
|
||||
*
|
||||
* ISO 15.2.12.5.26
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
mrb_value obj, blk;
|
||||
|
||||
if (mrb_get_args(mrb, "|o&", &obj, &blk) == 0 && mrb_nil_p(blk)) {
|
||||
return mrb_funcall_id(mrb, self, MRB_SYM(to_enum), 1, mrb_symbol_value(MRB_SYM(rindex)));
|
||||
}
|
||||
|
||||
for (mrb_int i = RARRAY_LEN(self) - 1; i >= 0; i--) {
|
||||
mrb_int len;
|
||||
|
||||
if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
|
||||
if (mrb_nil_p(blk)) {
|
||||
if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
|
||||
return mrb_int_value(mrb, i);
|
||||
}
|
||||
}
|
||||
if (i > (len = RARRAY_LEN(self))) {
|
||||
else {
|
||||
mrb_value eq = mrb_funcall_id(mrb, blk, MRB_SYM(call), 1, RARRAY_PTR(self)[i]);
|
||||
if (mrb_test(eq)) return mrb_int_value(mrb, i);
|
||||
}
|
||||
mrb_int len = RARRAY_LEN(self);
|
||||
if (i > len) {
|
||||
i = len;
|
||||
}
|
||||
}
|
||||
@@ -1623,7 +1676,6 @@ mrb_init_array(mrb_state *mrb)
|
||||
mrb_define_method_id(mrb, a, MRB_SYM(inspect), mrb_ary_to_s, MRB_ARGS_NONE());
|
||||
mrb_define_method_id(mrb, a, MRB_SYM_B(sort), mrb_ary_sort_bang, MRB_ARGS_NONE());
|
||||
|
||||
mrb_define_method_id(mrb, a, MRB_SYM(__ary_index), mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */
|
||||
mrb_define_method_id(mrb, a, MRB_SYM(__delete), mrb_ary_delete, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, a, MRB_SYM(__svalue), mrb_ary_svalue, MRB_ARGS_NONE());
|
||||
}
|
||||
|
||||
@@ -189,6 +189,11 @@ assert('Array#index', '15.2.12.5.14') do
|
||||
assert_equal(nil, a.index(0))
|
||||
end
|
||||
|
||||
assert("Array#index (block)") do
|
||||
assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
||||
assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
||||
end
|
||||
|
||||
assert('Array#initialize', '15.2.12.5.15') do
|
||||
a = [].initialize(1)
|
||||
b = [].initialize(2)
|
||||
@@ -288,6 +293,11 @@ assert('Array#rindex', '15.2.12.5.26') do
|
||||
assert_equal(nil, a.rindex(0))
|
||||
end
|
||||
|
||||
assert("Array#rindex (block)") do
|
||||
assert_nil (1..10).to_a.rindex { |i| i % 5 == 0 and i % 7 == 0 }
|
||||
assert_equal 69, (1..100).to_a.rindex { |i| i % 5 == 0 and i % 7 == 0 }
|
||||
end
|
||||
|
||||
assert('Array#shift', '15.2.12.5.27') do
|
||||
a = [1,2,3]
|
||||
b = a.shift
|
||||
|
||||
Reference in New Issue
Block a user