From 05dba2263cf86f7fce42f1918aa513385232f34c Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 16 Aug 2016 16:47:26 -0700 Subject: [PATCH] Make ASWeakSet and NSArray+Diffing public, add support for large arrays (#2078) --- AsyncDisplayKit.xcodeproj/project.pbxproj | 12 ++++++------ .../{Private => Details}/ASWeakSet.h | 0 .../{Private => Details}/ASWeakSet.m | 0 .../{Private => Details}/NSArray+Diffing.h | 0 .../{Private => Details}/NSArray+Diffing.m | 17 +++++++++++++++-- 5 files changed, 21 insertions(+), 8 deletions(-) rename AsyncDisplayKit/{Private => Details}/ASWeakSet.h (100%) rename AsyncDisplayKit/{Private => Details}/ASWeakSet.m (100%) rename AsyncDisplayKit/{Private => Details}/NSArray+Diffing.h (100%) rename AsyncDisplayKit/{Private => Details}/NSArray+Diffing.m (77%) diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 20082d807f..fddfab7eab 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -265,7 +265,7 @@ 9C70F20B1CDBE9A4007D6C76 /* ASDataController+Subclasses.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF61BBB3D690087C538 /* ASDataController+Subclasses.h */; }; 9C70F20C1CDBE9B6007D6C76 /* ASCollectionDataController.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF21BBB3D690087C538 /* ASCollectionDataController.h */; }; 9C70F20D1CDBE9CB007D6C76 /* ASDefaultPlayButton.h in Headers */ = {isa = PBXBuildFile; fileRef = AEB7B0181C5962EA00662EF4 /* ASDefaultPlayButton.h */; }; - 9C70F20E1CDBE9E5007D6C76 /* NSArray+Diffing.h in Headers */ = {isa = PBXBuildFile; fileRef = DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */; }; + 9C70F20E1CDBE9E5007D6C76 /* NSArray+Diffing.h in Headers */ = {isa = PBXBuildFile; fileRef = DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C70F20F1CDBE9FF007D6C76 /* ASLayoutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */; }; 9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */; }; 9C8221971BA237B80037F19A /* ASStackBaselinePositionedLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C8221941BA237B80037F19A /* ASStackBaselinePositionedLayout.mm */; }; @@ -410,7 +410,7 @@ CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; }; CC3B20851C3F76D600798563 /* ASPendingStateController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20821C3F76D600798563 /* ASPendingStateController.mm */; }; CC3B20861C3F76D600798563 /* ASPendingStateController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20821C3F76D600798563 /* ASPendingStateController.mm */; }; - CC3B208A1C3F7A5400798563 /* ASWeakSet.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20871C3F7A5400798563 /* ASWeakSet.h */; }; + CC3B208A1C3F7A5400798563 /* ASWeakSet.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20871C3F7A5400798563 /* ASWeakSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC3B208B1C3F7A5400798563 /* ASWeakSet.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20881C3F7A5400798563 /* ASWeakSet.m */; }; CC3B208C1C3F7A5400798563 /* ASWeakSet.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20881C3F7A5400798563 /* ASWeakSet.m */; }; CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */; }; @@ -1446,6 +1446,10 @@ 058D09FF195D050800B7D73C /* UIView+ASConvenience.h */, 9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */, 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */, + CC3B20871C3F7A5400798563 /* ASWeakSet.h */, + CC3B20881C3F7A5400798563 /* ASWeakSet.m */, + DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */, + DBC452DA1C5BF64600B16017 /* NSArray+Diffing.m */, ); path = Details; sourceTree = ""; @@ -1514,10 +1518,6 @@ ACF6ED4A1B17847A00DA7C62 /* ASStackUnpositionedLayout.mm */, 83A7D9581D44542100BF333E /* ASWeakMap.h */, 83A7D9591D44542100BF333E /* ASWeakMap.m */, - CC3B20871C3F7A5400798563 /* ASWeakSet.h */, - CC3B20881C3F7A5400798563 /* ASWeakSet.m */, - DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */, - DBC452DA1C5BF64600B16017 /* NSArray+Diffing.m */, 8B0768B11CE752EC002E1453 /* ASDefaultPlaybackButton.h */, 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */, ); diff --git a/AsyncDisplayKit/Private/ASWeakSet.h b/AsyncDisplayKit/Details/ASWeakSet.h similarity index 100% rename from AsyncDisplayKit/Private/ASWeakSet.h rename to AsyncDisplayKit/Details/ASWeakSet.h diff --git a/AsyncDisplayKit/Private/ASWeakSet.m b/AsyncDisplayKit/Details/ASWeakSet.m similarity index 100% rename from AsyncDisplayKit/Private/ASWeakSet.m rename to AsyncDisplayKit/Details/ASWeakSet.m diff --git a/AsyncDisplayKit/Private/NSArray+Diffing.h b/AsyncDisplayKit/Details/NSArray+Diffing.h similarity index 100% rename from AsyncDisplayKit/Private/NSArray+Diffing.h rename to AsyncDisplayKit/Details/NSArray+Diffing.h diff --git a/AsyncDisplayKit/Private/NSArray+Diffing.m b/AsyncDisplayKit/Details/NSArray+Diffing.m similarity index 77% rename from AsyncDisplayKit/Private/NSArray+Diffing.m rename to AsyncDisplayKit/Details/NSArray+Diffing.m index c34dfc2003..d7352a5c70 100644 --- a/AsyncDisplayKit/Private/NSArray+Diffing.m +++ b/AsyncDisplayKit/Details/NSArray+Diffing.m @@ -11,6 +11,7 @@ // #import "NSArray+Diffing.h" +#import "ASAssert.h" @implementation NSArray (Diffing) @@ -58,12 +59,24 @@ NSInteger selfCount = self.count; NSInteger arrayCount = array.count; - NSInteger lengths[selfCount+1][arrayCount+1]; + // Allocate the diff map in the heap so we don't blow the stack for large arrays. + NSInteger (*lengths)[arrayCount+1] = NULL; + size_t lengthsSize = ((selfCount+1) * sizeof(*lengths)); + // Would rather use initWithCapacity: to skip the zeroing, but TECHNICALLY + // `mutableBytes` is only guaranteed to be non-NULL if the data object has a non-zero length. + NS_VALID_UNTIL_END_OF_SCOPE NSMutableData *lengthsData = [[NSMutableData alloc] initWithLength:lengthsSize]; + lengths = lengthsData.mutableBytes; + if (lengths == NULL) { + ASDisplayNodeFailAssert(@"Failed to allocate memory for diffing with size %tu", lengthsSize); + return nil; + } + for (NSInteger i = 0; i <= selfCount; i++) { + id selfObj = i > 0 ? self[i-1] : nil; for (NSInteger j = 0; j <= arrayCount; j++) { if (i == 0 || j == 0) { lengths[i][j] = 0; - } else if (comparison(self[i-1], array[j-1])) { + } else if (comparison(selfObj, array[j-1])) { lengths[i][j] = 1 + lengths[i-1][j-1]; } else { lengths[i][j] = MAX(lengths[i-1][j], lengths[i][j-1]);