mirror of
				https://github.com/SoPat712/YTLitePlus.git
				synced 2025-10-30 20:34:04 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			213 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
| //
 | |
| //  FLEXProtocol.m
 | |
| //  FLEX
 | |
| //
 | |
| //  Derived from MirrorKit.
 | |
| //  Created by Tanner on 6/30/15.
 | |
| //  Copyright (c) 2020 FLEX Team. All rights reserved.
 | |
| //
 | |
| 
 | |
| #import "FLEXProtocol.h"
 | |
| #import "FLEXProperty.h"
 | |
| #import "FLEXRuntimeUtility.h"
 | |
| #import "NSArray+FLEX.h"
 | |
| #include <dlfcn.h>
 | |
| 
 | |
| @implementation FLEXProtocol
 | |
| 
 | |
| #pragma mark Initializers
 | |
| 
 | |
| + (NSArray *)allProtocols {
 | |
|     unsigned int prcount;
 | |
|     Protocol *__unsafe_unretained*protocols = objc_copyProtocolList(&prcount);
 | |
|     
 | |
|     NSMutableArray *all = [NSMutableArray new];
 | |
|     for(NSUInteger i = 0; i < prcount; i++)
 | |
|         [all addObject:[self protocol:protocols[i]]];
 | |
|     
 | |
|     free(protocols);
 | |
|     return all;
 | |
| }
 | |
| 
 | |
| + (instancetype)protocol:(Protocol *)protocol {
 | |
|     return [[self alloc] initWithProtocol:protocol];
 | |
| }
 | |
| 
 | |
| - (id)initWithProtocol:(Protocol *)protocol {
 | |
|     NSParameterAssert(protocol);
 | |
|     
 | |
|     self = [super init];
 | |
|     if (self) {
 | |
|         _objc_protocol = protocol;
 | |
|         [self examine];
 | |
|     }
 | |
|     
 | |
|     return self;
 | |
| }
 | |
| 
 | |
| #pragma mark Other
 | |
| 
 | |
| - (NSString *)description {
 | |
|     return self.name;
 | |
| }
 | |
| 
 | |
| - (NSString *)debugDescription {
 | |
|     return [NSString stringWithFormat:@"<%@ name=%@, %lu properties, %lu required methods, %lu optional methods, %lu protocols>",
 | |
|             NSStringFromClass(self.class), self.name, (unsigned long)self.properties.count,
 | |
|             (unsigned long)self.requiredMethods.count, (unsigned long)self.optionalMethods.count, (unsigned long)self.protocols.count];
 | |
| }
 | |
| 
 | |
| - (void)examine {
 | |
|     _name = @(protocol_getName(self.objc_protocol));
 | |
|     
 | |
|     // imagePath
 | |
|     Dl_info exeInfo;
 | |
|     if (dladdr((__bridge const void *)(_objc_protocol), &exeInfo)) {
 | |
|         _imagePath = exeInfo.dli_fname ? @(exeInfo.dli_fname) : nil;
 | |
|     }
 | |
|     
 | |
|     // Conformances and methods //
 | |
|     
 | |
|     unsigned int pccount, mdrcount, mdocount;
 | |
|     struct objc_method_description *objcrMethods, *objcoMethods;
 | |
|     Protocol *protocol = _objc_protocol;
 | |
|     Protocol * __unsafe_unretained *protocols = protocol_copyProtocolList(protocol, &pccount);
 | |
|     
 | |
|     // Protocols
 | |
|     _protocols = [NSArray flex_forEachUpTo:pccount map:^id(NSUInteger i) {
 | |
|         return [FLEXProtocol protocol:protocols[i]];
 | |
|     }];
 | |
|     free(protocols);
 | |
|     
 | |
|     // Required instance methods
 | |
|     objcrMethods = protocol_copyMethodDescriptionList(protocol, YES, YES, &mdrcount);
 | |
|     NSArray *rMethods = [NSArray flex_forEachUpTo:mdrcount map:^id(NSUInteger i) {
 | |
|         return [FLEXMethodDescription description:objcrMethods[i] instance:YES];
 | |
|     }];
 | |
|     free(objcrMethods);
 | |
|     
 | |
|     // Required class methods 
 | |
|     objcrMethods = protocol_copyMethodDescriptionList(protocol, YES, NO, &mdrcount);
 | |
|     _requiredMethods = [[NSArray flex_forEachUpTo:mdrcount map:^id(NSUInteger i) {
 | |
|         return [FLEXMethodDescription description:objcrMethods[i] instance:NO];
 | |
|     }] arrayByAddingObjectsFromArray:rMethods];
 | |
|     free(objcrMethods);
 | |
|     
 | |
|     // Optional instance methods
 | |
|     objcoMethods = protocol_copyMethodDescriptionList(protocol, NO, YES, &mdocount);
 | |
|     NSArray *oMethods = [NSArray flex_forEachUpTo:mdocount map:^id(NSUInteger i) {
 | |
|         return [FLEXMethodDescription description:objcoMethods[i] instance:YES];
 | |
|     }];
 | |
|     free(objcoMethods);
 | |
|     
 | |
|     // Optional class methods
 | |
|     objcoMethods = protocol_copyMethodDescriptionList(protocol, NO, NO, &mdocount);
 | |
|     _optionalMethods = [[NSArray flex_forEachUpTo:mdocount map:^id(NSUInteger i) {
 | |
|         return [FLEXMethodDescription description:objcoMethods[i] instance:NO];
 | |
|     }] arrayByAddingObjectsFromArray:oMethods];
 | |
|     free(objcoMethods);
 | |
|     
 | |
|     // Properties is a hassle because they didn't fix the API until iOS 10 //
 | |
|     
 | |
|     if (@available(iOS 10.0, *)) {
 | |
|         unsigned int prrcount, procount;
 | |
|         Class instance = [NSObject class], meta = objc_getMetaClass("NSObject");
 | |
|         
 | |
|         // Required class and instance properties //
 | |
|         
 | |
|         // Instance first
 | |
|         objc_property_t *rProps = protocol_copyPropertyList2(protocol, &prrcount, YES, YES);
 | |
|         NSArray *rProperties = [NSArray flex_forEachUpTo:prrcount map:^id(NSUInteger i) {
 | |
|             return [FLEXProperty property:rProps[i] onClass:instance];
 | |
|         }];
 | |
|         free(rProps);
 | |
|         
 | |
|         // Then class
 | |
|         rProps = protocol_copyPropertyList2(protocol, &prrcount, NO, YES);
 | |
|         _requiredProperties = [[NSArray flex_forEachUpTo:prrcount map:^id(NSUInteger i) {
 | |
|             return [FLEXProperty property:rProps[i] onClass:instance];
 | |
|         }] arrayByAddingObjectsFromArray:rProperties];
 | |
|         free(rProps);
 | |
|         
 | |
|         // Optional class and instance properties //
 | |
|         
 | |
|         // Instance first
 | |
|         objc_property_t *oProps = protocol_copyPropertyList2(protocol, &procount, YES, YES);
 | |
|         NSArray *oProperties = [NSArray flex_forEachUpTo:prrcount map:^id(NSUInteger i) {
 | |
|             return [FLEXProperty property:oProps[i] onClass:meta];
 | |
|         }];
 | |
|         free(oProps);
 | |
|         
 | |
|         // Then class
 | |
|         oProps = protocol_copyPropertyList2(protocol, &procount, NO, YES);
 | |
|         _optionalProperties = [[NSArray flex_forEachUpTo:procount map:^id(NSUInteger i) {
 | |
|             return [FLEXProperty property:oProps[i] onClass:meta];
 | |
|         }] arrayByAddingObjectsFromArray:oProperties];
 | |
|         free(oProps);
 | |
|         
 | |
|     } else {
 | |
|         unsigned int prcount;
 | |
|         objc_property_t *objcproperties = protocol_copyPropertyList(protocol, &prcount);
 | |
|         _properties = [NSArray flex_forEachUpTo:prcount map:^id(NSUInteger i) {
 | |
|             return [FLEXProperty property:objcproperties[i]];
 | |
|         }];
 | |
|         
 | |
|         _requiredProperties = @[];
 | |
|         _optionalProperties = @[];
 | |
|         
 | |
|         free(objcproperties);
 | |
|     }
 | |
| }
 | |
| 
 | |
| - (BOOL)conformsTo:(Protocol *)protocol {
 | |
|     return protocol_conformsToProtocol(self.objc_protocol, protocol);
 | |
| }
 | |
| 
 | |
| @end
 | |
| 
 | |
| #pragma mark FLEXMethodDescription
 | |
| 
 | |
| @implementation FLEXMethodDescription
 | |
| 
 | |
| - (id)init {
 | |
|     [NSException
 | |
|         raise:NSInternalInconsistencyException
 | |
|         format:@"Class instance should not be created with -init"
 | |
|     ];
 | |
|     return nil;
 | |
| }
 | |
| 
 | |
| + (instancetype)description:(struct objc_method_description)description {
 | |
|     return [[self alloc] initWithDescription:description instance:nil];
 | |
| }
 | |
| 
 | |
| + (instancetype)description:(struct objc_method_description)description instance:(BOOL)isInstance {
 | |
|     return [[self alloc] initWithDescription:description instance:@(isInstance)];
 | |
| }
 | |
| 
 | |
| - (id)initWithDescription:(struct objc_method_description)md instance:(NSNumber *)instance {
 | |
|     NSParameterAssert(md.name != NULL);
 | |
|     
 | |
|     self = [super init];
 | |
|     if (self) {
 | |
|         _objc_description = md;
 | |
|         _selector         = md.name;
 | |
|         _typeEncoding     = @(md.types);
 | |
|         _returnType       = (FLEXTypeEncoding)[self.typeEncoding characterAtIndex:0];
 | |
|         _instance         = instance;
 | |
|     }
 | |
|     
 | |
|     return self;
 | |
| }
 | |
| 
 | |
| - (NSString *)description {
 | |
|     return NSStringFromSelector(self.selector);
 | |
| }
 | |
| 
 | |
| - (NSString *)debugDescription {
 | |
|     return [NSString stringWithFormat:@"<%@ name=%@, type=%@>",
 | |
|             NSStringFromClass(self.class), NSStringFromSelector(self.selector), self.typeEncoding];
 | |
| }
 | |
| 
 | |
| @end
 | 
