mirror of
				https://github.com/SoPat712/YTLitePlus.git
				synced 2025-10-31 04:44:14 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
| //
 | |
| //  FLEXClassBuilder.m
 | |
| //  FLEX
 | |
| //
 | |
| //  Derived from MirrorKit.
 | |
| //  Created by Tanner on 7/3/15.
 | |
| //  Copyright (c) 2020 FLEX Team. All rights reserved.
 | |
| //
 | |
| 
 | |
| #import "FLEXClassBuilder.h"
 | |
| #import "FLEXProperty.h"
 | |
| #import "FLEXMethodBase.h"
 | |
| #import "FLEXProtocol.h"
 | |
| #import <objc/runtime.h>
 | |
| 
 | |
| 
 | |
| #pragma mark FLEXClassBuilder
 | |
| 
 | |
| @interface FLEXClassBuilder ()
 | |
| @property (nonatomic) NSString *name;
 | |
| @end
 | |
| 
 | |
| @implementation FLEXClassBuilder
 | |
| 
 | |
| - (id)init {
 | |
|     [NSException
 | |
|         raise:NSInternalInconsistencyException
 | |
|         format:@"Class instance should not be created with -init"
 | |
|     ];
 | |
|     return nil;
 | |
| }
 | |
| 
 | |
| #pragma mark Initializers
 | |
| + (instancetype)allocateClass:(NSString *)name {
 | |
|     return [self allocateClass:name superclass:NSObject.class];
 | |
| }
 | |
| 
 | |
| + (instancetype)allocateClass:(NSString *)name superclass:(Class)superclass {
 | |
|     return [self allocateClass:name superclass:superclass extraBytes:0];
 | |
| }
 | |
| 
 | |
| + (instancetype)allocateClass:(NSString *)name superclass:(Class)superclass extraBytes:(size_t)bytes {
 | |
|     NSParameterAssert(name);
 | |
|     return [[self alloc] initWithClass:objc_allocateClassPair(superclass, name.UTF8String, bytes)];
 | |
| }
 | |
| 
 | |
| + (instancetype)allocateRootClass:(NSString *)name {
 | |
|     NSParameterAssert(name);
 | |
|     return [[self alloc] initWithClass:objc_allocateClassPair(Nil, name.UTF8String, 0)];
 | |
| }
 | |
| 
 | |
| + (instancetype)builderForClass:(Class)cls {
 | |
|     return [[self alloc] initWithClass:cls];
 | |
| }
 | |
| 
 | |
| - (id)initWithClass:(Class)cls {
 | |
|     NSParameterAssert(cls);
 | |
|     
 | |
|     self = [super init];
 | |
|     if (self) {
 | |
|         _workingClass = cls;
 | |
|         _name = NSStringFromClass(_workingClass);
 | |
|     }
 | |
|     
 | |
|     return self;
 | |
| }
 | |
| 
 | |
| - (NSString *)description {
 | |
|     return [NSString stringWithFormat:@"<%@ name=%@, registered=%d>",
 | |
|             NSStringFromClass(self.class), self.name, self.isRegistered];
 | |
| }
 | |
| 
 | |
| #pragma mark Building
 | |
| - (NSArray *)addMethods:(NSArray *)methods {
 | |
|     NSParameterAssert(methods.count);
 | |
|     
 | |
|     NSMutableArray *failed = [NSMutableArray new];
 | |
|     for (FLEXMethodBase *m in methods) {
 | |
|         if (!class_addMethod(self.workingClass, m.selector, m.implementation, m.typeEncoding.UTF8String)) {
 | |
|             [failed addObject:m];
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     return failed;
 | |
| }
 | |
| 
 | |
| - (NSArray *)addProperties:(NSArray *)properties {
 | |
|     NSParameterAssert(properties.count);
 | |
|     
 | |
|     NSMutableArray *failed = [NSMutableArray new];
 | |
|     for (FLEXProperty *p in properties) {
 | |
|         unsigned int pcount;
 | |
|         objc_property_attribute_t *attributes = [p copyAttributesList:&pcount];
 | |
|         if (!class_addProperty(self.workingClass, p.name.UTF8String, attributes, pcount)) {
 | |
|             [failed addObject:p];
 | |
|         }
 | |
|         free(attributes);
 | |
|     }
 | |
|     
 | |
|     return failed;
 | |
| }
 | |
| 
 | |
| - (NSArray *)addProtocols:(NSArray *)protocols {
 | |
|     NSParameterAssert(protocols.count);
 | |
|     
 | |
|     NSMutableArray *failed = [NSMutableArray new];
 | |
|     for (FLEXProtocol *p in protocols) {
 | |
|         if (!class_addProtocol(self.workingClass, p.objc_protocol)) {
 | |
|             [failed addObject:p];
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     return failed;
 | |
| }
 | |
| 
 | |
| - (NSArray *)addIvars:(NSArray *)ivars {
 | |
|     NSParameterAssert(ivars.count);
 | |
|     
 | |
|     NSMutableArray *failed = [NSMutableArray new];
 | |
|     for (FLEXIvarBuilder *ivar in ivars) {
 | |
|         if (!class_addIvar(self.workingClass, ivar.name.UTF8String, ivar.size, ivar.alignment, ivar.encoding.UTF8String)) {
 | |
|             [failed addObject:ivar];
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     return failed;
 | |
| }
 | |
| 
 | |
| - (Class)registerClass {
 | |
|     if (self.isRegistered) {
 | |
|         [NSException raise:NSInternalInconsistencyException format:@"Class is already registered"];
 | |
|     }
 | |
|     
 | |
|     objc_registerClassPair(self.workingClass);
 | |
|     return self.workingClass;
 | |
| }
 | |
| 
 | |
| - (BOOL)isRegistered {
 | |
|     return objc_lookUpClass(self.name.UTF8String) != nil;
 | |
| }
 | |
| 
 | |
| @end
 | |
| 
 | |
| 
 | |
| #pragma mark FLEXIvarBuilder
 | |
| 
 | |
| @implementation FLEXIvarBuilder
 | |
| 
 | |
| + (instancetype)name:(NSString *)name size:(size_t)size alignment:(uint8_t)alignment typeEncoding:(NSString *)encoding {
 | |
|     return [[self alloc] initWithName:name size:size alignment:alignment typeEncoding:encoding];
 | |
| }
 | |
| 
 | |
| - (id)initWithName:(NSString *)name size:(size_t)size alignment:(uint8_t)alignment typeEncoding:(NSString *)encoding {
 | |
|     NSParameterAssert(name); NSParameterAssert(encoding);
 | |
|     NSParameterAssert(size > 0); NSParameterAssert(alignment > 0);
 | |
|     
 | |
|     self = [super init];
 | |
|     if (self) {
 | |
|         _name      = name;
 | |
|         _encoding  = encoding;
 | |
|         _size      = size;
 | |
|         _alignment = alignment;
 | |
|     }
 | |
|     
 | |
|     return self;
 | |
| }
 | |
| 
 | |
| @end
 | 
