aboutsummaryrefslogtreecommitdiff
path: root/Foundation/GTMObjC2Runtime.m
diff options
context:
space:
mode:
authorGravatar thomasvl <thomasvl@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-04-14 17:21:02 +0000
committerGravatar thomasvl <thomasvl@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-04-14 17:21:02 +0000
commitcdf070c8d76ffc4eaa24e8671756cbbe9ceb2890 (patch)
treefaa9ae3a72a6591d6a6add7ceed7f91e92ade11f /Foundation/GTMObjC2Runtime.m
parent0aaecac6ff2bc89e58a0c8c6d6ad62e02fb2b011 (diff)
See the ReleaseNotes for the full details, highlights:
- bug fixes - code coverage support - more complete unittests - full support for unittesting UIs - support for the iphone sdk (include ui unittesting)
Diffstat (limited to 'Foundation/GTMObjC2Runtime.m')
-rw-r--r--Foundation/GTMObjC2Runtime.m148
1 files changed, 148 insertions, 0 deletions
diff --git a/Foundation/GTMObjC2Runtime.m b/Foundation/GTMObjC2Runtime.m
new file mode 100644
index 0000000..00a3c6e
--- /dev/null
+++ b/Foundation/GTMObjC2Runtime.m
@@ -0,0 +1,148 @@
+//
+// GTMObjC2Runtime.m
+//
+// Copyright 2007-2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#import "GTMObjC2Runtime.h"
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+#import <stdlib.h>
+#import <string.h>
+
+Class object_getClass(id obj) {
+ if (!obj) return NULL;
+ return obj->isa;
+}
+
+const char *class_getName(Class cls) {
+ if (!cls) return "nil";
+ return cls->name;
+}
+
+BOOL class_conformsToProtocol(Class cls, Protocol *protocol) {
+ // We intentionally don't check cls as it crashes on Leopard so we want
+ // to crash on Tiger as well.
+ // I logged
+ // Radar 5572978 class_conformsToProtocol crashes when arg1 is passed as nil
+ // because it seems odd that this API won't accept nil for cls considering
+ // all the other apis will accept nil args.
+ // If this does get fixed, remember to enable the unit tests.
+ if (!protocol) return NO;
+
+ struct objc_protocol_list *protos;
+ for (protos = cls->protocols; protos != NULL; protos = protos->next) {
+ for (int i = 0; i < protos->count; i++) {
+ if ([protos->list[i] conformsTo:protocol]) {
+ return YES;
+ }
+ }
+ }
+ return NO;
+}
+
+Class class_getSuperclass(Class cls) {
+ if (!cls) return NULL;
+ return cls->super_class;
+}
+
+Method *class_copyMethodList(Class cls, unsigned int *outCount) {
+ if (!cls) return NULL;
+
+ unsigned int count = 0;
+ void *iterator = NULL;
+ struct objc_method_list *mlist;
+ Method *methods = NULL;
+ if (outCount) *outCount = 0;
+
+ while ( (mlist = class_nextMethodList(cls, &iterator)) ) {
+ if (mlist->method_count == 0) continue;
+ methods = (Method *)realloc(methods,
+ sizeof(Method) * (count + mlist->method_count + 1));
+ if (!methods) {
+ //Memory alloc failed, so what can we do?
+ return NULL; // COV_NF_LINE
+ }
+ for (int i = 0; i < mlist->method_count; i++) {
+ methods[i + count] = &mlist->method_list[i];
+ }
+ count += mlist->method_count;
+ }
+
+ // List must be NULL terminated
+ if (methods) {
+ methods[count] = NULL;
+ }
+ if (outCount) *outCount = count;
+ return methods;
+}
+
+SEL method_getName(Method method) {
+ if (!method) return NULL;
+ return method->method_name;
+}
+
+IMP method_getImplementation(Method method) {
+ if (!method) return NULL;
+ return method->method_imp;
+}
+
+IMP method_setImplementation(Method method, IMP imp) {
+ // We intentionally don't test method for nil.
+ // Leopard fails here, so should we.
+ // I logged this as Radar:
+ // 5572981 method_setImplementation crashes if you pass nil for the
+ // method arg (arg 1)
+ // because it seems odd that this API won't accept nil for method considering
+ // all the other apis will accept nil args.
+ // If this does get fixed, remember to enable the unit tests.
+ IMP oldImp = method->method_imp;
+ method->method_imp = imp;
+ return oldImp;
+}
+
+void method_exchangeImplementations(Method m1, Method m2) {
+ if (m1 == m2) return;
+ if (!m1 || !m2) return;
+ IMP imp2 = method_getImplementation(m2);
+ IMP imp1 = method_setImplementation(m1, imp2);
+ method_setImplementation(m2, imp1);
+}
+
+struct objc_method_description protocol_getMethodDescription(Protocol *p,
+ SEL aSel,
+ BOOL isRequiredMethod,
+ BOOL isInstanceMethod) {
+ struct objc_method_description *descPtr = NULL;
+ // No such thing as required in ObjC1.
+ if (isInstanceMethod) {
+ descPtr = [p descriptionForInstanceMethod:aSel];
+ } else {
+ descPtr = [p descriptionForClassMethod:aSel];
+ }
+
+ struct objc_method_description desc;
+ if (descPtr) {
+ desc = *descPtr;
+ } else {
+ bzero(&desc, sizeof(desc));
+ }
+ return desc;
+}
+
+
+#endif
+
+