Skip to content

Instantly share code, notes, and snippets.

@nicked
Created July 5, 2020 15:22
Show Gist options
  • Save nicked/b8b128b20010ce0205947c88354cbeda to your computer and use it in GitHub Desktop.
Save nicked/b8b128b20010ce0205947c88354cbeda to your computer and use it in GitHub Desktop.
Wrapper for Objective-C type encodings
@import Foundation;
typedef NS_ENUM(unichar, EncodedType) {
TypeChar = 'c',
TypeInt = 'i',
TypeShort = 's',
TypeLong = 'l', // note long encodes to q on 64 bit
TypeLongLong = 'q',
TypeUnsignedChar = 'C',
TypeUnsignedInt = 'I',
TypeUnsignedShort = 'S',
TypeUnsignedLong = 'L',
TypeUnsignedLongLong = 'Q',
TypeFloat = 'f',
TypeDouble = 'd',
TypeBool = 'B', // note, BOOL encodes to c on 64 bit
TypeVoid = 'v',
TypeCString = '*',
TypeObject = '@',
TypeClass = '#',
TypeSelector = ':',
TypeArray = '[',
TypeStruct = '{',
TypeUnion = '(',
TypeBitField = 'b',
TypePointer = '^',
TypeUnknown = '?',
};
NS_ASSUME_NONNULL_BEGIN
@interface TypeEncoding : NSObject
@property (nonatomic, readonly) EncodedType type;
/// The raw type encoding
@property (nonatomic, readonly, copy) NSString *encoding;
/// Either an object, a Class type, or a block
@property (nonatomic, readonly) BOOL isObjectType;
/// Float or double
@property (nonatomic, readonly) BOOL isFloatType;
/// A signed or unsigned integer of any size
@property (nonatomic, readonly) BOOL isIntType;
/// The class of the object. Nil for anything except TypeObject.
@property (nonatomic, readonly, nullable) Class classType;
- (instancetype)initWithEncoding:(NSString *)encoding;
@end
NS_ASSUME_NONNULL_END
#import "TypeEncoding.h"
@implementation TypeEncoding
- (instancetype)initWithEncoding:(NSString *)encoding {
self = [super init];
if (self) {
_encoding = [encoding copy];
_type = [encoding characterAtIndex:0];
static const unichar TypeConst = 'r';
if (_type == TypeConst) {
// const C strings are encoded as "r*" -- skip the leading 'r'
_type = [encoding characterAtIndex:1];
}
}
return self;
}
- (BOOL)isObjectType {
return _type == TypeObject || _type == TypeClass;
}
- (BOOL)isFloatType {
return _type == TypeFloat || _type == TypeDouble;
}
- (BOOL)isIntType {
static const char *integralTypes = "cislqCISLQB";
return strchr(integralTypes, _type) != NULL;
}
- (Class)classType {
if (_type == TypeObject
&& [_encoding hasPrefix:@"@\""] && [_encoding hasSuffix:@"\""]) {
NSRange range = NSMakeRange(2, _encoding.length - 3);
NSString *classStr = [_encoding substringWithRange:range];
return NSClassFromString(classStr) ?: NSObject.class;
}
return nil;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment