summaryrefslogtreecommitdiff
path: root/platform/darwin/src/NSPredicate+MGLAdditions.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin/src/NSPredicate+MGLAdditions.mm')
-rw-r--r--platform/darwin/src/NSPredicate+MGLAdditions.mm109
1 files changed, 88 insertions, 21 deletions
diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm
index 63c8307803..bbd324bb63 100644
--- a/platform/darwin/src/NSPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm
@@ -3,6 +3,8 @@
#import "MGLValueEvaluator.h"
#import "MGLStyleValue_Private.h"
+#include <mbgl/style/conversion/filter.hpp>
+
class FilterEvaluator {
public:
@@ -206,25 +208,18 @@ public:
- (mbgl::style::Filter)mgl_filter
{
- if ([self isEqual:[NSPredicate predicateWithValue:YES]])
- {
- return mbgl::style::AllFilter();
- }
-
- if ([self isEqual:[NSPredicate predicateWithValue:NO]])
- {
- return mbgl::style::AnyFilter();
- }
-
- if ([self.predicateFormat hasPrefix:@"BLOCKPREDICATE("])
- {
+ mbgl::style::conversion::Error valueError;
+ NSArray *jsonObject = self.mgl_jsonExpressionObject;
+ auto value = mbgl::style::conversion::convert<mbgl::style::Filter>(mbgl::style::conversion::makeConvertible(jsonObject), valueError);
+
+ if (!value) {
[NSException raise:NSInvalidArgumentException
- format:@"Block-based predicates are not supported."];
+ format:@"Invalid filter value: %@", @(valueError.message.c_str())];
+ return {};
}
-
- [NSException raise:NSInvalidArgumentException
- format:@"Unrecognized predicate type."];
- return {};
+ mbgl::style::Filter filter = std::move(*value);
+
+ return filter;
}
+ (instancetype)mgl_predicateWithFilter:(mbgl::style::Filter)filter
@@ -280,7 +275,7 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) {
}
if ([op isEqualToString:@">="]) {
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]);
- return [NSPredicate predicateWithFormat:@"%K >= %@" argumentArray:subexpressions];
+ return [NSPredicate predicateWithFormat:@"%@ >= %@" argumentArray:subexpressions];
}
if ([op isEqualToString:@"!"]) {
NSArray *subpredicates = MGLSubpredicatesWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]);
@@ -294,7 +289,43 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) {
return [NSPredicate predicateWithValue:YES];
}
if ([op isEqualToString:@"all"]) {
- NSArray *subpredicates = MGLSubpredicatesWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]);
+ NSArray<NSPredicate *> *subpredicates = MGLSubpredicatesWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]);
+ if (subpredicates.count == 2) {
+ // Determine if the expression is of BETWEEN type
+ if ([subpredicates[0] isKindOfClass:[NSComparisonPredicate class]] &&
+ [subpredicates[1] isKindOfClass:[NSComparisonPredicate class]]) {
+ NSComparisonPredicate *leftCondition = (NSComparisonPredicate *)subpredicates[0];
+ NSComparisonPredicate *rightCondition = (NSComparisonPredicate *)subpredicates[1];
+
+ NSArray *limits;
+ NSExpression *leftConditionExpression;
+
+ if(leftCondition.predicateOperatorType == NSGreaterThanOrEqualToPredicateOperatorType &&
+ rightCondition.predicateOperatorType == NSLessThanOrEqualToPredicateOperatorType) {
+ limits = @[leftCondition.rightExpression, rightCondition.rightExpression];
+ leftConditionExpression = leftCondition.leftExpression;
+
+ } else if (leftCondition.predicateOperatorType == NSLessThanOrEqualToPredicateOperatorType &&
+ rightCondition.predicateOperatorType == NSLessThanOrEqualToPredicateOperatorType) {
+ limits = @[leftCondition.leftExpression, rightCondition.rightExpression];
+ leftConditionExpression = leftCondition.rightExpression;
+
+ } else if(leftCondition.predicateOperatorType == NSLessThanOrEqualToPredicateOperatorType &&
+ rightCondition.predicateOperatorType == NSGreaterThanOrEqualToPredicateOperatorType) {
+ limits = @[leftCondition.leftExpression, rightCondition.leftExpression];
+ leftConditionExpression = leftCondition.rightExpression;
+
+ } else if(leftCondition.predicateOperatorType == NSGreaterThanOrEqualToPredicateOperatorType &&
+ rightCondition.predicateOperatorType == NSGreaterThanOrEqualToPredicateOperatorType) {
+ limits = @[leftCondition.rightExpression, rightCondition.leftExpression];
+ leftConditionExpression = leftCondition.leftExpression;
+ }
+
+ if (limits && leftConditionExpression) {
+ return [NSPredicate predicateWithFormat:@"%@ BETWEEN %@", leftConditionExpression, [NSExpression expressionForAggregate:limits]];
+ }
+ }
+ }
return [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
}
if ([op isEqualToString:@"any"]) {
@@ -302,8 +333,13 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) {
return [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates];
}
- NSAssert(NO, @"Unrecognized expression conditional operator %@.", op);
- return nil;
+ NSExpression *expression = [NSExpression expressionWithMGLJSONObject:object];
+ return [NSComparisonPredicate predicateWithLeftExpression:expression
+ rightExpression:[NSExpression expressionForConstantValue:@YES]
+ modifier:NSDirectPredicateModifier
+ type:NSEqualToPredicateOperatorType
+ options:0];
+
}
- (id)mgl_jsonExpressionObject {
@@ -324,4 +360,35 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) {
return nil;
}
+- (id)mgl_if:(id)firstValue, ... {
+
+ if ([self evaluateWithObject:nil]) {
+ return firstValue;
+ }
+
+ id eachExpression;
+ va_list argumentList;
+ va_start(argumentList, firstValue);
+
+ while ((eachExpression = va_arg(argumentList, id))) {
+ if ([eachExpression isKindOfClass:[NSComparisonPredicate class]]) {
+ id valueExpression = va_arg(argumentList, id);
+ if ([eachExpression evaluateWithObject:nil]) {
+ return valueExpression;
+ }
+ } else {
+ return eachExpression;
+ }
+ }
+ va_end(argumentList);
+
+ return nil;
+}
+
+- (id)mgl_match:(NSExpression *)firstCase, ... {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Match expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
@end