You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
5.2 KiB
115 lines
5.2 KiB
//
|
|
// FLEXRuntimeUtility.h
|
|
// Flipboard
|
|
//
|
|
// Created by Ryan Olson on 6/8/14.
|
|
// Copyright (c) 2014 Flipboard. All rights reserved.
|
|
//
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import <objc/runtime.h>
|
|
|
|
extern const unsigned int kFLEXNumberOfImplicitArgs;
|
|
|
|
// See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6
|
|
extern NSString *const kFLEXUtilityAttributeTypeEncoding;
|
|
extern NSString *const kFLEXUtilityAttributeBackingIvar;
|
|
extern NSString *const kFLEXUtilityAttributeReadOnly;
|
|
extern NSString *const kFLEXUtilityAttributeCopy;
|
|
extern NSString *const kFLEXUtilityAttributeRetain;
|
|
extern NSString *const kFLEXUtilityAttributeNonAtomic;
|
|
extern NSString *const kFLEXUtilityAttributeCustomGetter;
|
|
extern NSString *const kFLEXUtilityAttributeCustomSetter;
|
|
extern NSString *const kFLEXUtilityAttributeDynamic;
|
|
extern NSString *const kFLEXUtilityAttributeWeak;
|
|
extern NSString *const kFLEXUtilityAttributeGarbageCollectable;
|
|
extern NSString *const kFLEXUtilityAttributeOldStyleTypeEncoding;
|
|
|
|
typedef NS_ENUM(char, FLEXTypeEncoding)
|
|
{
|
|
FLEXTypeEncodingUnknown = '?',
|
|
FLEXTypeEncodingChar = 'c',
|
|
FLEXTypeEncodingInt = 'i',
|
|
FLEXTypeEncodingShort = 's',
|
|
FLEXTypeEncodingLong = 'l',
|
|
FLEXTypeEncodingLongLong = 'q',
|
|
FLEXTypeEncodingUnsignedChar = 'C',
|
|
FLEXTypeEncodingUnsignedInt = 'I',
|
|
FLEXTypeEncodingUnsignedShort = 'S',
|
|
FLEXTypeEncodingUnsignedLong = 'L',
|
|
FLEXTypeEncodingUnsignedLongLong = 'Q',
|
|
FLEXTypeEncodingFloat = 'f',
|
|
FLEXTypeEncodingDouble = 'd',
|
|
FLEXTypeEncodingLongDouble = 'D',
|
|
FLEXTypeEncodingCBool = 'B',
|
|
FLEXTypeEncodingVoid = 'v',
|
|
FLEXTypeEncodingCString = '*',
|
|
FLEXTypeEncodingObjcObject = '@',
|
|
FLEXTypeEncodingObjcClass = '#',
|
|
FLEXTypeEncodingSelector = ':',
|
|
FLEXTypeEncodingArrayBegin = '[',
|
|
FLEXTypeEncodingArrayEnd = ']',
|
|
FLEXTypeEncodingStructBegin = '{',
|
|
FLEXTypeEncodingStructEnd = '}',
|
|
FLEXTypeEncodingUnionBegin = '(',
|
|
FLEXTypeEncodingUnionEnd = ')',
|
|
FLEXTypeEncodingQuote = '\"',
|
|
FLEXTypeEncodingBitField = 'b',
|
|
FLEXTypeEncodingPointer = '^',
|
|
FLEXTypeEncodingConst = 'r'
|
|
};
|
|
|
|
#define FLEXEncodeClass(class) ("@\"" #class "\"")
|
|
#define FLEXEncodeObject(obj) (obj ? [NSString stringWithFormat:@"@\"%@\"", [obj class]].UTF8String : @encode(id))
|
|
|
|
@interface FLEXRuntimeUtility : NSObject
|
|
|
|
// General Helpers
|
|
+ (BOOL)pointerIsValidObjcObject:(const void *)pointer;
|
|
/// Unwraps raw pointers to objects stored in NSValue, and re-boxes C strings into NSStrings.
|
|
+ (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXTypeEncoding *)returnType;
|
|
/// Some fields have a name in their encoded string (e.g. \"width\"d)
|
|
/// @return the offset to skip the field name, 0 if there is no name
|
|
+ (NSUInteger)fieldNameOffsetForTypeEncoding:(const FLEXTypeEncoding *)typeEncoding;
|
|
|
|
/// @return The class hierarchy for the given object or class,
|
|
/// from the current class to the root-most class.
|
|
+ (NSArray<Class> *)classHierarchyOfObject:(id)objectOrClass;
|
|
|
|
// Property Helpers
|
|
+ (NSString *)prettyNameForProperty:(objc_property_t)property;
|
|
+ (NSString *)typeEncodingForProperty:(objc_property_t)property;
|
|
+ (BOOL)isReadonlyProperty:(objc_property_t)property;
|
|
+ (SEL)setterSelectorForProperty:(objc_property_t)property;
|
|
+ (NSString *)fullDescriptionForProperty:(objc_property_t)property;
|
|
+ (id)valueForProperty:(objc_property_t)property onObject:(id)object;
|
|
+ (NSString *)descriptionForIvarOrPropertyValue:(id)value;
|
|
+ (void)tryAddPropertyWithName:(const char *)name attributes:(NSDictionary<NSString *, NSString *> *)attributePairs toClass:(__unsafe_unretained Class)theClass;
|
|
|
|
// Ivar Helpers
|
|
+ (NSString *)prettyNameForIvar:(Ivar)ivar;
|
|
+ (id)valueForIvar:(Ivar)ivar onObject:(id)object;
|
|
+ (void)setValue:(id)value forIvar:(Ivar)ivar onObject:(id)object;
|
|
|
|
// Method Helpers
|
|
+ (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMethod;
|
|
+ (NSArray *)prettyArgumentComponentsForMethod:(Method)method;
|
|
+ (FLEXTypeEncoding *)returnTypeForMethod:(Method)method;
|
|
|
|
// Method Calling/Field Editing
|
|
+ (id)performSelector:(SEL)selector
|
|
onObject:(id)object
|
|
withArguments:(NSArray *)arguments
|
|
error:(NSError * __autoreleasing *)error;
|
|
+ (NSString *)editableJSONStringForObject:(id)object;
|
|
+ (id)objectValueFromEditableJSONString:(NSString *)string;
|
|
+ (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString;
|
|
+ (void)enumerateTypesInStructEncoding:(const char *)structEncoding
|
|
usingBlock:(void (^)(NSString *structName,
|
|
const char *fieldTypeEncoding,
|
|
NSString *prettyTypeEncoding,
|
|
NSUInteger fieldIndex,
|
|
NSUInteger fieldOffset))typeBlock;
|
|
+ (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type;
|
|
|
|
@end
|