object.c: rb_class_search_ancestor

* object.c (rb_class_search_ancestor): return ancestor class or
  iclass if inherited.

* object.c (rb_obj_is_kind_of, rb_class_inherited_p): share
  function to search the ancestor.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45584 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2014-04-14 07:59:42 +00:00
parent c3b82fc66e
commit c2a7a091cc
2 changed files with 26 additions and 15 deletions

View File

@ -715,6 +715,7 @@ rb_float_new_inline(double d)
/* object.c */ /* object.c */
VALUE rb_obj_equal(VALUE obj1, VALUE obj2); VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
struct RBasicRaw { struct RBasicRaw {
VALUE flags; VALUE flags;

View File

@ -587,6 +587,8 @@ class_or_module_required(VALUE c)
return c; return c;
} }
static VALUE class_search_ancestor(VALUE cl, VALUE c);
/* /*
* call-seq: * call-seq:
* obj.instance_of?(class) -> true or false * obj.instance_of?(class) -> true or false
@ -647,15 +649,27 @@ rb_obj_is_kind_of(VALUE obj, VALUE c)
VALUE cl = CLASS_OF(obj); VALUE cl = CLASS_OF(obj);
c = class_or_module_required(c); c = class_or_module_required(c);
c = RCLASS_ORIGIN(c); return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : Qfalse;
while (cl) {
if (cl == c || RCLASS_M_TBL_WRAPPER(cl) == RCLASS_M_TBL_WRAPPER(c))
return Qtrue;
cl = RCLASS_SUPER(cl);
}
return Qfalse;
} }
static VALUE
class_search_ancestor(VALUE cl, VALUE c)
{
while (cl) {
if (cl == c || RCLASS_M_TBL_WRAPPER(cl) == RCLASS_M_TBL_WRAPPER(c))
return cl;
cl = RCLASS_SUPER(cl);
}
return 0;
}
VALUE
rb_class_search_ancestor(VALUE cl, VALUE c)
{
cl = class_or_module_required(cl);
c = class_or_module_required(c);
return class_search_ancestor(cl, RCLASS_ORIGIN(c));
}
/* /*
* call-seq: * call-seq:
@ -1554,16 +1568,12 @@ rb_class_inherited_p(VALUE mod, VALUE arg)
rb_raise(rb_eTypeError, "compared with non class/module"); rb_raise(rb_eTypeError, "compared with non class/module");
} }
arg = RCLASS_ORIGIN(arg); arg = RCLASS_ORIGIN(arg);
while (mod) { if (class_search_ancestor(mod, arg)) {
if (RCLASS_M_TBL_WRAPPER(mod) == RCLASS_M_TBL_WRAPPER(arg)) return Qtrue;
return Qtrue;
mod = RCLASS_SUPER(mod);
} }
/* not mod < arg; check if mod > arg */ /* not mod < arg; check if mod > arg */
while (arg) { if (class_search_ancestor(arg, start)) {
if (RCLASS_M_TBL_WRAPPER(arg) == RCLASS_M_TBL_WRAPPER(start)) return Qfalse;
return Qfalse;
arg = RCLASS_SUPER(arg);
} }
return Qnil; return Qnil;
} }