diff options
Diffstat (limited to 'platform/darwin/src')
-rw-r--r-- | platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm | 14 | ||||
-rw-r--r-- | platform/darwin/src/NSExpression+MGLAdditions.mm | 9 | ||||
-rw-r--r-- | platform/darwin/src/NSPredicate+MGLAdditions.mm | 60 |
3 files changed, 58 insertions, 25 deletions
diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm index 15aa71419d..af9216f9ce 100644 --- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm @@ -140,10 +140,18 @@ [NSException raise:NSInvalidArgumentException format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType]; } - if (op) { - return @[op, self.leftExpression.mgl_jsonExpressionObject, self.rightExpression.mgl_jsonExpressionObject]; + if (!op) { + return nil; } - return nil; + NSArray *comparisonArray = @[op, self.leftExpression.mgl_jsonExpressionObject, self.rightExpression.mgl_jsonExpressionObject]; + if (self.options) { + NSDictionary *collatorObject = @{ + @"case-sensitive": @(!(self.options & NSCaseInsensitivePredicateOption)), + @"diacritic-sensitive": @(!(self.options & NSDiacriticInsensitivePredicateOption)), + }; + return [comparisonArray arrayByAddingObject:@[@"collator", collatorObject]]; + } + return comparisonArray; } @end diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 653e3d67e6..d03d7dbaec 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -784,6 +784,9 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { return [NSExpression expressionForFunction:functionName arguments:subexpressions]; + } else if ([op isEqualToString:@"collator"]) { + // Avoid wrapping collator options object in literal expression. + return [NSExpression expressionForFunction:@"MGL_FUNCTION" arguments:array]; } else if ([op isEqualToString:@"literal"]) { if ([argumentObjects.firstObject isKindOfClass:[NSArray class]]) { return [NSExpression expressionForAggregate:MGLSubexpressionsWithJSONObjects(argumentObjects.firstObject)]; @@ -1208,6 +1211,12 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { [NSException raise:NSInvalidArgumentException format:@"Casting expression to %@ not yet implemented.", type]; } else if ([function isEqualToString:@"MGL_FUNCTION"]) { + NSExpression *op = self.arguments.firstObject; + if (op.expressionType == NSConstantValueExpressionType + && [op.constantValue isEqualToString:@"collator"]) { + // Avoid wrapping collator options object in literal expression. + return @[@"collator", self.arguments[1].constantValue]; + } return self.arguments.mgl_jsonExpressionObject; } else if (op == [MGLColor class] && [function isEqualToString:@"colorWithRed:green:blue:alpha:"]) { NSArray *arguments = self.arguments.mgl_jsonExpressionObject; diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm index 4b9a4177cb..d01b2c8f83 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm @@ -46,6 +46,15 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) { return subpredicates; } +static NSDictionary * const MGLPredicateOperatorTypesByJSONOperator = @{ + @"==": @(NSEqualToPredicateOperatorType), + @"!=": @(NSNotEqualToPredicateOperatorType), + @"<": @(NSLessThanPredicateOperatorType), + @"<=": @(NSLessThanOrEqualToPredicateOperatorType), + @">": @(NSGreaterThanPredicateOperatorType), + @">=": @(NSGreaterThanOrEqualToPredicateOperatorType), +}; + + (instancetype)predicateWithMGLJSONObject:(id)object { if ([object isEqual:@YES]) { return [NSPredicate predicateWithValue:YES]; @@ -58,30 +67,37 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) { NSArray *objects = (NSArray *)object; NSString *op = objects.firstObject; - if ([op isEqualToString:@"=="]) { - NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]); - return [NSPredicate predicateWithFormat:@"%@ == %@" argumentArray:subexpressions]; - } - if ([op isEqualToString:@"!="]) { - NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]); - return [NSPredicate predicateWithFormat:@"%@ != %@" argumentArray:subexpressions]; - } - if ([op isEqualToString:@"<"]) { - NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]); - return [NSPredicate predicateWithFormat:@"%@ < %@" argumentArray:subexpressions]; - } - if ([op isEqualToString:@"<="]) { - NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]); - return [NSPredicate predicateWithFormat:@"%@ <= %@" argumentArray:subexpressions]; - } - if ([op isEqualToString:@">"]) { - NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]); - return [NSPredicate predicateWithFormat:@"%@ > %@" argumentArray:subexpressions]; - } - if ([op isEqualToString:@">="]) { + NSNumber *operatorTypeNumber = MGLPredicateOperatorTypesByJSONOperator[op]; + if (operatorTypeNumber) { + NSPredicateOperatorType operatorType = (NSPredicateOperatorType)[operatorTypeNumber unsignedIntegerValue]; + + NSComparisonPredicateOptions options = 0; + if (objects.count > 3) { + NSArray *collatorExpression = objects[3]; + NSCAssert([collatorExpression isKindOfClass:[NSArray class]], @"Collators must be dictionaries."); + NSCAssert(collatorExpression.count == 2, @"Malformed collator expression"); + NSDictionary *collator = collatorExpression[1]; + NSCAssert([collator isKindOfClass:[NSDictionary class]], @"Malformed collator in collator expression"); + + // Predicate options can’t express specific locales as collators can. + if (!collator[@"locale"]) { + if ([(collator[@"case-sensitive"] ?: @YES) isEqual:@NO]) { + options |= NSCaseInsensitivePredicateOption; + } + if ([(collator[@"diacritic-sensitive"] ?: @YES) isEqual:@NO]) { + options |= NSDiacriticInsensitivePredicateOption; + } + } + } + NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]); - return [NSPredicate predicateWithFormat:@"%@ >= %@" argumentArray:subexpressions]; + return [NSComparisonPredicate predicateWithLeftExpression:subexpressions[0] + rightExpression:subexpressions[1] + modifier:NSDirectPredicateModifier + type:operatorType + options:options]; } + if ([op isEqualToString:@"!"]) { NSArray *subpredicates = MGLSubpredicatesWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]); if (subpredicates.count > 1) { |