mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
* 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:
parent
daecca9270
commit
345563c947
5 changed files with 161 additions and 7 deletions
11
ChangeLog
11
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue