From a832f826b5ebfd054a6266b8b9dc55e021e61b5f Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Wed, 21 Mar 2018 15:17:11 -0400 Subject: [ios, macos] Case operator now has iOS 8 support. --- platform/darwin/src/NSExpression+MGLAdditions.mm | 54 +++++++++++----------- platform/darwin/src/NSPredicate+MGLAdditions.h | 2 + platform/darwin/src/NSPredicate+MGLAdditions.mm | 25 +++++++++++ platform/darwin/test/MGLExpressionTests.mm | 57 +++++++++--------------- 4 files changed, 76 insertions(+), 62 deletions(-) diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 5493c59381..bd747dc97e 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -464,36 +464,22 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { } else if ([op isEqualToString:@"var"]) { return [NSExpression expressionForVariable:argumentObjects.firstObject]; } else if ([op isEqualToString:@"case"]) { - NSPredicate *conditional = [NSPredicate mgl_predicateWithJSONObject:argumentObjects.firstObject]; - NSExpression *trueExpression; - NSInteger rightBranchIndex = 2; - - if ([argumentObjects[1] isKindOfClass:[NSArray class]] ) { - NSInteger length = 1; - for (NSInteger index = 1; index < argumentObjects.count - 2; index++) { - length++; - if (![argumentObjects[index] isKindOfClass:[NSArray class]] && ![argumentObjects[index + 1] isKindOfClass:[NSArray class]]) { - break; - } - } - NSArray *trueObjects = [@[@"case"] arrayByAddingObjectsFromArray: - [argumentObjects subarrayWithRange:NSMakeRange(1, length)]]; - trueExpression = [NSExpression mgl_expressionWithJSONObject:trueObjects]; - rightBranchIndex = length + 1; - } else { - trueExpression = [NSExpression mgl_expressionWithJSONObject:argumentObjects[1]]; - } + NSArray *caseExpressions = argumentObjects; + NSExpression *firstConditional = [NSExpression expressionWithFormat:@"%@", [NSPredicate mgl_predicateWithJSONObject:caseExpressions[0]]]; + NSMutableArray *arguments = [NSMutableArray array]; - NSExpression *falseExpression; - if ([argumentObjects[rightBranchIndex] isKindOfClass:[NSArray class]] ) { - NSArray *falseObjects = [@[@"case"] arrayByAddingObjectsFromArray: - [argumentObjects subarrayWithRange:NSMakeRange(rightBranchIndex, argumentObjects.count - rightBranchIndex)]]; - falseExpression = [NSExpression mgl_expressionWithJSONObject:falseObjects]; - } else { - falseExpression = [NSExpression mgl_expressionWithJSONObject:argumentObjects[rightBranchIndex]]; + for (NSUInteger index = 1; index < caseExpressions.count; index++) { + if ([caseExpressions[index] isKindOfClass:[NSArray class]]) { + NSPredicate *conditional = [NSPredicate mgl_predicateWithJSONObject:caseExpressions[index]]; + NSExpression *argument = [NSExpression expressionWithFormat:@"%@", conditional]; + [arguments addObject:argument]; + } else { + [arguments addObject:[NSExpression mgl_expressionWithJSONObject:caseExpressions[index]]]; + } + } - return [NSExpression expressionForConditional:conditional trueExpression:trueExpression falseExpression:falseExpression]; + return [NSExpression expressionForFunction:firstConditional selectorName:@"mgl_case:" arguments:arguments]; } else { [NSException raise:NSInvalidArgumentException format:@"Expression operator %@ not yet implemented.", op]; @@ -684,6 +670,20 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { [expressionObject addObject:obj.mgl_jsonExpressionObject]; }]; [expressionObject addObject:self.operand.mgl_jsonExpressionObject]; + return expressionObject; + } else if ([function isEqualToString:@"mgl_case:"]) { + NSPredicate *firstConditional = (NSPredicate *)self.operand.constantValue; + NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"case", firstConditional.mgl_jsonExpressionObject, nil]; + + for (NSExpression *option in self.arguments) { + if ([option respondsToSelector:@selector(constantValue)] && [option.constantValue isKindOfClass:[NSComparisonPredicate class]]) { + NSPredicate *predicate = (NSPredicate *)option.constantValue; + [expressionObject addObject:predicate.mgl_jsonExpressionObject]; + } else { + [expressionObject addObject:option.mgl_jsonExpressionObject]; + } + } + return expressionObject; } else if ([function isEqualToString:@"median:"] || [function isEqualToString:@"mode:"] || diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.h b/platform/darwin/src/NSPredicate+MGLAdditions.h index 89e9e65c64..cce7561add 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.h +++ b/platform/darwin/src/NSPredicate+MGLAdditions.h @@ -16,4 +16,6 @@ @property (nonatomic, readonly) id mgl_jsonExpressionObject; +- (id)mgl_case:(id)firstValue, ...; + @end diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm index 63c8307803..2d5b646ff2 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm @@ -324,4 +324,29 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) { return nil; } +- (id)mgl_case:(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; +} + @end diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm index 2e1c0e80fa..3f36a0cf61 100644 --- a/platform/darwin/test/MGLExpressionTests.mm +++ b/platform/darwin/test/MGLExpressionTests.mm @@ -573,42 +573,29 @@ using namespace std::string_literals; } - (void)testConditionalExpressionObject { - // FIXME: This test crashes because iOS 8 doesn't have `+[NSExpression expressionForConditional:trueExpression:falseExpression:]`. - // https://github.com/mapbox/mapbox-gl-native/issues/11007 - if (@available(iOS 9.0, *)) { - { - NSPredicate *conditional = [NSPredicate predicateWithFormat:@"1 = 2"]; - NSExpression *trueExpression = [NSExpression expressionForConstantValue:@YES]; - NSExpression *falseExpression = [NSExpression expressionForConstantValue:@NO]; - NSExpression *expression = [NSExpression expressionForConditional:conditional trueExpression:trueExpression falseExpression:falseExpression]; - NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @NO]; - XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); - XCTAssertEqualObjects([NSExpression expressionWithFormat:@"TERNARY(1 = 2, TRUE, FALSE)"].mgl_jsonExpressionObject, jsonExpression); - XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO); - XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); - } - { - NSExpression *expression = [NSExpression expressionWithFormat:@"TERNARY(0 = 1, TRUE, TERNARY(1 = 2, TRUE, FALSE))"]; - NSArray *jsonExpression = @[@"case", @[@"==", @0, @1], @YES, @[@"==", @1, @2], @YES, @NO]; - XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); - XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO); - XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); - } - { - NSExpression *expression = [NSExpression expressionWithFormat:@"TERNARY(0 = 1, TERNARY(1 = 2, TRUE, FALSE), TRUE)"]; - NSArray *jsonExpression = @[@"case", @[@"==", @0, @1], @[@"==", @1, @2], @YES, @NO, @YES]; - XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); - XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @YES); - XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); - } - { - NSExpression *nestedExpression = [NSExpression expressionWithFormat:@"TERNARY(1 == 2, TERNARY(0 == 1, FALSE, TERNARY(4 == 5, FALSE, FALSE)), TERNARY(1 == 1, TRUE, FALSE))"]; - NSArray *nestedJSONExpression = @[@"case", @[@"==", @1, @2], @[@"==", @0, @1], @NO, @[@"==", @4, @5], @NO, @NO, @[@"==", @1, @1], @YES, @NO]; - XCTAssertEqualObjects(nestedExpression.mgl_jsonExpressionObject, nestedJSONExpression); - XCTAssertEqualObjects([nestedExpression expressionValueWithObject:nil context:nil], @YES); - XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:nestedJSONExpression], nestedExpression); - } + { + NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_case:', %@, %@)", + [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 2"]], + MGLConstantExpression(@YES), + MGLConstantExpression(@NO)]; + NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @NO]; + XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); + XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); + XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO); } + { + NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_case:', %@, %@, %@, %@)", + [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 2"]], + MGLConstantExpression(@YES), + [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 1"]], + MGLConstantExpression(@YES), + MGLConstantExpression(@NO)]; + NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @[@"==", @1, @1], @YES, @NO]; + XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); + XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); + XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @YES); + } + } @end -- cgit v1.2.1