123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- //
- // FLEXBlockDescription.m
- // FLEX
- //
- // Created by Oliver Letterer on 2012-09-01
- // Forked from CTObjectiveCRuntimeAdditions (MIT License)
- // https://github.com/ebf/CTObjectiveCRuntimeAdditions
- //
- // Copyright (c) 2020 FLEX Team-EDV Beratung Föllmer GmbH
- // Permission is hereby granted, free of charge, to any person obtaining a copy of this
- // software and associated documentation files (the "Software"), to deal in the Software
- // without restriction, including without limitation the rights to use, copy, modify, merge,
- // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
- // to whom the Software is furnished to do so, subject to the following conditions:
- // The above copyright notice and this permission notice shall be included in all copies or
- // substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
- // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- #import "FLEXBlockDescription.h"
- #import "FLEXRuntimeUtility.h"
- struct block_object {
- void *isa;
- int flags;
- int reserved;
- void (*invoke)(void *, ...);
- struct block_descriptor {
- unsigned long int reserved; // NULL
- unsigned long int size; // sizeof(struct Block_literal_1)
- // optional helper functions
- void (*copy_helper)(void *dst, void *src); // IFF (1<<25)
- void (*dispose_helper)(void *src); // IFF (1<<25)
- // required ABI.2010.3.16
- const char *signature; // IFF (1<<30)
- } *descriptor;
- // imported variables
- };
- @implementation FLEXBlockDescription
- + (instancetype)describing:(id)block {
- return [[self alloc] initWithObjcBlock:block];
- }
- - (id)initWithObjcBlock:(id)block {
- self = [super init];
- if (self) {
- _block = block;
-
- struct block_object *blockRef = (__bridge struct block_object *)block;
- _flags = blockRef->flags;
- _size = blockRef->descriptor->size;
-
- if (_flags & FLEXBlockOptionHasSignature) {
- void *signatureLocation = blockRef->descriptor;
- signatureLocation += sizeof(unsigned long int);
- signatureLocation += sizeof(unsigned long int);
-
- if (_flags & FLEXBlockOptionHasCopyDispose) {
- signatureLocation += sizeof(void(*)(void *dst, void *src));
- signatureLocation += sizeof(void (*)(void *src));
- }
-
- const char *signature = (*(const char **)signatureLocation);
- _signatureString = @(signature);
-
- @try {
- _signature = [NSMethodSignature signatureWithObjCTypes:signature];
- } @catch (NSException *exception) { }
- }
-
- NSMutableString *summary = [NSMutableString stringWithFormat:
- @"Type signature: %@\nSize: %@\nIs global: %@\nHas constructor: %@\nIs stret: %@",
- self.signatureString ?: @"nil", @(self.size),
- @((BOOL)(_flags & FLEXBlockOptionIsGlobal)),
- @((BOOL)(_flags & FLEXBlockOptionHasCtor)),
- @((BOOL)(_flags & FLEXBlockOptionHasStret))
- ];
-
- if (!self.signature) {
- [summary appendFormat:@"\nNumber of arguments: %@", @(self.signature.numberOfArguments)];
- }
-
- _summary = summary.copy;
- _sourceDeclaration = [self buildLikelyDeclaration];
- }
-
- return self;
- }
- - (BOOL)isCompatibleForBlockSwizzlingWithMethodSignature:(NSMethodSignature *)methodSignature {
- if (!self.signature) {
- return NO;
- }
-
- if (self.signature.numberOfArguments != methodSignature.numberOfArguments + 1) {
- return NO;
- }
-
- if (strcmp(self.signature.methodReturnType, methodSignature.methodReturnType) != 0) {
- return NO;
- }
-
- for (int i = 0; i < methodSignature.numberOfArguments; i++) {
- if (i == 1) {
- // SEL in method, IMP in block
- if (strcmp([methodSignature getArgumentTypeAtIndex:i], ":") != 0) {
- return NO;
- }
-
- if (strcmp([self.signature getArgumentTypeAtIndex:i + 1], "^?") != 0) {
- return NO;
- }
- } else {
- if (strcmp([self.signature getArgumentTypeAtIndex:i], [self.signature getArgumentTypeAtIndex:i + 1]) != 0) {
- return NO;
- }
- }
- }
-
- return YES;
- }
- - (NSString *)buildLikelyDeclaration {
- NSMethodSignature *signature = self.signature;
- NSUInteger numberOfArguments = signature.numberOfArguments;
- const char *returnType = signature.methodReturnType;
-
- // Return type
- NSMutableString *decl = [NSMutableString stringWithString:@"^"];
- if (returnType[0] != FLEXTypeEncodingVoid) {
- [decl appendString:[FLEXRuntimeUtility readableTypeForEncoding:@(returnType)]];
- [decl appendString:@" "];
- }
-
- // Arguments
- if (numberOfArguments) {
- [decl appendString:@"("];
- for (NSUInteger i = 1; i < numberOfArguments; i++) {
- const char *argType = [self.signature getArgumentTypeAtIndex:i] ?: "?";
- NSString *readableArgType = [FLEXRuntimeUtility readableTypeForEncoding:@(argType)];
- [decl appendFormat:@"%@ arg%@, ", readableArgType, @(i)];
- }
-
- [decl deleteCharactersInRange:NSMakeRange(decl.length-2, 2)];
- [decl appendString:@")"];
- }
-
- return decl.copy;
- }
- @end
|