Tidy key value coding

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@12742 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2002-02-25 07:05:58 +00:00
parent dc0470796f
commit 80c8891b1f
5 changed files with 436 additions and 392 deletions

View file

@ -1280,397 +1280,6 @@ static BOOL double_release_check_enabled = NO;
#include <Foundation/NSValue.h>
#include <Foundation/NSKeyValueCoding.h>
#include <Foundation/NSNull.h>
@implementation NSObject (KeyValueCoding)
+ (BOOL) accessInstanceVariablesDirectly
{
return YES;
}
+ (BOOL) useStoredAccessor
{
return YES;
}
- (id) handleQueryWithUnboundKey: (NSString*)aKey
{
[NSException raise: NSGenericException
format: @"%@ -- %@ 0x%x: Unable to find value for key \"%@\"",
NSStringFromSelector(_cmd), NSStringFromClass([self class]), self, aKey];
return nil;
}
- (void) handleTakeValue: (id)anObject forUnboundKey: (NSString*)aKey
{
[NSException raise: NSGenericException
format: @"%@ -- %@ 0x%x: Unable set value \"%@\" for key \"%@\"",
NSStringFromSelector(_cmd), NSStringFromClass([self class]),
self, anObject, aKey];
}
- (id) storedValueForKey: (NSString*)aKey
{
unsigned size;
if ([[self class] useStoredAccessor] == NO)
{
return [self valueForKey: aKey];
}
size = [aKey cStringLength];
if (size < 1)
{
[NSException raise: NSInvalidArgumentException
format: @"storedValueForKey: ... empty key"];
return NO; // avoid compiler warnings.
}
else
{
SEL sel = 0;
const char *type = NULL;
unsigned off;
const char *name;
char buf[size+5];
char lo;
char hi;
strcpy(buf, "_get");
[aKey getCString: &buf[4]];
lo = buf[4];
hi = islower(lo) ? toupper(lo) : lo;
buf[4] = hi;
name = buf; // _getKey
sel = sel_get_any_uid(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
buf[3] = '_';
buf[4] = lo;
name = &buf[3]; // _key
sel = sel_get_any_uid(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
sel = 0;
}
}
if (sel == 0)
{
if ([[self class] accessInstanceVariablesDirectly] == YES)
{
// _key
if (GSFindInstanceVariable(self, name, &type, &size, &off) == NO)
{
name = &buf[4]; // key
GSFindInstanceVariable(self, name, &type, &size, &off);
}
}
if (type == NULL)
{
buf[3] = 't';
buf[4] = hi;
name = &buf[1]; // getKey
sel = sel_get_any_uid(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
buf[4] = lo;
name = &buf[4]; // key
sel = sel_get_any_uid(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
sel = 0;
}
}
}
}
return GSGetValue(self, aKey, sel, type, size, off);
}
}
- (void) takeStoredValue: (id)anObject forKey: (NSString*)aKey
{
unsigned size;
if ([[self class] useStoredAccessor] == NO)
{
[self takeValue: anObject forKey: aKey];
return;
}
size = [aKey length];
if (size < 1)
{
[NSException raise: NSInvalidArgumentException
format: @"takeStoredValue:forKey: ... empty key"];
}
else
{
SEL sel;
const char *type;
int off;
const char *name;
char buf[size+6];
char lo;
char hi;
strcpy(buf, "_set");
[aKey getCString: &buf[4]];
lo = buf[4];
hi = islower(lo) ? toupper(lo) : lo;
buf[4] = hi;
buf[size+4] = ':';
name = buf; // _setKey:
type = NULL;
sel = GSSelectorFromName(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
sel = 0;
if ([[self class] accessInstanceVariablesDirectly] == YES)
{
buf[size+4] = '\0';
buf[4] = lo;
buf[3] = '_';
name = &buf[3]; // _key
if (GSFindInstanceVariable(self, name, &type, &size, &off) == NO)
{
name = &buf[4]; // key
GSFindInstanceVariable(self, name, &type, &size, &off);
}
}
if (type == NULL)
{
buf[size+4] = ':';
buf[4] = hi;
buf[3] = 't';
name = &buf[1]; // setKey:
sel = GSSelectorFromName(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
sel = 0;
}
}
}
GSSetValue(self, aKey, anObject, sel, type, size, off);
}
}
- (void) takeValue: (id)anObject forKey: (NSString*)aKey
{
unsigned size;
size = [aKey length];
if (size < 1)
{
[NSException raise: NSInvalidArgumentException
format: @"takeValue:forKey: ... empty key"];
}
else
{
SEL sel;
const char *type;
int off;
const char *name;
char buf[size+6];
char lo;
char hi;
strcpy(buf, "_set");
[aKey getCString: &buf[4]];
lo = buf[4];
hi = islower(lo) ? toupper(lo) : lo;
buf[4] = hi;
buf[size+4] = ':';
name = &buf[1]; // setKey:
type = NULL;
sel = GSSelectorFromName(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
name = buf; // _setKey:
sel = GSSelectorFromName(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
sel = 0;
if ([[self class] accessInstanceVariablesDirectly] == YES)
{
buf[size+4] = '\0';
buf[3] = '_';
buf[4] = lo;
name = &buf[3]; // _key
if (GSFindInstanceVariable(self, name, &type, &size, &off)
== NO)
{
name = &buf[4]; // key
GSFindInstanceVariable(self, name, &type, &size, &off);
}
}
}
}
GSSetValue(self, aKey, anObject, sel, type, size, off);
}
}
- (void) takeValue: (id)anObject forKeyPath: (NSString*)aKey
{
NSRange r = [aKey rangeOfString: @"."];
if (r.length == 0)
{
[self takeValue: anObject forKey: aKey];
}
else
{
NSString *key = [aKey substringToIndex: r.location];
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
[[self valueForKey: key] takeValue: anObject forKeyPath: path];
}
}
- (void) takeValuesFromDictionary: (NSDictionary*)aDictionary
{
NSEnumerator *enumerator = [aDictionary keyEnumerator];
NSNull *null = [NSNull null];
NSString *key;
while ((key = [enumerator nextObject]) != nil)
{
id obj = [aDictionary objectForKey: key];
if (obj == null)
{
obj = nil;
}
[self takeValue: obj forKey: key];
}
}
- (void) unableToSetNilForKey: (NSString*)aKey
{
[NSException raise: NSInvalidArgumentException
format: @"%@ -- %@ 0x%x: Given nil value to set for key \"%@\"",
NSStringFromSelector(_cmd), NSStringFromClass([self class]), self, aKey];
}
- (id) valueForKey: (NSString*)aKey
{
unsigned size;
size = [aKey length];
if (size < 1)
{
[NSException raise: NSInvalidArgumentException
format: @"valueForKey: ... empty key"];
return nil;
}
else
{
SEL sel = 0;
const char *type = NULL;
unsigned off;
const char *name;
char buf[size+5];
char lo;
char hi;
strcpy(buf, "_get");
[aKey getCString: &buf[4]];
lo = buf[4];
hi = islower(lo) ? toupper(lo) : lo;
buf[4] = hi;
name = &buf[1]; // getKey
sel = GSSelectorFromName(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
buf[4] = lo;
name = &buf[4]; // key
sel = GSSelectorFromName(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
buf[4] = hi;
name = buf; // _getKey
sel = GSSelectorFromName(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
buf[4] = lo;
buf[3] = '_';
name = &buf[3]; // _key
sel = GSSelectorFromName(name);
if (sel == 0 || [self respondsToSelector: sel] == NO)
{
sel = 0;
}
}
}
}
if (sel == 0 && [[self class] accessInstanceVariablesDirectly] == YES)
{
buf[4] = lo;
buf[3] = '_';
name = &buf[3]; // _key
if (GSFindInstanceVariable(self, name, &type, &size, &off) == NO)
{
name = &buf[4]; // key
GSFindInstanceVariable(self, name, &type, &size, &off);
}
}
return GSGetValue(self, aKey, sel, type, size, off);
}
}
- (id) valueForKeyPath: (NSString*)aKey
{
NSRange r = [aKey rangeOfString: @"."];
id o;
if (r.length == 0)
{
o = [self valueForKey: aKey];
}
else
{
NSString *key = [aKey substringToIndex: r.location];
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
o = [[self valueForKey: key] valueForKeyPath: path];
}
return o;
}
- (NSDictionary*) valuesForKeys: (NSArray*)keys
{
NSMutableDictionary *dict;
NSNull *null = [NSNull null];
unsigned count = [keys count];
unsigned pos;
dict = [NSMutableDictionary dictionaryWithCapacity: count];
for (pos = 0; pos < count; pos++)
{
NSString *key = [keys objectAtIndex: pos];
id val = [self valueForKey: key];
if (val == nil)
{
val = null;
}
[dict setObject: val forKey: key];
}
return AUTORELEASE([dict copy]);
}
@end
@implementation NSObject (GNU)
/* GNU Object class compatibility */