lottie-ios 4.1.2 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/main.yml +27 -9
- package/Lottie.xcodeproj/project.pbxproj +158 -70
- package/Lottie.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +2 -2
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/IDEFindNavigatorScopes.plist +5 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +258 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +13 -2
- package/Package.swift +2 -1
- package/README.md +3 -3
- package/Rakefile +8 -4
- package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +16 -2
- package/Sources/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +1 -1
- package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +1 -1
- package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +1 -1
- package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +6 -6
- package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +76 -7
- package/Sources/Private/CoreAnimation/Animations/OpacityAnimation.swift +1 -1
- package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +1 -1
- package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +66 -102
- package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +2 -2
- package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +3 -3
- package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +66 -17
- package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +55 -32
- package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +16 -12
- package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +3 -3
- package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +24 -11
- package/Sources/Private/CoreAnimation/Layers/ImageLayer.swift +2 -2
- package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +1 -1
- package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +13 -2
- package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +9 -1
- package/Sources/Private/CoreAnimation/ValueProviderStore.swift +22 -11
- package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +1 -1
- package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +13 -2
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +16 -7
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +2 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +2 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +20 -8
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +28 -9
- package/Sources/Private/Model/Assets/ImageAsset.swift +4 -3
- package/Sources/Private/Model/DotLottie/DotLottieAnimation.swift +2 -8
- package/Sources/Private/Model/DotLottie/DotLottieManifest.swift +3 -14
- package/Sources/Private/Model/DotLottie/DotLottieUtils.swift +11 -1
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+BackingConfiguration.swift +147 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Helpers.swift +351 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+MemoryFile.swift +183 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Progress.swift +66 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Reading.swift +144 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+ReadingDeprecated.swift +49 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Writing.swift +385 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+WritingDeprecated.swift +91 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+ZIP64.swift +170 -0
- package/Sources/Private/Model/DotLottie/{Zip/ZipArchive.swift → ZipFoundation/Archive.swift} +150 -227
- package/Sources/Private/Model/DotLottie/ZipFoundation/Data+Compression.swift +403 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/Data+CompressionDeprecated.swift +44 -0
- package/Sources/Private/Model/DotLottie/{Zip → ZipFoundation}/Data+Serialization.swift +62 -0
- package/Sources/Private/Model/DotLottie/{Zip/ZipEntry+Serialization.swift → ZipFoundation/Entry+Serialization.swift} +7 -7
- package/Sources/Private/Model/DotLottie/{Zip/ZipEntry+ZIP64.swift → ZipFoundation/Entry+ZIP64.swift} +13 -19
- package/Sources/Private/Model/DotLottie/{Zip/ZipEntry.swift → ZipFoundation/Entry.swift} +141 -10
- package/Sources/Private/Model/DotLottie/ZipFoundation/FileManager+ZIP.swift +368 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/README.md +24 -0
- package/Sources/Private/Model/DotLottie/ZipFoundation/URL+ZIP.swift +32 -0
- package/Sources/Private/Model/Extensions/Bundle.swift +5 -14
- package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +31 -8
- package/Sources/Private/Model/Objects/Transform.swift +58 -17
- package/Sources/Private/Model/ShapeItems/Repeater.swift +41 -7
- package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +61 -7
- package/Sources/Private/Model/Text/TextAnimator.swift +37 -5
- package/Sources/Private/RootAnimationLayer.swift +3 -1
- package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +12 -4
- package/Sources/Private/Utility/Extensions/DataExtension.swift +14 -4
- package/Sources/Private/Utility/Primitives/BezierPathRoundExtension.swift +11 -0
- package/Sources/Private/Utility/Primitives/ColorExtension.swift +10 -13
- package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +28 -6
- package/Sources/Public/Animation/LottieAnimationHelpers.swift +12 -10
- package/Sources/Public/Animation/LottieAnimationView.swift +213 -186
- package/Sources/Public/DotLottie/DotLottieFile.swift +11 -34
- package/Sources/Public/DotLottie/DotLottieFileHelpers.swift +101 -74
- package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +90 -0
- package/Sources/Public/iOS/LottieAnimationViewBase.swift +1 -1
- package/Sources/Public/macOS/LottieAnimationViewBase.macOS.swift +1 -1
- package/lottie-ios.podspec +1 -1
- package/package.json +1 -1
- package/LottieAnimation/LottieAnimation.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/LottieAnimation/LottieAnimation.xcodeproj/project.xcworkspace/xcuserdata/valentinperignon.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/valentinperignon.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
- package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/valentinperignon.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/Sources/Private/Model/DotLottie/Zip/Data+Compression.swift +0 -134
- package/Sources/Private/Model/DotLottie/Zip/FileManager+ZIP.swift +0 -130
- package/Sources/Private/Utility/Interpolatable/KeyframeGroup+Extensions.swift +0 -59
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Archive+ZIP64.swift
|
|
3
|
+
// ZIPFoundation
|
|
4
|
+
//
|
|
5
|
+
// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
|
|
6
|
+
// Released under the MIT License.
|
|
7
|
+
//
|
|
8
|
+
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
|
|
9
|
+
//
|
|
10
|
+
|
|
11
|
+
import Foundation
|
|
12
|
+
|
|
13
|
+
let zip64EOCDRecordStructSignature = 0x06064b50
|
|
14
|
+
let zip64EOCDLocatorStructSignature = 0x07064b50
|
|
15
|
+
|
|
16
|
+
// MARK: - ExtraFieldHeaderID
|
|
17
|
+
|
|
18
|
+
enum ExtraFieldHeaderID: UInt16 {
|
|
19
|
+
case zip64ExtendedInformation = 0x0001
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
extension Archive {
|
|
23
|
+
struct ZIP64EndOfCentralDirectory {
|
|
24
|
+
let record: ZIP64EndOfCentralDirectoryRecord
|
|
25
|
+
let locator: ZIP64EndOfCentralDirectoryLocator
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
struct ZIP64EndOfCentralDirectoryRecord: DataSerializable {
|
|
29
|
+
let zip64EOCDRecordSignature = UInt32(zip64EOCDRecordStructSignature)
|
|
30
|
+
let sizeOfZIP64EndOfCentralDirectoryRecord: UInt64
|
|
31
|
+
let versionMadeBy: UInt16
|
|
32
|
+
let versionNeededToExtract: UInt16
|
|
33
|
+
let numberOfDisk: UInt32
|
|
34
|
+
let numberOfDiskStart: UInt32
|
|
35
|
+
let totalNumberOfEntriesOnDisk: UInt64
|
|
36
|
+
let totalNumberOfEntriesInCentralDirectory: UInt64
|
|
37
|
+
let sizeOfCentralDirectory: UInt64
|
|
38
|
+
let offsetToStartOfCentralDirectory: UInt64
|
|
39
|
+
let zip64ExtensibleDataSector: Data
|
|
40
|
+
static let size = 56
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
struct ZIP64EndOfCentralDirectoryLocator: DataSerializable {
|
|
44
|
+
let zip64EOCDLocatorSignature = UInt32(zip64EOCDLocatorStructSignature)
|
|
45
|
+
let numberOfDiskWithZIP64EOCDRecordStart: UInt32
|
|
46
|
+
let relativeOffsetOfZIP64EOCDRecord: UInt64
|
|
47
|
+
let totalNumberOfDisk: UInt32
|
|
48
|
+
static let size = 20
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
extension Archive.ZIP64EndOfCentralDirectoryRecord {
|
|
53
|
+
|
|
54
|
+
// MARK: Lifecycle
|
|
55
|
+
|
|
56
|
+
init?(data: Data, additionalDataProvider _: (Int) throws -> Data) {
|
|
57
|
+
guard data.count == Archive.ZIP64EndOfCentralDirectoryRecord.size else { return nil }
|
|
58
|
+
guard data.scanValue(start: 0) == zip64EOCDRecordSignature else { return nil }
|
|
59
|
+
sizeOfZIP64EndOfCentralDirectoryRecord = data.scanValue(start: 4)
|
|
60
|
+
versionMadeBy = data.scanValue(start: 12)
|
|
61
|
+
versionNeededToExtract = data.scanValue(start: 14)
|
|
62
|
+
// Version Needed to Extract: 4.5 - File uses ZIP64 format extensions
|
|
63
|
+
guard versionNeededToExtract >= Archive.Version.v45.rawValue else { return nil }
|
|
64
|
+
numberOfDisk = data.scanValue(start: 16)
|
|
65
|
+
numberOfDiskStart = data.scanValue(start: 20)
|
|
66
|
+
totalNumberOfEntriesOnDisk = data.scanValue(start: 24)
|
|
67
|
+
totalNumberOfEntriesInCentralDirectory = data.scanValue(start: 32)
|
|
68
|
+
sizeOfCentralDirectory = data.scanValue(start: 40)
|
|
69
|
+
offsetToStartOfCentralDirectory = data.scanValue(start: 48)
|
|
70
|
+
zip64ExtensibleDataSector = Data()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
init(
|
|
74
|
+
record: Archive.ZIP64EndOfCentralDirectoryRecord,
|
|
75
|
+
numberOfEntriesOnDisk: UInt64,
|
|
76
|
+
numberOfEntriesInCD: UInt64,
|
|
77
|
+
sizeOfCentralDirectory: UInt64,
|
|
78
|
+
offsetToStartOfCD: UInt64)
|
|
79
|
+
{
|
|
80
|
+
sizeOfZIP64EndOfCentralDirectoryRecord = record.sizeOfZIP64EndOfCentralDirectoryRecord
|
|
81
|
+
versionMadeBy = record.versionMadeBy
|
|
82
|
+
versionNeededToExtract = record.versionNeededToExtract
|
|
83
|
+
numberOfDisk = record.numberOfDisk
|
|
84
|
+
numberOfDiskStart = record.numberOfDiskStart
|
|
85
|
+
totalNumberOfEntriesOnDisk = numberOfEntriesOnDisk
|
|
86
|
+
totalNumberOfEntriesInCentralDirectory = numberOfEntriesInCD
|
|
87
|
+
self.sizeOfCentralDirectory = sizeOfCentralDirectory
|
|
88
|
+
offsetToStartOfCentralDirectory = offsetToStartOfCD
|
|
89
|
+
zip64ExtensibleDataSector = record.zip64ExtensibleDataSector
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// MARK: Internal
|
|
93
|
+
|
|
94
|
+
var data: Data {
|
|
95
|
+
var zip64EOCDRecordSignature = zip64EOCDRecordSignature
|
|
96
|
+
var sizeOfZIP64EOCDRecord = sizeOfZIP64EndOfCentralDirectoryRecord
|
|
97
|
+
var versionMadeBy = versionMadeBy
|
|
98
|
+
var versionNeededToExtract = versionNeededToExtract
|
|
99
|
+
var numberOfDisk = numberOfDisk
|
|
100
|
+
var numberOfDiskStart = numberOfDiskStart
|
|
101
|
+
var totalNumberOfEntriesOnDisk = totalNumberOfEntriesOnDisk
|
|
102
|
+
var totalNumberOfEntriesInCD = totalNumberOfEntriesInCentralDirectory
|
|
103
|
+
var sizeOfCD = sizeOfCentralDirectory
|
|
104
|
+
var offsetToStartOfCD = offsetToStartOfCentralDirectory
|
|
105
|
+
var data = Data()
|
|
106
|
+
withUnsafePointer(to: &zip64EOCDRecordSignature) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
107
|
+
withUnsafePointer(to: &sizeOfZIP64EOCDRecord) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
108
|
+
withUnsafePointer(to: &versionMadeBy) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
109
|
+
withUnsafePointer(to: &versionNeededToExtract) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
110
|
+
withUnsafePointer(to: &numberOfDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
111
|
+
withUnsafePointer(to: &numberOfDiskStart) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
112
|
+
withUnsafePointer(to: &totalNumberOfEntriesOnDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
113
|
+
withUnsafePointer(to: &totalNumberOfEntriesInCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
114
|
+
withUnsafePointer(to: &sizeOfCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
115
|
+
withUnsafePointer(to: &offsetToStartOfCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
116
|
+
data.append(zip64ExtensibleDataSector)
|
|
117
|
+
return data
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
extension Archive.ZIP64EndOfCentralDirectoryLocator {
|
|
123
|
+
|
|
124
|
+
// MARK: Lifecycle
|
|
125
|
+
|
|
126
|
+
init?(data: Data, additionalDataProvider _: (Int) throws -> Data) {
|
|
127
|
+
guard data.count == Archive.ZIP64EndOfCentralDirectoryLocator.size else { return nil }
|
|
128
|
+
guard data.scanValue(start: 0) == zip64EOCDLocatorSignature else { return nil }
|
|
129
|
+
numberOfDiskWithZIP64EOCDRecordStart = data.scanValue(start: 4)
|
|
130
|
+
relativeOffsetOfZIP64EOCDRecord = data.scanValue(start: 8)
|
|
131
|
+
totalNumberOfDisk = data.scanValue(start: 16)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
init(locator: Archive.ZIP64EndOfCentralDirectoryLocator, offsetOfZIP64EOCDRecord: UInt64) {
|
|
135
|
+
numberOfDiskWithZIP64EOCDRecordStart = locator.numberOfDiskWithZIP64EOCDRecordStart
|
|
136
|
+
relativeOffsetOfZIP64EOCDRecord = offsetOfZIP64EOCDRecord
|
|
137
|
+
totalNumberOfDisk = locator.totalNumberOfDisk
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// MARK: Internal
|
|
141
|
+
|
|
142
|
+
var data: Data {
|
|
143
|
+
var zip64EOCDLocatorSignature = zip64EOCDLocatorSignature
|
|
144
|
+
var numberOfDiskWithZIP64EOCD = numberOfDiskWithZIP64EOCDRecordStart
|
|
145
|
+
var offsetOfZIP64EOCDRecord = relativeOffsetOfZIP64EOCDRecord
|
|
146
|
+
var totalNumberOfDisk = totalNumberOfDisk
|
|
147
|
+
var data = Data()
|
|
148
|
+
withUnsafePointer(to: &zip64EOCDLocatorSignature) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
149
|
+
withUnsafePointer(to: &numberOfDiskWithZIP64EOCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
150
|
+
withUnsafePointer(to: &offsetOfZIP64EOCDRecord) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
151
|
+
withUnsafePointer(to: &totalNumberOfDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
152
|
+
return data
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
extension Archive.ZIP64EndOfCentralDirectory {
|
|
158
|
+
var data: Data { record.data + locator.data }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/// Properties that represent the maximum value of each field
|
|
162
|
+
var maxUInt32 = UInt32.max
|
|
163
|
+
var maxUInt16 = UInt16.max
|
|
164
|
+
|
|
165
|
+
var maxCompressedSize: UInt32 { maxUInt32 }
|
|
166
|
+
var maxUncompressedSize: UInt32 { maxUInt32 }
|
|
167
|
+
var maxOffsetOfLocalFileHeader: UInt32 { maxUInt32 }
|
|
168
|
+
var maxOffsetOfCentralDirectory: UInt32 { maxUInt32 }
|
|
169
|
+
var maxSizeOfCentralDirectory: UInt32 { maxUInt32 }
|
|
170
|
+
var maxTotalNumberOfEntries: UInt16 { maxUInt16 }
|
package/Sources/Private/Model/DotLottie/{Zip/ZipArchive.swift → ZipFoundation/Archive.swift}
RENAMED
|
@@ -10,26 +10,82 @@
|
|
|
10
10
|
|
|
11
11
|
import Foundation
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/// The default chunk size when reading entry data from an archive.
|
|
14
|
+
let defaultReadChunkSize = Int(16 * 1024)
|
|
15
|
+
/// The default chunk size when writing entry data to an archive.
|
|
16
|
+
let defaultWriteChunkSize = defaultReadChunkSize
|
|
17
|
+
/// The default permissions for newly added entries.
|
|
18
|
+
let defaultFilePermissions = UInt16(0o644)
|
|
19
|
+
/// The default permissions for newly added directories.
|
|
20
|
+
let defaultDirectoryPermissions = UInt16(0o755)
|
|
21
|
+
let defaultPOSIXBufferSize = defaultReadChunkSize
|
|
22
|
+
let defaultDirectoryUnitCount = Int64(1)
|
|
23
|
+
let minEndOfCentralDirectoryOffset = Int64(22)
|
|
24
|
+
let endOfCentralDirectoryStructSignature = 0x06054b50
|
|
25
|
+
let localFileHeaderStructSignature = 0x04034b50
|
|
26
|
+
let dataDescriptorStructSignature = 0x08074b50
|
|
27
|
+
let centralDirectoryStructSignature = 0x02014b50
|
|
28
|
+
let memoryURLScheme = "memory"
|
|
29
|
+
|
|
30
|
+
// MARK: - Archive
|
|
31
|
+
|
|
32
|
+
/// A sequence of uncompressed or compressed ZIP entries.
|
|
33
|
+
///
|
|
34
|
+
/// You use an `Archive` to create, read or update ZIP files.
|
|
35
|
+
/// To read an existing ZIP file, you have to pass in an existing file `URL` and `AccessMode.read`:
|
|
36
|
+
///
|
|
37
|
+
/// var archiveURL = URL(fileURLWithPath: "/path/file.zip")
|
|
38
|
+
/// var archive = Archive(url: archiveURL, accessMode: .read)
|
|
39
|
+
///
|
|
40
|
+
/// An `Archive` is a sequence of entries. You can
|
|
41
|
+
/// iterate over an archive using a `for`-`in` loop to get access to individual `Entry` objects:
|
|
42
|
+
///
|
|
43
|
+
/// for entry in archive {
|
|
44
|
+
/// print(entry.path)
|
|
45
|
+
/// }
|
|
46
|
+
///
|
|
47
|
+
/// Each `Entry` in an `Archive` is represented by its `path`. You can
|
|
48
|
+
/// use `path` to retrieve the corresponding `Entry` from an `Archive` via subscripting:
|
|
49
|
+
///
|
|
50
|
+
/// let entry = archive['/path/file.txt']
|
|
51
|
+
///
|
|
52
|
+
/// To create a new `Archive`, pass in a non-existing file URL and `AccessMode.create`. To modify an
|
|
53
|
+
/// existing `Archive` use `AccessMode.update`:
|
|
54
|
+
///
|
|
55
|
+
/// var archiveURL = URL(fileURLWithPath: "/path/file.zip")
|
|
56
|
+
/// var archive = Archive(url: archiveURL, accessMode: .update)
|
|
57
|
+
/// try archive?.addEntry("test.txt", relativeTo: baseURL, compressionMethod: .deflate)
|
|
58
|
+
final class Archive: Sequence {
|
|
16
59
|
|
|
17
60
|
// MARK: Lifecycle
|
|
18
61
|
|
|
19
62
|
/// Initializes a new ZIP `Archive`.
|
|
20
63
|
///
|
|
21
64
|
/// You can use this initalizer to create new archive files or to read and update existing ones.
|
|
65
|
+
/// The `mode` parameter indicates the intended usage of the archive: `.read`, `.create` or `.update`.
|
|
22
66
|
/// - Parameters:
|
|
23
67
|
/// - url: File URL to the receivers backing file.
|
|
68
|
+
/// - mode: Access mode of the receiver.
|
|
69
|
+
/// - preferredEncoding: Encoding for entry paths. Overrides the encoding specified in the archive.
|
|
70
|
+
/// This encoding is only used when _decoding_ paths from the receiver.
|
|
71
|
+
/// Paths of entries added with `addEntry` are always UTF-8 encoded.
|
|
24
72
|
/// - Returns: An archive initialized with a backing file at the passed in file URL and the given access mode
|
|
25
73
|
/// or `nil` if the following criteria are not met:
|
|
26
|
-
|
|
74
|
+
/// - Note:
|
|
75
|
+
/// - The file URL _must_ point to an existing file for `AccessMode.read`.
|
|
76
|
+
/// - The file URL _must_ point to a non-existing file for `AccessMode.create`.
|
|
77
|
+
/// - The file URL _must_ point to an existing file for `AccessMode.update`.
|
|
78
|
+
init?(url: URL, accessMode mode: AccessMode, preferredEncoding: String.Encoding? = nil) {
|
|
27
79
|
self.url = url
|
|
28
|
-
|
|
80
|
+
accessMode = mode
|
|
81
|
+
self.preferredEncoding = preferredEncoding
|
|
82
|
+
guard let config = Archive.makeBackingConfiguration(for: url, mode: mode) else {
|
|
83
|
+
return nil
|
|
84
|
+
}
|
|
29
85
|
archiveFile = config.file
|
|
30
86
|
endOfCentralDirectoryRecord = config.endOfCentralDirectoryRecord
|
|
31
87
|
zip64EndOfCentralDirectory = config.zip64EndOfCentralDirectory
|
|
32
|
-
setvbuf(archiveFile, nil, _IOFBF, Int(
|
|
88
|
+
setvbuf(archiveFile, nil, _IOFBF, Int(defaultPOSIXBufferSize))
|
|
33
89
|
}
|
|
34
90
|
|
|
35
91
|
deinit {
|
|
@@ -38,10 +94,10 @@ final class ZipArchive: Sequence {
|
|
|
38
94
|
|
|
39
95
|
// MARK: Internal
|
|
40
96
|
|
|
41
|
-
typealias LocalFileHeader =
|
|
42
|
-
typealias DataDescriptor =
|
|
43
|
-
typealias ZIP64DataDescriptor =
|
|
44
|
-
typealias CentralDirectoryStructure =
|
|
97
|
+
typealias LocalFileHeader = Entry.LocalFileHeader
|
|
98
|
+
typealias DataDescriptor = Entry.DefaultDataDescriptor
|
|
99
|
+
typealias ZIP64DataDescriptor = Entry.ZIP64DataDescriptor
|
|
100
|
+
typealias CentralDirectoryStructure = Entry.CentralDirectoryStructure
|
|
45
101
|
|
|
46
102
|
/// An error that occurs during reading, creating or updating a ZIP file.
|
|
47
103
|
enum ArchiveError: Error {
|
|
@@ -75,6 +131,24 @@ final class ZipArchive: Sequence {
|
|
|
75
131
|
case missingEndOfCentralDirectoryRecord
|
|
76
132
|
}
|
|
77
133
|
|
|
134
|
+
/// The access mode for an `Archive`.
|
|
135
|
+
enum AccessMode: UInt {
|
|
136
|
+
/// Indicates that a newly instantiated `Archive` should create its backing file.
|
|
137
|
+
case create
|
|
138
|
+
/// Indicates that a newly instantiated `Archive` should read from an existing backing file.
|
|
139
|
+
case read
|
|
140
|
+
/// Indicates that a newly instantiated `Archive` should update an existing backing file.
|
|
141
|
+
case update
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/// The version of an `Archive`
|
|
145
|
+
enum Version: UInt16 {
|
|
146
|
+
/// The minimum version for deflate compressed archives
|
|
147
|
+
case v20 = 20
|
|
148
|
+
/// The minimum version for archives making use of ZIP64 extensions
|
|
149
|
+
case v45 = 45
|
|
150
|
+
}
|
|
151
|
+
|
|
78
152
|
struct EndOfCentralDirectoryRecord: DataSerializable {
|
|
79
153
|
let endOfCentralDirectorySignature = UInt32(endOfCentralDirectoryStructSignature)
|
|
80
154
|
let numberOfDisk: UInt16
|
|
@@ -88,38 +162,14 @@ final class ZipArchive: Sequence {
|
|
|
88
162
|
static let size = 22
|
|
89
163
|
}
|
|
90
164
|
|
|
91
|
-
// MARK: - Helpers
|
|
92
|
-
|
|
93
|
-
typealias EndOfCentralDirectoryStructure = (EndOfCentralDirectoryRecord, ZIP64EndOfCentralDirectory?)
|
|
94
|
-
|
|
95
|
-
struct BackingConfiguration {
|
|
96
|
-
let file: FILEPointer
|
|
97
|
-
let endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord
|
|
98
|
-
let zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory?
|
|
99
|
-
|
|
100
|
-
init(
|
|
101
|
-
file: FILEPointer,
|
|
102
|
-
endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord,
|
|
103
|
-
zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory?)
|
|
104
|
-
{
|
|
105
|
-
self.file = file
|
|
106
|
-
self.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord
|
|
107
|
-
self.zip64EndOfCentralDirectory = zip64EndOfCentralDirectory
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
static let defaultPOSIXBufferSize = Int(16 * 1024)
|
|
112
|
-
static let minEndOfCentralDirectoryOffset = Int64(22)
|
|
113
|
-
static let endOfCentralDirectoryStructSignature = 0x06054b50
|
|
114
|
-
|
|
115
|
-
/// The default chunk size when reading entry data from an archive.
|
|
116
|
-
static let defaultReadChunkSize = Int(16 * 1024)
|
|
117
|
-
|
|
118
165
|
/// URL of an Archive's backing file.
|
|
119
166
|
let url: URL
|
|
167
|
+
/// Access mode for an archive file.
|
|
168
|
+
let accessMode: AccessMode
|
|
120
169
|
var archiveFile: FILEPointer
|
|
121
170
|
var endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord
|
|
122
171
|
var zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory?
|
|
172
|
+
var preferredEncoding: String.Encoding?
|
|
123
173
|
|
|
124
174
|
var totalNumberOfEntriesInCentralDirectory: UInt64 {
|
|
125
175
|
zip64EndOfCentralDirectory?.record.totalNumberOfEntriesInCentralDirectory
|
|
@@ -136,6 +186,43 @@ final class ZipArchive: Sequence {
|
|
|
136
186
|
?? UInt64(endOfCentralDirectoryRecord.offsetToStartOfCentralDirectory)
|
|
137
187
|
}
|
|
138
188
|
|
|
189
|
+
#if swift(>=5.0)
|
|
190
|
+
var memoryFile: MemoryFile?
|
|
191
|
+
|
|
192
|
+
/// Initializes a new in-memory ZIP `Archive`.
|
|
193
|
+
///
|
|
194
|
+
/// You can use this initalizer to create new in-memory archive files or to read and update existing ones.
|
|
195
|
+
///
|
|
196
|
+
/// - Parameters:
|
|
197
|
+
/// - data: `Data` object used as backing for in-memory archives.
|
|
198
|
+
/// - mode: Access mode of the receiver.
|
|
199
|
+
/// - preferredEncoding: Encoding for entry paths. Overrides the encoding specified in the archive.
|
|
200
|
+
/// This encoding is only used when _decoding_ paths from the receiver.
|
|
201
|
+
/// Paths of entries added with `addEntry` are always UTF-8 encoded.
|
|
202
|
+
/// - Returns: An in-memory archive initialized with passed in backing data.
|
|
203
|
+
/// - Note:
|
|
204
|
+
/// - The backing `data` _must_ contain a valid ZIP archive for `AccessMode.read` and `AccessMode.update`.
|
|
205
|
+
/// - The backing `data` _must_ be empty (or omitted) for `AccessMode.create`.
|
|
206
|
+
init?(data: Data = Data(), accessMode mode: AccessMode, preferredEncoding: String.Encoding? = nil) {
|
|
207
|
+
guard
|
|
208
|
+
let url = URL(string: "\(memoryURLScheme)://"),
|
|
209
|
+
let config = Archive.makeBackingConfiguration(for: data, mode: mode) else
|
|
210
|
+
{
|
|
211
|
+
return nil
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
self.url = url
|
|
215
|
+
accessMode = mode
|
|
216
|
+
self.preferredEncoding = preferredEncoding
|
|
217
|
+
archiveFile = config.file
|
|
218
|
+
memoryFile = config.memoryFile
|
|
219
|
+
endOfCentralDirectoryRecord = config.endOfCentralDirectoryRecord
|
|
220
|
+
zip64EndOfCentralDirectory = config.zip64EndOfCentralDirectory
|
|
221
|
+
}
|
|
222
|
+
#endif
|
|
223
|
+
|
|
224
|
+
// MARK: - Helpers
|
|
225
|
+
|
|
139
226
|
static func scanForEndOfCentralDirectoryRecord(in file: FILEPointer)
|
|
140
227
|
-> EndOfCentralDirectoryStructure?
|
|
141
228
|
{
|
|
@@ -160,22 +247,7 @@ final class ZipArchive: Sequence {
|
|
|
160
247
|
return nil
|
|
161
248
|
}
|
|
162
249
|
|
|
163
|
-
|
|
164
|
-
let fileManager = FileManager()
|
|
165
|
-
let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
|
|
166
|
-
guard
|
|
167
|
-
let archiveFile = fopen(fileSystemRepresentation, "rb"),
|
|
168
|
-
let (eocdRecord, zip64EOCD) = ZipArchive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else
|
|
169
|
-
{
|
|
170
|
-
return nil
|
|
171
|
-
}
|
|
172
|
-
return BackingConfiguration(
|
|
173
|
-
file: archiveFile,
|
|
174
|
-
endOfCentralDirectoryRecord: eocdRecord,
|
|
175
|
-
zip64EndOfCentralDirectory: zip64EOCD)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
func makeIterator() -> AnyIterator<ZipEntry> {
|
|
250
|
+
func makeIterator() -> AnyIterator<Entry> {
|
|
179
251
|
let totalNumberOfEntriesInCD = totalNumberOfEntriesInCentralDirectory
|
|
180
252
|
var directoryIndex = offsetToStartOfCentralDirectory
|
|
181
253
|
var index = 0
|
|
@@ -197,7 +269,7 @@ final class ZipArchive: Sequence {
|
|
|
197
269
|
var zip64DataDescriptor: ZIP64DataDescriptor?
|
|
198
270
|
if centralDirStruct.usesDataDescriptor {
|
|
199
271
|
let additionalSize = UInt64(localFileHeader.fileNameLength) + UInt64(localFileHeader.extraFieldLength)
|
|
200
|
-
let isCompressed = centralDirStruct.compressionMethod !=
|
|
272
|
+
let isCompressed = centralDirStruct.compressionMethod != CompressionMethod.none.rawValue
|
|
201
273
|
let dataSize = isCompressed
|
|
202
274
|
? centralDirStruct.effectiveCompressedSize
|
|
203
275
|
: centralDirStruct.effectiveUncompressedSize
|
|
@@ -215,7 +287,7 @@ final class ZipArchive: Sequence {
|
|
|
215
287
|
directoryIndex += UInt64(centralDirStruct.fileCommentLength)
|
|
216
288
|
index += 1
|
|
217
289
|
}
|
|
218
|
-
return
|
|
290
|
+
return Entry(
|
|
219
291
|
centralDirectoryStructure: centralDirStruct,
|
|
220
292
|
localFileHeader: localFileHeader,
|
|
221
293
|
dataDescriptor: dataDescriptor,
|
|
@@ -231,42 +303,11 @@ final class ZipArchive: Sequence {
|
|
|
231
303
|
///
|
|
232
304
|
/// - Parameter path: A relative file path identifying the corresponding `Entry`.
|
|
233
305
|
/// - Returns: An `Entry` with the given `path`. Otherwise, `nil`.
|
|
234
|
-
subscript(path: String) ->
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
/// Read a ZIP `Entry` from the receiver and write it to `url`.
|
|
239
|
-
///
|
|
240
|
-
/// - Parameters:
|
|
241
|
-
/// - entry: The ZIP `Entry` to read.
|
|
242
|
-
/// - url: The destination file URL.
|
|
243
|
-
/// - bufferSize: The maximum size of the read buffer and the decompression buffer (if needed).
|
|
244
|
-
/// - Returns: The checksum of the processed content or 0 if the `skipCRC32` flag was set to `true`.
|
|
245
|
-
/// - Throws: An error if the destination file cannot be written or the entry contains malformed content.
|
|
246
|
-
func extract(_ entry: ZipEntry, to url: URL, bufferSize: Int = defaultReadChunkSize) throws -> UInt32 {
|
|
247
|
-
guard bufferSize > 0 else { throw ArchiveError.invalidBufferSize }
|
|
248
|
-
let fileManager = FileManager()
|
|
249
|
-
try fileManager.createParentDirectoryStructure(for: url)
|
|
250
|
-
let destinationRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
|
|
251
|
-
guard let destinationFile: FILEPointer = fopen(destinationRepresentation, "wb+") else {
|
|
252
|
-
throw CocoaError(.fileNoSuchFile)
|
|
306
|
+
subscript(path: String) -> Entry? {
|
|
307
|
+
if let encoding = preferredEncoding {
|
|
308
|
+
return first { $0.path(using: encoding) == path }
|
|
253
309
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
guard bufferSize > 0 else { throw ArchiveError.invalidBufferSize }
|
|
257
|
-
guard entry.dataOffset <= .max else { throw ArchiveError.invalidLocalHeaderDataOffset }
|
|
258
|
-
fseeko(archiveFile, off_t(entry.dataOffset), SEEK_SET)
|
|
259
|
-
|
|
260
|
-
let attributes = FileManager.attributes(from: entry)
|
|
261
|
-
try fileManager.setAttributes(attributes, ofItemAtPath: url.path)
|
|
262
|
-
|
|
263
|
-
let size = entry.centralDirectoryStructure.effectiveCompressedSize
|
|
264
|
-
guard size <= .max else { throw ArchiveError.invalidEntrySize }
|
|
265
|
-
return try Data.decompress(size: Int64(size), bufferSize: bufferSize, provider: { _, chunkSize -> Data in
|
|
266
|
-
try Data.readChunk(of: chunkSize, from: self.archiveFile)
|
|
267
|
-
}, consumer: { data in
|
|
268
|
-
_ = try Data.write(chunk: data, to: destinationFile)
|
|
269
|
-
})
|
|
310
|
+
return first { $0.path == path }
|
|
270
311
|
}
|
|
271
312
|
|
|
272
313
|
// MARK: Private
|
|
@@ -293,147 +334,12 @@ final class ZipArchive: Sequence {
|
|
|
293
334
|
}
|
|
294
335
|
}
|
|
295
336
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
extension ZipArchive {
|
|
299
|
-
|
|
300
|
-
struct ZIP64EndOfCentralDirectory {
|
|
301
|
-
let record: ZIP64EndOfCentralDirectoryRecord
|
|
302
|
-
let locator: ZIP64EndOfCentralDirectoryLocator
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
struct ZIP64EndOfCentralDirectoryRecord: DataSerializable {
|
|
306
|
-
let zip64EOCDRecordSignature = UInt32(zip64EOCDRecordStructSignature)
|
|
307
|
-
let sizeOfZIP64EndOfCentralDirectoryRecord: UInt64
|
|
308
|
-
let versionMadeBy: UInt16
|
|
309
|
-
let versionNeededToExtract: UInt16
|
|
310
|
-
let numberOfDisk: UInt32
|
|
311
|
-
let numberOfDiskStart: UInt32
|
|
312
|
-
let totalNumberOfEntriesOnDisk: UInt64
|
|
313
|
-
let totalNumberOfEntriesInCentralDirectory: UInt64
|
|
314
|
-
let sizeOfCentralDirectory: UInt64
|
|
315
|
-
let offsetToStartOfCentralDirectory: UInt64
|
|
316
|
-
let zip64ExtensibleDataSector: Data
|
|
317
|
-
static let size = 56
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
struct ZIP64EndOfCentralDirectoryLocator: DataSerializable {
|
|
321
|
-
let zip64EOCDLocatorSignature = UInt32(zip64EOCDLocatorStructSignature)
|
|
322
|
-
let numberOfDiskWithZIP64EOCDRecordStart: UInt32
|
|
323
|
-
let relativeOffsetOfZIP64EOCDRecord: UInt64
|
|
324
|
-
let totalNumberOfDisk: UInt32
|
|
325
|
-
static let size = 20
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
static let zip64EOCDRecordStructSignature = 0x06064b50
|
|
329
|
-
static let zip64EOCDLocatorStructSignature = 0x07064b50
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
extension ZipArchive.ZIP64EndOfCentralDirectoryRecord {
|
|
333
|
-
|
|
334
|
-
// MARK: Lifecycle
|
|
335
|
-
|
|
336
|
-
init?(data: Data, additionalDataProvider _: (Int) throws -> Data) {
|
|
337
|
-
guard data.count == ZipArchive.ZIP64EndOfCentralDirectoryRecord.size else { return nil }
|
|
338
|
-
guard data.scanValue(start: 0) == zip64EOCDRecordSignature else { return nil }
|
|
339
|
-
sizeOfZIP64EndOfCentralDirectoryRecord = data.scanValue(start: 4)
|
|
340
|
-
versionMadeBy = data.scanValue(start: 12)
|
|
341
|
-
versionNeededToExtract = data.scanValue(start: 14)
|
|
342
|
-
// Version Needed to Extract: 4.5 - File uses ZIP64 format extensions
|
|
343
|
-
guard versionNeededToExtract >= 45 else { return nil }
|
|
344
|
-
numberOfDisk = data.scanValue(start: 16)
|
|
345
|
-
numberOfDiskStart = data.scanValue(start: 20)
|
|
346
|
-
totalNumberOfEntriesOnDisk = data.scanValue(start: 24)
|
|
347
|
-
totalNumberOfEntriesInCentralDirectory = data.scanValue(start: 32)
|
|
348
|
-
sizeOfCentralDirectory = data.scanValue(start: 40)
|
|
349
|
-
offsetToStartOfCentralDirectory = data.scanValue(start: 48)
|
|
350
|
-
zip64ExtensibleDataSector = Data()
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
init(
|
|
354
|
-
record: ZipArchive.ZIP64EndOfCentralDirectoryRecord,
|
|
355
|
-
numberOfEntriesOnDisk: UInt64,
|
|
356
|
-
numberOfEntriesInCD: UInt64,
|
|
357
|
-
sizeOfCentralDirectory: UInt64,
|
|
358
|
-
offsetToStartOfCD: UInt64)
|
|
359
|
-
{
|
|
360
|
-
sizeOfZIP64EndOfCentralDirectoryRecord = record.sizeOfZIP64EndOfCentralDirectoryRecord
|
|
361
|
-
versionMadeBy = record.versionMadeBy
|
|
362
|
-
versionNeededToExtract = record.versionNeededToExtract
|
|
363
|
-
numberOfDisk = record.numberOfDisk
|
|
364
|
-
numberOfDiskStart = record.numberOfDiskStart
|
|
365
|
-
totalNumberOfEntriesOnDisk = numberOfEntriesOnDisk
|
|
366
|
-
totalNumberOfEntriesInCentralDirectory = numberOfEntriesInCD
|
|
367
|
-
self.sizeOfCentralDirectory = sizeOfCentralDirectory
|
|
368
|
-
offsetToStartOfCentralDirectory = offsetToStartOfCD
|
|
369
|
-
zip64ExtensibleDataSector = record.zip64ExtensibleDataSector
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// MARK: Internal
|
|
373
|
-
|
|
374
|
-
var data: Data {
|
|
375
|
-
var zip64EOCDRecordSignature = zip64EOCDRecordSignature
|
|
376
|
-
var sizeOfZIP64EOCDRecord = sizeOfZIP64EndOfCentralDirectoryRecord
|
|
377
|
-
var versionMadeBy = versionMadeBy
|
|
378
|
-
var versionNeededToExtract = versionNeededToExtract
|
|
379
|
-
var numberOfDisk = numberOfDisk
|
|
380
|
-
var numberOfDiskStart = numberOfDiskStart
|
|
381
|
-
var totalNumberOfEntriesOnDisk = totalNumberOfEntriesOnDisk
|
|
382
|
-
var totalNumberOfEntriesInCD = totalNumberOfEntriesInCentralDirectory
|
|
383
|
-
var sizeOfCD = sizeOfCentralDirectory
|
|
384
|
-
var offsetToStartOfCD = offsetToStartOfCentralDirectory
|
|
385
|
-
var data = Data()
|
|
386
|
-
withUnsafePointer(to: &zip64EOCDRecordSignature) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
387
|
-
withUnsafePointer(to: &sizeOfZIP64EOCDRecord) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
388
|
-
withUnsafePointer(to: &versionMadeBy) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
389
|
-
withUnsafePointer(to: &versionNeededToExtract) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
390
|
-
withUnsafePointer(to: &numberOfDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
391
|
-
withUnsafePointer(to: &numberOfDiskStart) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
392
|
-
withUnsafePointer(to: &totalNumberOfEntriesOnDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
393
|
-
withUnsafePointer(to: &totalNumberOfEntriesInCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
394
|
-
withUnsafePointer(to: &sizeOfCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
395
|
-
withUnsafePointer(to: &offsetToStartOfCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
396
|
-
data.append(zip64ExtensibleDataSector)
|
|
397
|
-
return data
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
extension ZipArchive.ZIP64EndOfCentralDirectoryLocator {
|
|
403
|
-
|
|
404
|
-
// MARK: Lifecycle
|
|
405
|
-
|
|
406
|
-
init?(data: Data, additionalDataProvider _: (Int) throws -> Data) {
|
|
407
|
-
guard data.count == ZipArchive.ZIP64EndOfCentralDirectoryLocator.size else { return nil }
|
|
408
|
-
guard data.scanValue(start: 0) == zip64EOCDLocatorSignature else { return nil }
|
|
409
|
-
numberOfDiskWithZIP64EOCDRecordStart = data.scanValue(start: 4)
|
|
410
|
-
relativeOffsetOfZIP64EOCDRecord = data.scanValue(start: 8)
|
|
411
|
-
totalNumberOfDisk = data.scanValue(start: 16)
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// MARK: Internal
|
|
415
|
-
|
|
416
|
-
var data: Data {
|
|
417
|
-
var zip64EOCDLocatorSignature = zip64EOCDLocatorSignature
|
|
418
|
-
var numberOfDiskWithZIP64EOCD = numberOfDiskWithZIP64EOCDRecordStart
|
|
419
|
-
var offsetOfZIP64EOCDRecord = relativeOffsetOfZIP64EOCDRecord
|
|
420
|
-
var totalNumberOfDisk = totalNumberOfDisk
|
|
421
|
-
var data = Data()
|
|
422
|
-
withUnsafePointer(to: &zip64EOCDLocatorSignature) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
423
|
-
withUnsafePointer(to: &numberOfDiskWithZIP64EOCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
424
|
-
withUnsafePointer(to: &offsetOfZIP64EOCDRecord) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
425
|
-
withUnsafePointer(to: &totalNumberOfDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) }
|
|
426
|
-
return data
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
extension ZipArchive.EndOfCentralDirectoryRecord {
|
|
337
|
+
extension Archive.EndOfCentralDirectoryRecord {
|
|
432
338
|
|
|
433
339
|
// MARK: Lifecycle
|
|
434
340
|
|
|
435
341
|
init?(data: Data, additionalDataProvider provider: (Int) throws -> Data) {
|
|
436
|
-
guard data.count ==
|
|
342
|
+
guard data.count == Archive.EndOfCentralDirectoryRecord.size else { return nil }
|
|
437
343
|
guard data.scanValue(start: 0) == endOfCentralDirectorySignature else { return nil }
|
|
438
344
|
numberOfDisk = data.scanValue(start: 4)
|
|
439
345
|
numberOfDiskStart = data.scanValue(start: 6)
|
|
@@ -447,6 +353,23 @@ extension ZipArchive.EndOfCentralDirectoryRecord {
|
|
|
447
353
|
zipFileCommentData = commentData
|
|
448
354
|
}
|
|
449
355
|
|
|
356
|
+
init(
|
|
357
|
+
record: Archive.EndOfCentralDirectoryRecord,
|
|
358
|
+
numberOfEntriesOnDisk: UInt16,
|
|
359
|
+
numberOfEntriesInCentralDirectory: UInt16,
|
|
360
|
+
updatedSizeOfCentralDirectory: UInt32,
|
|
361
|
+
startOfCentralDirectory: UInt32)
|
|
362
|
+
{
|
|
363
|
+
numberOfDisk = record.numberOfDisk
|
|
364
|
+
numberOfDiskStart = record.numberOfDiskStart
|
|
365
|
+
totalNumberOfEntriesOnDisk = numberOfEntriesOnDisk
|
|
366
|
+
totalNumberOfEntriesInCentralDirectory = numberOfEntriesInCentralDirectory
|
|
367
|
+
sizeOfCentralDirectory = updatedSizeOfCentralDirectory
|
|
368
|
+
offsetToStartOfCentralDirectory = startOfCentralDirectory
|
|
369
|
+
zipFileCommentLength = record.zipFileCommentLength
|
|
370
|
+
zipFileCommentData = record.zipFileCommentData
|
|
371
|
+
}
|
|
372
|
+
|
|
450
373
|
// MARK: Internal
|
|
451
374
|
|
|
452
375
|
var data: Data {
|