Index: src/OFIntrospection.h ================================================================== --- src/OFIntrospection.h +++ src/OFIntrospection.h @@ -56,22 +56,62 @@ * \return The type encoding for the method */ - (const char*)typeEncoding; @end +/** + * \brief A class for describing an instance variable. + */ +@interface OFInstanceVariable: OFObject +{ + OFString *name; + ptrdiff_t offset; + const char *typeEncoding; +} + +#ifdef OF_HAVE_PROPERTIES +@property (readonly, copy) OFString *name; +@property (readonly) ptrdiff_t offset; +@property (readonly) const char *typeEncoding; +#endif + +/** + * \brief Returns the name of the instance variable. + * + * \return The name of the instance variable + */ +- (OFString*)name; + +/** + * \brief Returns the offset of the instance variable. + * + * \return The offset of the instance variable + */ +- (ptrdiff_t)offset; + +/** + * \brief Returns the type encoding for the instance variable. + * + * \return The type encoding for the instance variable + */ +- (const char*)typeEncoding; +@end + /** * \brief A class for introspecting classes. */ @interface OFIntrospection: OFObject { OFMutableArray *classMethods; OFMutableArray *instanceMethods; + OFMutableArray *instanceVariables; } #ifdef OF_HAVE_PROPERTIES @property (readonly, copy) OFArray *classMethods; @property (readonly, copy) OFArray *instanceMethods; +@property (readonly, copy) OFArray *instanceVariables; #endif /** * \brief Creates a new introspection for the specified class. * @@ -88,18 +128,25 @@ - initWithClass: (Class)class_; /** * \brief Returns the class methods of the class. * - * \return The class methods of the class + * \return An array of OFMethods */ - (OFArray*)classMethods; /** * \brief Returns the instance methods of the class. * - * \return The instance methods of the class + * \return An array of OFMethods */ - (OFArray*)instanceMethods; -/* TODO: ivars, properties */ +/** + * \brief Returns the instance variables of the class. + * + * \return An array of OFInstanceVariables + */ +- (OFArray*)instanceVariables; + +/* TODO: properties, protocols */ @end Index: src/OFIntrospection.m ================================================================== --- src/OFIntrospection.m +++ src/OFIntrospection.m @@ -96,10 +96,61 @@ { return [OFString stringWithFormat: @"", name, typeEncoding]; } @end + +@implementation OFInstanceVariable +#if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) +- _initWithIvar: (Ivar)ivar +{ + self = [super init]; + + @try { + name = [[OFString alloc] + initWithCString: ivar_getName(ivar) + encoding: OF_STRING_ENCODING_ASCII]; + offset = ivar_getOffset(ivar); + typeEncoding = ivar_getTypeEncoding(ivar); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} +#endif + +- (void)dealloc +{ + [name release]; + + [super dealloc]; +} + +- (OFString*)name +{ + OF_GETTER(name, YES); +} + +- (ptrdiff_t)offset +{ + return offset; +} + +- (const char*)typeEncoding +{ + return typeEncoding; +} + +- (OFString*)description +{ + return [OFString stringWithFormat: + @"", + name, typeEncoding, offset]; +} +@end @implementation OFIntrospection + introspectionWithClass: (Class)class { return [[[self alloc] initWithClass: class] autorelease]; @@ -111,15 +162,21 @@ @try { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) Method *methodList; + Ivar *ivarList; unsigned i, count; +#elif defined(OF_OLD_GNU_RUNTIME) + MethodList_t methodList; +#endif classMethods = [[OFMutableArray alloc] init]; instanceMethods = [[OFMutableArray alloc] init]; + instanceVariables = [[OFMutableArray alloc] init]; +#if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) methodList = class_copyMethodList(((OFObject*)class)->isa, &count); @try { for (i = 0; i < count; i++) { [classMethods addObject: [[[OFMethod alloc] @@ -140,16 +197,23 @@ [pool releaseObjects]; } } @finally { free(methodList); } -#elif defined(OF_OLD_GNU_RUNTIME) - MethodList_t methodList; - classMethods = [[OFMutableArray alloc] init]; - instanceMethods = [[OFMutableArray alloc] init]; - + ivarList = class_copyIvarList(class, &count); + @try { + for (i = 0; i < count; i++) { + [instanceVariables addObject: + [[[OFInstanceVariable alloc] + _initWithIvar: ivarList[i]] autorelease]]; + [pool releaseObjects]; + } + } @finally { + free(ivarList); + } +#elif defined(OF_OLD_GNU_RUNTIME) for (methodList = class->class_pointer->methods; methodList != NULL; methodList = methodList->method_next) { int i; for (i = 0; i < methodList->method_count; i++) @@ -169,10 +233,11 @@ } #endif [classMethods makeImmutable]; [instanceMethods makeImmutable]; + [instanceVariables makeImmutable]; [pool release]; } @catch (id e) { [self release]; @throw e; @@ -183,10 +248,11 @@ - (void)dealloc { [classMethods release]; [instanceMethods release]; + [instanceVariables release]; [super dealloc]; } - (OFArray*)classMethods @@ -196,6 +262,11 @@ - (OFArray*)instanceMethods { OF_GETTER(instanceMethods, YES) } + +- (OFArray*)instanceVariables +{ + OF_GETTER(instanceVariables, YES) +} @end