Fix static analyzer issue with common indexes algorithm in _asdk_commonIndexesWithArray:

The issue was: The left operand of '>=' is a garbage value in else if check for lengths[i+1][j] ... I had to rewrite the algorithm to quiet the static analyzer.
This commit is contained in:
Michael Schneider 2016-04-18 14:38:32 -07:00
parent 103506beec
commit 9d07336c75
2 changed files with 66 additions and 15 deletions

View File

@ -50,30 +50,36 @@
- (NSIndexSet *)_asdk_commonIndexesWithArray:(NSArray *)array compareBlock:(BOOL (^)(id lhs, id rhs))comparison - (NSIndexSet *)_asdk_commonIndexesWithArray:(NSArray *)array compareBlock:(BOOL (^)(id lhs, id rhs))comparison
{ {
NSAssert(comparison != nil, @"Comparison block is required"); NSAssert(comparison != nil, @"Comparison block is required");
NSInteger lengths[self.count+1][array.count+1];
for (NSInteger i = self.count; i >= 0; i--) { NSInteger selfCount = self.count;
for (NSInteger j = array.count; j >= 0; j--) { NSInteger arrayCount = array.count;
if (i == self.count || j == array.count) {
NSInteger lengths[selfCount+1][arrayCount+1];
for (NSInteger i = 0; i <= selfCount; i++) {
for (NSInteger j = 0; j <= arrayCount; j++) {
if (i == 0 || j == 0) {
lengths[i][j] = 0; lengths[i][j] = 0;
} else if (comparison(self[i], array[j])) { } else if (comparison(self[i-1], array[j-1])) {
lengths[i][j] = 1 + lengths[i+1][j+1]; lengths[i][j] = 1 + lengths[i-1][j-1];
} else { } else {
lengths[i][j] = MAX(lengths[i+1][j], lengths[i][j+1]); lengths[i][j] = MAX(lengths[i-1][j], lengths[i][j-1]);
} }
} }
} }
NSMutableIndexSet *common = [NSMutableIndexSet indexSet]; NSMutableIndexSet *common = [NSMutableIndexSet indexSet];
for (NSInteger i = 0, j = 0; i < self.count && j < array.count;) { NSInteger i = selfCount, j = arrayCount;
if (comparison(self[i], array[j])) { while(i > 0 && j > 0) {
[common addIndex:i]; if (comparison(self[i-1], array[j-1])) {
i++; j++; [common addIndex:(i-1)];
} else if (lengths[i+1][j] >= lengths[i][j+1]) { i--; j--;
i++; } else if (lengths[i-1][j] > lengths[i][j-1]) {
i--;
} else { } else {
j++; j--;
} }
} }
return common; return common;
} }

View File

@ -10,13 +10,58 @@
#import "NSArray+Diffing.h" #import "NSArray+Diffing.h"
@interface NSArray (ArrayDiffingTests)
- (NSIndexSet *)_asdk_commonIndexesWithArray:(NSArray *)array compareBlock:(BOOL (^)(id lhs, id rhs))comparison;
@end
@interface ArrayDiffingTests : XCTestCase @interface ArrayDiffingTests : XCTestCase
@end @end
@implementation ArrayDiffingTests @implementation ArrayDiffingTests
- (void)testDiffing { - (void)testDiffingCommonIndexes
{
NSArray<NSArray *> *tests = @[
@[
@[@"bob", @"alice", @"dave"],
@[@"bob", @"alice", @"dave", @"gary"],
@[@0, @1, @2]
],
@[
@[@"bob", @"alice", @"dave"],
@[@"bob", @"gary", @"dave"],
@[@0, @2]
],
@[
@[@"bob", @"alice"],
@[@"gary", @"dave"],
@[],
],
@[
@[@"bob", @"alice", @"dave"],
@[],
@[],
],
@[
@[],
@[@"bob", @"alice", @"dave"],
@[],
],
];
for (NSArray *test in tests) {
NSIndexSet *indexSet = [test[0] _asdk_commonIndexesWithArray:test[1] compareBlock:^BOOL(id lhs, id rhs) {
return [lhs isEqual:rhs];
}];
for (NSNumber *index in (NSArray *)test[2]) {
XCTAssert([indexSet containsIndex:[index integerValue]]);
}
}
}
- (void)testDiffingInsertionsAndDeletions {
NSArray<NSArray *> *tests = @[ NSArray<NSArray *> *tests = @[
@[ @[
@[@"bob", @"alice", @"dave"], @[@"bob", @"alice", @"dave"],