From d70523947b692e02644774eaddbba2dc821261fd Mon Sep 17 00:00:00 2001 From: theraven Date: Tue, 21 Sep 2010 13:05:24 +0000 Subject: [PATCH] Implement some missing runtime functions. --- objc/runtime.h | 27 ++++++++---------- properties.m | 56 +++++++++++++++++++++++++++++++++++++ protocol.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 143 insertions(+), 16 deletions(-) diff --git a/objc/runtime.h b/objc/runtime.h index f8abc8a..83378c7 100644 --- a/objc/runtime.h +++ b/objc/runtime.h @@ -13,10 +13,10 @@ #include "Availability.h" #ifdef ERROR_UNSUPPORTED_RUNTIME_FUNCTIONS -# define OBJC_GNU_RUNTIME_UNSUPPORTED(x) \ +# define OBJC_GNUSTEP_RUNTIME_UNSUPPORTED(x) \ __attribute__((error(x " not supported by this runtime"))) #else -# define OBJC_GNU_RUNTIME_UNSUPPORTED(x) +# define OBJC_GNUSTEP_RUNTIME_UNSUPPORTED(x) #endif // Undo GNUstep substitutions @@ -84,8 +84,8 @@ typedef unsigned char BOOL; #endif // __objc_INCLUDE_GNU - -typedef void *objc_property_t; +struct objc_property; +typedef struct objc_property* objc_property_t; #ifdef __OBJC__ @class Protocol; #else @@ -146,8 +146,7 @@ Ivar * class_copyIvarList(Class cls, unsigned int *outCount); Method * class_copyMethodList(Class cls, unsigned int *outCount); -OBJC_GNU_RUNTIME_UNSUPPORTED("Property introspection") -objc_property_t * class_copyPropertyList(Class cls, unsigned int *outCount); +objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount); Protocol ** class_copyProtocolList(Class cls, unsigned int *outCount); @@ -175,14 +174,13 @@ IMP class_getMethodImplementation_stret(Class cls, SEL name); const char * class_getName(Class cls); -OBJC_GNU_RUNTIME_UNSUPPORTED("Property introspection") objc_property_t class_getProperty(Class cls, const char *name); Class class_getSuperclass(Class cls); int class_getVersion(Class theClass); -OBJC_GNU_RUNTIME_UNSUPPORTED("Weak instance variables") +OBJC_GNUSTEP_RUNTIME_UNSUPPORTED("Weak instance variables") const char *class_getWeakIvarLayout(Class cls); BOOL class_isMetaClass(Class cls); @@ -198,7 +196,7 @@ Class class_setSuperclass(Class cls, Class newSuper); void class_setVersion(Class theClass, int version); -OBJC_GNU_RUNTIME_UNSUPPORTED("Weak instance variables") +OBJC_GNUSTEP_RUNTIME_UNSUPPORTED("Weak instance variables") void class_setWeakIvarLayout(Class cls, const char *layout); const char * ivar_getName(Ivar ivar); @@ -265,26 +263,25 @@ const char *object_getClassName(id obj); IMP objc_msg_lookup(id, SEL); IMP objc_msg_lookup_super(struct objc_super*, SEL); -OBJC_GNU_RUNTIME_UNSUPPORTED("Protocol introspection") BOOL protocol_conformsToProtocol(Protocol *p, Protocol *other); -OBJC_GNU_RUNTIME_UNSUPPORTED("Protocol introspection") struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *count); -OBJC_GNU_RUNTIME_UNSUPPORTED("Protocol introspection") objc_property_t *protocol_copyPropertyList(Protocol *p, unsigned int *count); -OBJC_GNU_RUNTIME_UNSUPPORTED("Protocol introspection") Protocol **protocol_copyProtocolList(Protocol *p, unsigned int *count); -OBJC_GNU_RUNTIME_UNSUPPORTED("Protocol introspection") struct objc_method_description protocol_getMethodDescription(Protocol *p, SEL aSel, BOOL isRequiredMethod, BOOL isInstanceMethod); const char *protocol_getName(Protocol *p); -OBJC_GNU_RUNTIME_UNSUPPORTED("Protocol introspection") +/** + * Note: The Apple documentation for this method contains some nonsense for + * isInstanceProperty. As there is no language syntax for defining properties + * on classes, we return NULL if this is not YES. + */ objc_property_t protocol_getProperty(Protocol *p, const char *name, BOOL isRequiredProperty, BOOL isInstanceProperty); diff --git a/properties.m b/properties.m index 0309070..ffad0fb 100644 --- a/properties.m +++ b/properties.m @@ -1,6 +1,10 @@ #include "objc/runtime.h" #include +#include +#include #include +#include "class.h" +#include "properties.h" #ifdef __MINGW32__ #include @@ -116,3 +120,55 @@ void objc_setProperty(id obj, SEL _cmd, int offset, id arg, BOOL isAtomic, BOOL } [old release]; } + +objc_property_t class_getProperty(Class cls, const char *name) +{ + // Old ABI classes don't have declared properties + if (!objc_test_class_flag(cls, objc_class_flag_new_abi)) + { + return NULL; + } + struct objc_property_list *properties = cls->properties; + while (NULL != properties) + { + for (int i=0 ; icount ; i++) + { + objc_property_t p = &properties->properties[i]; + if (strcmp(p->name, name) == 0) + { + return p; + } + } + properties = properties->next; + } + return NULL; +} +objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount) +{ + if (!objc_test_class_flag(cls, objc_class_flag_new_abi)) + { + return NULL; + } + struct objc_property_list *properties = cls->properties; + unsigned int count = 0; + for (struct objc_property_list *l=properties ; NULL!=l ; l=l->next) + { + count += l->count; + } + if (0 == count) + { + return NULL; + } + objc_property_t *list = calloc(sizeof(objc_property_t), count); + unsigned int out = 0; + for (struct objc_property_list *l=properties ; NULL!=l ; l=l->next) + { + for (int i=0 ; icount ; i++) + { + list[out] = &l->properties[i]; + } + } + *outCount = count; + return list; +} + diff --git a/protocol.c b/protocol.c index d451dff..121f580 100644 --- a/protocol.c +++ b/protocol.c @@ -303,7 +303,6 @@ get_method_list(Protocol *p, return list; } -//FIXME!!!! struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *count) { @@ -341,6 +340,81 @@ Protocol **protocol_copyProtocolList(Protocol *p, unsigned int *count) } return NULL; } + +objc_property_t *protocol_copyPropertyList(Protocol *protocol, + unsigned int *outCount) +{ + if (protocol->isa != ObjC2ProtocolClass) + { + return NULL; + } + Protocol2 *p = (Protocol2*)protocol; + struct objc_property_list *properties = p->properties; + unsigned int count = 0; + if (NULL != properties) + { + count = properties->count; + } + if (NULL != p->optional_properties) + { + count = p->optional_properties->count; + } + if (0 == count) + { + return NULL; + } + objc_property_t *list = calloc(sizeof(objc_property_t), count); + unsigned int out = 0; + if (properties) + { + for (int i=0 ; icount ; i++) + { + list[out] = &properties->properties[i]; + } + } + properties = p->optional_properties; + if (properties) + { + for (int i=0 ; icount ; i++) + { + list[out] = &properties->properties[i]; + } + } + *outCount = count; + return list; +} + +objc_property_t protocol_getProperty(Protocol *protocol, + const char *name, + BOOL isRequiredProperty, + BOOL isInstanceProperty) +{ + // Class properties are not supported yet (there is no language syntax for + // defining them!) + if (!isInstanceProperty) { return NULL; } + if (protocol->isa != ObjC2ProtocolClass) + { + return NULL; + } + Protocol2 *p = (Protocol2*)protocol; + struct objc_property_list *properties = + isRequiredProperty ? p->properties : p->optional_properties; + while (NULL != properties) + { + for (int i=0 ; icount ; i++) + { + objc_property_t prop = &properties->properties[i]; + if (strcmp(prop->name, name) == 0) + { + return prop; + } + } + properties = properties->next; + } + return NULL; +} + + struct objc_method_description protocol_getMethodDescription(Protocol *p, SEL aSel,