mirror of git://gcc.gnu.org/git/gcc.git
In libobjc/: 2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
In libobjc/: 2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com> * Makefile.in (C_SOURCE_FILES): Added protocols.c. * objc-private/protocols.h: New. * protocols.c: New. * init.c: Include objc-private/protocols.h. (__objc_exec_class): Call __objc_protocols_init on startup. (__objc_init_protocols): Call __objc_protocols_add_protocol. * objc-private/runtime.h: Use (struct objc_method_list *) instead of MethodList_t, and (struct objc_method *) instead of Method_t. * objc/deprecated/struct_objc_class.h: Define __objc_STRUCT_OBJC_CLASS_defined. * objc-private/module-abi-8.h (struct objc_method_description_list): New. (struct objc_class): Only define if __objc_STRUCT_OBJC_CLASS_defined is undefined. * objc/runtime.h (class_getName): New. (objc_getProtocol): New. (objc_copyProtocolList): New. (class_addProtocol): New. (class_conformsToProtocol): New. (class_copyProtocolList): New. (protocol_conformsToProtocol): New. (protocol_isEqual): New. (protocol_getName): New. (protocol_getMethodDescription): New. (protocol_copyMethodDescriptionList): New. (protocol_getProperty): New. (protocol_copyPropertyList): New. (protocol_copyProtocolList): New. * class.c (class_getName): New. * selector.c (sel_isEqual): New. From-SVN: r165349
This commit is contained in:
parent
524660d2e3
commit
debfbfeefc
|
@ -1,3 +1,36 @@
|
||||||
|
2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
|
* Makefile.in (C_SOURCE_FILES): Added protocols.c.
|
||||||
|
* objc-private/protocols.h: New.
|
||||||
|
* protocols.c: New.
|
||||||
|
* init.c: Include objc-private/protocols.h.
|
||||||
|
(__objc_exec_class): Call __objc_protocols_init on startup.
|
||||||
|
(__objc_init_protocols): Call __objc_protocols_add_protocol.
|
||||||
|
* objc-private/runtime.h: Use (struct objc_method_list *) instead
|
||||||
|
of MethodList_t, and (struct objc_method *) instead of Method_t.
|
||||||
|
* objc/deprecated/struct_objc_class.h: Define
|
||||||
|
__objc_STRUCT_OBJC_CLASS_defined.
|
||||||
|
* objc-private/module-abi-8.h (struct
|
||||||
|
objc_method_description_list): New.
|
||||||
|
(struct objc_class): Only define if
|
||||||
|
__objc_STRUCT_OBJC_CLASS_defined is undefined.
|
||||||
|
* objc/runtime.h (class_getName): New.
|
||||||
|
(objc_getProtocol): New.
|
||||||
|
(objc_copyProtocolList): New.
|
||||||
|
(class_addProtocol): New.
|
||||||
|
(class_conformsToProtocol): New.
|
||||||
|
(class_copyProtocolList): New.
|
||||||
|
(protocol_conformsToProtocol): New.
|
||||||
|
(protocol_isEqual): New.
|
||||||
|
(protocol_getName): New.
|
||||||
|
(protocol_getMethodDescription): New.
|
||||||
|
(protocol_copyMethodDescriptionList): New.
|
||||||
|
(protocol_getProperty): New.
|
||||||
|
(protocol_copyPropertyList): New.
|
||||||
|
(protocol_copyProtocolList): New.
|
||||||
|
* class.c (class_getName): New.
|
||||||
|
* selector.c (sel_isEqual): New.
|
||||||
|
|
||||||
2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
|
2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
* selector.c (sel_getName): Return "<null selector>" for a NULL
|
* selector.c (sel_getName): Return "<null selector>" for a NULL
|
||||||
|
|
|
@ -177,6 +177,7 @@ C_SOURCE_FILES = \
|
||||||
objc-foreach.c \
|
objc-foreach.c \
|
||||||
objc-sync.c \
|
objc-sync.c \
|
||||||
objects.c \
|
objects.c \
|
||||||
|
protocols.c \
|
||||||
sarray.c \
|
sarray.c \
|
||||||
selector.c \
|
selector.c \
|
||||||
sendmsg.c \
|
sendmsg.c \
|
||||||
|
|
|
@ -139,7 +139,8 @@ static class_node_ptr class_table_array[CLASS_TABLE_SIZE];
|
||||||
/* The table writing mutex - we lock on writing to avoid conflicts
|
/* The table writing mutex - we lock on writing to avoid conflicts
|
||||||
between different writers, but we read without locks. That is
|
between different writers, but we read without locks. That is
|
||||||
possible because we assume pointer assignment to be an atomic
|
possible because we assume pointer assignment to be an atomic
|
||||||
operation. */
|
operation. TODO: This is only true under certain circumstances,
|
||||||
|
which should be clarified. */
|
||||||
static objc_mutex_t __class_table_lock = NULL;
|
static objc_mutex_t __class_table_lock = NULL;
|
||||||
|
|
||||||
/* CLASS_TABLE_HASH is how we compute the hash of a class name. It is
|
/* CLASS_TABLE_HASH is how we compute the hash of a class name. It is
|
||||||
|
@ -730,7 +731,14 @@ __objc_resolve_class_links (void)
|
||||||
objc_mutex_unlock (__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
class_getName (Class class_)
|
||||||
|
{
|
||||||
|
if (class_ == Nil)
|
||||||
|
return "nil";
|
||||||
|
|
||||||
|
return class_->name;
|
||||||
|
}
|
||||||
|
|
||||||
#define CLASSOF(c) ((c)->class_pointer)
|
#define CLASSOF(c) ((c)->class_pointer)
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
#include "objc-private/objc-list.h"
|
#include "objc-private/objc-list.h"
|
||||||
#include "objc-private/runtime.h"
|
#include "objc-private/runtime.h"
|
||||||
#include "objc-private/objc-sync.h" /* For __objc_sync_init() */
|
#include "objc-private/objc-sync.h" /* For __objc_sync_init() */
|
||||||
|
#include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */
|
||||||
|
|
||||||
/* The version number of this runtime. This must match the number
|
/* The version number of this runtime. This must match the number
|
||||||
defined in gcc (objc-act.c). */
|
defined in gcc (objc-act.c). */
|
||||||
|
@ -48,7 +49,17 @@ static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
|
||||||
/* List of unresolved static instances. */
|
/* List of unresolved static instances. */
|
||||||
static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
|
static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
|
||||||
|
|
||||||
/* Global runtime "write" mutex. */
|
/* Global runtime "write" mutex. Having a single mutex prevents
|
||||||
|
deadlocks, but reduces concurrency. To improve concurrency, some
|
||||||
|
groups of functions in the runtime have their own separate mutex
|
||||||
|
(eg, __class_table_lock in class.c); to avoid deadlocks, these
|
||||||
|
routines must make sure that they never acquire any other lock
|
||||||
|
while holding their own local lock. Ie, they should lock, execute
|
||||||
|
some C code that does not perform any calls to other runtime
|
||||||
|
functions which may potentially lock different locks, then unlock.
|
||||||
|
If they need to perform any calls to other runtime functions that
|
||||||
|
may potentially lock other locks, then they should use the global
|
||||||
|
__objc_runtime_mutex. */
|
||||||
objc_mutex_t __objc_runtime_mutex = 0;
|
objc_mutex_t __objc_runtime_mutex = 0;
|
||||||
|
|
||||||
/* Number of threads that are alive. */
|
/* Number of threads that are alive. */
|
||||||
|
@ -551,6 +562,7 @@ __objc_exec_class (Module_t module)
|
||||||
__objc_load_methods = objc_hash_new (128,
|
__objc_load_methods = objc_hash_new (128,
|
||||||
(hash_func_type)objc_hash_ptr,
|
(hash_func_type)objc_hash_ptr,
|
||||||
objc_compare_ptrs);
|
objc_compare_ptrs);
|
||||||
|
__objc_protocols_init ();
|
||||||
__objc_sync_init ();
|
__objc_sync_init ();
|
||||||
previous_constructors = 1;
|
previous_constructors = 1;
|
||||||
}
|
}
|
||||||
|
@ -862,10 +874,14 @@ __objc_init_protocols (struct objc_protocol_list *protos)
|
||||||
struct objc_protocol *aProto = protos->list[i];
|
struct objc_protocol *aProto = protos->list[i];
|
||||||
if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
|
if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
|
||||||
{
|
{
|
||||||
/* assign class pointer */
|
/* Assign class pointer */
|
||||||
aProto->class_pointer = proto_class;
|
aProto->class_pointer = proto_class;
|
||||||
|
|
||||||
/* init super protocols */
|
/* Register the protocol in the hashtable or protocols by
|
||||||
|
name. */
|
||||||
|
__objc_protocols_add_protocol (aProto->protocol_name, aProto);
|
||||||
|
|
||||||
|
/* Init super protocols */
|
||||||
__objc_init_protocols (aProto->protocol_list);
|
__objc_init_protocols (aProto->protocol_list);
|
||||||
}
|
}
|
||||||
else if (protos->list[i]->class_pointer != proto_class)
|
else if (protos->list[i]->class_pointer != proto_class)
|
||||||
|
|
|
@ -138,6 +138,24 @@ struct objc_method_list
|
||||||
structure. */
|
structure. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Currently defined in Protocol.m (that definition should go away
|
||||||
|
once we include this file). */
|
||||||
|
struct objc_method_description_list
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
struct objc_method_description list[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Currently defined by objc/objc.h. */
|
||||||
|
/*
|
||||||
|
struct objc_protocol {
|
||||||
|
struct objc_class* class_pointer;
|
||||||
|
char *protocol_name;
|
||||||
|
struct objc_protocol_list *protocol_list;
|
||||||
|
struct objc_method_description_list *instance_methods, *class_methods;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
struct objc_protocol_list
|
struct objc_protocol_list
|
||||||
{
|
{
|
||||||
struct objc_protocol_list *next;
|
struct objc_protocol_list *next;
|
||||||
|
@ -155,6 +173,7 @@ struct objc_protocol_list
|
||||||
some members change type. The compiler generates "char* const" and
|
some members change type. The compiler generates "char* const" and
|
||||||
places a string in the following member variables: super_class.
|
places a string in the following member variables: super_class.
|
||||||
*/
|
*/
|
||||||
|
#ifndef __objc_STRUCT_OBJC_CLASS_defined
|
||||||
struct objc_class {
|
struct objc_class {
|
||||||
struct objc_class* class_pointer; /* Pointer to the class's meta
|
struct objc_class* class_pointer; /* Pointer to the class's meta
|
||||||
class. */
|
class. */
|
||||||
|
@ -197,6 +216,7 @@ struct objc_class {
|
||||||
struct objc_protocol_list *protocols; /* Protocols conformed to */
|
struct objc_protocol_list *protocols; /* Protocols conformed to */
|
||||||
void* gc_object_type;
|
void* gc_object_type;
|
||||||
};
|
};
|
||||||
|
#endif /* __objc_STRUCT_OBJC_CLASS_defined */
|
||||||
|
|
||||||
/* The compiler generates one of these structures for each category.
|
/* The compiler generates one of these structures for each category.
|
||||||
A class may have many categories and contain both instance and
|
A class may have many categories and contain both instance and
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* GNU Objective C Runtime protocols - Private functions
|
||||||
|
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
|
Contributed by Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef __objc_private_protocols_INCLUDE_GNU
|
||||||
|
#define __objc_private_protocols_INCLUDE_GNU
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/* This function needs to be called at startup by init.c. */
|
||||||
|
void
|
||||||
|
__objc_protocols_init (void);
|
||||||
|
|
||||||
|
/* This function adds a protocol to the internal hashtable of
|
||||||
|
protocols by name, which allows objc_getProtocol(name) to be
|
||||||
|
implemented efficiently. */
|
||||||
|
void
|
||||||
|
__objc_protocols_add_protocol (const char *name, Protocol *object);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* not __objc_private_protocols_INCLUDE_GNU */
|
|
@ -58,18 +58,18 @@ extern void __objc_init_dispatch_tables(void); /* (objc-dispatch.c) */
|
||||||
extern void __objc_install_premature_dtable(Class); /* (objc-dispatch.c) */
|
extern void __objc_install_premature_dtable(Class); /* (objc-dispatch.c) */
|
||||||
extern void __objc_resolve_class_links(void); /* (objc-class.c) */
|
extern void __objc_resolve_class_links(void); /* (objc-class.c) */
|
||||||
extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */
|
extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */
|
||||||
extern void __objc_register_selectors_from_list (MethodList_t); /* (selector.c) */
|
extern void __objc_register_selectors_from_list (struct objc_method_list *); /* (selector.c) */
|
||||||
extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
|
extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
|
||||||
|
|
||||||
extern int __objc_init_thread_system(void); /* thread.c */
|
extern int __objc_init_thread_system(void); /* thread.c */
|
||||||
extern int __objc_fini_thread_system(void); /* thread.c */
|
extern int __objc_fini_thread_system(void); /* thread.c */
|
||||||
extern void __objc_print_dtable_stats(void); /* sendmsg.c */
|
extern void __objc_print_dtable_stats(void); /* sendmsg.c */
|
||||||
|
|
||||||
extern void class_add_method_list(Class, MethodList_t);
|
extern void class_add_method_list(Class, struct objc_method_list *);
|
||||||
|
|
||||||
/* Registering instance methods as class methods for root classes */
|
/* Registering instance methods as class methods for root classes */
|
||||||
extern void __objc_register_instance_methods_to_class(Class);
|
extern void __objc_register_instance_methods_to_class(Class);
|
||||||
extern Method_t search_for_method_in_list(MethodList_t list, SEL op);
|
extern struct objc_method * search_for_method_in_list(struct objc_method_list * list, SEL op);
|
||||||
|
|
||||||
/* True when class links has been resolved */
|
/* True when class links has been resolved */
|
||||||
extern BOOL __objc_class_links_resolved;
|
extern BOOL __objc_class_links_resolved;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* This structure used to be public, but is now private to the runtime. */
|
/* This structure used to be public, but is now private to the runtime. */
|
||||||
|
#define __objc_STRUCT_OBJC_CLASS_defined
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The compiler generates one of these structures for each class.
|
** The compiler generates one of these structures for each class.
|
||||||
|
|
|
@ -356,6 +356,138 @@ objc_EXPORT int objc_getClassList (Class *returnValue, int maxNumberOfClassesToR
|
||||||
the documentation is unclear on what they are supposed to do, and
|
the documentation is unclear on what they are supposed to do, and
|
||||||
the GNU Objective-C Runtime currently does not provide them. */
|
the GNU Objective-C Runtime currently does not provide them. */
|
||||||
|
|
||||||
|
/* Return the name of the class 'class_', or the string "nil" if the
|
||||||
|
class_ is Nil. */
|
||||||
|
objc_EXPORT const char * class_getName (Class class_);
|
||||||
|
|
||||||
|
|
||||||
|
/** Implementation: the following functions are in protocols.c. */
|
||||||
|
|
||||||
|
/* Return the protocol with name 'name', or nil if it the protocol is
|
||||||
|
not known to the runtime. */
|
||||||
|
objc_EXPORT Protocol *objc_getProtocol (const char *name);
|
||||||
|
|
||||||
|
/* Return all the protocols known to the runtime. The return value of
|
||||||
|
the function is a pointer to an area, allocated with malloc(), that
|
||||||
|
contains all the protocols known to the runtime; the list is
|
||||||
|
terminated by NULL. You should free this area using free() once
|
||||||
|
you no longer need it. Optionally, if you pass a non-NULL
|
||||||
|
'numberOfReturnedProtocols' pointer, the unsigned int that it
|
||||||
|
points to will be filled with the number of protocols returned. If
|
||||||
|
there are no protocols known to the runtime, NULL is returned. */
|
||||||
|
objc_EXPORT Protocol **objc_copyProtocolList (unsigned int *numberOfReturnedProtocols);
|
||||||
|
|
||||||
|
/* Add a protocol to a class, and return YES if it was done
|
||||||
|
succesfully, and NO if not. At the moment, NO should only happen
|
||||||
|
if class_ or protocol are nil, if the protocol is not a Protocol
|
||||||
|
object or if the class already conforms to the protocol. */
|
||||||
|
objc_EXPORT BOOL class_addProtocol (Class class_, Protocol *protocol);
|
||||||
|
|
||||||
|
/* Return YES if the class 'class_' conforms to Protocol 'protocol',
|
||||||
|
and NO if not. */
|
||||||
|
objc_EXPORT BOOL class_conformsToProtocol (Class class_, Protocol *protocol);
|
||||||
|
|
||||||
|
/* Return all the protocols that the class conforms to. The return
|
||||||
|
value of the function is a pointer to an area, allocated with
|
||||||
|
malloc(), that contains all the protocols formally adopted by the
|
||||||
|
class. It does not include protocols adopted by superclasses. The
|
||||||
|
list is terminated by NULL. Optionally, if you pass a non-NULL
|
||||||
|
'numberOfReturnedProtocols' pointer, the unsigned int that it
|
||||||
|
points to will be filled with the number of protocols returned. */
|
||||||
|
objc_EXPORT Protocol **class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols);
|
||||||
|
|
||||||
|
/* Return YES if protocol 'protocol' conforms to protocol
|
||||||
|
'anotherProtocol', and NO if not. Note that if one of the two
|
||||||
|
protocols is nil, it returns NO. */
|
||||||
|
objc_EXPORT BOOL protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol);
|
||||||
|
|
||||||
|
/* Return YES if protocol 'protocol' is the same as protocol
|
||||||
|
'anotherProtocol', and 'NO' if not. Note that it returns YES if
|
||||||
|
the two protocols are both nil. */
|
||||||
|
objc_EXPORT BOOL protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol);
|
||||||
|
|
||||||
|
/* Return the name of protocol 'protocol'. If 'protocol' is nil or is
|
||||||
|
not a Protocol, return NULL. */
|
||||||
|
objc_EXPORT const char *protocol_getName (Protocol *protocol);
|
||||||
|
|
||||||
|
/* Return the method description for the method with selector
|
||||||
|
'selector' in protocol 'protocol'; if 'requiredMethod' is YES, the
|
||||||
|
function searches the list of required methods; if NO, the list of
|
||||||
|
optional methods. If 'instanceMethod' is YES, the function search
|
||||||
|
for an instance method; if NO, for a class method. If there is no
|
||||||
|
matching method, an objc_method_description structure with both
|
||||||
|
name and types set to NULL is returned. This function will only
|
||||||
|
find methods that are directly declared in the protocol itself, not
|
||||||
|
in other protocols that this protocol adopts.
|
||||||
|
|
||||||
|
Note that the traditional ABI does not store the list of optional
|
||||||
|
methods of a protocol in a compiled module, so the traditional ABI
|
||||||
|
will always return (NULL, NULL) when requiredMethod == NO. */
|
||||||
|
objc_EXPORT struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
|
||||||
|
SEL selector,
|
||||||
|
BOOL requiredMethod,
|
||||||
|
BOOL instanceMethod);
|
||||||
|
|
||||||
|
/* Return the method descriptions of all the methods of the protocol.
|
||||||
|
The return value of the function is a pointer to an area, allocated
|
||||||
|
with malloc(), that contains all the method descriptions of the
|
||||||
|
methods of the protocol. It does not recursively include methods
|
||||||
|
of the protocols adopted by this protocol. The list is terminated
|
||||||
|
by a NULL objc_method_description (one with both fields set to
|
||||||
|
NULL). Optionally, if you pass a non-NULL
|
||||||
|
'numberOfReturnedMethods' pointer, the unsigned int that it points
|
||||||
|
to will be filled with the number of properties returned.
|
||||||
|
|
||||||
|
Note that the traditional ABI does not store the list of optional
|
||||||
|
methods of a protocol in a compiled module, so the traditional ABI
|
||||||
|
will always return an empty list if requiredMethod is set to
|
||||||
|
NO. */
|
||||||
|
objc_EXPORT struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
|
||||||
|
BOOL requiredMethod,
|
||||||
|
BOOL instanceMethod,
|
||||||
|
unsigned int *numberOfReturnedMethods);
|
||||||
|
|
||||||
|
/* Return the property with name 'propertyName' of the protocol
|
||||||
|
'protocol'. If 'requiredProperty' is YES, the function searches
|
||||||
|
the list of required properties; if NO, the list of optional
|
||||||
|
properties. If 'instanceProperty' is YES, the function searches
|
||||||
|
the list of instance properties; if NO, the list of class
|
||||||
|
properties. At the moment, optional properties and class
|
||||||
|
properties are not part of the Objective-C language, so both
|
||||||
|
'requiredProperty' and 'instanceProperty' should be set to YES.
|
||||||
|
This function returns NULL if the required property can not be
|
||||||
|
found.
|
||||||
|
|
||||||
|
Note that the traditional ABI does not store the list of properties
|
||||||
|
of a protocol in a compiled module, so the traditional ABI will
|
||||||
|
always return NULL. */
|
||||||
|
objc_EXPORT Property protocol_getProperty (Protocol *protocol, const char *propertyName,
|
||||||
|
BOOL requiredProperty, BOOL instanceProperty);
|
||||||
|
|
||||||
|
/* Return all the properties of the protocol. The return value of the
|
||||||
|
function is a pointer to an area, allocated with malloc(), that
|
||||||
|
contains all the properties of the protocol. It does not
|
||||||
|
recursively include properties of the protocols adopted by this
|
||||||
|
protocol. The list is terminated by NULL. Optionally, if you pass
|
||||||
|
a non-NULL 'numberOfReturnedProperties' pointer, the unsigned int
|
||||||
|
that it points to will be filled with the number of properties
|
||||||
|
returned.
|
||||||
|
|
||||||
|
Note that the traditional ABI does not store the list of properties
|
||||||
|
of a protocol in a compiled module, so the traditional ABI will
|
||||||
|
always return NULL and store 0 in numberOfReturnedProperties. */
|
||||||
|
objc_EXPORT Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties);
|
||||||
|
|
||||||
|
/* Return all the protocols that the protocol conforms to. The return
|
||||||
|
value of the function is a pointer to an area, allocated with
|
||||||
|
malloc(), that contains all the protocols formally adopted by the
|
||||||
|
protocol. It does not recursively include protocols adopted by the
|
||||||
|
protocols adopted by this protocol. The list is terminated by
|
||||||
|
NULL. Optionally, if you pass a non-NULL
|
||||||
|
'numberOfReturnedProtocols' pointer, the unsigned int that it
|
||||||
|
points to will be filled with the number of protocols returned. */
|
||||||
|
objc_EXPORT Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols);
|
||||||
|
|
||||||
|
|
||||||
/* TODO: Add all the other functions in the API. */
|
/* TODO: Add all the other functions in the API. */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,550 @@
|
||||||
|
/* GNU Objective C Runtime protocol related functions.
|
||||||
|
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
|
Contributed by Nicola Pero
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include "objc-private/common.h"
|
||||||
|
#include "objc/objc.h"
|
||||||
|
#include "objc/runtime.h"
|
||||||
|
#include "objc-private/module-abi-8.h" /* For runtime structures */
|
||||||
|
#include "objc/thr.h"
|
||||||
|
#include "objc-private/runtime.h" /* the kitchen sink */
|
||||||
|
#include "objc-private/hash.h" /* For the hash table of protocols. */
|
||||||
|
#include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */
|
||||||
|
|
||||||
|
/* This is a table that maps a name to a Protocol instance with that
|
||||||
|
name. Because there may be multiple Protocol instances with the
|
||||||
|
same name (no harm in that) the table records only one
|
||||||
|
instance. */
|
||||||
|
static cache_ptr __protocols_hashtable;
|
||||||
|
|
||||||
|
/* A mutex protecting the protocol_hashtable. */
|
||||||
|
static objc_mutex_t __protocols_hashtable_lock = NULL;
|
||||||
|
|
||||||
|
/* Called at startup by init.c. */
|
||||||
|
void
|
||||||
|
__objc_protocols_init (void)
|
||||||
|
{
|
||||||
|
__protocols_hashtable_lock = objc_mutex_allocate ();
|
||||||
|
|
||||||
|
/* The keys in the table are strings, and the values are Protocol
|
||||||
|
objects. */
|
||||||
|
__protocols_hashtable = objc_hash_new (64, (hash_func_type) objc_hash_string,
|
||||||
|
(compare_func_type) objc_compare_strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a protocol to the hashtable. */
|
||||||
|
void
|
||||||
|
__objc_protocols_add_protocol (const char *name, Protocol *object)
|
||||||
|
{
|
||||||
|
objc_mutex_lock (__protocols_hashtable_lock);
|
||||||
|
|
||||||
|
/* If we find a protocol with the same name already in the
|
||||||
|
hashtable, we do not need to add the new one, because it will be
|
||||||
|
identical to it. This in the reasonable assumption that two
|
||||||
|
protocols with the same name are identical, which is expected in
|
||||||
|
any sane program. If we are really paranoid, we would compare
|
||||||
|
the protocols and abort if they are not identical.
|
||||||
|
Unfortunately, this would slow down the startup of all
|
||||||
|
Objective-C programs while trying to catch a problem that has
|
||||||
|
never been seen in practice, so we don't do it. */
|
||||||
|
if (! objc_hash_is_key_in_hash (__protocols_hashtable, name))
|
||||||
|
{
|
||||||
|
objc_hash_add (&__protocols_hashtable, name, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
objc_mutex_unlock (__protocols_hashtable_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
Protocol *
|
||||||
|
objc_getProtocol (const char *name)
|
||||||
|
{
|
||||||
|
Protocol *protocol;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
objc_mutex_lock (__protocols_hashtable_lock);
|
||||||
|
protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name));
|
||||||
|
objc_mutex_unlock (__protocols_hashtable_lock);
|
||||||
|
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
Protocol **
|
||||||
|
objc_copyProtocolList (unsigned int *numberOfReturnedProtocols)
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
Protocol **returnValue = NULL;
|
||||||
|
node_ptr node;
|
||||||
|
|
||||||
|
objc_mutex_lock (__protocols_hashtable_lock);
|
||||||
|
|
||||||
|
/* Count how many protocols we have. */
|
||||||
|
node = objc_hash_next (__protocols_hashtable, NULL);
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
node = objc_hash_next (__protocols_hashtable, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
/* Allocate enough memory to hold them. */
|
||||||
|
returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
|
||||||
|
|
||||||
|
/* Copy the protocols. */
|
||||||
|
node = objc_hash_next (__protocols_hashtable, NULL);
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
returnValue[i] = node->value;
|
||||||
|
i++;
|
||||||
|
node = objc_hash_next (__protocols_hashtable, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue[i] = NULL;
|
||||||
|
}
|
||||||
|
objc_mutex_unlock (__protocols_hashtable_lock);
|
||||||
|
|
||||||
|
if (numberOfReturnedProtocols)
|
||||||
|
*numberOfReturnedProtocols = count;
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
class_addProtocol (Class class_, Protocol *protocol)
|
||||||
|
{
|
||||||
|
struct objc_protocol_list *protocols;
|
||||||
|
|
||||||
|
if (class_ == Nil || protocol == NULL)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
if (class_conformsToProtocol (class_, protocol))
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
/* Check that it is a Protocol object before casting it to (struct
|
||||||
|
objc_protocol *). */
|
||||||
|
if (protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
|
/* Create the objc_protocol_list. */
|
||||||
|
protocols = malloc (sizeof (struct objc_protocol_list));
|
||||||
|
protocols->count = 1;
|
||||||
|
protocols->list[0] = protocol;
|
||||||
|
|
||||||
|
/* Attach it to the list of class protocols. */
|
||||||
|
protocols->next = class_->protocols;
|
||||||
|
class_->protocols = protocols;
|
||||||
|
|
||||||
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
class_conformsToProtocol (Class class_, Protocol *protocol)
|
||||||
|
{
|
||||||
|
struct objc_protocol_list* proto_list;
|
||||||
|
|
||||||
|
if (class_ == Nil || protocol == NULL)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
/* Check that it is a Protocol object before casting it to (struct
|
||||||
|
objc_protocol *). */
|
||||||
|
if (protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
/* Acquire the runtime lock because the list of protocols for a
|
||||||
|
class may be modified concurrently, for example if another thread
|
||||||
|
calls class_addProtocol(), or dynamically loads from a file a
|
||||||
|
category of the class. */
|
||||||
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
proto_list = class_->protocols;
|
||||||
|
|
||||||
|
while (proto_list)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < proto_list->count; i++)
|
||||||
|
{
|
||||||
|
if (proto_list->list[i] == protocol
|
||||||
|
|| protocol_conformsToProtocol (proto_list->list[i],
|
||||||
|
protocol))
|
||||||
|
{
|
||||||
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proto_list = proto_list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
Protocol **
|
||||||
|
class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
Protocol **returnValue = NULL;
|
||||||
|
struct objc_protocol_list* proto_list;
|
||||||
|
|
||||||
|
/* Lock the runtime mutex because the class protocols may be
|
||||||
|
concurrently modified. */
|
||||||
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
|
/* Count how many protocols we have. */
|
||||||
|
proto_list = class_->protocols;
|
||||||
|
|
||||||
|
while (proto_list)
|
||||||
|
{
|
||||||
|
count = count + proto_list->count;
|
||||||
|
proto_list = proto_list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
/* Allocate enough memory to hold them. */
|
||||||
|
returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
|
||||||
|
|
||||||
|
/* Copy the protocols. */
|
||||||
|
proto_list = class_->protocols;
|
||||||
|
|
||||||
|
while (proto_list)
|
||||||
|
{
|
||||||
|
size_t j;
|
||||||
|
for (j = 0; j < proto_list->count; j++)
|
||||||
|
{
|
||||||
|
returnValue[i] = proto_list->list[j];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
proto_list = proto_list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue[i] = NULL;
|
||||||
|
}
|
||||||
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
|
if (numberOfReturnedProtocols)
|
||||||
|
*numberOfReturnedProtocols = count;
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol)
|
||||||
|
{
|
||||||
|
struct objc_protocol_list* proto_list;
|
||||||
|
|
||||||
|
if (protocol == NULL || anotherProtocol == NULL)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
if (protocol == anotherProtocol)
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
/* Check that the objects are Protocol objects before casting them
|
||||||
|
to (struct objc_protocol *). */
|
||||||
|
if (protocol->class_pointer != anotherProtocol->class_pointer)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
if (protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
|
||||||
|
((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
/* We do not acquire any lock because protocols are currently
|
||||||
|
immutable. We can freely iterate over a protocol structure. */
|
||||||
|
proto_list = ((struct objc_protocol *)protocol)->protocol_list;
|
||||||
|
while (proto_list)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < proto_list->count; i++)
|
||||||
|
{
|
||||||
|
if (protocol_conformsToProtocol (proto_list->list[i], anotherProtocol))
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
proto_list = proto_list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol)
|
||||||
|
{
|
||||||
|
if (protocol == anotherProtocol)
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
if (protocol == NULL || anotherProtocol == NULL)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
/* Check that the objects are Protocol objects before casting them
|
||||||
|
to (struct objc_protocol *). */
|
||||||
|
if (protocol->class_pointer != anotherProtocol->class_pointer)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
if (protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
/* Equality between formal protocols is only formal (nothing to do
|
||||||
|
with actually checking the list of methods they have!). Two
|
||||||
|
formal Protocols are equal if and only if they have the same
|
||||||
|
name.
|
||||||
|
|
||||||
|
Please note (for comparisons with other implementations) that
|
||||||
|
checking the names is equivalent to checking that Protocol A
|
||||||
|
conforms to Protocol B and Protocol B conforms to Protocol A,
|
||||||
|
because this happens iff they have the same name. If they have
|
||||||
|
different names, A conforms to B if and only if A includes B, but
|
||||||
|
the situation where A includes B and B includes A is a circular
|
||||||
|
dependency between Protocols which is forbidden by the compiler,
|
||||||
|
so A conforms to B and B conforms to A with A and B having
|
||||||
|
different names is an impossible case. */
|
||||||
|
if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
|
||||||
|
((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
protocol_getName (Protocol *protocol)
|
||||||
|
{
|
||||||
|
/* Check that it is a Protocol object before casting it to (struct
|
||||||
|
objc_protocol *). */
|
||||||
|
if (protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ((struct objc_protocol *)protocol)->protocol_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
|
||||||
|
SEL selector,
|
||||||
|
BOOL requiredMethod,
|
||||||
|
BOOL instanceMethod)
|
||||||
|
{
|
||||||
|
struct objc_method_description no_result = { NULL, NULL };
|
||||||
|
const char* selector_name;
|
||||||
|
struct objc_method_description_list *methods;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* TODO: New ABI. */
|
||||||
|
/* The current ABI does not have any information on optional protocol methods. */
|
||||||
|
if (! requiredMethod)
|
||||||
|
return no_result;
|
||||||
|
|
||||||
|
/* Check that it is a Protocol object before casting it to (struct
|
||||||
|
objc_protocol *). */
|
||||||
|
if (protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
return no_result;
|
||||||
|
|
||||||
|
selector_name = sel_getName (selector);
|
||||||
|
|
||||||
|
if (instanceMethod)
|
||||||
|
methods = ((struct objc_protocol *)protocol)->instance_methods;
|
||||||
|
else
|
||||||
|
methods = ((struct objc_protocol *)protocol)->class_methods;
|
||||||
|
|
||||||
|
if (methods)
|
||||||
|
{
|
||||||
|
for (i = 0; i < methods->count; i++)
|
||||||
|
{
|
||||||
|
if (strcmp ((char*)(methods->list[i].name), selector_name) == 0)
|
||||||
|
return methods->list[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return no_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
|
||||||
|
BOOL requiredMethod,
|
||||||
|
BOOL instanceMethod,
|
||||||
|
unsigned int *numberOfReturnedMethods)
|
||||||
|
{
|
||||||
|
struct objc_method_description_list *methods;
|
||||||
|
unsigned int count = 0;
|
||||||
|
struct objc_method_description *returnValue = NULL;
|
||||||
|
|
||||||
|
/* TODO: New ABI */
|
||||||
|
/* The current ABI does not have any information on optional protocol methods. */
|
||||||
|
if (! requiredMethod)
|
||||||
|
{
|
||||||
|
if (numberOfReturnedMethods)
|
||||||
|
*numberOfReturnedMethods = 0;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that it is a Protocol object before casting it to (struct
|
||||||
|
objc_protocol *). */
|
||||||
|
if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
{
|
||||||
|
if (numberOfReturnedMethods)
|
||||||
|
*numberOfReturnedMethods = 0;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We do not acquire any lock because protocols are currently
|
||||||
|
immutable. We can freely iterate over a protocol structure. */
|
||||||
|
|
||||||
|
if (instanceMethod)
|
||||||
|
methods = ((struct objc_protocol *)protocol)->instance_methods;
|
||||||
|
else
|
||||||
|
methods = ((struct objc_protocol *)protocol)->class_methods;
|
||||||
|
|
||||||
|
if (methods)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
count = methods->count;
|
||||||
|
|
||||||
|
/* Allocate enough memory to hold them. */
|
||||||
|
returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1)));
|
||||||
|
|
||||||
|
/* Copy them. */
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
returnValue[i].name = methods->list[i].name;
|
||||||
|
returnValue[i].types = methods->list[i].types;
|
||||||
|
}
|
||||||
|
returnValue[i].name = NULL;
|
||||||
|
returnValue[i].types = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numberOfReturnedMethods)
|
||||||
|
*numberOfReturnedMethods = count;
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Property protocol_getProperty (Protocol *protocol, const char *propertyName,
|
||||||
|
BOOL requiredProperty, BOOL instanceProperty)
|
||||||
|
{
|
||||||
|
if (protocol == NULL || propertyName == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!requiredProperty || !instanceProperty)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Check that it is a Protocol object before casting it to (struct
|
||||||
|
objc_protocol *). */
|
||||||
|
if (protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* TODO: New ABI. */
|
||||||
|
/* The current ABI does not have any information on protocol properties. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties)
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
Property *returnValue = NULL;
|
||||||
|
|
||||||
|
/* Check that it is a Protocol object before casting it to (struct
|
||||||
|
objc_protocol *). */
|
||||||
|
if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
{
|
||||||
|
if (numberOfReturnedProperties)
|
||||||
|
*numberOfReturnedProperties = 0;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We do not acquire any lock because protocols are currently
|
||||||
|
immutable. We can freely iterate over a protocol structure. */
|
||||||
|
|
||||||
|
/* TODO: New ABI. */
|
||||||
|
/* The current ABI does not have any information on protocol properties. */
|
||||||
|
if (numberOfReturnedProperties)
|
||||||
|
*numberOfReturnedProperties = count;
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols)
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
Protocol **returnValue = NULL;
|
||||||
|
struct objc_protocol_list* proto_list;
|
||||||
|
|
||||||
|
/* Check that it is a Protocol object before casting it to (struct
|
||||||
|
objc_protocol *). */
|
||||||
|
if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
|
||||||
|
{
|
||||||
|
if (numberOfReturnedProtocols)
|
||||||
|
*numberOfReturnedProtocols = 0;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We do not acquire any lock because protocols are currently
|
||||||
|
immutable. We can freely iterate over a protocol structure. */
|
||||||
|
|
||||||
|
/* Count how many protocols we have. */
|
||||||
|
proto_list = ((struct objc_protocol *)protocol)->protocol_list;
|
||||||
|
|
||||||
|
while (proto_list)
|
||||||
|
{
|
||||||
|
count = count + proto_list->count;
|
||||||
|
proto_list = proto_list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
/* Allocate enough memory to hold them. */
|
||||||
|
returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
|
||||||
|
|
||||||
|
/* Copy the protocols. */
|
||||||
|
proto_list = ((struct objc_protocol *)protocol)->protocol_list;
|
||||||
|
|
||||||
|
while (proto_list)
|
||||||
|
{
|
||||||
|
size_t j;
|
||||||
|
for (j = 0; j < proto_list->count; j++)
|
||||||
|
{
|
||||||
|
returnValue[i] = proto_list->list[j];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
proto_list = proto_list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numberOfReturnedProtocols)
|
||||||
|
*numberOfReturnedProtocols = count;
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
|
@ -163,6 +163,14 @@ void __objc_register_instance_methods_to_class (Class class)
|
||||||
__objc_update_dispatch_table_for_class (class->class_pointer);
|
__objc_update_dispatch_table_for_class (class->class_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
sel_isEqual (SEL s1, SEL s2)
|
||||||
|
{
|
||||||
|
if (s1 == 0 || s2 == 0)
|
||||||
|
return s1 == s2;
|
||||||
|
else
|
||||||
|
return s1->sel_id == s2->sel_id;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns YES iff t1 and t2 have same method types, but we ignore
|
/* Returns YES iff t1 and t2 have same method types, but we ignore
|
||||||
the argframe layout */
|
the argframe layout */
|
||||||
|
|
Loading…
Reference in New Issue