diff options
Diffstat (limited to 'libobjc/methods.c')
-rw-r--r-- | libobjc/methods.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/libobjc/methods.c b/libobjc/methods.c new file mode 100644 index 000000000..b4faee533 --- /dev/null +++ b/libobjc/methods.c @@ -0,0 +1,177 @@ +/* GNU Objective C Runtime method 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/runtime.h" +#include "objc-private/module-abi-8.h" /* For runtime structures. */ +#include "objc/thr.h" +#include "objc-private/runtime.h" /* For __objc_runtime_mutex. */ +#include <stdlib.h> /* For malloc. */ + +SEL +method_getName (struct objc_method * method) +{ + if (method == NULL) + return NULL; + + return method->method_name; +} + +const char * +method_getTypeEncoding (struct objc_method * method) +{ + if (method == NULL) + return NULL; + + return method->method_types; +} + +IMP +method_getImplementation (struct objc_method * method) +{ + if (method == NULL) + return NULL; + + return method->method_imp; +} + +struct objc_method_description * +method_getDescription (struct objc_method * method) +{ + /* Note that the following returns NULL if method is NULL, which is + fine. */ + return (struct objc_method_description *)method; +} + +struct objc_method ** +class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods) +{ + unsigned int count = 0; + struct objc_method **returnValue = NULL; + struct objc_method_list* method_list; + + if (class_ == Nil) + { + if (numberOfReturnedMethods) + *numberOfReturnedMethods = 0; + return NULL; + } + + /* Lock the runtime mutex because the class methods may be + concurrently modified. */ + objc_mutex_lock (__objc_runtime_mutex); + + /* Count how many methods we have. */ + method_list = class_->methods; + + while (method_list) + { + count = count + method_list->method_count; + method_list = method_list->method_next; + } + + if (count != 0) + { + unsigned int i = 0; + + /* Allocate enough memory to hold them. */ + returnValue + = (struct objc_method **)(malloc (sizeof (struct objc_method *) + * (count + 1))); + + /* Copy the methods. */ + method_list = class_->methods; + + while (method_list) + { + int j; + for (j = 0; j < method_list->method_count; j++) + { + returnValue[i] = &(method_list->method_list[j]); + i++; + } + method_list = method_list->method_next; + } + + returnValue[i] = NULL; + } + + objc_mutex_unlock (__objc_runtime_mutex); + + if (numberOfReturnedMethods) + *numberOfReturnedMethods = count; + + return returnValue; +} + +IMP +method_setImplementation (struct objc_method * method, IMP implementation) +{ + IMP old_implementation; + + if (method == NULL || implementation == NULL) + return NULL; + + /* We lock the runtime mutex so that concurrent calls to change the + same method won't conflict with each other. */ + objc_mutex_lock (__objc_runtime_mutex); + + old_implementation = method->method_imp; + method->method_imp = implementation; + + /* That was easy :-). But now we need to find all classes that use + this method, and update the IMP in the dispatch tables. */ + __objc_update_classes_with_methods (method, NULL); + + objc_mutex_unlock (__objc_runtime_mutex); + + return old_implementation; +} + +void +method_exchangeImplementations (struct objc_method * method_a, struct objc_method * method_b) +{ + IMP old_implementation_a; + IMP old_implementation_b; + + if (method_a == NULL || method_b == NULL) + return; + + /* We lock the runtime mutex so that concurrent calls to exchange + similar methods won't conflict with each other. Each of them + should be atomic. */ + objc_mutex_lock (__objc_runtime_mutex); + + old_implementation_a = method_a->method_imp; + old_implementation_b = method_b->method_imp; + + method_a->method_imp = old_implementation_b; + method_b->method_imp = old_implementation_a; + + /* That was easy :-). But now we need to find all classes that use + these methods, and update the IMP in the dispatch tables. */ + __objc_update_classes_with_methods (method_a, method_b); + + objc_mutex_unlock (__objc_runtime_mutex); +} |