mirror of
https://github.com/gnustep/libs-base.git
synced 2025-06-01 17:12:03 +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
ce6e171204
commit
24537a3b54
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>
|
2008-03-14 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
* Source/NSDictionary.m ([-initWithObjectsAndKeys:],
|
* Source/NSDictionary.m ([-initWithObjectsAndKeys:],
|
||||||
|
|
223
Source/NSArray.m
223
Source/NSArray.m
|
@ -46,6 +46,8 @@
|
||||||
#import "Foundation/NSDebug.h"
|
#import "Foundation/NSDebug.h"
|
||||||
#import "Foundation/NSValue.h"
|
#import "Foundation/NSValue.h"
|
||||||
#import "Foundation/NSNull.h"
|
#import "Foundation/NSNull.h"
|
||||||
|
#import "Foundation/NSKeyValueCoding.h"
|
||||||
|
#import "Foundation/NSSet.h"
|
||||||
#import "Foundation/NSUserDefaults.h"
|
#import "Foundation/NSUserDefaults.h"
|
||||||
#import "Foundation/NSIndexSet.h"
|
#import "Foundation/NSIndexSet.h"
|
||||||
// For private method _decodeArrayOfObjectsForKey:
|
// For private method _decodeArrayOfObjectsForKey:
|
||||||
|
@ -1313,6 +1315,227 @@ compare(id elem1, id elem2, void* context)
|
||||||
return result;
|
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
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
224
Source/NSSet.m
224
Source/NSSet.m
|
@ -26,11 +26,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "Foundation/NSArray.h"
|
||||||
#include "Foundation/NSSet.h"
|
#include "Foundation/NSSet.h"
|
||||||
#include "Foundation/NSCoder.h"
|
#include "Foundation/NSCoder.h"
|
||||||
#include "Foundation/NSArray.h"
|
#include "Foundation/NSArray.h"
|
||||||
#include "Foundation/NSEnumerator.h"
|
#include "Foundation/NSEnumerator.h"
|
||||||
|
#include "Foundation/NSKeyValueCoding.h"
|
||||||
#include "Foundation/NSString.h"
|
#include "Foundation/NSString.h"
|
||||||
|
#include "Foundation/NSValue.h"
|
||||||
#include "Foundation/NSException.h"
|
#include "Foundation/NSException.h"
|
||||||
#include "Foundation/NSObjCRuntime.h"
|
#include "Foundation/NSObjCRuntime.h"
|
||||||
#include "Foundation/NSDebug.h"
|
#include "Foundation/NSDebug.h"
|
||||||
|
@ -613,6 +616,227 @@ static Class NSMutableSet_concrete_class;
|
||||||
return [[self allObjects] descriptionWithLocale: locale];
|
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
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue