* Source/ObjectiveC2/runtime.h:

* Source/ObjectiveC2/runtime.m:
Implement protocol_copyMethodDescriptionList, protocol_copyProtocolList,
protocol_getMethodDescription, as well as a dummy version of
objc_copyProtocolList.
* Headers/Additions/GNUstepBase/GSObjCRuntime.h:
* Source/Additions/GSObjCRuntime.m:
Implement a convenience method, GSProtocolGetMethodDescriptionRecursive



git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@31254 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Eric Wasylishen 2010-09-08 20:30:19 +00:00
parent daecca9270
commit 345563c947
5 changed files with 161 additions and 7 deletions

View file

@ -1,3 +1,14 @@
2010-09-08 Eric Wasylishen <ewasylishen@gmail.com>
* Source/ObjectiveC2/runtime.h:
* Source/ObjectiveC2/runtime.m:
Implement protocol_copyMethodDescriptionList, protocol_copyProtocolList,
protocol_getMethodDescription, as well as a dummy version of
objc_copyProtocolList.
* Headers/Additions/GNUstepBase/GSObjCRuntime.h:
* Source/Additions/GSObjCRuntime.m:
Implement a convenience method, GSProtocolGetMethodDescriptionRecursive
2010-09-08 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSObject.h:

View file

@ -323,6 +323,16 @@ GSProtocolFromName(const char *name);
GS_EXPORT void
GSRegisterProtocol(Protocol *proto);
/**
* A variant of protocol_getMethodDescription which recursively searches
* parent protocols if the requested selector isn't found in the given
* protocol.
*
* Returns a {NULL, NULL} structure if the requested selector couldn't be
* found.
*/
GS_EXPORT struct objc_method_description
GSProtocolGetMethodDescriptionRecursive(Protocol *aProtocol, SEL aSel, BOOL isRequired, BOOL isInstance);
/*
* Unfortunately the definition of the symbols

View file

@ -777,6 +777,34 @@ GSProtocolFromName(const char *name)
return p;
}
struct objc_method_description
GSProtocolGetMethodDescriptionRecursive(Protocol *aProtocol, SEL aSel, BOOL isRequired, BOOL isInstance)
{
struct objc_method_description desc;
desc = protocol_getMethodDescription(aProtocol, aSel, isRequired, isInstance);
if (desc.name == NULL && desc.types == NULL)
{
Protocol **list;
unsigned int count;
list = protocol_copyProtocolList(aProtocol, &count);
if (list != NULL)
{
unsigned int i;
for (i = 0; i < count; i++)
{
desc = GSProtocolGetMethodDescriptionRecursive(list[i], aSel, isRequired, isInstance);
if (desc.name != NULL || desc.types != NULL)
{
return desc;
}
}
free(list);
}
}
return desc;
}
void
GSObjCAddClassBehavior(Class receiver, Class behavior)

View file

@ -1082,6 +1082,12 @@ objc_getProtocol(const char *name)
return p;
}
Protocol **objc_copyProtocolList(unsigned int *count)
{
*count = 0;
return NULL;
}
BOOL protocol_conformsToProtocol(Protocol *p1, Protocol *p2)
{
struct objc_protocol_list *list = p1->protocol_list;
@ -1134,20 +1140,81 @@ BOOL class_conformsToProtocol(Class cls, Protocol *protocol)
return NO;
}
struct objc_method_description_list {
int count;
struct objc_method_description list[1];
};
struct objc_method_description *
protocol_copyMethodDescriptionList(Protocol * p,
BOOL isRequiredMethod,
BOOL isInstanceMethod, unsigned int *count)
{
*count = 0;
return NULL;
struct objc_method_description *output = NULL;
unsigned int outputCount = 0;
struct objc_method_description_list *methods;
if (isInstanceMethod)
{
methods = p->instance_methods;
}
else
{
methods = p->class_methods;
}
if (methods != NULL)
{
int i;
outputCount = methods->count;
output = malloc(outputCount * sizeof(struct objc_method_description));
for (i=0 ; i<methods->count; i++)
{
output[i] = methods->list[i];
// HACK: the name field of the objc_method_description struct
// is supposed to be a selector, but testing reveals it is a string
output[i].name = sel_registerName((const char *) output[i].name);
}
}
*count = outputCount;
return output;
}
Protocol **
protocol_copyProtocolList(Protocol * p, unsigned int *count)
{
*count = 0;
return NULL;
Protocol **output = NULL;
unsigned int outputCount = 0;
struct objc_protocol_list *list;
for (list = p->protocol_list ; list != NULL ; list = list->next)
{
int i;
for (i=0 ; i<list->count ; i++)
{
outputCount++;
}
}
if (outputCount > 0)
{
output = malloc(outputCount * sizeof(Protocol *));
}
for (list = p->protocol_list ; list != NULL ; list = list->next)
{
int i;
for (i=0 ; i<list->count ; i++)
{
output[i] = (Protocol*)list->list[i];
}
}
*count = outputCount;
return output;
}
const char *
@ -1160,6 +1227,45 @@ protocol_getName(Protocol * p)
return NULL;
}
struct objc_method_description protocol_getMethodDescription(Protocol *p,
SEL aSel, BOOL isRequiredMethod, BOOL isInstanceMethod)
{
struct objc_method_description output = {NULL, NULL};
if (p != NULL)
{
struct objc_method_description_list *methods;
const char *name = sel_getName(aSel);
int i;
if (isInstanceMethod)
{
methods = p->instance_methods;
}
else
{
methods = p->class_methods;
}
if (methods != NULL)
{
for (i = 0; i < methods->count; i++)
{
if (!strcmp((char*)methods->list[i].name, name))
{
output = methods->list[i];
// HACK: the name field of the objc_method_description struct
// is supposed to be a selector, but testing reveals it is a string
output.name = sel_registerName((const char *) output.name);
break;
}
}
}
}
return output;
}
BOOL
protocol_isEqual(Protocol * p, Protocol * other)
{

View file

@ -242,19 +242,18 @@ IMP objc_msg_lookup(id, SEL);
IMP objc_msg_lookup_super(struct objc_super*, SEL);
OBJC_GNU_RUNTIME_UNSUPPORTED("Protocol introspection")
Protocol **objc_copyProtocolList(unsigned int *count);
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);