Index: src/OFIntrospection.m ================================================================== --- src/OFIntrospection.m +++ src/OFIntrospection.m @@ -146,21 +146,21 @@ classMethods = [[OFMutableArray alloc] init]; instanceMethods = [[OFMutableArray alloc] init]; for (methodList = class->class_pointer->methods; methodList != NULL; methodList = methodList->method_next) { - size_t i; + int i; for (i = 0; i < methodList->method_count; i++) [classMethods addObject: [[[OFMethod alloc] _initWithMethod: &methodList->method_list[i]] autorelease]]; } for (methodList = class->methods; methodList != NULL; methodList = methodList->method_next) { - size_t i; + int i; for (i = 0; i < methodList->method_count; i++) [instanceMethods addObject: [[[OFMethod alloc] _initWithMethod: &methodList->method_list[i]] autorelease]]; Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -25,13 +25,10 @@ #include #include #import "OFObject.h" -#import "OFArray.h" -#import "OFSet.h" -#import "OFIntrospection.h" #import "OFAutoreleasePool.h" #import "OFAllocFailedException.h" #import "OFEnumerationMutationException.h" #import "OFInitializationFailedException.h" @@ -585,85 +582,147 @@ #endif } + (void)inheritMethodsFromClass: (Class)class { - OFAutoreleasePool *pool; - OFMutableSet *classMethods, *instanceMethods; - OFIntrospection *introspection; - OFMethod **cArray; - size_t i, count; + Class superclass = [self superclass]; if ([self isSubclassOfClass: class]) return; - pool = [[OFAutoreleasePool alloc] init]; - - classMethods = [OFMutableSet set]; - instanceMethods = [OFMutableSet set]; - - introspection = [OFIntrospection introspectionWithClass: self]; - - cArray = [[introspection classMethods] cArray]; - count = [[introspection classMethods] count]; - - for (i = 0; i < count; i++) - [classMethods addObject: [cArray[i] name]]; - - cArray = [[introspection instanceMethods] cArray]; - count = [[introspection instanceMethods] count]; - - for (i = 0; i < count; i++) - [instanceMethods addObject: [cArray[i] name]]; - - introspection = [OFIntrospection introspectionWithClass: class]; - - cArray = [[introspection classMethods] cArray]; - count = [[introspection classMethods] count]; - - for (i = 0; i < count; i++) { - SEL selector; - IMP implementation; - - if ([classMethods containsObject: [cArray[i] name]]) - continue; - - selector = [cArray[i] selector]; - implementation = [class methodForSelector: selector]; - - if ([self respondsToSelector: selector]) - [self setImplementation: implementation - forClassMethod: selector]; - else - [self addClassMethod: selector - withTypeEncoding: [cArray[i] typeEncoding] - implementation: implementation]; - } - - cArray = [[introspection instanceMethods] cArray]; - count = [[introspection instanceMethods] count]; - - for (i = 0; i < count; i++) { - SEL selector; - IMP implementation; - - if ([instanceMethods containsObject: [cArray[i] name]]) - continue; - - selector = [cArray[i] selector]; - implementation = [class instanceMethodForSelector: selector]; - - if ([self instancesRespondToSelector: selector]) - [self setImplementation: implementation - forInstanceMethod: selector]; - else - [self addInstanceMethod: selector - withTypeEncoding: [cArray[i] typeEncoding] - implementation: implementation]; - } - - [pool release]; +#if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) + Method *methodList; + unsigned i, count; + + 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]; + } + } + } @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]; + } + } + } @finally { + free(methodList); + } +#elif defined(OF_OLD_GNU_RUNTIME) + MethodList_t methodList; + + for (methodList = class->class_pointer->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 + forClassMethod: selector]; + else { + const char *typeEncoding = + methodList->method_list[i].method_types; + [self addClassMethod: selector + withTypeEncoding: typeEncoding + implementation: implementation]; + } + } + } + + 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]; + } + } + } +#else + @throw [OFNotImplementedException newWithClass: self + selector: _cmd]; +#endif [self inheritMethodsFromClass: [class superclass]]; } - init