static VALUE method_eq(VALUE method, SEL sel, VALUE other) { rb_vm_method_t *m1, *m2; if (CLASS_OF(method) != CLASS_OF(other)) { return Qfalse; } Data_Get_Struct(method, rb_vm_method_t, m1); Data_Get_Struct(other, rb_vm_method_t, m2); if (m1->oclass != m2->oclass || m1->rclass != m2->rclass || m1->recv != m2->recv) { return Qfalse; } IMP m1_imp = m1->node == NULL ? class_getMethodImplementation((Class)m1->oclass, m1->sel) : m1->node->objc_imp; IMP m2_imp = m2->node == NULL ? class_getMethodImplementation((Class)m2->oclass, m2->sel) : m2->node->objc_imp; if (m1_imp != m2_imp) { return Qfalse; } return Qtrue; }
static inline bool sel_equal(Class klass, SEL x, SEL y) { if (x == y) { return true; } IMP x_imp = class_getMethodImplementation(klass, x); IMP y_imp = class_getMethodImplementation(klass, y); return x_imp == y_imp; }
static void * rb_obj_imp_description(void *rcv, SEL sel) { // If #description and #to_s are the same method (ex. when aliased) Class rcv_class = (Class)CLASS_OF(rcv); IMP desc_imp = class_getMethodImplementation(rcv_class, selDescription); IMP to_s_imp = class_getMethodImplementation(rcv_class, selToS); if (desc_imp == to_s_imp) { return (void *)rb_any_to_string((VALUE)rcv, sel); } return (void *)rb_vm_call(OC2RB(rcv), selToS, 0, NULL); }
/// @see http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html XAOriginImpType originImplementationType(Class cls, SEL selector) { Class superclass; if (!class_respondsToSelector(cls, selector)) { return XAOriginImpTypeNotExists; } else if ((superclass = class_getSuperclass(cls)) && (class_getMethodImplementation(cls, selector) == class_getMethodImplementation(superclass, selector))) { return XAOriginImpTypeExistsInSuperclass; } else { return XAOriginImpTypeExists; } }
void releaseNSObject(id a) { if (!impRelease) { selRelease = sel_registerName("release:"); impRelease = class_getMethodImplementation((Class)objc_getClass("NSObject"), selRelease); } impRelease(a, selRelease); }
void retainNSObject(id a) { if (!impRetain) { selRetain = sel_registerName("retain:"); impRetain = class_getMethodImplementation((Class)objc_getClass("NSObject"), selRetain); } impRetain(a, selRetain); }
void Init_eval_method(void) { rb_objc_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1); rb_objc_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2); selRespondToDefault = sel_registerName("respond_to_missing?:"); basic_respond_to_imp = class_getMethodImplementation((Class)rb_mKernel, selRespondTo); rb_objc_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1); rb_objc_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1); rb_objc_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2); rb_objc_define_private_method(rb_cModule, "public", rb_mod_public, -1); rb_objc_define_private_method(rb_cModule, "protected", rb_mod_protected, -1); rb_objc_define_private_method(rb_cModule, "private", rb_mod_private, -1); rb_objc_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1); rb_objc_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1); rb_objc_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1); rb_objc_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1); rb_objc_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1); rb_objc_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1); rb_objc_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1); VALUE cTopLevel = *(VALUE *)rb_vm_top_self(); rb_objc_define_method(cTopLevel, "public", top_public, -1); rb_objc_define_method(cTopLevel, "private", top_private, -1); object_id = rb_intern("object_id"); __send__ = rb_intern("__send__"); eqq = rb_intern("==="); each = rb_intern("each"); aref = rb_intern("[]"); aset = rb_intern("[]="); match = rb_intern("=~"); missing = rb_intern("method_missing"); added = rb_intern("method_added"); singleton_added = rb_intern("singleton_method_added"); removed = rb_intern("method_removed"); singleton_removed = rb_intern("singleton_method_removed"); undefined = rb_intern("method_undefined"); singleton_undefined = rb_intern("singleton_method_undefined"); }
bool RoxorCore::respond_to(VALUE obj, VALUE klass, SEL sel, bool priv, bool check_override) { if (klass == Qnil) { klass = CLASS_OF(obj); } else { assert(!check_override); } IMP imp = NULL; const bool overriden = check_override ? ((imp = class_getMethodImplementation((Class)klass, selRespondTo)) != basic_respond_to_imp) : false; if (!overriden) { lock(); const long key = respond_to_key((Class)klass, sel); std::map<long, int>::iterator iter = respond_to_cache.find(key); int iter_cached = (iter != respond_to_cache.end()); unlock(); int status; if (iter_cached) { status = iter->second; } else { Method m = class_getInstanceMethod((Class)klass, sel); if (m == NULL) { const char *selname = sel_getName(sel); sel = helper_sel(selname, strlen(selname)); if (sel != NULL) { m = class_getInstanceMethod((Class)klass, sel); } } IMP imp = method_getImplementation(m); if (UNAVAILABLE_IMP(imp) || imp == (IMP)rb_f_notimplement) { status = RESPOND_TO_NOT_EXIST; } else { rb_vm_method_node_t *node = method_node_get(m); if (node != NULL && (node->flags & VM_METHOD_PRIVATE)) { status = RESPOND_TO_PRIVATE; } else { status = RESPOND_TO_PUBLIC; } } lock(); respond_to_cache[key] = status; unlock(); } return status == RESPOND_TO_PUBLIC || (priv && status == RESPOND_TO_PRIVATE); } else { if (imp == NULL || imp == _objc_msgForward) { // The class does not respond to respond_to?:, it's probably // NSProxy-based. return false; } VALUE args[2]; int n = 0; args[n++] = ID2SYM(rb_intern(sel_getName(sel))); if (priv) { rb_vm_method_node_t *node = method_node_get(imp); if (node != NULL && (2 < node->arity.min || (node->arity.max != -1 && 2 > node->arity.max))) { // Do nothing, custom respond_to? method incompatible arity. } else { args[n++] = Qtrue; } } return rb_vm_call(obj, selRespondTo, n, args) == Qtrue; } }