Optimized property setting and conversion

This commit is contained in:
Nick Lockwood 2015-07-24 09:34:18 -07:00
parent 4499f28c1d
commit 81dd9c27ea
2 changed files with 108 additions and 30 deletions

View File

@ -1075,14 +1075,51 @@ BOOL RCTSetProperty(id target, NSString *keyPath, SEL type, id json)
} }
@try { @try {
// Get converted value
NSMethodSignature *signature = [RCTConvert methodSignatureForSelector:type]; NSMethodSignature *signature = [RCTConvert methodSignatureForSelector:type];
switch (signature.methodReturnType[0]) {
#define RCT_SET_CASE(_value, _type) \
case _value: { \
_type (*convert)(id, SEL, id) = (typeof(convert))objc_msgSend; \
void (*set)(id, SEL, _type) = (typeof(set))objc_msgSend; \
set(target, setter, convert([RCTConvert class], type, json)); \
break; \
}
RCT_SET_CASE(':', SEL)
RCT_SET_CASE('*', const char *)
RCT_SET_CASE('c', char)
RCT_SET_CASE('C', unsigned char)
RCT_SET_CASE('s', short)
RCT_SET_CASE('S', unsigned short)
RCT_SET_CASE('i', int)
RCT_SET_CASE('I', unsigned int)
RCT_SET_CASE('l', long)
RCT_SET_CASE('L', unsigned long)
RCT_SET_CASE('q', long long)
RCT_SET_CASE('Q', unsigned long long)
RCT_SET_CASE('f', float)
RCT_SET_CASE('d', double)
RCT_SET_CASE('B', BOOL)
RCT_SET_CASE('^', void *)
case '@': {
id (*convert)(id, SEL, id) = (typeof(convert))objc_msgSend;
void (*set)(id, SEL, id) = (typeof(set))objc_msgSend;
set(target, setter, convert([RCTConvert class], type, json));
break;
}
case '{':
default: {
// Get converted value
void *value = malloc(signature.methodReturnLength);
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setArgument:&type atIndex:1]; [invocation setTarget:[RCTConvert class]];
[invocation setSelector:type];
[invocation setArgument:&json atIndex:2]; [invocation setArgument:&json atIndex:2];
[invocation invokeWithTarget:[RCTConvert class]]; [invocation invoke];
NSUInteger length = [signature methodReturnLength];
void *value = malloc(length);
[invocation getReturnValue:value]; [invocation getReturnValue:value];
// Set converted value // Set converted value
@ -1093,6 +1130,9 @@ BOOL RCTSetProperty(id target, NSString *keyPath, SEL type, id json)
[invocation invokeWithTarget:target]; [invocation invokeWithTarget:target];
free(value); free(value);
break;
}
}
return YES; return YES;
} }
@catch (NSException *exception) { @catch (NSException *exception) {
@ -1128,13 +1168,48 @@ BOOL RCTCopyProperty(id target, id source, NSString *keyPath)
return NO; return NO;
} }
// Get value
NSMethodSignature *signature = [source methodSignatureForSelector:getter]; NSMethodSignature *signature = [source methodSignatureForSelector:getter];
switch (signature.methodReturnType[0]) {
#define RCT_COPY_CASE(_value, _type) \
case _value: { \
_type (*get)(id, SEL) = (typeof(get))objc_msgSend; \
void (*set)(id, SEL, _type) = (typeof(set))objc_msgSend; \
set(target, setter, get(source, getter)); \
break; \
}
RCT_COPY_CASE(':', SEL)
RCT_COPY_CASE('*', const char *)
RCT_COPY_CASE('c', char)
RCT_COPY_CASE('C', unsigned char)
RCT_COPY_CASE('s', short)
RCT_COPY_CASE('S', unsigned short)
RCT_COPY_CASE('i', int)
RCT_COPY_CASE('I', unsigned int)
RCT_COPY_CASE('l', long)
RCT_COPY_CASE('L', unsigned long)
RCT_COPY_CASE('q', long long)
RCT_COPY_CASE('Q', unsigned long long)
RCT_COPY_CASE('f', float)
RCT_COPY_CASE('d', double)
RCT_COPY_CASE('B', BOOL)
RCT_COPY_CASE('^', void *)
case '@': {
id (*get)(id, SEL) = (typeof(get))objc_msgSend;
void (*set)(id, SEL, id) = (typeof(set))objc_msgSend;
set(target, setter, get(source, getter));
break;
}
case '{':
default: {
// Get value
void *value = malloc(signature.methodReturnLength);
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setArgument:&getter atIndex:1]; [invocation setArgument:&getter atIndex:1];
[invocation invokeWithTarget:source]; [invocation invokeWithTarget:source];
NSUInteger length = [signature methodReturnLength];
void *value = malloc(length);
[invocation getReturnValue:value]; [invocation getReturnValue:value];
// Set value // Set value
@ -1145,5 +1220,8 @@ BOOL RCTCopyProperty(id target, id source, NSString *keyPath)
[invocation invokeWithTarget:target]; [invocation invokeWithTarget:target];
free(value); free(value);
break;
}
}
return YES; return YES;
} }

View File

@ -91,7 +91,7 @@ RCT_NOT_IMPLEMENTED(-init)
[argumentBlocks addObject:^(__unused RCTBridge *bridge, NSInvocation *invocation, NSUInteger index, id json) { \ [argumentBlocks addObject:^(__unused RCTBridge *bridge, NSInvocation *invocation, NSUInteger index, id json) { \
_logic \ _logic \
[invocation setArgument:&value atIndex:index]; \ [invocation setArgument:&value atIndex:index]; \
}]; \ }];
void (^addBlockArgument)(void) = ^{ void (^addBlockArgument)(void) = ^{
RCT_ARG_BLOCK( RCT_ARG_BLOCK(