Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -93,13 +93,13 @@ 4B29BC5C133AC8540004B236 /* OFRenameFileFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B29BC54133AC81B0004B236 /* OFRenameFileFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B29BC61133AC9CB0004B236 /* OFLinkFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B29BC5D133AC9C40004B236 /* OFLinkFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B29BC62133AC9CB0004B236 /* OFLinkFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B29BC5E133AC9C40004B236 /* OFLinkFailedException.m */; }; 4B29BC63133AC9CB0004B236 /* OFSymlinkFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B29BC5F133AC9C60004B236 /* OFSymlinkFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B29BC64133AC9CB0004B236 /* OFSymlinkFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B29BC60133AC9C90004B236 /* OFSymlinkFailedException.m */; }; - 4B39844213D3A24600E6F825 /* OFSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B39844013D3A24600E6F825 /* OFSet.h */; }; + 4B39844213D3A24600E6F825 /* OFSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B39844013D3A24600E6F825 /* OFSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B39844313D3A24600E6F825 /* OFSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B39844113D3A24600E6F825 /* OFSet.m */; }; - 4B39844713D3AFB400E6F825 /* OFMutableSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B39844513D3AFB400E6F825 /* OFMutableSet.h */; }; + 4B39844713D3AFB400E6F825 /* OFMutableSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B39844513D3AFB400E6F825 /* OFMutableSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B39844813D3AFB400E6F825 /* OFMutableSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B39844613D3AFB400E6F825 /* OFMutableSet.m */; }; 4B39844A13D3D03000E6F825 /* OFSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B39844913D3D03000E6F825 /* OFSet.m */; }; 4B3D238B1337FC0D00DD29B8 /* OFApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B175C1E116D130B003C99CB /* OFApplication.m */; }; 4B3D238C1337FC0D00DD29B8 /* OFArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B67995B1099E7C50041064A /* OFArray.m */; }; 4B3D238D1337FC0D00DD29B8 /* OFAutoreleasePool.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B67995D1099E7C50041064A /* OFAutoreleasePool.m */; }; @@ -239,10 +239,12 @@ 4B90B7A4133AD87D00BD33CB /* OFConnectionFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90B79A133AD87D00BD33CB /* OFConnectionFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B90B7A5133AD87D00BD33CB /* OFConnectionFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B79B133AD87D00BD33CB /* OFConnectionFailedException.m */; }; 4B90B7A6133AD87D00BD33CB /* OFListenFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90B79C133AD87D00BD33CB /* OFListenFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B90B7A7133AD87D00BD33CB /* OFListenFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B79D133AD87D00BD33CB /* OFListenFailedException.m */; }; 4B989C2F13771A3700109A30 /* OFSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B989C2E13771A3700109A30 /* OFSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BA49D9013DB113B00381CDB /* OFIntrospection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA49D8E13DB113B00381CDB /* OFIntrospection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BA49D9113DB113B00381CDB /* OFIntrospection.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BA49D8F13DB113B00381CDB /* OFIntrospection.m */; }; 4BAE7354139C508E00F682ED /* serialization.xml in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BAE7353139C507F00F682ED /* serialization.xml */; }; 4BB25E88139C388A00F574EA /* OFObject+Serialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB25E82139C388A00F574EA /* OFObject+Serialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BB25E89139C388A00F574EA /* OFObject+Serialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB25E83139C388A00F574EA /* OFObject+Serialization.m */; }; 4BB25E8A139C388A00F574EA /* OFString+Serialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB25E84139C388A00F574EA /* OFString+Serialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BB25E8B139C388A00F574EA /* OFString+Serialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB25E85139C388A00F574EA /* OFString+Serialization.m */; }; @@ -547,10 +549,12 @@ 4B981CDE116F71DD00294DB7 /* OFSeekableStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSeekableStream.h; path = src/OFSeekableStream.h; sourceTree = ""; }; 4B981CDF116F71DD00294DB7 /* OFSeekableStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSeekableStream.m; path = src/OFSeekableStream.m; sourceTree = ""; }; 4B989C2E13771A3700109A30 /* OFSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSerialization.h; path = src/OFSerialization.h; sourceTree = ""; }; 4B99250F12E0780000215DBE /* OFHTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFHTTPRequest.h; path = src/OFHTTPRequest.h; sourceTree = ""; }; 4B99251012E0780000215DBE /* OFHTTPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFHTTPRequest.m; path = src/OFHTTPRequest.m; sourceTree = ""; }; + 4BA49D8E13DB113B00381CDB /* OFIntrospection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFIntrospection.h; path = src/OFIntrospection.h; sourceTree = ""; }; + 4BA49D8F13DB113B00381CDB /* OFIntrospection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFIntrospection.m; path = src/OFIntrospection.m; sourceTree = ""; }; 4BAE7353139C507F00F682ED /* serialization.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = serialization.xml; path = tests/serialization.xml; sourceTree = ""; }; 4BAF5F46123460C900F4E111 /* OFCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCollection.h; path = src/OFCollection.h; sourceTree = ""; }; 4BAF5F47123460C900F4E111 /* OFStreamObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStreamObserver.h; path = src/OFStreamObserver.h; sourceTree = ""; }; 4BAF5F48123460C900F4E111 /* OFStreamObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStreamObserver.m; path = src/OFStreamObserver.m; sourceTree = ""; }; 4BAF5F49123460C900F4E111 /* OFStreamSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStreamSocket.h; path = src/OFStreamSocket.h; sourceTree = ""; }; @@ -825,10 +829,12 @@ 4BE920A713A2ECEF00154B94 /* OFFloatVector.m */, 4BF1BCC011C9663F0025511F /* OFHash.h */, 4BF1BCC111C9663F0025511F /* OFHash.m */, 4B99250F12E0780000215DBE /* OFHTTPRequest.h */, 4B99251012E0780000215DBE /* OFHTTPRequest.m */, + 4BA49D8E13DB113B00381CDB /* OFIntrospection.h */, + 4BA49D8F13DB113B00381CDB /* OFIntrospection.m */, 4B67996C1099E7C50041064A /* OFList.h */, 4B67996D1099E7C50041064A /* OFList.m */, 4BF1BCC211C9663F0025511F /* OFMD5Hash.h */, 4BF1BCC311C9663F0025511F /* OFMD5Hash.m */, 4B67996F1099E7C50041064A /* OFMutableArray.h */, @@ -1013,22 +1019,25 @@ 4B3D23C81337FCB000DD29B8 /* OFFile.h in Headers */, 4B6965E213A58B1B004F1C3A /* OFFloatMatrix.h in Headers */, 4BE920A813A2ECEF00154B94 /* OFFloatVector.h in Headers */, 4B3D23C91337FCB000DD29B8 /* OFHash.h in Headers */, 4B3D23CA1337FCB000DD29B8 /* OFHTTPRequest.h in Headers */, + 4BA49D9013DB113B00381CDB /* OFIntrospection.h in Headers */, 4B3D23CB1337FCB000DD29B8 /* OFList.h in Headers */, 4B3D23CC1337FCB000DD29B8 /* OFMD5Hash.h in Headers */, 4B3D23CD1337FCB000DD29B8 /* OFMutableArray.h in Headers */, 4B3D23CE1337FCB000DD29B8 /* OFMutableDictionary.h in Headers */, + 4B39844713D3AFB400E6F825 /* OFMutableSet.h in Headers */, 4B3D23CF1337FCB000DD29B8 /* OFMutableString.h in Headers */, 4B511B7C139C0A34003764A5 /* OFNull.h in Headers */, 4B3D23D01337FCB000DD29B8 /* OFNumber.h in Headers */, 4B3D23D11337FCB000DD29B8 /* OFObject.h in Headers */, 4BB25E88139C388A00F574EA /* OFObject+Serialization.h in Headers */, 4B3D23D21337FCB000DD29B8 /* OFPlugin.h in Headers */, 4B3D23D31337FCB000DD29B8 /* OFSeekableStream.h in Headers */, 4B989C2F13771A3700109A30 /* OFSerialization.h in Headers */, + 4B39844213D3A24600E6F825 /* OFSet.h in Headers */, 4B3D23D41337FCB000DD29B8 /* OFSHA1Hash.h in Headers */, 4B3D23D51337FCB000DD29B8 /* OFStream.h in Headers */, 4B3D23D61337FCB000DD29B8 /* OFStreamObserver.h in Headers */, 4B3D23D71337FCB000DD29B8 /* OFStreamSocket.h in Headers */, 4B3D23D81337FCB000DD29B8 /* OFString.h in Headers */, @@ -1104,12 +1113,10 @@ 4B55A101133ABEA900B58A93 /* OFThreadStartFailedException.h in Headers */, 4B55A103133ABEA900B58A93 /* OFThreadStillRunningException.h in Headers */, 4B55A116133AC24600B58A93 /* OFWriteFailedException.h in Headers */, 4B55A109133AC05100B58A93 /* common.h in Headers */, 4BDF37B51338055600F9A81A /* config.h in Headers */, - 4B39844213D3A24600E6F825 /* OFSet.h in Headers */, - 4B39844713D3AFB400E6F825 /* OFMutableSet.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ @@ -1270,21 +1277,24 @@ 4B3D23961337FC0D00DD29B8 /* OFFile.m in Sources */, 4B6965E313A58B1B004F1C3A /* OFFloatMatrix.m in Sources */, 4BE920A913A2ECEF00154B94 /* OFFloatVector.m in Sources */, 4B3D23971337FC0D00DD29B8 /* OFHash.m in Sources */, 4B3D23981337FC0D00DD29B8 /* OFHTTPRequest.m in Sources */, + 4BA49D9113DB113B00381CDB /* OFIntrospection.m in Sources */, 4B3D23991337FC0D00DD29B8 /* OFList.m in Sources */, 4B3D239A1337FC0D00DD29B8 /* OFMD5Hash.m in Sources */, 4B3D239B1337FC0D00DD29B8 /* OFMutableArray.m in Sources */, 4B3D239C1337FC0D00DD29B8 /* OFMutableDictionary.m in Sources */, + 4B39844813D3AFB400E6F825 /* OFMutableSet.m in Sources */, 4B3D239D1337FC0D00DD29B8 /* OFMutableString.m in Sources */, 4B511B7D139C0A34003764A5 /* OFNull.m in Sources */, 4B3D239E1337FC0D00DD29B8 /* OFNumber.m in Sources */, 4B3D239F1337FC0D00DD29B8 /* OFObject.m in Sources */, 4BB25E89139C388A00F574EA /* OFObject+Serialization.m in Sources */, 4B3D23A01337FC0D00DD29B8 /* OFPlugin.m in Sources */, 4B3D23A11337FC0D00DD29B8 /* OFSeekableStream.m in Sources */, + 4B39844313D3A24600E6F825 /* OFSet.m in Sources */, 4B3D23A21337FC0D00DD29B8 /* OFSHA1Hash.m in Sources */, 4B3D23A31337FC0D00DD29B8 /* OFStream.m in Sources */, 4B3D23A41337FC0D00DD29B8 /* OFStreamObserver.m in Sources */, 4B3D23A51337FC0D00DD29B8 /* OFStreamSocket.m in Sources */, 4B3D23A61337FC0D00DD29B8 /* OFString.m in Sources */, @@ -1356,12 +1366,10 @@ 4B55A104133ABEA900B58A93 /* OFThreadStillRunningException.m in Sources */, 4B17FFAA133A34E7003E6DCD /* OFTruncatedDataException.m in Sources */, 4B17FFB6133A375B003E6DCD /* OFUnboundNamespaceException.m in Sources */, 4B17FFB2133A3664003E6DCD /* OFUnsupportedProtocolException.m in Sources */, 4B55A117133AC24600B58A93 /* OFWriteFailedException.m in Sources */, - 4B39844313D3A24600E6F825 /* OFSet.m in Sources */, - 4B39844813D3AFB400E6F825 /* OFMutableSet.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 4BF33AEC133807310059CEF7 /* Sources */ = { isa = PBXSourcesBuildPhase; Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -22,10 +22,11 @@ OFFile.m \ OFFloatMatrix.m \ OFFloatVector.m \ OFHash.m \ OFHTTPRequest.m \ + OFIntrospection.m \ OFList.m \ OFMD5Hash.m \ OFMutableArray.m \ OFMutableDictionary.m \ OFMutableSet.m \ ADDED src/OFIntrospection.h Index: src/OFIntrospection.h ================================================================== --- src/OFIntrospection.h +++ src/OFIntrospection.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFObject.h" + +@class OFString; +@class OFArray; +@class OFMutableArray; + +/** + * \brief A class for describing a method. + */ +@interface OFMethod: OFObject +{ + SEL selector; + OFString *name; + OFString *typeEncoding; +} + +#ifdef OF_HAVE_PROPERTIES +@property (readonly) SEL selector; +@property (readonly, copy) OFString *name; +@property (readonly, copy) OFString *typeEncoding; +#endif + +/** + * \brief Returns the selector of the method. + * + * \return The selector of the method + */ +- (SEL)selector; + +/** + * \brief Returns the name of the method. + * + * \return The name of the method + */ +- (OFString*)name; + +/** + * \brief Returns the type encoding for the method. + * + * \return The type encoding for the method + */ +- (OFString*)typeEncoding; +@end + +/** + * \brief A class for introspecting classes. + */ +@interface OFIntrospection: OFObject +{ + OFMutableArray *classMethods; + OFMutableArray *instanceMethods; +} + +#ifdef OF_HAVE_PROPERTIES +@property (readonly, copy) OFArray *classMethods; +@property (readonly, copy) OFArray *instanceMethods; +#endif + +/** + * \brief Creates a new, autoreleased introspection for the specified class. + * + * \return A new, autoreleased introspection for the specified class + */ ++ introspectionWithClass: (Class)class_; + +/** + * \brief Initializes an already allocated OFIntrospection with the specified + * class. + * + * \return An initialized OFIntrospection + */ +- initWithClass: (Class)class_; + +/** + * \brief Returns the class methods of the class. + * + * \return The class methods of the class + */ +- (OFArray*)classMethods; + +/** + * \brief Returns the instance methods of the class. + * + * \return The instance methods of the class + */ +- (OFArray*)instanceMethods; + +/* TODO: Ivars, properties */ +@end ADDED src/OFIntrospection.m Index: src/OFIntrospection.m ================================================================== --- src/OFIntrospection.m +++ src/OFIntrospection.m @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) +# import +#elif defined(OF_OLD_GNU_RUNTIME) +# import +#endif + +#import "OFIntrospection.h" +#import "OFString.h" +#import "OFArray.h" +#import "OFAutoreleasePool.h" + +#import "macros.h" + +@implementation OFMethod +#if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) +- _initWithMethod: (Method)method +{ + self = [super init]; + + @try { + selector = method_getName(method); + name = [[OFString alloc] + initWithCString: sel_getName(selector)]; + typeEncoding = [[OFString alloc] + initWithCString: method_getTypeEncoding(method)]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} +#elif defined(OF_OLD_GNU_RUNTIME) +- _initWithMethod: (Method_t)method +{ + self = [super init]; + + @try { + selector = method->method_name; + name = [[OFString alloc] + initWithCString: sel_get_name(selector)]; + typeEncoding = [[OFString alloc] + initWithCString: method->method_types]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} +#endif + +- (void)dealloc +{ + [name release]; + [typeEncoding release]; + + [super dealloc]; +} + +- (SEL)selector +{ + return selector; +} + +- (OFString*)name +{ + OF_GETTER(name, YES) +} + +- (OFString*)typeEncoding +{ + OF_GETTER(typeEncoding, YES) +} + +- (OFString*)description +{ + return [OFString stringWithFormat: @"", + name, typeEncoding]; +} +@end + +@implementation OFIntrospection ++ introspectionWithClass: (Class)class +{ + return [[[self alloc] initWithClass: class] autorelease]; +} + +- initWithClass: (Class)class +{ + self = [super init]; + + @try { + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; +#if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) + Method *methodList; + unsigned i, count; + + classMethods = [[OFMutableArray alloc] init]; + instanceMethods = [[OFMutableArray alloc] init]; + + methodList = class_copyMethodList(((OFObject*)class)->isa, + &count); + for (i = 0; i < count; i++) { + [classMethods addObject: [[[OFMethod alloc] + _initWithMethod: methodList[i]] autorelease]]; + [pool releaseObjects]; + } + + methodList = class_copyMethodList(class, &count); + for (i = 0; i < count; i++) { + [instanceMethods addObject: [[[OFMethod alloc] + _initWithMethod: methodList[i]] autorelease]]; + [pool releaseObjects]; + } +#elif defined(OF_OLD_GNU_RUNTIME) + MethodList_t methodList; + + classMethods = [[OFMutableArray alloc] init]; + instanceMethods = [[OFMutableArray alloc] init]; + + for (methodList = class->class_pointer->methods; + methodList != NULL; methodList = methodList->method_next) { + size_t 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; + + for (i = 0; i < methodList->method_count; i++) + [instanceMethods addObject: [[[OFMethod alloc] + _initWithMethod: + &methodList->method_list[i]] autorelease]]; + } +#endif + + classMethods->isa = [OFArray class]; + instanceMethods->isa = [OFArray class]; + + [pool release]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [classMethods release]; + [instanceMethods release]; + + [super dealloc]; +} + +- (OFArray*)classMethods +{ + OF_GETTER(classMethods, YES) +} + +- (OFArray*)instanceMethods +{ + OF_GETTER(instanceMethods, YES) +} +@end Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -32,10 +32,12 @@ #import "OFSet.h" #import "OFEnumerator.h" #import "OFNull.h" + +#import "OFIntrospection.h" #import "OFNumber.h" #import "OFDate.h" #import "OFURL.h"