2
Copyright (C) 2000-2005 SKYRIX Software AG
4
This file is part of SOPE.
6
SOPE is free software; you can redistribute it and/or modify it under
7
the terms of the GNU Lesser General Public License as published by the
8
Free Software Foundation; either version 2, or (at your option) any
11
SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14
License for more details.
16
You should have received a copy of the GNU Lesser General Public
17
License along with SOPE; see the file COPYING. If not, write to the
18
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22
#include "EOKeyValueCoding.h"
27
# include <objc/objc-api.h>
28
# include <objc/encoding.h>
31
static EONull *null = nil;
33
#if !NeXT_Foundation_LIBRARY
35
static id idMethodGetFunc(void* info1, void* info2, id self);
36
static id idIvarGetFunc(void* info1, void* info2, id self);
37
static void idMethodSetFunc(void* info1, void* info2, id self, id val);
38
static void idIvarSetFunc(void* info1, void* info2, id self, id val);
39
static id charMethodGetFunc(void* info1, void* info2, id self);
40
static id charIvarGetFunc(void* info1, void* info2, id self);
41
static void charMethodSetFunc(void* info1, void* info2, id self, id val);
42
static void charIvarSetFunc(void* info1, void* info2, id self, id val);
43
static id unsignedCharMethodGetFunc(void* info1, void* info2, id self);
44
static id unsignedCharIvarGetFunc(void* info1, void* info2, id self);
45
static void unsignedCharMethodSetFunc(void* info1, void* info2, id self, id val);
46
static void unsignedCharIvarSetFunc(void* info1, void* info2, id self, id val);
47
static id shortMethodGetFunc(void* info1, void* info2, id self);
48
static id shortIvarGetFunc(void* info1, void* info2, id self);
49
static void shortMethodSetFunc(void* info1, void* info2, id self, id val);
50
static void shortIvarSetFunc(void* info1, void* info2, id self, id val);
51
static id unsignedShortMethodGetFunc(void* info1, void* info2, id self);
52
static id unsignedShortIvarGetFunc(void* info1, void* info2, id self);
53
static void unsignedShortMethodSetFunc(void* info1, void* info2, id self, id val);
54
static void unsignedShortIvarSetFunc(void* info1, void* info2, id self, id val);
55
static id intMethodGetFunc(void* info1, void* info2, id self);
56
static id intIvarGetFunc(void* info1, void* info2, id self);
57
static void intMethodSetFunc(void* info1, void* info2, id self, id val);
58
static void intIvarSetFunc(void* info1, void* info2, id self, id val);
59
static id unsignedIntMethodGetFunc(void* info1, void* info2, id self);
60
static id unsignedIntIvarGetFunc(void* info1, void* info2, id self);
61
static void unsignedIntMethodSetFunc(void* info1, void* info2, id self, id val);
62
static void unsignedIntIvarSetFunc(void* info1, void* info2, id self, id val);
63
static id longMethodGetFunc(void* info1, void* info2, id self);
64
static id longIvarGetFunc(void* info1, void* info2, id self);
65
static void longMethodSetFunc(void* info1, void* info2, id self, id val);
66
static void longIvarSetFunc(void* info1, void* info2, id self, id val);
67
static id unsignedLongMethodGetFunc(void* info1, void* info2, id self);
68
static id unsignedLongIvarGetFunc(void* info1, void* info2, id self);
69
static void unsignedLongMethodSetFunc(void* info1, void* info2, id self, id val);
70
static void unsignedLongIvarSetFunc(void* info1, void* info2, id self, id val);
71
static id longLongMethodGetFunc(void* info1, void* info2, id self);
72
static id longLongIvarGetFunc(void* info1, void* info2, id self);
73
static void longLongMethodSetFunc(void* info1, void* info2, id self, id val);
74
static void longLongIvarSetFunc(void* info1, void* info2, id self, id val);
75
static id unsignedLongLongMethodGetFunc(void* info1, void* info2, id self);
76
static id unsignedLongLongIvarGetFunc(void* info1, void* info2, id self);
77
static void unsignedLongLongMethodSetFunc(void* info1, void* info2, id self, id val);
78
static void unsignedLongLongIvarSetFunc(void* info1, void* info2, id self, id val);
79
static id floatMethodGetFunc(void* info1, void* info2, id self);
80
static id floatIvarGetFunc(void* info1, void* info2, id self);
81
static void floatMethodSetFunc(void* info1, void* info2, id self, id val);
82
static void floatIvarSetFunc(void* info1, void* info2, id self, id val);
83
static id doubleMethodGetFunc(void* info1, void* info2, id self);
84
static id doubleIvarGetFunc(void* info1, void* info2, id self);
85
static void doubleMethodSetFunc(void* info1, void* info2, id self, id val);
86
static void doubleIvarSetFunc(void* info1, void* info2, id self, id val);
88
static Class NumberClass = Nil;
89
static Class StringClass = Nil;
91
@implementation NSObject(EOKeyValueCoding)
97
typedef struct _KeyValueMethod {
102
typedef struct _GetKeyValueBinding {
103
/* info1, info2, self */
104
id (*access)(void *, void *, id);
107
} GetKeyValueBinding;
109
typedef struct _SetKeyValueBinding {
110
/* info1, info2, self, val */
111
void (*access)(void *, void *, id, id);
114
} SetKeyValueBinding;
120
static NSMapTable* getValueBindings = NULL;
121
static NSMapTable* setValueBindings = NULL;
122
static BOOL keyValueDebug = NO;
123
static BOOL keyValueInit = NO;
129
static GetKeyValueBinding* newGetBinding(NSString* key, id instance)
131
GetKeyValueBinding *ret = NULL;
134
id (*fptr)(void*, void*, id) = NULL;
136
// Lookup method name [-(type)key]
138
Class class = [instance class];
139
unsigned clen = [key cStringLength];
143
struct objc_method* mth;
145
cbuf = malloc(clen + 1);
146
[key getCString:cbuf]; cbuf[clen] = '\0';
148
sel = sel_get_any_uid(ckey);
150
if (sel && (mth = class_get_instance_method(class, sel)) &&
151
method_get_number_of_arguments(mth) == 2) {
152
switch(*objc_skip_type_qualifiers(mth->method_types)) {
154
fptr = (id (*)(void*, void*, id))idMethodGetFunc;
157
fptr = (id (*)(void*, void*, id))charMethodGetFunc;
160
fptr = (id (*)(void*, void*, id))unsignedCharMethodGetFunc;
163
fptr = (id (*)(void*, void*, id))shortMethodGetFunc;
166
fptr = (id (*)(void*, void*, id))unsignedShortMethodGetFunc;
169
fptr = (id (*)(void*, void*, id))intMethodGetFunc;
172
fptr = (id (*)(void*, void*, id))unsignedIntMethodGetFunc;
175
fptr = (id (*)(void*, void*, id))longMethodGetFunc;
178
fptr = (id (*)(void*, void*, id))unsignedLongMethodGetFunc;
181
fptr = (id (*)(void*, void*, id))longLongMethodGetFunc;
184
fptr = (id (*)(void*, void*, id))unsignedLongLongMethodGetFunc;
187
fptr = (id (*)(void*, void*, id))floatMethodGetFunc;
190
fptr = (id (*)(void*, void*, id))doubleMethodGetFunc;
194
info1 = (void*)(mth->method_imp);
195
info2 = (void*)(mth->method_name);
198
if (cbuf) free(cbuf);
203
Class class = [instance class];
209
clen = [key cStringLength];
210
cbuf = malloc(clen + 1);
211
[key getCString:cbuf]; cbuf[clen] = '\0';
215
for (i = 0; class->ivars && i < class->ivars->ivar_count; i++) {
216
if (!Strcmp(ckey, class->ivars->ivar_list[i].ivar_name)) {
217
switch(*objc_skip_type_qualifiers(class->ivars->ivar_list[i].ivar_type)) {
219
fptr = (id (*)(void*, void*, id))idIvarGetFunc;
222
fptr = (id (*)(void*, void*, id))charIvarGetFunc;
225
fptr = (id (*)(void*, void*, id))unsignedCharIvarGetFunc;
228
fptr = (id (*)(void*, void*, id))shortIvarGetFunc;
231
fptr = (id (*)(void*, void*, id))unsignedShortIvarGetFunc;
234
fptr = (id (*)(void*, void*, id))intIvarGetFunc;
237
fptr = (id (*)(void*, void*, id))unsignedIntIvarGetFunc;
240
fptr = (id (*)(void*, void*, id))longIvarGetFunc;
243
fptr = (id (*)(void*, void*, id))unsignedLongIvarGetFunc;
246
fptr = (id (*)(void*, void*, id))longLongIvarGetFunc;
249
fptr = (id (*)(void*, void*, id))unsignedLongLongIvarGetFunc;
252
fptr = (id (*)(void*, void*, id))floatIvarGetFunc;
255
fptr = (id (*)(void*, void*, id))doubleIvarGetFunc;
259
info2 = (void*)(class->ivars->ivar_list[i].ivar_offset);
264
class = class->super_class;
266
if (cbuf) free(cbuf);
269
// Make binding and insert into map
271
KeyValueMethod *mkey;
272
GetKeyValueBinding *bin;
274
mkey = Malloc(sizeof(KeyValueMethod));
275
bin = Malloc(sizeof(GetKeyValueBinding));
276
mkey->key = [key copy];
277
mkey->class = [instance class];
283
NSMapInsert(getValueBindings, mkey, bin);
287
// If no way to access value warn
288
if (!ret && keyValueDebug)
289
NSLog(@"cannnot get key `%@' for instance of class `%@'",
290
key, NSStringFromClass([instance class]));
295
static SetKeyValueBinding* newSetBinding(NSString* key, id instance)
297
SetKeyValueBinding *ret = NULL;
300
void (*fptr)(void*, void*, id, id) = NULL;
302
// Lookup method name [-(void)setKey:(type)arg]
304
Class class = [instance class];
305
unsigned clen = [key cStringLength];
309
struct objc_method* mth;
310
char sname[clen + 7];
312
cbuf = malloc(clen + 1);
313
[key getCString:cbuf]; cbuf[clen] = '\0';
316
// Make sel from name
317
Strcpy(sname, "set");
320
sname[3] = islower((int)sname[3]) ? toupper((int)sname[3]) : sname[3];
321
sel = sel_get_any_uid(sname);
323
if (sel && (mth = class_get_instance_method(class, sel)) &&
324
method_get_number_of_arguments(mth) == 3 &&
325
*objc_skip_type_qualifiers(mth->method_types) == _C_VOID) {
326
char* argType = (char*)(mth->method_types);
328
argType = (char*)objc_skip_argspec(argType); // skip return
329
argType = (char*)objc_skip_argspec(argType); // skip self
330
argType = (char*)objc_skip_argspec(argType); // skip SEL
332
switch(*objc_skip_type_qualifiers(argType)) {
334
fptr = (void (*)(void*, void*, id, id))idMethodSetFunc;
337
fptr = (void (*)(void*, void*, id, id))charMethodSetFunc;
340
fptr = (void (*)(void*, void*, id, id))unsignedCharMethodSetFunc;
343
fptr = (void (*)(void*, void*, id, id))shortMethodSetFunc;
346
fptr = (void (*)(void*, void*, id, id))unsignedShortMethodSetFunc;
349
fptr = (void (*)(void*, void*, id, id))intMethodSetFunc;
352
fptr = (void (*)(void*, void*, id, id))unsignedIntMethodSetFunc;
355
fptr = (void (*)(void*, void*, id, id))longMethodSetFunc;
358
fptr = (void (*)(void*, void*, id, id))unsignedLongMethodSetFunc;
361
fptr = (void (*)(void*, void*, id, id))longLongMethodSetFunc;
364
fptr = (void (*)(void*, void*, id, id))unsignedLongLongMethodSetFunc;
367
fptr = (void (*)(void*, void*, id, id))floatMethodSetFunc;
370
fptr = (void (*)(void*, void*, id, id))doubleMethodSetFunc;
374
info1 = (void*)(mth->method_imp);
375
info2 = (void*)(mth->method_name);
378
if (cbuf) free(cbuf);
382
Class class = [instance class];
383
unsigned clen = [key cStringLength];
388
cbuf = malloc(clen + 1);
389
[key getCString:cbuf]; cbuf[clen] = '\0';
393
for (i = 0; class->ivars && i < class->ivars->ivar_count; i++) {
394
if (!Strcmp(ckey, class->ivars->ivar_list[i].ivar_name)) {
395
switch(*objc_skip_type_qualifiers(class->ivars->ivar_list[i].ivar_type)) {
397
fptr = (void (*)(void*, void*, id, id))idIvarSetFunc;
400
fptr = (void (*)(void*, void*, id, id))charIvarSetFunc;
403
fptr = (void (*)(void*, void*, id, id))unsignedCharIvarSetFunc;
406
fptr = (void (*)(void*, void*, id, id))shortIvarSetFunc;
409
fptr = (void (*)(void*, void*, id, id))unsignedShortIvarSetFunc;
412
fptr = (void (*)(void*, void*, id, id))intIvarSetFunc;
415
fptr = (void (*)(void*, void*, id, id))unsignedIntIvarSetFunc;
418
fptr = (void (*)(void*, void*, id, id))longIvarSetFunc;
421
fptr = (void (*)(void*, void*, id, id))unsignedLongIvarSetFunc;
424
fptr = (void (*)(void*, void*, id, id))longLongIvarSetFunc;
427
fptr = (void (*)(void*, void*, id, id))unsignedLongLongIvarSetFunc;
430
fptr = (void (*)(void*, void*, id, id))floatIvarSetFunc;
433
fptr = (void (*)(void*, void*, id, id))doubleIvarSetFunc;
437
info2 = (void*)(class->ivars->ivar_list[i].ivar_offset);
442
class = class->super_class;
444
if (cbuf) free(cbuf);
447
// Make binding and insert into map
449
KeyValueMethod *mkey;
450
SetKeyValueBinding *bin;
452
mkey = Malloc(sizeof(KeyValueMethod));
453
bin = Malloc(sizeof(SetKeyValueBinding));
454
mkey->key = [key copy];
455
mkey->class = [instance class];
461
NSMapInsert(setValueBindings, mkey, bin);
464
// If no way to access value warn
465
if (!ret && keyValueDebug)
466
NSLog(@"cannnot set key `%@' for instance of class `%@'",
467
key, NSStringFromClass([instance class]));
473
* MapTable initialization
476
static unsigned keyValueMapHash(NSMapTable* table, KeyValueMethod* map) {
477
return [map->key hash] + (((int)(map->class)) >> 4);
480
static BOOL keyValueMapCompare(NSMapTable* table,
481
KeyValueMethod* map1, KeyValueMethod* map2)
483
return (map1->class == map2->class) && [map1->key isEqual:map2->key];
486
static void mapRetainNothing(NSMapTable* table, KeyValueMethod* map) {
489
static void keyValueMapKeyRelease(NSMapTable* table, KeyValueMethod* map) {
494
static void keyValueMapValRelease(NSMapTable* table, void* map) {
498
static NSString* keyValueMapDescribe(NSMapTable* table, KeyValueMethod* map) {
499
if (StringClass == Nil) StringClass = [NSString class];
500
return [StringClass stringWithFormat:@"%@:%@",
501
NSStringFromClass(map->class), map->key];
504
static NSString* describeBinding(NSMapTable* table, GetKeyValueBinding* bin) {
505
if (StringClass == Nil) StringClass = [NSString class];
506
return [StringClass stringWithFormat:@"%08x:%08x", bin->info1, bin->info2];
509
static NSMapTableKeyCallBacks keyValueKeyCallbacks = {
510
(unsigned(*)(NSMapTable *, const void *))keyValueMapHash,
511
(BOOL(*)(NSMapTable *, const void *, const void *))keyValueMapCompare,
512
(void (*)(NSMapTable *, const void *anObject))mapRetainNothing,
513
(void (*)(NSMapTable *, void *anObject))keyValueMapKeyRelease,
514
(NSString *(*)(NSMapTable *, const void *))keyValueMapDescribe,
518
const NSMapTableValueCallBacks keyValueValueCallbacks = {
519
(void (*)(NSMapTable *, const void *))mapRetainNothing,
520
(void (*)(NSMapTable *, void *))keyValueMapValRelease,
521
(NSString *(*)(NSMapTable *, const void *))describeBinding
524
static void initKeyValueBindings(void)
526
getValueBindings = NSCreateMapTable(keyValueKeyCallbacks,
527
keyValueValueCallbacks, 31);
528
setValueBindings = NSCreateMapTable(keyValueKeyCallbacks,
529
keyValueValueCallbacks, 31);
537
static inline void removeAllBindings(void) {
538
NSResetMapTable(getValueBindings);
539
NSResetMapTable(setValueBindings);
542
static inline id getValue(NSString* key, id instance) {
543
KeyValueMethod mkey = { key, [instance class] };
544
GetKeyValueBinding *bin;
547
if (NumberClass == Nil)
548
NumberClass = [NSNumber class];
552
initKeyValueBindings();
554
// Get existing binding
555
bin = (GetKeyValueBinding *)NSMapGet(getValueBindings, &mkey);
557
// Create new binding
559
bin = newGetBinding(key, instance);
561
// Get value if binding is ok
563
value = bin->access(bin->info1, bin->info2, instance);
568
static inline BOOL setValue(NSString* key, id instance, id value)
570
KeyValueMethod mkey = {key, [instance class]};
571
SetKeyValueBinding* bin;
573
if (NumberClass == Nil)
574
NumberClass = [NSNumber class];
578
initKeyValueBindings();
580
// Get existing binding
581
bin = (SetKeyValueBinding *)NSMapGet(setValueBindings, &mkey);
583
// Create new binding
585
bin = newSetBinding(key, instance);
587
// Get value if binding is ok
589
bin->access(bin->info1, bin->info2, instance, value);
591
return (bin != NULL);
594
+ (BOOL)accessInstanceVariablesDirectly {
598
- (void)handleTakeValue:(id)_value forUnboundKey:(NSString *)_key {
601
ui = [NSDictionary dictionaryWithObjectsAndKeys:
602
self, @"EOTargetObjectUserInfoKey",
604
@"EOTargetObjectClassUserInfoKey",
605
_key, @"EOUnknownUserInfoKey",
607
[[NSException exceptionWithName:@"EOUnknownKeyException"
608
reason:@"called -takeValue:forKey: with unknown key"
612
- (id)handleQueryWithUnboundKey:(NSString *)_key {
615
ui = [NSDictionary dictionaryWithObjectsAndKeys:
616
self, @"EOTargetObjectUserInfoKey",
617
_key, @"EOUnknownUserInfoKey",
619
[[NSException exceptionWithName:@"EOUnknownKeyException"
620
reason:@"called -valueForKey: with unknown key"
625
- (void)unableToSetNullForKey:(NSString *)_key {
626
[NSException raise:@"NSInvalidArgumentException"
628
@"EOKeyValueCoding cannot set EONull value for key %@,"
629
@"in instance of %@ class.",
630
_key, NSStringFromClass([self class])];
633
+ (void)flushAllKeyBindings {
636
- (void)flushKeyBindings {
641
- (void)setKeyValueCodingWarnings:(BOOL)aFlag {
642
keyValueDebug = aFlag;
645
- (void)takeValuesFromDictionary:(NSDictionary *)dictionary {
646
NSEnumerator *keyEnum;
649
if (null == nil) null = [EONull null];
650
keyEnum = [dictionary keyEnumerator];
652
while ((key = [keyEnum nextObject])) {
655
value = [dictionary objectForKey:key];
657
/* automagically convert EONull to nil */
658
if (value == null) value = nil;
660
[self takeValue:value forKey:key];
662
#if 0 // this doesn't support overridden methods ...
663
if (!setValue(key, self, value)) {
664
[self handleTakeValue:value forUnboundKey:key];
670
- (NSDictionary *)valuesForKeys:(NSArray *)keys {
671
static Class NSDictionaryClass = Nil;
672
int n = [keys count];
674
if (NSDictionaryClass == Nil)
675
NSDictionaryClass = [NSDictionary class];
677
null = [EONull null];
680
return [NSDictionaryClass dictionary];
685
key = [keys objectAtIndex:0];
686
//value = getValue(key, self);
687
value = [self valueForKey:key];
689
/* automagically convert 'nil' to EONull */
690
if (value == nil) value = null;
692
return [NSDictionaryClass dictionaryWithObject:value forKey:key];
699
for (i = 0; i < n; i++) {
703
key = [keys objectAtIndex:i];
704
//val = getValue(key, self);
705
val = [self valueForKey:key];
707
/* automagically convert 'nil' to EONull */
708
if (val == nil) val = null;
714
return [NSDictionaryClass dictionaryWithObjects:newVals
720
- (void)takeValue:(id)_value forKey:(NSString *)_key {
721
if (!setValue(_key, self, _value)) {
722
//NSLog(@"ERROR(%s): couldn't take value for key %@", key);
723
[self handleTakeValue:_value forUnboundKey:_key];
727
- (id)valueForKey:(NSString *)key {
730
if ((val = getValue(key, self)))
738
+ (BOOL)useStoredAccessor {
742
- (void)takeStoredValue:(id)_value forKey:(NSString *)_key {
743
if ([[self class] useStoredAccessor]) {
746
/* this should be different */
748
ok = setValue(_key, self, _value);
749
if (!ok) [self handleTakeValue:_value forUnboundKey:_key];
752
[self takeValue:_value forKey:_key];
755
- (id)storedValueForKey:(NSString *)_key {
756
if ([[self class] useStoredAccessor]) {
759
/* this should be different */
761
if ((val = getValue(_key, self)))
764
/* val = [self handleQueryWithUnboundKey:_key] */
769
return [self valueForKey:_key];
772
@end /* NSObject(EOKeyValueCoding) */
774
@implementation NSObject(EOKeyPathValueCoding)
776
- (void)takeValue:(id)_value forKeyPath:(NSString *)_keyPath {
781
keyPath = [_keyPath componentsSeparatedByString:@"."];
782
count = [keyPath count];
785
[self takeValue:_value forKey:_keyPath];
789
for (i = 0; i < (count - 1) ; i++) {
790
if ((target = [target valueForKey:[keyPath objectAtIndex:i]]) == nil)
795
[target takeValue:_value forKey:[keyPath lastObject]];
798
- (id)valueForKeyPath:(NSString *)_keyPath {
800
const unsigned char *buf;
801
unsigned int i, start, len;
804
if ((len = [_keyPath cStringLength]) == 0)
805
return [self valueForKey:_keyPath];
807
if (StringClass == Nil) StringClass = [NSString class];
810
buf = [_keyPath cString];
811
if (index(buf, '.') == NULL)
812
/* no point contained .. */
813
return [self valueForKey:_keyPath];
815
for (i = start = 0; i < len; i++) {
821
? [StringClass stringWithCString:&(buf[start]) length:(i - start)]
824
if ((value = [value valueForKey:key]) == nil)
827
start = (i + 1); /* next part is after the pt */
830
/* check last part */
835
? [StringClass stringWithCString:&(buf[start]) length:(i - start)]
837
return [value valueForKey:key];
840
/* naive implementation */
841
NSEnumerator *keyPath;
846
keyPath = [[_keyPath componentsSeparatedByString:@"."] objectEnumerator];
847
while ((key = [keyPath nextObject]) && (value != nil))
848
value = [value valueForKey:key];
853
@end /* NSObject(EOKeyPathValueCoding) */
855
@implementation NSArray(EOKeyValueCoding)
857
- (id)computeSumForKey:(NSString *)_key {
858
unsigned i, cc = [self count];
859
id (*objAtIdx)(id, SEL, unsigned int);
862
if (cc == 0) return [NSNumber numberWithDouble:0.0];
864
objAtIdx = (void*)[self methodForSelector:@selector(objectAtIndex:)];
866
for (i = 0, sum = 0.0; i < cc; i++) {
869
o = objAtIdx(self, @selector(objectAtIndex:), i);
870
sum += [o doubleValue];
872
return [NSNumber numberWithDouble:sum];
875
- (id)computeAvgForKey:(NSString *)_key {
876
unsigned i, cc = [self count];
877
id (*objAtIdx)(id, SEL, unsigned int);
880
if (cc == 0) return [NSNumber numberWithDouble:0.0];
882
objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
884
for (i = 0, sum = 0.0; i < cc; i++) {
887
o = objAtIdx(self, @selector(objectAtIndex:), i);
889
sum += [o doubleValue];
891
return [NSNumber numberWithDouble:(sum / (double)cc)];
894
- (id)computeCountForKey:(NSString *)_key {
895
return [NSNumber numberWithUnsignedInt:[self count]];
898
- (id)computeMaxForKey:(NSString *)_key {
899
unsigned i, cc = [self count];
900
id (*objAtIdx)(id, SEL, unsigned int);
903
if (cc == 0) return nil;
905
objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
907
max = [objAtIdx(self, @selector(objectAtIndex:), 0) doubleValue];
908
for (i = 1; i < cc; i++) {
911
ov = [objAtIdx(self, @selector(objectAtIndex:), i) doubleValue];
912
if (ov > max) max = ov;
914
return [NSNumber numberWithDouble:max];
917
- (id)computeMinForKey:(NSString *)_key {
918
unsigned i, cc = [self count];
919
id (*objAtIdx)(id, SEL, unsigned int);
922
if (cc == 0) return nil;
924
objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
926
min = [objAtIdx(self, @selector(objectAtIndex:), 0) doubleValue];
927
for (i = 1; i < cc; i++) {
930
ov = [objAtIdx(self, @selector(objectAtIndex:), i) doubleValue];
931
if (ov < min) min = ov;
933
return [NSNumber numberWithDouble:min];
936
- (id)valueForKey:(NSString *)_key {
937
if ([_key hasPrefix:@"@"]) {
938
/* process a computed function */
941
unsigned keyLen = [_key cStringLength];
945
kbuf = malloc(keyLen + 4);
946
buf = malloc(keyLen + 20);
947
[_key getCString:kbuf];
950
strcpy(buf, "compute"); bufPtr += 7;
951
*bufPtr = toupper(keyStr[1]); bufPtr++;
952
strncpy(&(buf[8]), &(keyStr[2]), keyLen - 2); bufPtr += (keyLen - 2);
953
strcpy(bufPtr, "ForKey:");
954
if (kbuf) free(kbuf);
956
sel = sel_get_any_uid(buf);
959
return sel != NULL ? [self performSelector:sel withObject:_key] : nil;
962
/* process the _key in a map function */
963
unsigned i, cc = [self count];
965
id (*objAtIdx)(id, SEL, unsigned int);
968
if ([_key isEqualToString:@"count"]) {
969
NSLog(@"WARNING(%s): USED -valueForKey(@\"count\") ON NSArray, YOU"
970
@"PROBABLY WANT TO USE @count INSTEAD !",
971
__PRETTY_FUNCTION__);
972
return [self valueForKey:@"@count"];
976
objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
978
for (i = 0; i < cc; i++) {
981
o = [objAtIdx(self, @selector(objectAtIndex:), i) valueForKey:_key];
986
if (null == nil) null = [EONull null];
991
return [NSArray arrayWithObjects:objects count:cc];
995
@end /* NSArray(EOKeyValueCoding) */
997
@implementation NSDictionary(EOKeyValueCoding)
999
- (NSDictionary *)valuesForKeys:(NSArray *)keys {
1000
int n = [keys count];
1003
return [NSDictionary dictionary];
1005
NSString *key = [keys objectAtIndex:0];
1007
return [NSDictionary dictionaryWithObject:[self objectForKey:key]
1011
NSMutableArray *newKeys, *newVals;
1014
newKeys = [NSMutableArray arrayWithCapacity:n];
1015
newVals = [NSMutableArray arrayWithCapacity:n];
1017
for (i = 0; i < n; i++) {
1018
id key = [keys objectAtIndex:i];
1019
id val = [self objectForKey:key];
1022
[newKeys addObject:key];
1023
[newVals addObject:val];
1027
return [NSDictionary dictionaryWithObjects:newVals forKeys:newKeys];
1031
- (void)takeValue:(id)_value forKey:(NSString *)_key {
1032
//#warning takeValue:forKey: is ignored in NSDictionaries !
1034
//[self handleTakeValue:_value forUnboundKey:_key];
1037
- (id)valueForKey:(id)_key {
1040
if (_key == nil) // TODO: warn about nil key?
1042
if ((obj = [self objectForKey:_key]) == nil)
1045
if (null == nil) null = [[NSNull null] retain];
1052
@end /* NSDictionary(EOKeyValueCoding) */
1054
@implementation NSMutableDictionary(EOKeyValueCoding)
1056
- (void)takeValuesFromDictionary:(NSDictionary*)dictionary {
1057
[self addEntriesFromDictionary:dictionary];
1060
- (void)takeValue:(id)_value forKey:(id)_key {
1061
if (_value == nil) _value = [NSNull null];
1062
[self setObject:_value forKey:_key];
1065
@end /* NSMutableDictionary(EOKeyValueCoding) */
1068
* Accessor functions
1071
/* ACCESS to keys of id type. */
1073
static id idMethodGetFunc(void* info1, void* info2, id self) {
1074
id (*fptr)(id, SEL) = (id(*)(id, SEL))info1;
1075
id val = fptr(self, (SEL)info2);
1078
static id idIvarGetFunc(void* info1, void* info2, id self) {
1079
id* ptr = (id*)((char*)self + (int)info2);
1083
static void idMethodSetFunc(void* info1, void* info2, id self, id val) {
1084
void (*fptr)(id, SEL, id) = (void(*)(id, SEL, id))info1;
1085
fptr(self, (SEL)info2, val);
1088
static void idIvarSetFunc(void* info1, void* info2, id self, id val)
1090
id* ptr = (id*)((char*)self + (int)info2);
1094
/* ACCESS to keys of char type. */
1096
static id charMethodGetFunc(void* info1, void* info2, id self)
1098
char (*fptr)(id, SEL) = (char(*)(id, SEL))info1;
1099
char val = fptr(self, (SEL)info2);
1100
return [NumberClass numberWithChar:val];
1103
static id charIvarGetFunc(void* info1, void* info2, id self)
1105
char* ptr = (char*)((char*)self + (int)info2);
1106
return [NumberClass numberWithChar:*ptr];
1109
static void charMethodSetFunc(void* info1, void* info2, id self, id val)
1111
void (*fptr)(id, SEL, char) = (void(*)(id, SEL, char))info1;
1112
fptr(self, (SEL)info2, [val charValue]);
1115
static void charIvarSetFunc(void* info1, void* info2, id self, id val)
1117
char* ptr = (char*)((char*)self + (int)info2);
1118
*ptr = [val charValue];
1122
/* ACCESS to keys of unsigned char type. */
1124
static id unsignedCharMethodGetFunc(void* info1, void* info2, id self)
1126
unsigned char (*fptr)(id, SEL) = (unsigned char(*)(id, SEL))info1;
1127
unsigned char val = fptr(self, (SEL)info2);
1128
return [NumberClass numberWithUnsignedChar:val];
1131
static id unsignedCharIvarGetFunc(void* info1, void* info2, id self)
1133
unsigned char* ptr = (unsigned char*)((char*)self + (int)info2);
1134
return [NumberClass numberWithUnsignedChar:*ptr];
1137
static void unsignedCharMethodSetFunc(void* info1, void* info2, id self, id val)
1139
void (*fptr)(id, SEL, unsigned char) = (void(*)(id, SEL, unsigned char))info1;
1140
fptr(self, (SEL)info2, [val unsignedCharValue]);
1143
static void unsignedCharIvarSetFunc(void* info1, void* info2, id self, id val)
1145
unsigned char* ptr = (unsigned char*)((char*)self + (int)info2);
1146
*ptr = [val unsignedCharValue];
1150
/* ACCESS to keys of short type. */
1152
static id shortMethodGetFunc(void* info1, void* info2, id self)
1154
short (*fptr)(id, SEL) = (short(*)(id, SEL))info1;
1155
short val = fptr(self, (SEL)info2);
1156
return [NumberClass numberWithShort:val];
1159
static id shortIvarGetFunc(void* info1, void* info2, id self)
1161
short* ptr = (short*)((char*)self + (int)info2);
1162
return [NumberClass numberWithShort:*ptr];
1165
static void shortMethodSetFunc(void* info1, void* info2, id self, id val)
1167
void (*fptr)(id, SEL, short) = (void(*)(id, SEL, short))info1;
1168
fptr(self, (SEL)info2, [val shortValue]);
1171
static void shortIvarSetFunc(void* info1, void* info2, id self, id val)
1173
short* ptr = (short*)((char*)self + (int)info2);
1174
*ptr = [val shortValue];
1178
/* ACCESS to keys of unsigned short type. */
1180
static id unsignedShortMethodGetFunc(void* info1, void* info2, id self)
1182
unsigned short (*fptr)(id, SEL) = (unsigned short(*)(id, SEL))info1;
1183
unsigned short val = fptr(self, (SEL)info2);
1184
return [NumberClass numberWithUnsignedShort:val];
1187
static id unsignedShortIvarGetFunc(void* info1, void* info2, id self)
1189
unsigned short* ptr = (unsigned short*)((char*)self + (int)info2);
1190
return [NumberClass numberWithUnsignedShort:*ptr];
1193
static void unsignedShortMethodSetFunc(void* info1, void* info2, id self, id val)
1195
void (*fptr)(id, SEL, unsigned short) = (void(*)(id, SEL, unsigned short))info1;
1196
fptr(self, (SEL)info2, [val unsignedShortValue]);
1199
static void unsignedShortIvarSetFunc(void* info1, void* info2, id self, id val)
1201
unsigned short* ptr = (unsigned short*)((char*)self + (int)info2);
1202
*ptr = [val unsignedShortValue];
1206
/* ACCESS to keys of int type. */
1208
static id intMethodGetFunc(void* info1, void* info2, id self)
1210
int (*fptr)(id, SEL) = (int(*)(id, SEL))info1;
1211
int val = fptr(self, (SEL)info2);
1212
return [NumberClass numberWithInt:val];
1215
static id intIvarGetFunc(void* info1, void* info2, id self)
1217
int* ptr = (int*)((char*)self + (int)info2);
1218
return [NumberClass numberWithInt:*ptr];
1221
static void intMethodSetFunc(void* info1, void* info2, id self, id val)
1223
void (*fptr)(id, SEL, int) = (void(*)(id, SEL, int))info1;
1224
fptr(self, (SEL)info2, [val intValue]);
1227
static void intIvarSetFunc(void* info1, void* info2, id self, id val)
1229
int* ptr = (int*)((char*)self + (int)info2);
1230
*ptr = [val intValue];
1234
/* ACCESS to keys of unsigned int type. */
1236
static id unsignedIntMethodGetFunc(void* info1, void* info2, id self)
1238
unsigned int (*fptr)(id, SEL) = (unsigned int(*)(id, SEL))info1;
1239
unsigned int val = fptr(self, (SEL)info2);
1240
return [NumberClass numberWithUnsignedInt:val];
1243
static id unsignedIntIvarGetFunc(void* info1, void* info2, id self)
1245
unsigned int* ptr = (unsigned int*)((char*)self + (int)info2);
1246
return [NumberClass numberWithUnsignedInt:*ptr];
1249
static void unsignedIntMethodSetFunc(void* info1, void* info2, id self, id val)
1251
void (*fptr)(id, SEL, unsigned int) = (void(*)(id, SEL, unsigned int))info1;
1252
fptr(self, (SEL)info2, [val unsignedIntValue]);
1255
static void unsignedIntIvarSetFunc(void* info1, void* info2, id self, id val)
1257
unsigned int* ptr = (unsigned int*)((char*)self + (int)info2);
1258
*ptr = [val unsignedIntValue];
1262
/* ACCESS to keys of long type. */
1264
static id longMethodGetFunc(void* info1, void* info2, id self)
1266
long (*fptr)(id, SEL) = (long(*)(id, SEL))info1;
1267
long val = fptr(self, (SEL)info2);
1268
return [NumberClass numberWithLong:val];
1271
static id longIvarGetFunc(void* info1, void* info2, id self)
1273
long* ptr = (long*)((char*)self + (int)info2);
1274
return [NumberClass numberWithLong:*ptr];
1277
static void longMethodSetFunc(void* info1, void* info2, id self, id val)
1279
void (*fptr)(id, SEL, long) = (void(*)(id, SEL, long))info1;
1280
fptr(self, (SEL)info2, [val longValue]);
1283
static void longIvarSetFunc(void* info1, void* info2, id self, id val)
1285
long* ptr = (long*)((char*)self + (int)info2);
1286
*ptr = [val longValue];
1290
/* unsigned long type */
1292
static id unsignedLongMethodGetFunc(void* info1, void* info2, id self) {
1293
unsigned long (*fptr)(id, SEL) = (unsigned long(*)(id, SEL))info1;
1294
unsigned long val = fptr(self, (SEL)info2);
1295
return [NumberClass numberWithUnsignedLong:val];
1298
static id unsignedLongIvarGetFunc(void* info1, void* info2, id self) {
1299
unsigned long* ptr = (unsigned long*)((char*)self + (int)info2);
1300
return [NumberClass numberWithUnsignedLong:*ptr];
1303
static void unsignedLongMethodSetFunc(void* info1, void* info2, id self, id val) {
1304
void (*fptr)(id, SEL, unsigned long) = (void(*)(id, SEL, unsigned long))info1;
1305
fptr(self, (SEL)info2, [val unsignedLongValue]);
1308
static void unsignedLongIvarSetFunc(void* info1, void* info2, id self, id val) {
1309
unsigned long* ptr = (unsigned long*)((char*)self + (int)info2);
1310
*ptr = [val unsignedLongValue];
1314
/* long long type */
1316
static id longLongMethodGetFunc(void* info1, void* info2, id self) {
1317
long long (*fptr)(id, SEL) = (long long(*)(id, SEL))info1;
1318
long long val = fptr(self, (SEL)info2);
1319
return [NumberClass numberWithLongLong:val];
1322
static id longLongIvarGetFunc(void* info1, void* info2, id self) {
1323
long long* ptr = (long long*)((char*)self + (int)info2);
1324
return [NumberClass numberWithLongLong:*ptr];
1327
static void longLongMethodSetFunc(void* info1, void* info2, id self, id val) {
1328
void (*fptr)(id, SEL, long long) = (void(*)(id, SEL, long long))info1;
1329
fptr(self, (SEL)info2, [val longLongValue]);
1332
static void longLongIvarSetFunc(void* info1, void* info2, id self, id val) {
1333
long long* ptr = (long long*)((char*)self + (int)info2);
1334
*ptr = [val longLongValue];
1338
/* unsigned long long type */
1340
static id unsignedLongLongMethodGetFunc(void* info1, void* info2, id self) {
1341
unsigned long long (*fptr)(id, SEL) = (unsigned long long(*)(id, SEL))info1;
1342
unsigned long long val = fptr(self, (SEL)info2);
1343
return [NumberClass numberWithUnsignedLongLong:val];
1346
static id unsignedLongLongIvarGetFunc(void* info1, void* info2, id self) {
1347
unsigned long long* ptr = (unsigned long long*)((char*)self + (int)info2);
1348
return [NumberClass numberWithUnsignedLongLong:*ptr];
1351
static void unsignedLongLongMethodSetFunc(void* info1, void* info2, id self, id val) {
1352
void (*fptr)(id, SEL, unsigned long long) = (void(*)(id, SEL, unsigned long long))info1;
1353
fptr(self, (SEL)info2, [val unsignedLongLongValue]);
1356
static void unsignedLongLongIvarSetFunc(void* info1, void* info2, id self, id val) {
1357
unsigned long long* ptr = (unsigned long long*)((char*)self + (int)info2);
1358
*ptr = [val unsignedLongLongValue];
1364
static id floatMethodGetFunc(void* info1, void* info2, id self) {
1365
float (*fptr)(id, SEL) = (float(*)(id, SEL))info1;
1366
float val = fptr(self, (SEL)info2);
1367
return [NumberClass numberWithFloat:val];
1370
static id floatIvarGetFunc(void* info1, void* info2, id self) {
1371
float* ptr = (float*)((char*)self + (int)info2);
1372
return [NumberClass numberWithFloat:*ptr];
1375
static void floatMethodSetFunc(void* info1, void* info2, id self, id val) {
1376
void (*fptr)(id, SEL, float) = (void(*)(id, SEL, float))info1;
1377
fptr(self, (SEL)info2, [val floatValue]);
1380
static void floatIvarSetFunc(void* info1, void* info2, id self, id val) {
1381
float* ptr = (float*)((char*)self + (int)info2);
1382
*ptr = [val floatValue];
1388
static id doubleMethodGetFunc(void* info1, void* info2, id self) {
1389
double (*fptr)(id, SEL) = (double(*)(id, SEL))info1;
1390
double val = fptr(self, (SEL)info2);
1391
return [NumberClass numberWithDouble:val];
1394
static id doubleIvarGetFunc(void* info1, void* info2, id self) {
1395
double* ptr = (double*)((char*)self + (int)info2);
1396
return [NumberClass numberWithDouble:*ptr];
1399
static void doubleMethodSetFunc(void* info1, void* info2, id self, id val) {
1400
void (*fptr)(id, SEL, double) = (void(*)(id, SEL, double))info1;
1401
fptr(self, (SEL)info2, [val doubleValue]);
1404
static void doubleIvarSetFunc(void* info1, void* info2, id self, id val) {
1405
double* ptr = (double*)((char*)self + (int)info2);
1406
*ptr = [val doubleValue];
1409
#else /* NeXT_Foundation_LIBRARY */
1411
@implementation NSArray(EOKeyValueCoding)
1413
- (id)computeSumForKey:(NSString *)_key {
1414
unsigned i, cc = [self count];
1415
id (*objAtIdx)(id, SEL, unsigned int);
1418
if (cc == 0) return [NSNumber numberWithDouble:0.0];
1420
objAtIdx = (void*)[self methodForSelector:@selector(objectAtIndex:)];
1422
for (i = 0, sum = 0.0; i < cc; i++) {
1425
o = objAtIdx(self, @selector(objectAtIndex:), i);
1426
sum += [o doubleValue];
1428
return [NSNumber numberWithDouble:sum];
1431
- (id)computeAvgForKey:(NSString *)_key {
1432
unsigned i, cc = [self count];
1433
id (*objAtIdx)(id, SEL, unsigned int);
1436
if (cc == 0) return [NSNumber numberWithDouble:0.0];
1438
objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
1440
for (i = 0, sum = 0.0; i < cc; i++) {
1443
o = objAtIdx(self, @selector(objectAtIndex:), i);
1445
sum += [o doubleValue];
1447
return [NSNumber numberWithDouble:(sum / (double)cc)];
1450
- (id)computeCountForKey:(NSString *)_key {
1451
return [NSNumber numberWithUnsignedInt:[self count]];
1454
- (id)computeMaxForKey:(NSString *)_key {
1455
unsigned i, cc = [self count];
1456
id (*objAtIdx)(id, SEL, unsigned int);
1459
if (cc == 0) return nil;
1461
objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
1463
max = [objAtIdx(self, @selector(objectAtIndex:), 0) doubleValue];
1464
for (i = 1; i < cc; i++) {
1467
ov = [objAtIdx(self, @selector(objectAtIndex:), i) doubleValue];
1468
if (ov > max) max = ov;
1470
return [NSNumber numberWithDouble:max];
1473
- (id)computeMinForKey:(NSString *)_key {
1474
unsigned i, cc = [self count];
1475
id (*objAtIdx)(id, SEL, unsigned int);
1478
if (cc == 0) return nil;
1480
objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
1482
min = [objAtIdx(self, @selector(objectAtIndex:), 0) doubleValue];
1483
for (i = 1; i < cc; i++) {
1486
ov = [objAtIdx(self, @selector(objectAtIndex:), i) doubleValue];
1487
if (ov < min) min = ov;
1489
return [NSNumber numberWithDouble:min];
1492
- (id)valueForKey:(NSString *)_key {
1493
if (null == nil) null = [[EONull null] retain];
1495
if ([_key hasPrefix:@"@"]) {
1496
/* process a computed function */
1499
unsigned keyLen = [_key cStringLength];
1503
kbuf = malloc(keyLen + 1);
1504
buf = malloc(keyLen + 16);
1505
[_key getCString:kbuf];
1508
strcpy(buf, "compute"); bufPtr += 7;
1509
*bufPtr = toupper(keyStr[1]); bufPtr++;
1510
strncpy(&(buf[8]), &(keyStr[2]), keyLen - 2); bufPtr += (keyLen - 2);
1511
strcpy(bufPtr, "ForKey:");
1512
if (kbuf) free(kbuf);
1515
sel = sel_getUid(buf);
1517
sel = sel_get_any_uid(buf);
1521
return sel != NULL ? [self performSelector:sel withObject:_key] : nil;
1524
/* process the _key in a map function */
1525
unsigned i, cc = [self count];
1528
id (*objAtIdx)(id, SEL, unsigned int);
1531
if ([_key isEqualToString:@"count"]) {
1532
NSLog(@"WARNING(%s): USED -valueForKey(@\"count\") ON NSArray, YOU"
1533
@"PROBABLY WANT TO USE @count INSTEAD !",
1534
__PRETTY_FUNCTION__);
1535
return [self valueForKey:@"@count"];
1539
if (cc == 0) return [NSArray array];
1541
objects = calloc(cc + 2, sizeof(id));
1542
objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
1544
for (i = 0; i < cc; i++) {
1547
o = [objAtIdx(self, @selector(objectAtIndex:), i) valueForKey:_key];
1548
objects[i] = o ? o : null;
1551
result = [NSArray arrayWithObjects:objects count:cc];
1552
if (objects) free(objects);
1557
@end /* NSArray(EOKeyValueCoding) */
1559
#endif /* !NeXT_Foundation_LIBRARY */