summaryrefslogtreecommitdiff
path: root/libobjc/methods.c
diff options
context:
space:
mode:
Diffstat (limited to 'libobjc/methods.c')
-rw-r--r--libobjc/methods.c177
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);
+}