PageRenderTime 46ms CodeModel.GetById 15ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/core/externals/update-engine/externals/google-toolbox-for-mac/Foundation/GTMObjC2Runtime.m

http://macfuse.googlecode.com/
Objective C | 163 lines | 101 code | 20 blank | 42 comment | 31 complexity | 42e09ce87bcba77abba15d303e4ddd83 MD5 | raw file
  1//
  2//  GTMObjC2Runtime.m
  3//
  4//  Copyright 2007-2008 Google Inc.
  5//
  6//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7//  use this file except in compliance with the License.  You may obtain a copy
  8//  of the License at
  9//
 10//  http://www.apache.org/licenses/LICENSE-2.0
 11//
 12//  Unless required by applicable law or agreed to in writing, software
 13//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 14//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 15//  License for the specific language governing permissions and limitations under
 16//  the License.
 17//
 18
 19#import "GTMObjC2Runtime.h"
 20
 21#if GTM_MACOS_SDK && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
 22#import <stdlib.h>
 23#import <string.h>
 24
 25Class object_getClass(id obj) {
 26  if (!obj) return NULL;
 27  return obj->isa;
 28}
 29
 30const char *class_getName(Class cls) {
 31  if (!cls) return "nil";
 32  return cls->name;
 33}
 34
 35BOOL class_conformsToProtocol(Class cls, Protocol *protocol) {
 36  // We intentionally don't check cls as it crashes on Leopard so we want
 37  // to crash on Tiger as well.
 38  // I logged
 39  // Radar 5572978 class_conformsToProtocol crashes when arg1 is passed as nil
 40  // because it seems odd that this API won't accept nil for cls considering
 41  // all the other apis will accept nil args.
 42  // If this does get fixed, remember to enable the unit tests.
 43  if (!protocol) return NO;
 44
 45  struct objc_protocol_list *protos;
 46  for (protos = cls->protocols; protos != NULL; protos = protos->next) {
 47    for (long i = 0; i < protos->count; i++) {
 48      if ([protos->list[i] conformsTo:protocol]) {
 49        return YES;
 50      }
 51    }
 52  }
 53  return NO;
 54}
 55
 56Class class_getSuperclass(Class cls) {
 57  if (!cls) return NULL;
 58  return cls->super_class;
 59}
 60
 61BOOL class_respondsToSelector(Class cls, SEL sel) {
 62  return class_getInstanceMethod(cls, sel) != nil;
 63}
 64
 65Method *class_copyMethodList(Class cls, unsigned int *outCount) {
 66  if (!cls) return NULL;
 67
 68  unsigned int count = 0;
 69  void *iterator = NULL;
 70  struct objc_method_list *mlist;
 71  Method *methods = NULL;
 72  if (outCount) *outCount = 0;
 73
 74  while ( (mlist = class_nextMethodList(cls, &iterator)) ) {
 75    if (mlist->method_count == 0) continue;
 76    methods = (Method *)realloc(methods,
 77                                sizeof(Method) * (count + mlist->method_count + 1));
 78    if (!methods) {
 79      //Memory alloc failed, so what can we do?
 80      return NULL;  // COV_NF_LINE
 81    }
 82    for (int i = 0; i < mlist->method_count; i++) {
 83      methods[i + count] = &mlist->method_list[i];
 84    }
 85    count += mlist->method_count;
 86  }
 87
 88  // List must be NULL terminated
 89  if (methods) {
 90    methods[count] = NULL;
 91  }
 92  if (outCount) *outCount = count;
 93  return methods;
 94}
 95
 96SEL method_getName(Method method) {
 97  if (!method) return NULL;
 98  return method->method_name;
 99}
100
101IMP method_getImplementation(Method method) {
102  if (!method) return NULL;
103  return method->method_imp;
104}
105
106IMP method_setImplementation(Method method, IMP imp) {
107  // We intentionally don't test method for nil.
108  // Leopard fails here, so should we.
109  // I logged this as Radar:
110  // 5572981 method_setImplementation crashes if you pass nil for the
111  // method arg (arg 1)
112  // because it seems odd that this API won't accept nil for method considering
113  // all the other apis will accept nil args.
114  // If this does get fixed, remember to enable the unit tests.
115  // This method works differently on SnowLeopard than
116  // on Leopard. If you pass in a nil for IMP on SnowLeopard
117  // it doesn't change anything. On Leopard it will. Since
118  // attempting to change a sel to nil is probably an error
119  // we follow the SnowLeopard way of doing things.
120  IMP oldImp = NULL;
121  if (imp) {
122    oldImp = method->method_imp;
123    method->method_imp = imp;
124  }
125  return oldImp;
126}
127
128void method_exchangeImplementations(Method m1, Method m2) {
129  if (m1 == m2) return;
130  if (!m1 || !m2) return;
131  IMP imp2 = method_getImplementation(m2);
132  IMP imp1 = method_setImplementation(m1, imp2);
133  method_setImplementation(m2, imp1);
134}
135
136struct objc_method_description protocol_getMethodDescription(Protocol *p,
137                                                             SEL aSel,
138                                                             BOOL isRequiredMethod,
139                                                             BOOL isInstanceMethod) {
140  struct objc_method_description *descPtr = NULL;
141  // No such thing as required in ObjC1.
142  if (isInstanceMethod) {
143    descPtr = [p descriptionForInstanceMethod:aSel];
144  } else {
145    descPtr = [p descriptionForClassMethod:aSel];
146  }
147
148  struct objc_method_description desc;
149  if (descPtr) {
150    desc = *descPtr;
151  } else {
152    bzero(&desc, sizeof(desc));
153  }
154  return desc;
155}
156
157BOOL sel_isEqual(SEL lhs, SEL rhs) {
158  // Apple (informally) promises this will work in the future:
159  // http://twitter.com/#!/gparker/status/2400099786
160  return (lhs == rhs) ? YES : NO;
161}
162
163#endif  // GTM_MACOS_SDK && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)