OLD | NEW |
1 //------------------------------------------------------------------------------
--------- | 1 /* |
2 // $Id$ | 2 * Copyright (c) 2009-2015 Erik Doernenburg and contributors |
3 // Copyright (c) 2009 by Mulle Kybernetik. See License file for details. | 3 * |
4 //------------------------------------------------------------------------------
--------- | 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 5 * not use these files except in compliance with the License. You may obtain |
| 6 * a copy of the License at |
| 7 * |
| 8 * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 * |
| 10 * Unless required by applicable law or agreed to in writing, software |
| 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 13 * License for the specific language governing permissions and limitations |
| 14 * under the License. |
| 15 */ |
5 | 16 |
6 #import "NSMethodSignature+OCMAdditions.h" | 17 #import "NSMethodSignature+OCMAdditions.h" |
| 18 #import "OCMFunctionsPrivate.h" |
| 19 #import <objc/runtime.h> |
7 | 20 |
8 | 21 |
9 @implementation NSMethodSignature(OCMAdditions) | 22 @implementation NSMethodSignature(OCMAdditions) |
10 | 23 |
11 - (const char *)methodReturnTypeWithoutQualifiers | 24 + (NSMethodSignature *)signatureOfGetterForDynamicProperty:(NSString *)propertyN
ame inClass:(Class)aClass |
12 { | 25 { |
13 » const char *returnType = [self methodReturnType]; | 26 objc_property_t property = class_getProperty(aClass, [propertyName cStringUs
ingEncoding:NSASCIIStringEncoding]); |
14 » while(strchr("rnNoORV", returnType[0]) != NULL) | 27 if(property == NULL) |
15 » » returnType += 1; | 28 return nil; |
16 » return returnType; | 29 |
| 30 const char *propertyAttributesString = property_getAttributes(property); |
| 31 if(propertyAttributesString == NULL) |
| 32 return nil; |
| 33 |
| 34 NSArray *propertyAttributes = [[NSString stringWithCString:propertyAttribute
sString |
| 35 encoding:NSASCIIStringEnco
ding] componentsSeparatedByString:@","]; |
| 36 BOOL isDynamic = NO; |
| 37 NSString *typeStr = nil; |
| 38 for(NSString *attribute in propertyAttributes) |
| 39 { |
| 40 if([attribute isEqualToString:@"D"]) |
| 41 { |
| 42 //property is @dynamic, but we can synthesize the signature |
| 43 isDynamic = YES; |
| 44 } |
| 45 else if([attribute hasPrefix:@"T"]) |
| 46 { |
| 47 typeStr = [attribute substringFromIndex:1]; |
| 48 } |
| 49 } |
| 50 |
| 51 if(!isDynamic) |
| 52 return nil; |
| 53 |
| 54 NSRange r = [typeStr rangeOfString:@"\""]; |
| 55 if(r.location != NSNotFound) |
| 56 { |
| 57 typeStr = [typeStr substringToIndex:r.location]; |
| 58 } |
| 59 const char *str = [[NSString stringWithFormat:@"%@@:", typeStr] cStringUsing
Encoding:NSASCIIStringEncoding]; |
| 60 return [NSMethodSignature signatureWithObjCTypes:str]; |
| 61 } |
| 62 |
| 63 |
| 64 struct OCMBlockDef |
| 65 { |
| 66 void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlo
ck |
| 67 int flags; |
| 68 int reserved; |
| 69 void (*invoke)(void *, ...); |
| 70 struct block_descriptor { |
| 71 unsigned long int reserved; // NULL |
| 72 unsigned long int size; // sizeof(struct Block_liter
al_1) |
| 73 // optional helper functions |
| 74 void (*copy_helper)(void *dst, void *src); // IFF (1<<25) |
| 75 void (*dispose_helper)(void *src); // IFF (1<<25) |
| 76 // required ABI.2010.3.16 |
| 77 const char *signature; // IFF (1<<30) |
| 78 } *descriptor; |
| 79 }; |
| 80 |
| 81 enum |
| 82 { |
| 83 OCMBlockDescriptionFlagsHasCopyDispose = (1 << 25), |
| 84 OCMBlockDescriptionFlagsHasSignature = (1 << 30) |
| 85 }; |
| 86 |
| 87 |
| 88 + (NSMethodSignature *)signatureForBlock:(id)block |
| 89 { |
| 90 /* For a more complete implementation of parsing the block data structure se
e: |
| 91 * |
| 92 * https://github.com/ebf/CTObjectiveCRuntimeAdditions/tree/master/CTObjecti
veCRuntimeAdditions/CTObjectiveCRuntimeAdditions |
| 93 */ |
| 94 |
| 95 struct OCMBlockDef *blockRef = (__bridge struct OCMBlockDef *)block; |
| 96 |
| 97 if(!(blockRef->flags & OCMBlockDescriptionFlagsHasSignature)) |
| 98 return nil; |
| 99 |
| 100 void *signatureLocation = blockRef->descriptor; |
| 101 signatureLocation += sizeof(unsigned long int); |
| 102 signatureLocation += sizeof(unsigned long int); |
| 103 if(blockRef->flags & OCMBlockDescriptionFlagsHasCopyDispose) |
| 104 { |
| 105 signatureLocation += sizeof(void(*)(void *dst, void *src)); |
| 106 signatureLocation += sizeof(void (*)(void *src)); |
| 107 } |
| 108 |
| 109 const char *signature = (*(const char **)signatureLocation); |
| 110 return [NSMethodSignature signatureWithObjCTypes:signature]; |
| 111 } |
| 112 |
| 113 |
| 114 - (BOOL)usesSpecialStructureReturn |
| 115 { |
| 116 const char *types = OCMTypeWithoutQualifiers([self methodReturnType]); |
| 117 |
| 118 if((types == NULL) || (types[0] != '{')) |
| 119 return NO; |
| 120 |
| 121 /* In some cases structures are returned by ref. The rules are complex and d
epend on the |
| 122 architecture, see: |
| 123 |
| 124 http://sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSe
nd_stret.html |
| 125 http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conc
eptual/LowLevelABI/000-Introduction/introduction.html |
| 126 https://github.com/atgreen/libffi/blob/master/src/x86/ffi64.c |
| 127 http://www.uclibc.org/docs/psABI-x86_64.pdf |
| 128 http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.
pdf |
| 129 |
| 130 NSMethodSignature knows the details but has no API to return it, though i
t is in |
| 131 the debugDescription. Horribly kludgy. |
| 132 */ |
| 133 NSRange range = [[self debugDescription] rangeOfString:@"is special struct r
eturn? YES"]; |
| 134 return range.length > 0; |
| 135 } |
| 136 |
| 137 |
| 138 - (NSString *)fullTypeString |
| 139 { |
| 140 NSMutableString *typeString = [NSMutableString string]; |
| 141 [typeString appendFormat:@"%s", [self methodReturnType]]; |
| 142 for (NSUInteger i=0; i<[self numberOfArguments]; i++) |
| 143 [typeString appendFormat:@"%s", [self getArgumentTypeAtIndex:i]]; |
| 144 return typeString; |
| 145 } |
| 146 |
| 147 |
| 148 - (const char *)fullObjCTypes |
| 149 { |
| 150 return [[self fullTypeString] UTF8String]; |
17 } | 151 } |
18 | 152 |
19 @end | 153 @end |
OLD | NEW |