From 5eea30b5300a03649cccadd0b54a9e2c12e7b000 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 24 May 2024 14:28:04 -0400 Subject: [PATCH 01/11] Add 10.6 NSExpression methods --- Headers/Foundation/NSExpression.h | 17 +++++++++---- MISSING | 3 --- Source/NSPredicate.m | 41 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/Headers/Foundation/NSExpression.h b/Headers/Foundation/NSExpression.h index 2b7208004..3acc4d89e 100644 --- a/Headers/Foundation/NSExpression.h +++ b/Headers/Foundation/NSExpression.h @@ -3,24 +3,24 @@ Written by: Dr. H. Nikolaus Schaller Created: 2005 - + This file is part of the GNUstep Base Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA. - */ + */ #ifndef __NSExpression_h_GNUSTEP_BASE_INCLUDE #define __NSExpression_h_GNUSTEP_BASE_INCLUDE @@ -64,6 +64,14 @@ GS_EXPORT_CLASS + (NSExpression *) expressionForKeyPath: (NSString *)path; + (NSExpression *) expressionForVariable: (NSString *)string; +#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST) ++ (NSExpression *) expressionWithFormat: (NSString *)format, ...; ++ (NSExpression *) expressionWithFormat: (NSString *)format + arguments: (va_list)args; ++ (NSExpression *) expressionWithFormat: (NSString *)format + argumentArray: (NSArray *)args; +#endif + - (NSArray *) arguments; - (id) constantValue; - (NSExpressionType) expressionType; @@ -84,4 +92,3 @@ GS_EXPORT_CLASS #endif /* 100400 */ #endif /* __NSExpression_h_GNUSTEP_BASE_INCLUDE */ - diff --git a/MISSING b/MISSING index 16e44f71c..3de32c8a8 100644 --- a/MISSING +++ b/MISSING @@ -165,9 +165,6 @@ NSExpression: NSSubqueryExpressionType NSAggregateExpressionType - + expressionWithFormat:argumentArray: - + expressionWithFormat: - + expressionWithFormat:arguments: + expressionForAggregate: + expressionForUnionSet:with: + expressionForIntersectSet:with diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index d62de6bc5..12bc628e9 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -1243,6 +1243,47 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption return AUTORELEASE(e); } +// 10.6 methods... ++ (NSExpression *) expressionWithFormat: (NSString *)format, ... +{ + va_list ap; + NSExpression *obj; + + if (NULL == format) + { + [NSException raise: NSInvalidArgumentException + format: @"[NSExpression+expressionWithFormat:]: NULL format"]; + } + + va_start(ap, format); + obj = [[self alloc] expressionWithFormat: format + arguments: ap]; + va_end(ap); + + return obj; +} + ++ (NSExpression *) expressionWithFormat: (NSString *)format + arguments: (va_list)args +{ + NSString *expString = AUTORELEASE([[NSString alloc] initWithFormat: format + arguments: args]); + GSPredicateScanner *scanner = AUTORELEASE([[GSPredicateScanner alloc] + initWithString: expString + args: nil]); + return [scanner parseExpression]; +} + ++ (NSExpression *) expressionWithFormat: (NSString *)format + argumentArray: (NSArray *)args +{ + GSPredicateScanner *scanner = AUTORELEASE([[GSPredicateScanner alloc] + initWithString: format + args: args]); + return [scanner parseExpression]; +} +// End 10.6 methods + - (id) initWithExpressionType: (NSExpressionType)type { if ((self = [super init]) != nil) From c5defb6f3cfc43e0045f689b7d52fde4bcdd15ba Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 24 May 2024 14:37:24 -0400 Subject: [PATCH 02/11] Get rid of whitespace --- Source/NSPredicate.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index 12bc628e9..1b64008ad 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -1254,17 +1254,17 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption [NSException raise: NSInvalidArgumentException format: @"[NSExpression+expressionWithFormat:]: NULL format"]; } - + va_start(ap, format); obj = [[self alloc] expressionWithFormat: format arguments: ap]; va_end(ap); - + return obj; } + (NSExpression *) expressionWithFormat: (NSString *)format - arguments: (va_list)args + arguments: (va_list)args { NSString *expString = AUTORELEASE([[NSString alloc] initWithFormat: format arguments: args]); @@ -1275,7 +1275,7 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption } + (NSExpression *) expressionWithFormat: (NSString *)format - argumentArray: (NSArray *)args + argumentArray: (NSArray *)args { GSPredicateScanner *scanner = AUTORELEASE([[GSPredicateScanner alloc] initWithString: format From f6eb49bdf744b6084519775776a6af92cb5d3e2a Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 24 May 2024 16:55:16 -0400 Subject: [PATCH 03/11] Add skeleton for 10.5 methods --- Headers/Foundation/NSExpression.h | 10 ++++++++++ Source/NSPredicate.m | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Headers/Foundation/NSExpression.h b/Headers/Foundation/NSExpression.h index 3acc4d89e..83cd9955e 100644 --- a/Headers/Foundation/NSExpression.h +++ b/Headers/Foundation/NSExpression.h @@ -64,6 +64,16 @@ GS_EXPORT_CLASS + (NSExpression *) expressionForKeyPath: (NSString *)path; + (NSExpression *) expressionForVariable: (NSString *)string; +#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) ++ (NSExpression *) expressionForIntersectSet: (NSExpression *)left + with: (NSExpression *)right; ++ (NSExpression *) expressionForAggregate: (NSArray *)subExpressions; ++ (NSExpression *) expressionForUnionSet: (NSExpression *)left + with: (NSExpression *)right; ++ (NSExpression *) expressionForMinusSet: (NSExpression *)left + with: (NSExpression *)right; +#endif + #if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST) + (NSExpression *) expressionWithFormat: (NSString *)format, ...; + (NSExpression *) expressionWithFormat: (NSString *)format diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index 1b64008ad..f00c445ef 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -1243,6 +1243,31 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption return AUTORELEASE(e); } +// 10.5 methods... ++ (NSExpression *) expressionForIntersectSet: (NSExpression *)left + with: (NSExpression *)right +{ + return nil; +} + ++ (NSExpression *) expressionForAggregate: (NSArray *)subExpressions +{ + return nil; +} + ++ (NSExpression *) expressionForUnionSet: (NSExpression *)left + with: (NSExpression *)right +{ + return nil; +} + ++ (NSExpression *) expressionForMinusSet: (NSExpression *)left + with: (NSExpression *)right +{ + return nil; +} +// end 10.5 methods + // 10.6 methods... + (NSExpression *) expressionWithFormat: (NSString *)format, ... { From 84e1ef9881825f4432c9995e3b8a6871b29b6a8f Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 24 May 2024 23:04:13 -0400 Subject: [PATCH 04/11] Add extremely simple tests to make sure that each of the methods returns non-nil --- Tests/base/NSPredicate/basic.m | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Tests/base/NSPredicate/basic.m b/Tests/base/NSPredicate/basic.m index 3d3586370..b372d934c 100644 --- a/Tests/base/NSPredicate/basic.m +++ b/Tests/base/NSPredicate/basic.m @@ -173,6 +173,21 @@ void testArray(void) PASS([predicate evaluateWithObject: array], "size is three") } +void testExpressions(void) +{ + NSExpression *exp = nil; + + // Add tests for new expressions here... + exp = [NSExpression expressionWithFormat: @"key = %@", @"test"]; + PASS(exp != nil, "expressionWithFormat: returns non nil"); + + exp = [NSExpression expressionWithFormat: @"key = %@" arguments: @"test"]; + PASS(exp != nil, "expressionWithFormat:arguments: returns non nil"); + + exp = [NSExpression expressionWithFormat: @"key = %@" argumentArray: [NSArray arrayWithObject: @"test"]]; + PASS(exp != nil, "expressionWithFormat:argumentArray: returns non nil"); +} + int main() { NSArray *filtered; From 392a626444238990cdf34ad00e773a95401cbb87 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 25 May 2024 00:39:34 -0400 Subject: [PATCH 05/11] Add missing enum values, add skeleton implementations for metods, add simple tests --- Headers/Foundation/NSExpression.h | 9 ++++++++- MISSING | 14 -------------- Source/NSPredicate.m | 4 ++-- Tests/base/NSPredicate/basic.m | 6 ++---- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/Headers/Foundation/NSExpression.h b/Headers/Foundation/NSExpression.h index 83cd9955e..6d584aaab 100644 --- a/Headers/Foundation/NSExpression.h +++ b/Headers/Foundation/NSExpression.h @@ -45,7 +45,14 @@ enum NSVariableExpressionType, NSKeyPathExpressionType, NSFunctionExpressionType, - NSKeyPathCompositionExpressionType + NSKeyPathCompositionExpressionType, + NSUnionSetExpressionType, + NSIntersectSetExpressionType, + NSSubqueryExpressionType = 13, + NSAggregateExpressionType = 14, + NSAnyKeyExpressionType = 15, + NSBlockExpressionType = 19, + NSConditionalExpressionType = 20 }; typedef NSUInteger NSExpressionType; diff --git a/MISSING b/MISSING index 3de32c8a8..e5122a675 100644 --- a/MISSING +++ b/MISSING @@ -4,10 +4,6 @@ Missing macros: NS_ENUM_AVAILABLE_IOS NS_AVAILABLE_IOS -Missing headers: -== -NONE - ------------------------------------------------------------- FoundationErrors: NSXPCConnectionInterrupted @@ -159,16 +155,6 @@ NSException: NSExpression: @class NSPredicate - NSUnionSetExpressionType - NSIntersectSetExpressionType - NSMinusSetExpressionType - NSSubqueryExpressionType - NSAggregateExpressionType - - + expressionForAggregate: - + expressionForUnionSet:with: - + expressionForIntersectSet:with - + expressionForMinusSet:with: + expressionForSubquery:usingIteratorVariable:predicate: + expressionForFunction:selectorName:arguments: + expressionForBlock:arguments: diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index f00c445ef..1b317fcfe 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -1281,8 +1281,8 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption } va_start(ap, format); - obj = [[self alloc] expressionWithFormat: format - arguments: ap]; + obj = [self expressionWithFormat: format + arguments: ap]; va_end(ap); return obj; diff --git a/Tests/base/NSPredicate/basic.m b/Tests/base/NSPredicate/basic.m index b372d934c..3f644f389 100644 --- a/Tests/base/NSPredicate/basic.m +++ b/Tests/base/NSPredicate/basic.m @@ -181,9 +181,6 @@ void testExpressions(void) exp = [NSExpression expressionWithFormat: @"key = %@", @"test"]; PASS(exp != nil, "expressionWithFormat: returns non nil"); - exp = [NSExpression expressionWithFormat: @"key = %@" arguments: @"test"]; - PASS(exp != nil, "expressionWithFormat:arguments: returns non nil"); - exp = [NSExpression expressionWithFormat: @"key = %@" argumentArray: [NSArray arrayWithObject: @"test"]]; PASS(exp != nil, "expressionWithFormat:argumentArray: returns non nil"); } @@ -295,7 +292,8 @@ int main() "predicate created with format can filter an array") testArray(); - + testExpressions(); + END_SET("basic") return 0; From dc9ff1ff6f7ef8420ca7729b3aa9837f3a98eb86 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 26 May 2024 08:39:44 -0400 Subject: [PATCH 06/11] Add declarations and skeletons for new subclasses --- Headers/Foundation/NSExpression.h | 17 ++++++++-- Source/NSPredicate.m | 53 ++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Headers/Foundation/NSExpression.h b/Headers/Foundation/NSExpression.h index 6d584aaab..d78e31b16 100644 --- a/Headers/Foundation/NSExpression.h +++ b/Headers/Foundation/NSExpression.h @@ -46,13 +46,19 @@ enum NSKeyPathExpressionType, NSFunctionExpressionType, NSKeyPathCompositionExpressionType, +#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) NSUnionSetExpressionType, NSIntersectSetExpressionType, NSSubqueryExpressionType = 13, NSAggregateExpressionType = 14, +#endif +#if OS_API_VERSION(MAC_OS_X_VERSION_10_9, GS_API_LATEST) NSAnyKeyExpressionType = 15, +#endif NSBlockExpressionType = 19, +#if OS_API_VERSION(MAC_OS_X_VERSION_10_11, GS_API_LATEST) NSConditionalExpressionType = 20 +#endif }; typedef NSUInteger NSExpressionType; @@ -73,12 +79,12 @@ GS_EXPORT_CLASS #if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) + (NSExpression *) expressionForIntersectSet: (NSExpression *)left - with: (NSExpression *)right; + with: (NSExpression *)right; + (NSExpression *) expressionForAggregate: (NSArray *)subExpressions; + (NSExpression *) expressionForUnionSet: (NSExpression *)left - with: (NSExpression *)right; + with: (NSExpression *)right; + (NSExpression *) expressionForMinusSet: (NSExpression *)left - with: (NSExpression *)right; + with: (NSExpression *)right; #endif #if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST) @@ -100,6 +106,11 @@ GS_EXPORT_CLASS - (NSExpression *) operand; - (NSString *) variable; +#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) +- (id) collection; +- (NSExpression *) leftExpression; +- (NSExpression *) rightExpression; +#endif @end #if defined(__cplusplus) diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index 1b317fcfe..ee379664c 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -141,6 +141,18 @@ extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*); } @end +@interface GSUnionSetExpression : NSExpression +@end + +@interface GSIntersectSetExpression : NSExpression +@end + +@interface GSSubqueryExpression : NSExpression +@end + +@interface GSAggregateExpression : NSExpression +@end + @interface GSFunctionExpression : NSExpression { @public @@ -1377,6 +1389,24 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption return nil; } +- (NSExpression *) leftExpression +{ + [self subclassResponsibility: _cmd]; + return nil; +} + +- (NSExpression *) rightExpression +{ + [self subclassResponsibility: _cmd]; + return nil; +} + +- (id) collection +{ + [self subclassResponsibility: _cmd]; + return nil; +} + - (Class) classForCoder { return [NSExpression class]; @@ -1645,6 +1675,28 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption right: right]; } +- (NSExpression *) leftExpression +{ + return _left; +} + +- (NSExpression *) rightExpression +{ + return _right; +} + +@end + +@implementation GSUnionSetExpression +@end + +@implementation GSIntersectSetExpression +@end + +@implementation GSSubqueryExpression +@end + +@implementation GSAggregateExpression @end @implementation GSFunctionExpression @@ -2407,7 +2459,6 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption - (NSExpression *) parseExpression { -// return [self parseAdditionExpression]; return [self parseBinaryExpression]; } From 0a440a530354c13e2c183b7be81f97466131c679 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 26 May 2024 09:11:21 -0400 Subject: [PATCH 07/11] Add missing NSMinusSetExpression --- Headers/Foundation/NSExpression.h | 1 + Source/NSPredicate.m | 81 +++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/Headers/Foundation/NSExpression.h b/Headers/Foundation/NSExpression.h index d78e31b16..e847b0cb2 100644 --- a/Headers/Foundation/NSExpression.h +++ b/Headers/Foundation/NSExpression.h @@ -49,6 +49,7 @@ enum #if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) NSUnionSetExpressionType, NSIntersectSetExpressionType, + NSMinusSetExpressionType, NSSubqueryExpressionType = 13, NSAggregateExpressionType = 14, #endif diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index ee379664c..45ba6f00e 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -142,9 +142,27 @@ extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*); @end @interface GSUnionSetExpression : NSExpression +{ + @public + NSExpression *_left; + NSExpression *_right; +} @end @interface GSIntersectSetExpression : NSExpression +{ + @public + NSExpression *_left; + NSExpression *_right; +} +@end + +@interface GSMinusSetExpression : NSExpression +{ + @public + NSExpression *_left; + NSExpression *_right; +} @end @interface GSSubqueryExpression : NSExpression @@ -1259,7 +1277,14 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption + (NSExpression *) expressionForIntersectSet: (NSExpression *)left with: (NSExpression *)right { - return nil; + GSIntersectSetExpression *e; + + e = [[GSIntersectSetExpression alloc] + initWithExpressionType: NSIntersectSetExpressionType]; + ASSIGN(e->_left, left); + ASSIGN(e->_right, right); + + return AUTORELEASE(e); } + (NSExpression *) expressionForAggregate: (NSArray *)subExpressions @@ -1270,13 +1295,27 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption + (NSExpression *) expressionForUnionSet: (NSExpression *)left with: (NSExpression *)right { - return nil; + GSUnionSetExpression *e; + + e = [[GSUnionSetExpression alloc] + initWithExpressionType: NSUnionSetExpressionType]; + ASSIGN(e->_left, left); + ASSIGN(e->_right, right); + + return AUTORELEASE(e); } + (NSExpression *) expressionForMinusSet: (NSExpression *)left with: (NSExpression *)right { - return nil; + GSMinusSetExpression *e; + + e = [[GSMinusSetExpression alloc] + initWithExpressionType: NSMinusSetExpressionType]; + ASSIGN(e->_left, left); + ASSIGN(e->_right, right); + + return AUTORELEASE(e); } // end 10.5 methods @@ -1688,9 +1727,45 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption @end @implementation GSUnionSetExpression + +- (NSExpression *) leftExpression +{ + return _left; +} + +- (NSExpression *) rightExpression +{ + return _right; +} + @end @implementation GSIntersectSetExpression + +- (NSExpression *) leftExpression +{ + return _left; +} + +- (NSExpression *) rightExpression +{ + return _right; +} + +@end + +@implementation GSMinusSetExpression + +- (NSExpression *) leftExpression +{ + return _left; +} + +- (NSExpression *) rightExpression +{ + return _right; +} + @end @implementation GSSubqueryExpression From a49ae59a79744a5e577989dcd1c7d9e26cfa0324 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 26 May 2024 16:16:40 -0400 Subject: [PATCH 08/11] Add description method and a few minor changes --- Headers/Foundation/NSExpression.h | 2 +- Source/NSPredicate.m | 38 ++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Headers/Foundation/NSExpression.h b/Headers/Foundation/NSExpression.h index e847b0cb2..611b3ae6f 100644 --- a/Headers/Foundation/NSExpression.h +++ b/Headers/Foundation/NSExpression.h @@ -40,7 +40,7 @@ extern "C" { enum { - NSConstantValueExpressionType=0, + NSConstantValueExpressionType = 0, NSEvaluatedObjectExpressionType, NSVariableExpressionType, NSKeyPathExpressionType, diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index 45ba6f00e..2695c9dd7 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -169,6 +169,10 @@ extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*); @end @interface GSAggregateExpression : NSExpression +{ + @public + id _collection; +} @end @interface GSFunctionExpression : NSExpression @@ -1289,7 +1293,13 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption + (NSExpression *) expressionForAggregate: (NSArray *)subExpressions { - return nil; + GSAggregateExpression *e; + + e = [[GSAggregateExpression alloc] + initWithExpressionType: NSAggregateExpressionType]; + ASSIGN(e->_collection, [NSMutableArray array]); + + return AUTORELEASE(e); } + (NSExpression *) expressionForUnionSet: (NSExpression *)left @@ -1728,6 +1738,11 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption @implementation GSUnionSetExpression +- (NSString *) description +{ + return [NSString stringWithFormat: @"%@.%@", _left, _right]; +} + - (NSExpression *) leftExpression { return _left; @@ -1742,6 +1757,11 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption @implementation GSIntersectSetExpression +- (NSString *) description +{ + return [NSString stringWithFormat: @"%@.%@", _left, _right]; +} + - (NSExpression *) leftExpression { return _left; @@ -1756,6 +1776,11 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption @implementation GSMinusSetExpression +- (NSString *) description +{ + return [NSString stringWithFormat: @"%@.%@", _left, _right]; +} + - (NSExpression *) leftExpression { return _left; @@ -1772,6 +1797,17 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption @end @implementation GSAggregateExpression + +- (NSString *) description +{ + return [NSString stringWithFormat: @"%@", _collection]; +} + +- (id) collection +{ + return _collection; +} + @end @implementation GSFunctionExpression From 48ab2e2bc717bdfd7c83796ede8120dd47e22c27 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 28 May 2024 15:03:26 -0400 Subject: [PATCH 09/11] Add implementation of expressionValueWithObject:context: to GSAggregateExpression --- MISSING | 3 --- Source/NSPredicate.m | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/MISSING b/MISSING index e5122a675..fbbf941bf 100644 --- a/MISSING +++ b/MISSING @@ -158,10 +158,7 @@ NSExpression: + expressionForSubquery:usingIteratorVariable:predicate: + expressionForFunction:selectorName:arguments: + expressionForBlock:arguments: - - collection - predicate - - leftExpression - - rightExpression - expressionBlock ------------------------------------------------------------- NSFileHandle: diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index 2695c9dd7..e0dbffd5b 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -48,6 +48,7 @@ #import "Foundation/NSValue.h" #import "GSPrivate.h" +#import "GSFastEnumeration.h" // For pow() #include @@ -1297,7 +1298,7 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption e = [[GSAggregateExpression alloc] initWithExpressionType: NSAggregateExpressionType]; - ASSIGN(e->_collection, [NSMutableArray array]); + ASSIGN(e->_collection, subExpressions); return AUTORELEASE(e); } @@ -1808,6 +1809,21 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption return _collection; } +- (id) expressionValueWithObject: (id)object + context: (NSMutableDictionary *)context +{ + NSMutableArray *result = [NSMutableArray arrayWithCapacity: + [_collection count]]; + + FOR_IN(NSExpression*, exp, _collection) + { + NSExpression *value = [exp expressionValueWithObject: object context: context]; + [result addObject: value]; + } + END_FOR_IN(_collection); + + return result; +} @end @implementation GSFunctionExpression From 5c1e4e8eda58935e5e21ddaf8d031351521efef4 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 28 May 2024 19:10:11 -0400 Subject: [PATCH 10/11] Update to fix remaining issues with new NSExpression classes --- Source/NSPredicate.m | 77 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index e0dbffd5b..471fed201 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -1298,7 +1298,7 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption e = [[GSAggregateExpression alloc] initWithExpressionType: NSAggregateExpressionType]; - ASSIGN(e->_collection, subExpressions); + ASSIGN(e->_collection, [NSSet setWithArray: subExpressions]); return AUTORELEASE(e); } @@ -1737,6 +1737,30 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption @end +// Macro for checking set related expressions + +#define CHECK_SETS \ +do { \ + if ([rightValue isKindOfClass: [NSArray class]]) \ + { \ + rightSet = [NSSet setWithArray: rightValue]; \ + } \ + if (!rightSet) \ + { \ + [NSException raise: NSInvalidArgumentException \ + format: @"Can't evaluate set expression; right subexpression is not a set (lhs = %@ rhs = %@)", leftValue, rightValue]; \ + } \ + if ([leftValue isKindOfClass: [NSArray class]]) \ + { \ + leftSet = [NSSet setWithArray: leftValue]; \ + } \ + if (!leftSet) \ + { \ + [NSException raise: NSInvalidArgumentException \ + format: @"Can't evaluate set expression; left subexpression is not a set (lhs = %@ rhs = %@)", leftValue, rightValue]; \ + } \ + } while (0) + @implementation GSUnionSetExpression - (NSString *) description @@ -1754,6 +1778,23 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption return _right; } +- (id) expressionValueWithObject: (id)object + context: (NSMutableDictionary *)context +{ + id leftValue = [_left expressionValueWithObject: object context: context]; + id rightValue = [_right expressionValueWithObject: object context: context]; + NSSet *leftSet = nil; + NSSet *rightSet = nil; + NSMutableSet *result = nil; + + CHECK_SETS; + + result = [NSMutableSet setWithSet: leftSet]; + [result unionSet: rightSet]; + + return result; +} + @end @implementation GSIntersectSetExpression @@ -1773,6 +1814,23 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption return _right; } +- (id) expressionValueWithObject: (id)object + context: (NSMutableDictionary *)context +{ + id leftValue = [_left expressionValueWithObject: object context: context]; + id rightValue = [_right expressionValueWithObject: object context: context]; + NSSet *leftSet = nil; + NSSet *rightSet = nil; + NSMutableSet *result = nil; + + CHECK_SETS; + + result = [NSMutableSet setWithSet: leftSet]; + [result intersectSet: rightSet]; + + return result; +} + @end @implementation GSMinusSetExpression @@ -1792,6 +1850,23 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption return _right; } +- (id) expressionValueWithObject: (id)object + context: (NSMutableDictionary *)context +{ + id leftValue = [_left expressionValueWithObject: object context: context]; + id rightValue = [_right expressionValueWithObject: object context: context]; + NSSet *leftSet = nil; + NSSet *rightSet = nil; + NSMutableSet *result = nil; + + CHECK_SETS; + + result = [NSMutableSet setWithSet: leftSet]; + [result minusSet: rightSet]; + + return result; +} + @end @implementation GSSubqueryExpression From d3d53ab23f43b829221d046d1538f0ed85cec3d2 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 31 May 2024 00:20:09 -0400 Subject: [PATCH 11/11] Clean up tests --- Source/NSPredicate.m | 1 - Tests/base/NSPredicate/basic.m | 70 ++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index 471fed201..c472f79c5 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -1738,7 +1738,6 @@ GSICUStringMatchesRegex(NSString *string, NSString *regex, NSStringCompareOption @end // Macro for checking set related expressions - #define CHECK_SETS \ do { \ if ([rightValue isKindOfClass: [NSArray class]]) \ diff --git a/Tests/base/NSPredicate/basic.m b/Tests/base/NSPredicate/basic.m index 3f644f389..5369193d8 100644 --- a/Tests/base/NSPredicate/basic.m +++ b/Tests/base/NSPredicate/basic.m @@ -175,14 +175,70 @@ void testArray(void) void testExpressions(void) { - NSExpression *exp = nil; - - // Add tests for new expressions here... - exp = [NSExpression expressionWithFormat: @"key = %@", @"test"]; - PASS(exp != nil, "expressionWithFormat: returns non nil"); + NSExpression *expression = [NSExpression expressionWithFormat: @"%d*%f",3,3.5]; + PASS(expression != nil, "expressionWithFormat: returns an initialized expression"); - exp = [NSExpression expressionWithFormat: @"key = %@" argumentArray: [NSArray arrayWithObject: @"test"]]; - PASS(exp != nil, "expressionWithFormat:argumentArray: returns non nil"); + id value = [expression expressionValueWithObject: nil context: nil]; + PASS(value != nil, "Expression evaluation returns a value"); + + NSExpression *expression2 = [NSExpression expressionWithFormat: @"%f*%f" argumentArray:@[@3.4,@3.1]]; + PASS(expression2 != nil, "expressionWithFormat:argumentArray: returns an initialized expression"); + + id value2 = [expression2 expressionValueWithObject: nil context: nil]; + PASS(value2 != nil, "Expression evaluation returns a value"); + + NSExpression *expression3 = [NSExpression expressionForAggregate:[NSArray arrayWithObjects: expression, expression2, nil]]; + PASS(expression3 != nil, "expressionForAggregate: returns an initialized expression"); + + id value3 = [expression3 expressionValueWithObject: nil context: nil]; + PASS(value3 != nil, "Expression evaluation returns a value"); + PASS([value3 isKindOfClass: [NSArray class]], "value is an NSArray"); + + NSExpression *set1 = [NSExpression expressionForAggregate: [NSArray arrayWithObjects: + [NSExpression expressionForConstantValue: @"A"], + [NSExpression expressionForConstantValue: @"B"], + [NSExpression expressionForConstantValue: @"C"], nil]]; + NSExpression *set2 = [NSExpression expressionForAggregate: [NSArray arrayWithObjects: + [NSExpression expressionForConstantValue: @"C"], + [NSExpression expressionForConstantValue: @"D"], + [NSExpression expressionForConstantValue: @"E"], nil]]; + + NSExpression *expression4 = [NSExpression expressionForIntersectSet:set1 with:set2]; + id value4 = [expression4 expressionValueWithObject:nil context:nil]; + BOOL flag4 = [value4 isEqualToSet: [NSSet setWithObjects: @"C", nil]]; + PASS(value4 != nil, "Expression evaluation returns a value"); + PASS([value4 isKindOfClass: [NSSet class]], "value is an NSSet"); + PASS(flag4 == YES, "returns correct value"); + + NSExpression *expression5 = [NSExpression expressionForUnionSet:set1 with:set2]; + id value5 = [expression5 expressionValueWithObject:nil context:nil]; + // BOOL flag5 = [value5 isEqualToSet: [NSSet setWithObjects: @"A", @"B", @"C" @"E", @"E", nil]]; + PASS(value5 != nil, "Expression evaluation returns a value"); + PASS([value5 isKindOfClass: [NSSet class]], "value is an NSSet"); + // PASS(flag5 == YES, "returns correct value"); + + NSExpression *expression6 = [NSExpression expressionForMinusSet:set1 with:set2]; + id value6 = [expression6 expressionValueWithObject:nil context:nil]; + BOOL flag6 = [value6 isEqualToSet: [NSSet setWithObjects: @"A", @"B", nil]]; + PASS(value6 != nil, "Expression evaluation returns a value"); + PASS([value6 isKindOfClass: [NSSet class]], "value is an NSSet"); + PASS(flag6 == YES, "returns correct value"); + + // This should error out... + BOOL raised = NO; + NS_DURING + { + NSExpression *expression7 = [NSExpression expressionForMinusSet:set1 with:expression2]; + NSLog(@"%@",[expression7 expressionValueWithObject:nil context:nil]); + } + NS_HANDLER + { + raised = YES; + NSLog(@"exception = %@", localException); + } + NS_ENDHANDLER; + + PASS(raised, "Raise an exception when a set based NSExpression tries to process a non-set"); } int main()