@@ -18,38 +18,29 @@ #include #import "OFObject.h" #import "OFObject+KeyValueCoding.h" +#import "OFMethodSignature.h" #import "OFString.h" #import "OFNumber.h" #import "OFInvalidArgumentException.h" #import "OFOutOfMemoryException.h" #import "OFUndefinedKeyException.h" int _OFObject_KeyValueCoding_reference; -static char OF_INLINE -nextType(const char **typeEncoding) -{ - char ret = *(*typeEncoding)++; - - while (**typeEncoding >= '0' && **typeEncoding <= '9') - (*typeEncoding)++; - - return ret; -} - @implementation OFObject (KeyValueCoding) - (id)valueForKey: (OFString *)key { SEL selector = sel_registerName([key UTF8String]); - const char *typeEncoding = [self typeEncodingForSelector: selector]; + OFMethodSignature *methodSignature = + [self methodSignatureForSelector: selector]; id ret; - if (typeEncoding == NULL) { + if (methodSignature == nil) { size_t keyLength; char *name; if ((keyLength = [key UTF8StringLength]) < 1) return [self valueForUndefinedKey: key]; @@ -68,18 +59,28 @@ selector = sel_registerName(name); } @finally { free(name); } - typeEncoding = [self typeEncodingForSelector: selector]; + methodSignature = [self methodSignatureForSelector: selector]; + + if (methodSignature == NULL) + return [self valueForUndefinedKey: key]; - if (typeEncoding == NULL || - *typeEncoding == '@' || *typeEncoding == '#') + switch (*[methodSignature methodReturnType]) { + case '@': + case '#': return [self valueForUndefinedKey: key]; + } } - switch (nextType(&typeEncoding)) { + if ([methodSignature numberOfArguments] != 2 || + *[methodSignature argumentTypeAtIndex: 0] != '@' || + *[methodSignature argumentTypeAtIndex: 1] != ':') + return [self valueForUndefinedKey: key]; + + switch (*[methodSignature methodReturnType]) { case '@': case '#': ret = [self performSelector: selector]; break; #define CASE(encoding, type, method) \ @@ -106,14 +107,10 @@ #undef CASE default: return [self valueForUndefinedKey: key]; } - if (nextType(&typeEncoding) != '@' || nextType(&typeEncoding) != ':' || - *typeEncoding != 0) - return [self valueForUndefinedKey: key]; - return ret; } - (id)valueForUndefinedKey: (OFString *)key { @@ -125,12 +122,12 @@ forKey: (OFString *)key { size_t keyLength; char *name; SEL selector; - const char *typeEncoding; - char valueType; + OFMethodSignature *methodSignature; + const char *valueType; if ((keyLength = [key UTF8StringLength]) < 1) { [self setValue: value forUndefinedKey: key]; return; @@ -150,33 +147,30 @@ selector = sel_registerName(name); } @finally { free(name); } - typeEncoding = [self typeEncodingForSelector: selector]; + methodSignature = [self methodSignatureForSelector: selector]; - if (typeEncoding == NULL || nextType(&typeEncoding) != 'v' || - nextType(&typeEncoding) != '@' || nextType(&typeEncoding) != ':') { + if (methodSignature == nil || + [methodSignature numberOfArguments] != 3 || + *[methodSignature methodReturnType] != 'v' || + *[methodSignature argumentTypeAtIndex: 0] != '@' || + *[methodSignature argumentTypeAtIndex: 1] != ':') { [self setValue: value forUndefinedKey: key]; return; } - valueType = nextType(&typeEncoding); - - if (*typeEncoding != 0) { - [self setValue: value - forUndefinedKey: key]; - return; - } - - if (valueType != '@' && valueType != '#' && value == nil) { + valueType = [methodSignature argumentTypeAtIndex: 2]; + + if (*valueType != '@' && *valueType != '#' && value == nil) { [self setNilValueForKey: key]; return; } - switch (valueType) { + switch (*valueType) { case '@': case '#': { void (*setter)(id, SEL, id) = (void (*)(id, SEL, id)) [self methodForSelector: selector];