mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 08:21:25 +00:00
Add KVC aggregate operators
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@26309 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
cf1a0d7780
commit
bf72375a70
3 changed files with 453 additions and 0 deletions
|
@ -1,3 +1,9 @@
|
|||
2008-03-16 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSArray.m:
|
||||
* Source/NSSet.m:
|
||||
Add ([-valueForKeyPath:]) to implement KVC aggregate operators.
|
||||
|
||||
2008-03-14 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* Source/NSDictionary.m ([-initWithObjectsAndKeys:],
|
||||
|
|
223
Source/NSArray.m
223
Source/NSArray.m
|
@ -46,6 +46,8 @@
|
|||
#import "Foundation/NSDebug.h"
|
||||
#import "Foundation/NSValue.h"
|
||||
#import "Foundation/NSNull.h"
|
||||
#import "Foundation/NSKeyValueCoding.h"
|
||||
#import "Foundation/NSSet.h"
|
||||
#import "Foundation/NSUserDefaults.h"
|
||||
#import "Foundation/NSIndexSet.h"
|
||||
// For private method _decodeArrayOfObjectsForKey:
|
||||
|
@ -1313,6 +1315,227 @@ compare(id elem1, id elem2, void* context)
|
|||
return result;
|
||||
}
|
||||
|
||||
- (id) valueForKeyPath: (NSString*)path
|
||||
{
|
||||
id result;
|
||||
|
||||
if ([path hasPrefix: @"@"])
|
||||
{
|
||||
NSRange r;
|
||||
|
||||
r = [path rangeOfString: @"."];
|
||||
if (r.length == 0)
|
||||
{
|
||||
result = [self valueForKey: path];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *op = [path substringToIndex: r.location];
|
||||
NSString *rem = [path substringFromIndex: NSMaxRange(r)];
|
||||
unsigned count = [self count];
|
||||
|
||||
if ([op isEqualToString: @"@avg"] == YES)
|
||||
{
|
||||
double d = 0;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
d += [[o valueForKeyPath: rem] doubleValue];
|
||||
}
|
||||
d /= count;
|
||||
}
|
||||
result = [NSNumber numberWithDouble: d];
|
||||
}
|
||||
else if ([op isEqualToString: @"@max"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
if (result == nil
|
||||
|| [result compare: o] == NSOrderedAscending)
|
||||
{
|
||||
result = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@min"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
if (result == nil
|
||||
|| [result compare: o] == NSOrderedDescending)
|
||||
{
|
||||
result = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@sum"] == YES)
|
||||
{
|
||||
double d = 0;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
d += [[o valueForKeyPath: rem] doubleValue];
|
||||
}
|
||||
}
|
||||
result = [NSNumber numberWithDouble: d];
|
||||
}
|
||||
else if ([op isEqualToString: @"@distinctUnionOfArrays"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [NSMutableSet set];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObjectsFromArray: o];
|
||||
}
|
||||
result = [result allObjects];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@distinctUnionOfObjects"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [NSMutableSet set];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObject: o];
|
||||
}
|
||||
result = [result allObjects];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@distinctUnionOfSets"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [NSMutableSet set];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObjectsFromArray: [o allObjects]];
|
||||
}
|
||||
result = [result allObjects];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@unionOfArrays"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [GSMutableArray array];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObjectsFromArray: o];
|
||||
}
|
||||
[result makeImmutableCopyOnFail: NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@unionOfObjects"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [GSMutableArray array];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObject: o];
|
||||
}
|
||||
[result makeImmutableCopyOnFail: NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@unionOfSets"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [GSMutableArray array];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObjectsFromArray: [o allObjects]];
|
||||
}
|
||||
[result makeImmutableCopyOnFail: NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [self valueForKeyPath: path];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [super valueForKeyPath: path];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
|
224
Source/NSSet.m
224
Source/NSSet.m
|
@ -26,11 +26,14 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "Foundation/NSArray.h"
|
||||
#include "Foundation/NSSet.h"
|
||||
#include "Foundation/NSCoder.h"
|
||||
#include "Foundation/NSArray.h"
|
||||
#include "Foundation/NSEnumerator.h"
|
||||
#include "Foundation/NSKeyValueCoding.h"
|
||||
#include "Foundation/NSString.h"
|
||||
#include "Foundation/NSValue.h"
|
||||
#include "Foundation/NSException.h"
|
||||
#include "Foundation/NSObjCRuntime.h"
|
||||
#include "Foundation/NSDebug.h"
|
||||
|
@ -613,6 +616,227 @@ static Class NSMutableSet_concrete_class;
|
|||
return [[self allObjects] descriptionWithLocale: locale];
|
||||
}
|
||||
|
||||
- (id) valueForKeyPath: (NSString*)path
|
||||
{
|
||||
id result;
|
||||
|
||||
if ([path hasPrefix: @"@"])
|
||||
{
|
||||
NSRange r;
|
||||
|
||||
r = [path rangeOfString: @"."];
|
||||
if (r.length == 0)
|
||||
{
|
||||
result = [self valueForKey: path];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *op = [path substringToIndex: r.location];
|
||||
NSString *rem = [path substringFromIndex: NSMaxRange(r)];
|
||||
unsigned count = [self count];
|
||||
|
||||
if ([op isEqualToString: @"@avg"] == YES)
|
||||
{
|
||||
double d = 0;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
d += [[o valueForKeyPath: rem] doubleValue];
|
||||
}
|
||||
d /= count;
|
||||
}
|
||||
result = [NSNumber numberWithDouble: d];
|
||||
}
|
||||
else if ([op isEqualToString: @"@max"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
if (result == nil
|
||||
|| [result compare: o] == NSOrderedAscending)
|
||||
{
|
||||
result = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@min"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
if (result == nil
|
||||
|| [result compare: o] == NSOrderedDescending)
|
||||
{
|
||||
result = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@sum"] == YES)
|
||||
{
|
||||
double d = 0;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
d += [[o valueForKeyPath: rem] doubleValue];
|
||||
}
|
||||
}
|
||||
result = [NSNumber numberWithDouble: d];
|
||||
}
|
||||
else if ([op isEqualToString: @"@distinctUnionOfArrays"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [NSMutableSet set];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObjectsFromArray: o];
|
||||
}
|
||||
result = [result allObjects];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@distinctUnionOfObjects"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [NSMutableSet set];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObject: o];
|
||||
}
|
||||
result = [result allObjects];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@distinctUnionOfSets"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [NSMutableSet set];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObjectsFromArray: [o allObjects]];
|
||||
}
|
||||
result = [result allObjects];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@unionOfArrays"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [GSMutableArray array];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObjectsFromArray: o];
|
||||
}
|
||||
[result makeImmutableCopyOnFail: NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@unionOfObjects"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [GSMutableArray array];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObject: o];
|
||||
}
|
||||
[result makeImmutableCopyOnFail: NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else if ([op isEqualToString: @"@unionOfSets"] == YES)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
NSEnumerator *e = [self objectEnumerator];
|
||||
id o;
|
||||
|
||||
result = [GSMutableArray array];
|
||||
while ((o = [e nextObject]) != nil)
|
||||
{
|
||||
o = [o valueForKeyPath: rem];
|
||||
[result addObjectsFromArray: [o allObjects]];
|
||||
}
|
||||
[result makeImmutableCopyOnFail: NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [NSArray array];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [self valueForKeyPath: path];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [super valueForKeyPath: path];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue