mirror of
				https://github.com/SoPat712/YTLitePlus.git
				synced 2025-10-31 12:54:13 -04:00 
			
		
		
		
	added files via upload
This commit is contained in:
		
							
								
								
									
										430
									
								
								Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethod.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										430
									
								
								Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethod.m
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,430 @@ | ||||
| // | ||||
| //  FLEXMethod.m | ||||
| //  FLEX | ||||
| // | ||||
| //  Derived from MirrorKit. | ||||
| //  Created by Tanner on 6/30/15. | ||||
| //  Copyright (c) 2020 FLEX Team. All rights reserved. | ||||
| // | ||||
|  | ||||
| #import "FLEXMethod.h" | ||||
| #import "FLEXMirror.h" | ||||
| #import "FLEXTypeEncodingParser.h" | ||||
| #import "FLEXRuntimeUtility.h" | ||||
| #include <dlfcn.h> | ||||
|  | ||||
| @implementation FLEXMethod | ||||
| @synthesize imagePath = _imagePath; | ||||
| @dynamic implementation; | ||||
|  | ||||
| + (instancetype)buildMethodNamed:(NSString *)name withTypes:(NSString *)typeEncoding implementation:(IMP)implementation { | ||||
|     [NSException raise:NSInternalInconsistencyException format:@"Class instance should not be created with +buildMethodNamed:withTypes:implementation"]; return nil; | ||||
| } | ||||
|  | ||||
| - (id)init { | ||||
|     [NSException | ||||
|         raise:NSInternalInconsistencyException | ||||
|         format:@"Class instance should not be created with -init" | ||||
|     ]; | ||||
|     return nil; | ||||
| } | ||||
|  | ||||
| #pragma mark Initializers | ||||
|  | ||||
| + (instancetype)method:(Method)method { | ||||
|     return [[self alloc] initWithMethod:method isInstanceMethod:YES]; | ||||
| } | ||||
|  | ||||
| + (instancetype)method:(Method)method isInstanceMethod:(BOOL)isInstanceMethod { | ||||
|     return [[self alloc] initWithMethod:method isInstanceMethod:isInstanceMethod]; | ||||
| } | ||||
|  | ||||
| + (instancetype)selector:(SEL)selector class:(Class)cls { | ||||
|     BOOL instance = !class_isMetaClass(cls); | ||||
|     // class_getInstanceMethod will return an instance method if not given | ||||
|     // not given a metaclass, or a class method if given a metaclass, but | ||||
|     // this isn't documented so we just want to be safe here. | ||||
|     Method m = instance ? class_getInstanceMethod(cls, selector) : class_getClassMethod(cls, selector); | ||||
|     if (m == NULL) return nil; | ||||
|      | ||||
|     return [self method:m isInstanceMethod:instance]; | ||||
| } | ||||
|  | ||||
| + (instancetype)selector:(SEL)selector implementedInClass:(Class)cls { | ||||
|     if (![cls superclass]) { return [self selector:selector class:cls]; } | ||||
|      | ||||
|     BOOL unique = [cls methodForSelector:selector] != [[cls superclass] methodForSelector:selector]; | ||||
|      | ||||
|     if (unique) { | ||||
|         return [self selector:selector class:cls]; | ||||
|     } | ||||
|      | ||||
|     return nil; | ||||
| } | ||||
|  | ||||
| - (id)initWithMethod:(Method)method isInstanceMethod:(BOOL)isInstanceMethod { | ||||
|     NSParameterAssert(method); | ||||
|      | ||||
|     self = [super init]; | ||||
|     if (self) { | ||||
|         _objc_method = method; | ||||
|         _isInstanceMethod = isInstanceMethod; | ||||
|         _signatureString = @(method_getTypeEncoding(method) ?: "?@:"); | ||||
|          | ||||
|         NSString *cleanSig = nil; | ||||
|         if ([FLEXTypeEncodingParser methodTypeEncodingSupported:_signatureString cleaned:&cleanSig]) { | ||||
|             _signature = [NSMethodSignature signatureWithObjCTypes:cleanSig.UTF8String]; | ||||
|         } | ||||
|  | ||||
|         [self examine]; | ||||
|     } | ||||
|      | ||||
|     return self; | ||||
| } | ||||
|  | ||||
|  | ||||
| #pragma mark Other | ||||
|  | ||||
| - (NSString *)description { | ||||
|     if (!_flex_description) { | ||||
|         _flex_description = [self prettyName]; | ||||
|     } | ||||
|      | ||||
|     return _flex_description; | ||||
| } | ||||
|  | ||||
| - (NSString *)debugNameGivenClassName:(NSString *)name { | ||||
|     NSMutableString *string = [NSMutableString stringWithString:_isInstanceMethod ? @"-[" : @"+["]; | ||||
|     [string appendString:name]; | ||||
|     [string appendString:@" "]; | ||||
|     [string appendString:self.selectorString]; | ||||
|     [string appendString:@"]"]; | ||||
|     return string; | ||||
| } | ||||
|  | ||||
| - (NSString *)prettyName { | ||||
|     NSString *methodTypeString = self.isInstanceMethod ? @"-" : @"+"; | ||||
|     NSString *readableReturnType = [FLEXRuntimeUtility readableTypeForEncoding:@(self.signature.methodReturnType ?: "")]; | ||||
|      | ||||
|     NSString *prettyName = [NSString stringWithFormat:@"%@ (%@)", methodTypeString, readableReturnType]; | ||||
|     NSArray *components = [self prettyArgumentComponents]; | ||||
|  | ||||
|     if (components.count) { | ||||
|         return [prettyName stringByAppendingString:[components componentsJoinedByString:@" "]]; | ||||
|     } else { | ||||
|         return [prettyName stringByAppendingString:self.selectorString]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| - (NSArray *)prettyArgumentComponents { | ||||
|     // NSMethodSignature can't handle some type encodings | ||||
|     // like ^AI@:ir* which happen to very much exist | ||||
|     if (self.signature.numberOfArguments < self.numberOfArguments) { | ||||
|         return nil; | ||||
|     } | ||||
|      | ||||
|     NSMutableArray *components = [NSMutableArray new]; | ||||
|  | ||||
|     NSArray *selectorComponents = [self.selectorString componentsSeparatedByString:@":"]; | ||||
|     NSUInteger numberOfArguments = self.numberOfArguments; | ||||
|      | ||||
|     for (NSUInteger argIndex = 2; argIndex < numberOfArguments; argIndex++) { | ||||
|         assert(argIndex < self.signature.numberOfArguments); | ||||
|          | ||||
|         const char *argType = [self.signature getArgumentTypeAtIndex:argIndex] ?: "?"; | ||||
|         NSString *readableArgType = [FLEXRuntimeUtility readableTypeForEncoding:@(argType)]; | ||||
|         NSString *prettyComponent = [NSString | ||||
|             stringWithFormat:@"%@:(%@) ", | ||||
|             selectorComponents[argIndex - 2], | ||||
|             readableArgType | ||||
|         ]; | ||||
|  | ||||
|         [components addObject:prettyComponent]; | ||||
|     } | ||||
|      | ||||
|     return components; | ||||
| } | ||||
|  | ||||
| - (NSString *)debugDescription { | ||||
|     return [NSString stringWithFormat:@"<%@ selector=%@, signature=%@>", | ||||
|             NSStringFromClass(self.class), self.selectorString, self.signatureString]; | ||||
| } | ||||
|  | ||||
| - (void)examine { | ||||
|     _implementation    = method_getImplementation(_objc_method); | ||||
|     _selector          = method_getName(_objc_method); | ||||
|     _numberOfArguments = method_getNumberOfArguments(_objc_method); | ||||
|     _name              = NSStringFromSelector(_selector); | ||||
|     _returnType        = (FLEXTypeEncoding *)_signature.methodReturnType ?: ""; | ||||
|     _returnSize        = _signature.methodReturnLength; | ||||
| } | ||||
|  | ||||
| #pragma mark Public | ||||
|  | ||||
| - (void)setImplementation:(IMP)implementation { | ||||
|     NSParameterAssert(implementation); | ||||
|     method_setImplementation(self.objc_method, implementation); | ||||
|     [self examine]; | ||||
| } | ||||
|  | ||||
| - (NSString *)typeEncoding { | ||||
|     if (!_typeEncoding) { | ||||
|         _typeEncoding = [_signatureString | ||||
|             stringByReplacingOccurrencesOfString:@"[0-9]" | ||||
|             withString:@"" | ||||
|             options:NSRegularExpressionSearch | ||||
|             range:NSMakeRange(0, _signatureString.length) | ||||
|         ]; | ||||
|     } | ||||
|      | ||||
|     return _typeEncoding; | ||||
| } | ||||
|  | ||||
| - (NSString *)imagePath { | ||||
|     if (!_imagePath) { | ||||
|         Dl_info exeInfo; | ||||
|         if (dladdr(_implementation, &exeInfo)) { | ||||
|             _imagePath = exeInfo.dli_fname ? @(exeInfo.dli_fname) : @""; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return _imagePath; | ||||
| } | ||||
|  | ||||
| #pragma mark Misc | ||||
|  | ||||
| - (void)swapImplementations:(FLEXMethod *)method { | ||||
|     method_exchangeImplementations(self.objc_method, method.objc_method); | ||||
|     [self examine]; | ||||
|     [method examine]; | ||||
| } | ||||
|  | ||||
| // Some code borrowed from MAObjcRuntime, by Mike Ash. | ||||
| - (id)sendMessage:(id)target, ... { | ||||
|     id ret = nil; | ||||
|     va_list args; | ||||
|     va_start(args, target); | ||||
|      | ||||
|     switch (self.returnType[0]) { | ||||
|         case FLEXTypeEncodingUnknown: { | ||||
|             [self getReturnValue:NULL forMessageSend:target arguments:args]; | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingChar: { | ||||
|             char val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingInt: { | ||||
|             int val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingShort: { | ||||
|             short val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingLong: { | ||||
|             long val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingLongLong: { | ||||
|             long long val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingUnsignedChar: { | ||||
|             unsigned char val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingUnsignedInt: { | ||||
|             unsigned int val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingUnsignedShort: { | ||||
|             unsigned short val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingUnsignedLong: { | ||||
|             unsigned long val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingUnsignedLongLong: { | ||||
|             unsigned long long val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingFloat: { | ||||
|             float val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingDouble: { | ||||
|             double val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingLongDouble: { | ||||
|             long double val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = [NSValue value:&val withObjCType:self.returnType]; | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingCBool: { | ||||
|             bool val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingVoid: { | ||||
|             [self getReturnValue:NULL forMessageSend:target arguments:args]; | ||||
|             return nil; | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingCString: { | ||||
|             char *val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = @(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingObjcObject: { | ||||
|             id val = nil; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = val; | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingObjcClass: { | ||||
|             Class val = Nil; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = val; | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingSelector: { | ||||
|             SEL val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = NSStringFromSelector(val); | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingArrayBegin: { | ||||
|             void *val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = [NSValue valueWithBytes:val objCType:self.signature.methodReturnType]; | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingUnionBegin: | ||||
|         case FLEXTypeEncodingStructBegin: { | ||||
|             if (self.signature.methodReturnLength) { | ||||
|                 void * val = malloc(self.signature.methodReturnLength); | ||||
|                 [self getReturnValue:val forMessageSend:target arguments:args]; | ||||
|                 ret = [NSValue valueWithBytes:val objCType:self.signature.methodReturnType]; | ||||
|             } else { | ||||
|                 [self getReturnValue:NULL forMessageSend:target arguments:args]; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingBitField: { | ||||
|             [self getReturnValue:NULL forMessageSend:target arguments:args]; | ||||
|             break; | ||||
|         } | ||||
|         case FLEXTypeEncodingPointer: { | ||||
|             void * val = 0; | ||||
|             [self getReturnValue:&val forMessageSend:target arguments:args]; | ||||
|             ret = [NSValue valueWithPointer:val]; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         default: { | ||||
|             [NSException raise:NSInvalidArgumentException | ||||
|                         format:@"Unsupported type encoding: %s", (char *)self.returnType]; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     va_end(args); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| // Code borrowed from MAObjcRuntime, by Mike Ash. | ||||
| - (void)getReturnValue:(void *)retPtr forMessageSend:(id)target, ... { | ||||
|     va_list args; | ||||
|     va_start(args, target); | ||||
|     [self getReturnValue:retPtr forMessageSend:target arguments:args]; | ||||
|     va_end(args); | ||||
| } | ||||
|  | ||||
| // Code borrowed from MAObjcRuntime, by Mike Ash. | ||||
| - (void)getReturnValue:(void *)retPtr forMessageSend:(id)target arguments:(va_list)args { | ||||
|     if (!_signature) { | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:_signature]; | ||||
|     NSUInteger argumentCount = _signature.numberOfArguments; | ||||
|      | ||||
|     invocation.target = target; | ||||
|      | ||||
|     for (NSUInteger i = 2; i < argumentCount; i++) { | ||||
|         int cookie = va_arg(args, int); | ||||
|         if (cookie != FLEXMagicNumber) { | ||||
|             [NSException | ||||
|                 raise:NSInternalInconsistencyException | ||||
|                 format:@"%s: incorrect magic cookie %08x; make sure you didn't forget " | ||||
|                 "any arguments and that all arguments are wrapped in FLEXArg().", __func__, cookie | ||||
|             ]; | ||||
|         } | ||||
|         const char *typeString = va_arg(args, char *); | ||||
|         void *argPointer       = va_arg(args, void *); | ||||
|          | ||||
|         NSUInteger inSize, sigSize; | ||||
|         NSGetSizeAndAlignment(typeString, &inSize, NULL); | ||||
|         NSGetSizeAndAlignment([_signature getArgumentTypeAtIndex:i], &sigSize, NULL); | ||||
|          | ||||
|         if (inSize != sigSize) { | ||||
|             [NSException | ||||
|                 raise:NSInternalInconsistencyException | ||||
|                 format:@"%s:size mismatch between passed-in argument and " | ||||
|                 "required argument; in type:%s (%lu) requested:%s (%lu)", | ||||
|                 __func__, typeString, (long)inSize, [_signature getArgumentTypeAtIndex:i], (long)sigSize | ||||
|             ]; | ||||
|         } | ||||
|          | ||||
|         [invocation setArgument:argPointer atIndex:i]; | ||||
|     } | ||||
|      | ||||
|     // Hack to make NSInvocation invoke the desired implementation | ||||
|     IMP imp = [invocation methodForSelector:NSSelectorFromString(@"invokeUsingIMP:")]; | ||||
|     void (*invokeWithIMP)(id, SEL, IMP) = (void *)imp; | ||||
|     invokeWithIMP(invocation, 0, _implementation); | ||||
|      | ||||
|     if (_signature.methodReturnLength && retPtr) { | ||||
|         [invocation getReturnValue:retPtr]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @end | ||||
|  | ||||
|  | ||||
| @implementation FLEXMethod (Comparison) | ||||
|  | ||||
| - (NSComparisonResult)compare:(FLEXMethod *)method { | ||||
|     return [self.selectorString compare:method.selectorString]; | ||||
| } | ||||
|  | ||||
| @end | ||||
		Reference in New Issue
	
	Block a user
	 Balackburn
					Balackburn