@@ -365,172 +365,66 @@ + (OFString*)description { return [self className]; } -+ (IMP)setImplementation: (IMP)newImp - forClassMethod: (SEL)selector -{ -#if defined(OF_OBJFW_RUNTIME) - if (newImp == (IMP)0 || !class_respondsToSelector(self->isa, selector)) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - return objc_replace_class_method(self, selector, newImp); -#elif defined(OF_OLD_GNU_RUNTIME) - Method_t method; - MethodList_t iter; - - method = class_get_class_method(self->class_pointer, selector); - - if (newImp == (IMP)0 || method == METHOD_NULL) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - for (iter = ((Class)self->class_pointer)->methods; iter != NULL; - iter = iter->method_next) { - int i; - - for (i = 0; i < iter->method_count; i++) - if (sel_eq(iter->method_list[i].method_name, - selector)) { - IMP oldImp; - - oldImp = iter->method_list[i].method_imp; - iter->method_list[i].method_imp = newImp; - - __objc_update_dispatch_table_for_class( - (Class)self->class_pointer); - - return oldImp; - } - } - - assert([self addClassMethod: selector - withTypeEncoding: method->method_types - implementation: newImp]); - - return (IMP)0; -#else - Method method; - - if (newImp == (IMP)0 || - (method = class_getClassMethod(self, selector)) == NULL) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - /* - * Cast needed because it's isa in the Apple runtime, but class_pointer - * in the GNU runtime. - */ - return class_replaceMethod(((OFObject*)self)->isa, selector, newImp, - method_getTypeEncoding(method)); -#endif -} - + (IMP)replaceClassMethod: (SEL)selector withMethodFromClass: (Class)class { IMP newImp; - - if (![class isSubclassOfClass: self]) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; + const char *typeEncoding; newImp = [class methodForSelector: selector]; - - return [self setImplementation: newImp - forClassMethod: selector]; -} - -+ (IMP)setImplementation: (IMP)newImp - forInstanceMethod: (SEL)selector -{ -#if defined(OF_OBJFW_RUNTIME) - if (newImp == (IMP)0 || !class_respondsToSelector(self, selector)) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - return objc_replace_instance_method(self, selector, newImp); -#elif defined(OF_OLD_GNU_RUNTIME) - Method_t method; - MethodList_t iter; - - method = class_get_instance_method(self, selector); - - if (newImp == (IMP)0 || method == METHOD_NULL) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - for (iter = ((Class)self)->methods; iter != NULL; - iter = iter->method_next) { - int i; - - for (i = 0; i < iter->method_count; i++) - if (sel_eq(iter->method_list[i].method_name, - selector)) { - IMP oldImp; - - oldImp = iter->method_list[i].method_imp; - iter->method_list[i].method_imp = newImp; - - __objc_update_dispatch_table_for_class(self); - - return oldImp; - } - } - - assert([self addInstanceMethod: selector - withTypeEncoding: method->method_types - implementation: newImp]); - - return (IMP)0; -#else - Method method; - - if (newImp == (IMP)0 || - (method = class_getInstanceMethod(self, selector)) == NULL) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - return class_replaceMethod(self, selector, newImp, - method_getTypeEncoding(method)); -#endif + typeEncoding = [class typeEncodingForSelector: selector]; + + return [self replaceClassMethod: selector + withImplementation: newImp + typeEncoding: typeEncoding]; } + (IMP)replaceInstanceMethod: (SEL)selector withMethodFromClass: (Class)class { IMP newImp; - - if (![class isSubclassOfClass: self]) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; + const char *typeEncoding; newImp = [class instanceMethodForSelector: selector]; + typeEncoding = [class typeEncodingForInstanceSelector: selector]; - return [self setImplementation: newImp - forInstanceMethod: selector]; + return [self replaceInstanceMethod: selector + withImplementation: newImp + typeEncoding: typeEncoding]; } -+ (BOOL)addInstanceMethod: (SEL)selector - withTypeEncoding: (const char*)typeEncoding - implementation: (IMP)implementation ++ (IMP)replaceInstanceMethod: (SEL)selector + withImplementation: (IMP)implementation + typeEncoding: (const char*)typeEncoding { #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) - return class_addMethod(self, selector, implementation, typeEncoding); + return class_replaceMethod(self, selector, implementation, + typeEncoding); #elif defined(OF_OLD_GNU_RUNTIME) MethodList_t methodList; for (methodList = ((Class)self)->methods; methodList != NULL; methodList = methodList->method_next) { int i; - for (i = 0; i < methodList->method_count; i++) + for (i = 0; i < methodList->method_count; i++) { if (sel_eq(methodList->method_list[i].method_name, - selector)) - return NO; + selector)) { + IMP oldImp; + oldImp = methodList->method_list[i].method_imp; + + methodList->method_list[i].method_imp = + implementation; + + __objc_update_dispatch_table_for_class(self); + + return oldImp; + } + } } if ((methodList = malloc(sizeof(*methodList))) == NULL) @throw [OFOutOfMemoryException exceptionWithClass: self @@ -545,35 +439,46 @@ ((Class)self)->methods = methodList; __objc_update_dispatch_table_for_class(self); - return YES; + return (IMP)nil; #else @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; #endif } -+ (BOOL)addClassMethod: (SEL)selector - withTypeEncoding: (const char*)typeEncoding - implementation: (IMP)implementation ++ (IMP)replaceClassMethod: (SEL)selector + withImplementation: (IMP)implementation + typeEncoding: (const char*)typeEncoding { #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) - return class_addMethod(((OFObject*)self)->isa, selector, implementation, - typeEncoding); + return class_replaceMethod(((OFObject*)self)->isa, selector, + implementation, typeEncoding); #elif defined(OF_OLD_GNU_RUNTIME) MethodList_t methodList; for (methodList = ((Class)self->class_pointer)->methods; methodList != NULL; methodList = methodList->method_next) { int i; - for (i = 0; i < methodList->method_count; i++) + for (i = 0; i < methodList->method_count; i++) { if (sel_eq(methodList->method_list[i].method_name, - selector)) - return NO; + selector)) { + IMP oldImp; + oldImp = methodList->method_list[i].method_imp; + + methodList->method_list[i].method_imp = + implementation; + + __objc_update_dispatch_table_for_class( + (Class)self->class_pointer); + + return oldImp; + } + } } if ((methodList = malloc(sizeof(*methodList))) == NULL) @throw [OFOutOfMemoryException exceptionWithClass: self @@ -588,11 +493,11 @@ ((Class)self->class_pointer)->methods = methodList; __objc_update_dispatch_table_for_class((Class)self->class_pointer); - return YES; + return (IMP)nil; #else @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; #endif } @@ -610,62 +515,39 @@ methodList = class_copyMethodList(((OFObject*)class)->isa, &count); @try { for (i = 0; i < count; i++) { SEL selector = method_getName(methodList[i]); - IMP implementation; /* * Don't replace methods implemented in receiving class. */ if ([self methodForSelector: selector] != [superclass methodForSelector: selector]) continue; - implementation = [class methodForSelector: selector]; - - if ([self respondsToSelector: selector]) - [self setImplementation: implementation - forClassMethod: selector]; - else { - const char *typeEncoding = - method_getTypeEncoding(methodList[i]); - [self addClassMethod: selector - withTypeEncoding: typeEncoding - implementation: implementation]; - } + [self replaceClassMethod: selector + withMethodFromClass: class]; } } @finally { free(methodList); } methodList = class_copyMethodList(class, &count); @try { for (i = 0; i < count; i++) { SEL selector = method_getName(methodList[i]); - IMP implementation; /* * Don't replace methods implemented in receiving class. */ if ([self instanceMethodForSelector: selector] != [superclass instanceMethodForSelector: selector]) continue; - implementation = - [class instanceMethodForSelector: selector]; - - if ([self instancesRespondToSelector: selector]) - [self setImplementation: implementation - forInstanceMethod: selector]; - else { - const char *typeEncoding = - method_getTypeEncoding(methodList[i]); - [self addInstanceMethod: selector - withTypeEncoding: typeEncoding - implementation: implementation]; - } + [self replaceInstanceMethod: selector + withMethodFromClass: class]; } } @finally { free(methodList); } #elif defined(OF_OLD_GNU_RUNTIME) @@ -675,62 +557,39 @@ methodList != NULL; methodList = methodList->method_next) { int i; for (i = 0; i < methodList->method_count; i++) { SEL selector = methodList->method_list[i].method_name; - IMP implementation; /* * Don't replace methods implemented in receiving class. */ if ([self methodForSelector: selector] != [superclass methodForSelector: selector]) continue; - implementation = [class methodForSelector: selector]; - - if ([self respondsToSelector: selector]) - [self setImplementation: implementation - forClassMethod: selector]; - else { - const char *typeEncoding = - methodList->method_list[i].method_types; - [self addClassMethod: selector - withTypeEncoding: typeEncoding - implementation: implementation]; - } + [self replaceClassMethod: selector + withMethodFromClass: class]; } } for (methodList = class->methods; methodList != NULL; methodList = methodList->method_next) { int i; for (i = 0; i < methodList->method_count; i++) { SEL selector = methodList->method_list[i].method_name; - IMP implementation; /* * Don't replace methods implemented in receiving class. */ if ([self instanceMethodForSelector: selector] != [superclass instanceMethodForSelector: selector]) continue; - implementation = - [class instanceMethodForSelector: selector]; - - if ([self instancesRespondToSelector: selector]) - [self setImplementation: implementation - forInstanceMethod: selector]; - else { - const char *typeEncoding = - methodList->method_list[i].method_types; - [self addInstanceMethod: selector - withTypeEncoding: typeEncoding - implementation: implementation]; - } + [self replaceInstanceMethod: selector + withMethodFromClass: class]; } } #else @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd];