Implement [NSPredicate predicateWithBlock:].

Fixes https://savannah.gnu.org/bugs/?46418


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@39493 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Niels Grewe 2016-03-09 13:19:35 +00:00
parent 62d2bcbabc
commit 6e6ee05a80
4 changed files with 147 additions and 5 deletions

View file

@ -1,3 +1,10 @@
2016-03-09 Niels Grewe <niels.grewe@halbordnung.de>
* Headers/Foundation/NSPredicate.h
* Source/NSPredicate.m
* Tests/base/NSPredicate/basic.m:
Implementation and tests for +predicateWithBlock:
2016-03-09 Richard Frith-Macdonald <rfm@gnu.org>
* Source\NSSocketPortNameServer.m:

View file

@ -30,12 +30,17 @@
#import <Foundation/NSObject.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSSet.h>
#if defined(__cplusplus)
extern "C" {
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
DEFINE_BLOCK_TYPE(GSBlockPredicateBlock, BOOL, id, GS_GENERIC_CLASS(NSDictionary,NSString*,id)*);
#endif
@interface NSPredicate : NSObject <NSCoding, NSCopying>
+ (NSPredicate *) predicateWithFormat: (NSString *)format, ...;
@ -44,10 +49,13 @@ extern "C" {
+ (NSPredicate *) predicateWithFormat: (NSString *)format
arguments: (va_list)args;
+ (NSPredicate *) predicateWithValue: (BOOL)value;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+ (NSPredicate *) predicateWithBlock: (GSBlockPredicateBlock)block;
#endif
- (BOOL) evaluateWithObject: (id)object;
- (NSString *) predicateFormat;
- (NSPredicate *) predicateWithSubstitutionVariables: (NSDictionary *)variables;
- (NSPredicate *) predicateWithSubstitutionVariables:
(GS_GENERIC_CLASS(NSDictionary,NSString*,id)*)variables;
@end
@ -84,4 +92,4 @@ extern "C" {
#endif
#endif /* 100400 */
#endif /* __NSPredicate_h_GNUSTEP_BASE_INCLUDE */
#endif /* __NSPredicate_h_GNUSTEP_BASE_INCLUDE */

View file

@ -141,7 +141,24 @@ extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*);
}
@end
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
@interface GSBlockPredicate : NSPredicate
{
GSBlockPredicateBlock _block;
}
- (instancetype) initWithBlock: (GSBlockPredicateBlock)block;
@end
@interface GSBoundBlockPredicate : GSBlockPredicate
{
GS_GENERIC_CLASS(NSDictionary,NSString*,id)* _bindings;
}
- (instancetype) initWithBlock: (GSBlockPredicateBlock)block
bindings: (GS_GENERIC_CLASS(NSDictionary,NSString*,id)*)bindings;
@end
#endif
@implementation NSPredicate
@ -361,6 +378,11 @@ extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*);
return self;
}
+ (NSPredicate*)predicateWithBlock: (GSBlockPredicateBlock)block
{
return [[[GSBlockPredicate alloc] initWithBlock: block] autorelease];
}
@end
@implementation GSTruePredicate
@ -2591,5 +2613,82 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption
}
}
}
@end
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
@implementation GSBlockPredicate
- (instancetype) initWithBlock: (GSBlockPredicateBlock)block
{
if (nil == (self = [super init]))
{
return nil;
}
_block = (GSBlockPredicateBlock)[(id)block retain];
return self;
}
- (instancetype) predicateWithSubstitutionVariables:
(GS_GENERIC_CLASS(NSDictionary,NSString*,id)*)variables
{
return [[[GSBoundBlockPredicate alloc] initWithBlock: _block
bindings: variables] autorelease];
}
- (BOOL) evaluateWithObject: (id)object
substitutionVariables: (GS_GENERIC_CLASS(NSDictionary,
NSString*,id)*)variables
{
return CALL_BLOCK(_block, object, variables);
}
- (BOOL) evaluateWithObject: (id)object
{
return [self evaluateWithObject: object
substitutionVariables: nil];
}
- (void) dealloc
{
[(id)_block release];
_block = NULL;
[super dealloc];
}
- (NSString*) predicateFormat
{
return [NSString stringWithFormat: @"BLOCKPREDICATE(%p)", (void*)_block];
}
@end
@implementation GSBoundBlockPredicate
- (instancetype) initWithBlock: (GSBlockPredicateBlock)block
bindings: (GS_GENERIC_CLASS(NSDictionary,
NSString*,id)*)bindings
{
if (nil == (self = [super initWithBlock: block]))
{
return nil;
}
ASSIGN(_bindings, bindings);
return self;
}
- (BOOL) evaluateWithObject: (id)object
{
return [self evaluateWithObject: object
substitutionVariables: _bindings];
}
- (void) dealloc
{
DESTROY(_bindings);
[super dealloc];
}
@end
#endif

View file

@ -101,6 +101,33 @@ testAttregate(NSDictionary *dict)
PASS([p evaluateWithObject: dict], "Any %%K == %%@");
}
void
testBlock(NSDictionary* dict)
{
START_SET("Block predicates");
NSPredicate *p = nil;
NSPredicate *p2 = nil;
# if __has_feature(blocks)
p = [NSPredicate predicateWithBlock: ^BOOL(id obj,
GS_GENERIC_CLASS(NSDictionary,NSString*,id)* bindings){
NSString *key = [bindings objectForKey: @"Key"];
if (nil == key)
{
key = @"Record1";
}
NSString *value = [[obj objectForKey: key] objectForKey: @"Name"];
return [value isEqualToString: @"John"];
}];
PASS([p evaluateWithObject: dict], "BLOCKPREDICATE() without bindings");
p2 = [p predicateWithSubstitutionVariables:
[NSDictionary dictionaryWithObjectsAndKeys: @"Record2", @"Key", nil]];
PASS(![p2 evaluateWithObject: dict], "BLOCKPREDICATE() with bound variables");
# else
SKIP("No blocks support in the compiler.");
# endif
END_SET("Block predicates");
}
int main()
{
NSArray *filtered;
@ -134,6 +161,7 @@ int main()
testInteger(dict);
testFloat(dict);
testAttregate(dict);
testBlock(dict);
[dict release];
pitches = [NSArray arrayWithObjects: