diff --git a/.jazzy.yaml b/.jazzy.yaml
index 9e1d8f58..74b84506 100644
--- a/.jazzy.yaml
+++ b/.jazzy.yaml
@@ -3,11 +3,11 @@ sourcekitten_sourcefile: docs.json
clean: false
author: Timofey Solomko
module: SWCompression
-module_version: 4.6.0
+module_version: 4.6.1
copyright: '© 2021 Timofey Solomko'
readme: README.md
github_url: https://github.com/tsolomko/SWCompression
-github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.6.0
+github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.6.1
theme: fullwidth
custom_categories:
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c82083ca..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# TODO: There is probably a way to simplify this very explicit build matrix.
-git:
- depth: 1
- submodules: false
-jobs:
- include:
- - stage: test
- language: swift
- os: osx
- osx_image: xcode12.5 # Swift 5.4
- env:
- - HOMEBREW_NO_INSTALL_CLEANUP=1
- - WATCHOS_ACTIONS='clean test'
- - WATCHOS_SIMULATOR='Apple Watch Series 6 - 44mm'
- before_install:
- - brew update
- install:
- - ./utils.py ci install-macos
- before_script:
- - ./utils.py prepare-workspace macos --xcf
- script:
- - ./utils.py ci script-macos
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 85bb1312..fb937343 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## 4.6.1
+
+- Fixed a crash in LZMA2 when trying to process an empty `Data`.
+- swcomp changes:
+ - Added `benchmark create-tar` benchmarking command.
+ - Benchmarking results are now printed in the units of speed instead of time elapsed.
+
## 4.6.0
- Swift 4.2 is no longer supported.
diff --git a/README.md b/README.md
index d59f3905..7f81eea8 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
[](https://developer.apple.com/swift/)
[](https://raw.githubusercontent.com/tsolomko/SWCompression/master/LICENSE)
-[](https://travis-ci.com/tsolomko/SWCompression)
[](https://dev.azure.com/tsolomko/SWCompression/_build/latest?definitionId=3&branchName=develop)
A framework with (de)compression algorithms and functions for working with various archives and containers.
diff --git a/SWCompression.podspec b/SWCompression.podspec
index 428d48fe..c87570c7 100644
--- a/SWCompression.podspec
+++ b/SWCompression.podspec
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "SWCompression"
- s.version = "4.6.0"
+ s.version = "4.6.1"
s.summary = "A framework with functions for working with compression, archives and containers."
s.description = "A framework with (de)compression algorithms and functions for processing various archives and containers."
diff --git a/SWCompression.xcodeproj/SWCompression.plist b/SWCompression.xcodeproj/SWCompression.plist
index f6f8a4ef..b18df6cd 100644
--- a/SWCompression.xcodeproj/SWCompression.plist
+++ b/SWCompression.xcodeproj/SWCompression.plist
@@ -15,9 +15,9 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 4.6.0
+ 4.6.1
CFBundleVersion
- 80
+ 81
NSHumanReadableCopyright
Copyright © 2021 Timofey Solomko
diff --git a/SWCompression.xcodeproj/TestSWCompression.plist b/SWCompression.xcodeproj/TestSWCompression.plist
index 95886263..eefd1cd8 100644
--- a/SWCompression.xcodeproj/TestSWCompression.plist
+++ b/SWCompression.xcodeproj/TestSWCompression.plist
@@ -15,8 +15,8 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 4.6.0
+ 4.6.1
CFBundleVersion
- 80
+ 81
diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj
index bb016374..c3ee7d09 100644
--- a/SWCompression.xcodeproj/project.pbxproj
+++ b/SWCompression.xcodeproj/project.pbxproj
@@ -220,6 +220,9 @@
E652D8F5263D678000FC229B /* test_nonstandard_runlength.answer in Resources */ = {isa = PBXBuildFile; fileRef = E652D8F4263D678000FC229B /* test_nonstandard_runlength.answer */; };
E66F36242538726E00076A6E /* test_empty.lzma in Resources */ = {isa = PBXBuildFile; fileRef = E66F36232538726E00076A6E /* test_empty.lzma */; };
E66F362C2538E2B700076A6E /* test_empty.zlib in Resources */ = {isa = PBXBuildFile; fileRef = E66F362B2538E2B700076A6E /* test_empty.zlib */; };
+ E6EDD6A826F7767F00884532 /* test_minor_version_3.7z in Resources */ = {isa = PBXBuildFile; fileRef = E6EDD6A626F7767E00884532 /* test_minor_version_3.7z */; };
+ E6EDD6A926F7767F00884532 /* test_minor_version_4.7z in Resources */ = {isa = PBXBuildFile; fileRef = E6EDD6A726F7767E00884532 /* test_minor_version_4.7z */; };
+ E6EDD6AC26F77C0E00884532 /* test_minor_version_2.7z in Resources */ = {isa = PBXBuildFile; fileRef = E6EDD6AB26F77C0E00884532 /* test_minor_version_2.7z */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -447,6 +450,9 @@
E652D8F4263D678000FC229B /* test_nonstandard_runlength.answer */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_nonstandard_runlength.answer; sourceTree = ""; };
E66F36232538726E00076A6E /* test_empty.lzma */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty.lzma; sourceTree = ""; };
E66F362B2538E2B700076A6E /* test_empty.zlib */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty.zlib; sourceTree = ""; };
+ E6EDD6A626F7767E00884532 /* test_minor_version_3.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_minor_version_3.7z; sourceTree = ""; };
+ E6EDD6A726F7767E00884532 /* test_minor_version_4.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_minor_version_4.7z; sourceTree = ""; };
+ E6EDD6AB26F77C0E00884532 /* test_minor_version_2.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_minor_version_2.7z; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -883,6 +889,9 @@
06F066061FFB763300312A82 /* test_win.7z */,
0627A4D220FE521B0023987C /* test_unicode.7z */,
068D070321368617002A6C3B /* test_delta_filter.7z */,
+ E6EDD6AB26F77C0E00884532 /* test_minor_version_2.7z */,
+ E6EDD6A626F7767E00884532 /* test_minor_version_3.7z */,
+ E6EDD6A726F7767E00884532 /* test_minor_version_4.7z */,
06F066071FFB763300312A82 /* SWCompressionSourceCode.7z */,
);
path = 7z;
@@ -949,7 +958,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
- LastUpgradeCheck = 1250;
+ LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "Timofey Solomko";
TargetAttributes = {
06BE1AC71DB410F100EE0F59 = {
@@ -991,6 +1000,7 @@
06F066201FFB763300312A82 /* test1.answer in Resources */,
06F0664E1FFB763400312A82 /* test_v7.tar in Resources */,
06F0662E1FFB763400312A82 /* test2.gz in Resources */,
+ E6EDD6AC26F77C0E00884532 /* test_minor_version_2.7z in Resources */,
06F0665C1FFB763400312A82 /* test9.lzma in Resources */,
06F066661FFB763400312A82 /* test3.7z in Resources */,
06F0664B1FFB763400312A82 /* test.tar in Resources */,
@@ -1073,6 +1083,7 @@
06F066351FFB763400312A82 /* test5.xz in Resources */,
06F066631FFB763400312A82 /* test_complicated_coding_scheme.7z in Resources */,
06F066641FFB763400312A82 /* test_anti_file.7z in Resources */,
+ E6EDD6A826F7767F00884532 /* test_minor_version_3.7z in Resources */,
064D01AD20FD077D00CAE058 /* test_unicode_pax.tar in Resources */,
06F0665E1FFB763400312A82 /* test_empty_cont.7z in Resources */,
06F066731FFB763400312A82 /* test3.bz2 in Resources */,
@@ -1083,6 +1094,7 @@
06F066571FFB763400312A82 /* test_empty_file.tar in Resources */,
06F066441FFB763400312A82 /* test_data_descriptor.zip in Resources */,
06F066581FFB763400312A82 /* full_test.tar in Resources */,
+ E6EDD6A926F7767F00884532 /* test_minor_version_4.7z in Resources */,
06F0662B1FFB763400312A82 /* test3.gz in Resources */,
06F0664C1FFB763400312A82 /* test_pax.tar in Resources */,
06F0663A1FFB763400312A82 /* test_multi.xz in Resources */,
@@ -1270,7 +1282,7 @@
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CURRENT_PROJECT_VERSION = 80;
+ CURRENT_PROJECT_VERSION = 81;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -1351,7 +1363,7 @@
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CURRENT_PROJECT_VERSION = 80;
+ CURRENT_PROJECT_VERSION = 81;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
"FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = (
@@ -1412,7 +1424,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 80;
+ DYLIB_CURRENT_VERSION = 81;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -1439,7 +1451,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 80;
+ DYLIB_CURRENT_VERSION = 81;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
diff --git a/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme b/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme
index d423d3f1..de89491d 100644
--- a/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme
+++ b/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme
@@ -1,6 +1,6 @@
Data {
let byteReader = LittleEndianByteReader(data: data)
+ guard byteReader.bytesLeft >= 1
+ else { throw LZMAError.rangeDecoderInitError }
return try decompress(byteReader, byteReader.byte())
}
diff --git a/Sources/ZIP/LittleEndianByteReader+Zip.swift b/Sources/ZIP/LittleEndianByteReader+Zip.swift
index bcb9f870..f5246e35 100644
--- a/Sources/ZIP/LittleEndianByteReader+Zip.swift
+++ b/Sources/ZIP/LittleEndianByteReader+Zip.swift
@@ -6,10 +6,6 @@
import Foundation
import BitByteData
-#if os(Linux)
- import CoreFoundation
-#endif
-
extension LittleEndianByteReader {
func zipString(_ length: Int, _ useUtf8: Bool) -> String? {
@@ -21,12 +17,7 @@ extension LittleEndianByteReader {
return String(data: stringData, encoding: .utf8)
}
if String.cp437Available && !stringData.needsUtf8() {
- #if os(Windows)
return String(data: stringData, encoding: String.cp437Encoding)
- #else
- return String(data: stringData, encoding: String.Encoding(rawValue:
- CFStringConvertEncodingToNSStringEncoding(String.cp437Encoding)))
- #endif
} else {
return String(data: stringData, encoding: .utf8)
}
@@ -36,21 +27,9 @@ extension LittleEndianByteReader {
fileprivate extension String {
- #if os(Linux)
- #if compiler(>=5.3)
- static let cp437Encoding: CFStringEncoding = CFStringEncoding(CFStringEncodings.dosLatinUS.rawValue)
- #else
- static let cp437Encoding: CFStringEncoding = UInt32(truncatingIfNeeded: UInt(kCFStringEncodingDOSLatinUS))
- #endif
- static let cp437Available: Bool = CFStringIsEncodingAvailable(cp437Encoding)
- #elseif os(Windows)
- // "Latin-US (DOS)" CP437-2147483120
- static let cp437Encoding = String.Encoding(rawValue: 0x80000400)
- static let cp437Available = String.availableStringEncodings.contains(cp437Encoding)
- #else
- static let cp437Encoding = CFStringEncoding(CFStringEncodings.dosLatinUS.rawValue)
- static let cp437Available = CFStringIsEncodingAvailable(cp437Encoding)
- #endif
+ // "Latin-US (DOS)" CP437-2147483120
+ static let cp437Encoding = String.Encoding(rawValue: 0x80000400)
+ static let cp437Available = String.availableStringEncodings.contains(cp437Encoding)
}
diff --git a/Sources/swcomp/Benchmarks/BenchmarkCommand.swift b/Sources/swcomp/Benchmarks/BenchmarkCommand.swift
index c731780c..fa80bce7 100644
--- a/Sources/swcomp/Benchmarks/BenchmarkCommand.swift
+++ b/Sources/swcomp/Benchmarks/BenchmarkCommand.swift
@@ -13,12 +13,28 @@ import SwiftCLI
protocol BenchmarkCommand: Command {
- var files: CollectedParameter { get }
+ associatedtype InputType
+
+ var inputs: CollectedParameter { get }
var benchmarkName: String { get }
- var benchmarkFunction: (Data) throws -> Any { get }
+ func loadInput(_ input: String) throws -> (InputType, Double)
+ var benchmarkFunction: (InputType) throws -> Any { get }
+
+}
+
+extension BenchmarkCommand where InputType == Data {
+
+ func loadInput(_ input: String) throws -> (Data, Double) {
+ let inputURL = URL(fileURLWithPath: input)
+ let inputData = try Data(contentsOf: inputURL, options: .mappedIfSafe)
+ let attr = try FileManager.default.attributesOfItem(atPath: input)
+ let inputSize = Double(attr[.size] as! UInt64)
+ return (inputData, inputSize)
+ }
+
}
extension BenchmarkCommand {
@@ -28,16 +44,15 @@ extension BenchmarkCommand {
print(String(repeating: "=", count: title.count))
print(title)
- for file in self.files.value {
- print("File: \(file)")
+ for input in self.inputs.value {
+ print("Input: \(input)")
- let inputURL = URL(fileURLWithPath: file)
- let fileData = try Data(contentsOf: inputURL, options: .mappedIfSafe)
+ let (loadedInput, inputSize) = try self.loadInput(input)
- var totalTime: Double = 0
+ var totalSpeed: Double = 0
- var maxTime = Double(Int.min)
- var minTime = Double(Int.max)
+ var maxSpeed = Double(Int.min)
+ var minSpeed = Double(Int.max)
print("Iterations: ", terminator: "")
#if !os(Linux)
@@ -45,30 +60,35 @@ extension BenchmarkCommand {
#endif
// Zeroth (excluded) iteration.
let startTime = CFAbsoluteTimeGetCurrent()
- _ = try benchmarkFunction(fileData)
+ _ = try benchmarkFunction(loadedInput)
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
- print(String(format: "(%.3f) ", timeElapsed), terminator: "")
+ let speed = inputSize / timeElapsed
+ print("(\(SpeedFormat(speed).format())), ", terminator: "")
#if !os(Linux)
fflush(__stdoutp)
#endif
for _ in 1...10 {
let startTime = CFAbsoluteTimeGetCurrent()
- _ = try benchmarkFunction(fileData)
+ _ = try benchmarkFunction(loadedInput)
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
- print(String(format: "%.3f ", timeElapsed), terminator: "")
+ let speed = inputSize / timeElapsed
+ print(SpeedFormat(speed).format() + ", ", terminator: "")
#if !os(Linux)
fflush(__stdoutp)
#endif
- totalTime += timeElapsed
- if timeElapsed > maxTime {
- maxTime = timeElapsed
+ totalSpeed += speed
+ if speed > maxSpeed {
+ maxSpeed = speed
}
- if timeElapsed < minTime {
- minTime = timeElapsed
+ if speed < minSpeed {
+ minSpeed = speed
}
}
- print(String(format: "\nAverage: %.3f \u{B1} %.3f\n", totalTime / 10, (maxTime - minTime) / 2))
+ let avgSpeed = totalSpeed / 10
+ let avgSpeedFormat = SpeedFormat(avgSpeed)
+ let speedUncertainty = (maxSpeed - minSpeed) / 2
+ print("\nAverage: \(avgSpeedFormat.format().prefix { $0 != " " }) \u{B1} \(avgSpeedFormat.format(speedUncertainty))\n")
}
}
diff --git a/Sources/swcomp/Benchmarks/BenchmarkGroup.swift b/Sources/swcomp/Benchmarks/BenchmarkGroup.swift
index 984acca1..61516c3b 100644
--- a/Sources/swcomp/Benchmarks/BenchmarkGroup.swift
+++ b/Sources/swcomp/Benchmarks/BenchmarkGroup.swift
@@ -4,6 +4,7 @@
// See LICENSE for license information
import Foundation
+import SWCompression
import SwiftCLI
class BenchmarkGroup: CommandGroup {
@@ -11,6 +12,102 @@ class BenchmarkGroup: CommandGroup {
let name = "benchmark"
let shortDescription = "Run the specified benchmark using external files"
- let children: [Routable] = [UnGzip(), UnXz(), UnBz2(), InfoTar(), InfoZip(), Info7z(), CompDeflate(), CompBz2()]
+ let children: [Routable] = [UnGzip(), UnXz(), UnBz2(), InfoTar(), InfoZip(), Info7z(), CompDeflate(), CompBz2(), CreateTar()]
+
+}
+
+class CompBz2: BenchmarkCommand {
+
+ let name = "comp-bz2"
+ let shortDescription = "BZip2 compression"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "BZip2 Compression"
+ let benchmarkFunction: (Data) throws -> Any = BZip2.compress
+
+}
+
+class CompDeflate: BenchmarkCommand {
+
+ let name = "comp-deflate"
+ let shortDescription = "Deflate compression"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "Deflate Compression"
+ let benchmarkFunction: (Data) throws -> Any = Deflate.compress
+
+}
+
+class Info7z: BenchmarkCommand {
+
+ let name = "info-7z"
+ let shortDescription = "7-Zip info function"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "7-Zip info function"
+ let benchmarkFunction: (Data) throws -> Any = SevenZipContainer.info
+
+}
+
+class InfoTar: BenchmarkCommand {
+
+ let name = "info-tar"
+ let shortDescription = "TAR info function"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "TAR info function"
+ let benchmarkFunction: (Data) throws -> Any = TarContainer.info
+
+}
+
+class InfoZip: BenchmarkCommand {
+
+ let name = "info-zip"
+ let shortDescription = "ZIP info function"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "ZIP info function"
+ let benchmarkFunction: (Data) throws -> Any = ZipContainer.info
+
+}
+
+class UnBz2: BenchmarkCommand {
+
+ let name = "un-bz2"
+ let shortDescription = "BZip2 unarchiving"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "BZip2 Unarchive"
+ let benchmarkFunction: (Data) throws -> Any = BZip2.decompress
+
+}
+
+class UnGzip: BenchmarkCommand {
+
+ let name = "un-gzip"
+ let shortDescription = "GZip unarchiving"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "GZip Unarchive"
+ let benchmarkFunction: (Data) throws -> Any = GzipArchive.unarchive
+
+}
+
+class UnXz: BenchmarkCommand {
+
+ let name = "un-xz"
+ let shortDescription = "XZ unarchiving"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "XZ Unarchive"
+ let benchmarkFunction: (Data) throws -> Any = XZArchive.unarchive
}
diff --git a/Sources/swcomp/Benchmarks/CompBz2.swift b/Sources/swcomp/Benchmarks/CompBz2.swift
deleted file mode 100644
index a1b06f61..00000000
--- a/Sources/swcomp/Benchmarks/CompBz2.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2021 Timofey Solomko
-// Licensed under MIT License
-//
-// See LICENSE for license information
-
-import Foundation
-import SWCompression
-import SwiftCLI
-
-class CompBz2: BenchmarkCommand {
-
- let name = "comp-bz2"
- let shortDescription = "BZip2 compression"
-
- let files = CollectedParameter()
-
- let benchmarkName = "BZip2 Compression"
- let benchmarkFunction: (Data) throws -> Any = BZip2.compress
-
-}
diff --git a/Sources/swcomp/Benchmarks/CompDeflate.swift b/Sources/swcomp/Benchmarks/CompDeflate.swift
deleted file mode 100644
index addfaf82..00000000
--- a/Sources/swcomp/Benchmarks/CompDeflate.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2021 Timofey Solomko
-// Licensed under MIT License
-//
-// See LICENSE for license information
-
-import Foundation
-import SWCompression
-import SwiftCLI
-
-class CompDeflate: BenchmarkCommand {
-
- let name = "comp-deflate"
- let shortDescription = "Deflate compression"
-
- let files = CollectedParameter()
-
- let benchmarkName = "Deflate Compression"
- let benchmarkFunction: (Data) throws -> Any = Deflate.compress
-
-}
diff --git a/Sources/swcomp/Benchmarks/CreateTar.swift b/Sources/swcomp/Benchmarks/CreateTar.swift
new file mode 100644
index 00000000..404ee8a3
--- /dev/null
+++ b/Sources/swcomp/Benchmarks/CreateTar.swift
@@ -0,0 +1,35 @@
+// Copyright (c) 2021 Timofey Solomko
+// Licensed under MIT License
+//
+// See LICENSE for license information
+
+import Foundation
+import SWCompression
+import SwiftCLI
+
+class CreateTar: BenchmarkCommand {
+
+ let name = "create-tar"
+ let shortDescription = "Tar container creation"
+
+ let inputs = CollectedParameter()
+
+ let benchmarkName = "TAR Create"
+ let benchmarkFunction: ([TarEntry]) throws -> Any = TarContainer.create
+
+ func loadInput(_ input: String) throws -> ([TarEntry], Double) {
+ return try (TarEntry.createEntries(input, false), Double(URL(fileURLWithPath: input).directorySize()))
+ }
+
+}
+
+fileprivate extension URL {
+
+ func directorySize() throws -> Int {
+ let urls = FileManager.default.enumerator(at: self, includingPropertiesForKeys: nil)?.allObjects as! [URL]
+ return try urls.lazy.reduce(0) {
+ (try $1.resourceValues(forKeys: [.totalFileAllocatedSizeKey]).totalFileAllocatedSize ?? 0) + $0
+ }
+ }
+
+}
diff --git a/Sources/swcomp/Benchmarks/Info7z.swift b/Sources/swcomp/Benchmarks/Info7z.swift
deleted file mode 100644
index 943294e4..00000000
--- a/Sources/swcomp/Benchmarks/Info7z.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2021 Timofey Solomko
-// Licensed under MIT License
-//
-// See LICENSE for license information
-
-import Foundation
-import SWCompression
-import SwiftCLI
-
-class Info7z: BenchmarkCommand {
-
- let name = "info-7z"
- let shortDescription = "7-Zip info function"
-
- let files = CollectedParameter()
-
- let benchmarkName = "7-Zip info function"
- let benchmarkFunction: (Data) throws -> Any = SevenZipContainer.info
-
-}
diff --git a/Sources/swcomp/Benchmarks/InfoTar.swift b/Sources/swcomp/Benchmarks/InfoTar.swift
deleted file mode 100644
index 55bf3aab..00000000
--- a/Sources/swcomp/Benchmarks/InfoTar.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2021 Timofey Solomko
-// Licensed under MIT License
-//
-// See LICENSE for license information
-
-import Foundation
-import SWCompression
-import SwiftCLI
-
-class InfoTar: BenchmarkCommand {
-
- let name = "info-tar"
- let shortDescription = "TAR info function"
-
- let files = CollectedParameter()
-
- let benchmarkName = "TAR info function"
- let benchmarkFunction: (Data) throws -> Any = TarContainer.info
-
-}
diff --git a/Sources/swcomp/Benchmarks/InfoZip.swift b/Sources/swcomp/Benchmarks/InfoZip.swift
deleted file mode 100644
index a44aeae9..00000000
--- a/Sources/swcomp/Benchmarks/InfoZip.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2021 Timofey Solomko
-// Licensed under MIT License
-//
-// See LICENSE for license information
-
-import Foundation
-import SWCompression
-import SwiftCLI
-
-class InfoZip: BenchmarkCommand {
-
- let name = "info-zip"
- let shortDescription = "ZIP info function"
-
- let files = CollectedParameter()
-
- let benchmarkName = "ZIP info function"
- let benchmarkFunction: (Data) throws -> Any = ZipContainer.info
-
-}
diff --git a/Sources/swcomp/Benchmarks/SpeedFormat.swift b/Sources/swcomp/Benchmarks/SpeedFormat.swift
new file mode 100644
index 00000000..678079b4
--- /dev/null
+++ b/Sources/swcomp/Benchmarks/SpeedFormat.swift
@@ -0,0 +1,60 @@
+// Copyright (c) 2021 Timofey Solomko
+// Licensed under MIT License
+//
+// See LICENSE for license information
+
+import Foundation
+
+enum SpeedFormat {
+
+ case bytes(Double)
+ case kilo(Double)
+ case mega(Double)
+ case giga(Double)
+ case tera(Double)
+
+ init(_ speed: Double) {
+ if speed > pow(1000, 4) {
+ self = .tera(speed)
+ } else if speed > pow(1000, 3) {
+ self = .giga(speed)
+ } else if speed > pow(1000, 2) {
+ self = .mega(speed)
+ } else if speed > 1000 {
+ self = .kilo(speed)
+ } else {
+ self = .bytes(speed)
+ }
+ }
+
+ func format() -> String {
+ switch self {
+ case .bytes(let speed):
+ return String(format: "%.3f B/s", speed)
+ case .kilo(let speed):
+ return String(format: "%.3f kB/s", speed / 1000)
+ case .mega(let speed):
+ return String(format: "%.3f MB/s", speed / 1000 / 1000)
+ case .giga(let speed):
+ return String(format: "%.3f GB/s", speed / 1000 / 1000 / 1000)
+ case .tera(let speed):
+ return String(format: "%.3f TB/s", speed / 1000 / 1000 / 1000 / 1000)
+ }
+ }
+
+ func format(_ speed: Double) -> String {
+ switch self {
+ case .bytes(_):
+ return String(format: "%.3f B/s", speed)
+ case .kilo(_):
+ return String(format: "%.3f kB/s", speed / 1000)
+ case .mega(_):
+ return String(format: "%.3f MB/s", speed / 1000 / 1000)
+ case .giga(_):
+ return String(format: "%.3f GB/s", speed / 1000 / 1000 / 1000)
+ case .tera(_):
+ return String(format: "%.3f TB/s", speed / 1000 / 1000 / 1000 / 1000)
+ }
+ }
+
+}
diff --git a/Sources/swcomp/Benchmarks/UnBz2.swift b/Sources/swcomp/Benchmarks/UnBz2.swift
deleted file mode 100644
index b6c279e3..00000000
--- a/Sources/swcomp/Benchmarks/UnBz2.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2021 Timofey Solomko
-// Licensed under MIT License
-//
-// See LICENSE for license information
-
-import Foundation
-import SWCompression
-import SwiftCLI
-
-class UnBz2: BenchmarkCommand {
-
- let name = "un-bz2"
- let shortDescription = "BZip2 unarchiving"
-
- let files = CollectedParameter()
-
- let benchmarkName = "BZip2 Unarchive"
- let benchmarkFunction: (Data) throws -> Any = BZip2.decompress
-
-}
diff --git a/Sources/swcomp/Benchmarks/UnGzip.swift b/Sources/swcomp/Benchmarks/UnGzip.swift
deleted file mode 100644
index 690a0037..00000000
--- a/Sources/swcomp/Benchmarks/UnGzip.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2021 Timofey Solomko
-// Licensed under MIT License
-//
-// See LICENSE for license information
-
-import Foundation
-import SWCompression
-import SwiftCLI
-
-class UnGzip: BenchmarkCommand {
-
- let name = "un-gzip"
- let shortDescription = "GZip unarchiving"
-
- let files = CollectedParameter()
-
- let benchmarkName = "GZip Unarchive"
- let benchmarkFunction: (Data) throws -> Any = GzipArchive.unarchive
-
-}
diff --git a/Sources/swcomp/Benchmarks/UnXz.swift b/Sources/swcomp/Benchmarks/UnXz.swift
deleted file mode 100644
index f0cb7a2c..00000000
--- a/Sources/swcomp/Benchmarks/UnXz.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2021 Timofey Solomko
-// Licensed under MIT License
-//
-// See LICENSE for license information
-
-import Foundation
-import SWCompression
-import SwiftCLI
-
-class UnXz: BenchmarkCommand {
-
- let name = "un-xz"
- let shortDescription = "XZ unarchiving"
-
- let files = CollectedParameter()
-
- let benchmarkName = "XZ Unarchive"
- let benchmarkFunction: (Data) throws -> Any = XZArchive.unarchive
-
-}
diff --git a/Sources/swcomp/Containers/7ZipCommand.swift b/Sources/swcomp/Containers/7ZipCommand.swift
index b96fbea9..f09f801f 100644
--- a/Sources/swcomp/Containers/7ZipCommand.swift
+++ b/Sources/swcomp/Containers/7ZipCommand.swift
@@ -9,6 +9,8 @@ import SwiftCLI
class SevenZipCommand: ContainerCommand {
+ typealias ContainerType = SevenZipContainer
+
let name = "7z"
let shortDescription = "Extracts a 7-Zip container"
@@ -18,7 +20,4 @@ class SevenZipCommand: ContainerCommand {
let archive = Parameter()
- let openFunction: (Data) throws -> [SevenZipEntry] = SevenZipContainer.open
- let infoFunction: (Data) throws -> [SevenZipEntryInfo] = SevenZipContainer.info
-
}
diff --git a/Sources/swcomp/Containers/ContainerCommand.swift b/Sources/swcomp/Containers/ContainerCommand.swift
index 32459532..a156d85d 100644
--- a/Sources/swcomp/Containers/ContainerCommand.swift
+++ b/Sources/swcomp/Containers/ContainerCommand.swift
@@ -9,7 +9,7 @@ import SwiftCLI
protocol ContainerCommand: Command {
- associatedtype Entry: ContainerEntry
+ associatedtype ContainerType: Container
var info: Flag { get }
var extract: Key { get }
@@ -17,9 +17,6 @@ protocol ContainerCommand: Command {
var archive: Parameter { get }
- var openFunction: (Data) throws -> [Entry] { get }
- var infoFunction: (Data) throws -> [Entry.Info] { get }
-
}
extension ContainerCommand {
@@ -33,7 +30,7 @@ extension ContainerCommand {
let fileData = try Data(contentsOf: URL(fileURLWithPath: self.archive.value),
options: .mappedIfSafe)
if info.value {
- let entries = try infoFunction(fileData)
+ let entries = try ContainerType.info(container: fileData)
swcomp.printInfo(entries)
} else if let outputPath = self.extract.value {
if try !isValidOutputDirectory(outputPath, create: true) {
@@ -41,7 +38,7 @@ extension ContainerCommand {
exit(1)
}
- let entries = try openFunction(fileData)
+ let entries = try ContainerType.open(container: fileData)
try swcomp.write(entries, outputPath, verbose.value)
}
}
diff --git a/Sources/swcomp/Containers/TarCommand.swift b/Sources/swcomp/Containers/TarCommand.swift
index 54ec091d..c37db1ea 100644
--- a/Sources/swcomp/Containers/TarCommand.swift
+++ b/Sources/swcomp/Containers/TarCommand.swift
@@ -92,94 +92,10 @@ class TarCommand: Command {
print("Creating new container at \"\(self.archive.value)\" from \"\(inputPath)\"")
print("d = directory, f = file, l = symbolic link")
}
- let entries = try self.createEntries(inputPath, verbose.value)
+ let entries = try TarEntry.createEntries(inputPath, verbose.value)
let containerData = TarContainer.create(from: entries)
try containerData.write(to: URL(fileURLWithPath: self.archive.value))
}
}
- private func createEntries(_ inputPath: String, _ verbose: Bool) throws -> [TarEntry] {
- let inputURL = URL(fileURLWithPath: inputPath)
- let fileManager = FileManager.default
-
- let fileAttributes = try fileManager.attributesOfItem(atPath: inputPath)
-
- let name = inputURL.relativePath
-
- let entryType: ContainerEntryType
- if let typeFromAttributes = fileAttributes[.type] as? FileAttributeType {
- switch typeFromAttributes {
- case .typeBlockSpecial:
- entryType = .blockSpecial
- case .typeCharacterSpecial:
- entryType = .characterSpecial
- case .typeDirectory:
- entryType = .directory
- case .typeRegular:
- entryType = .regular
- case .typeSocket:
- entryType = .socket
- case .typeSymbolicLink:
- entryType = .symbolicLink
- case .typeUnknown:
- entryType = .unknown
- default:
- entryType = .unknown
- }
- } else {
- entryType = .unknown
- }
-
- var info = TarEntryInfo(name: name, type: entryType)
- info.creationTime = fileAttributes[.creationDate] as? Date
- info.groupID = (fileAttributes[.groupOwnerAccountID] as? NSNumber)?.intValue
- info.ownerGroupName = fileAttributes[.groupOwnerAccountName] as? String
- info.modificationTime = fileAttributes[.modificationDate] as? Date
- info.ownerID = (fileAttributes[.ownerAccountID] as? NSNumber)?.intValue
- info.ownerUserName = fileAttributes[.ownerAccountName] as? String
- if let posixPermissions = (fileAttributes[.posixPermissions] as? NSNumber)?.intValue {
- info.permissions = Permissions(rawValue: UInt32(truncatingIfNeeded: posixPermissions))
- }
-
- var entryData = Data()
- if entryType == .symbolicLink {
- info.linkName = try fileManager.destinationOfSymbolicLink(atPath: inputPath)
- } else if entryType != .directory {
- entryData = try Data(contentsOf: URL(fileURLWithPath: inputPath))
- }
-
- if verbose {
- var log = ""
- switch entryType {
- case .regular:
- log += "f: "
- case .directory:
- log += "d: "
- case .symbolicLink:
- log += "l:"
- default:
- log += "u: "
- }
- log += name
- if entryType == .symbolicLink {
- log += " -> " + info.linkName
- }
- print(log)
- }
-
- let entry = TarEntry(info: info, data: entryData)
-
- var entries = [TarEntry]()
- entries.append(entry)
-
- if entryType == .directory {
- for subPath in try fileManager.contentsOfDirectory(atPath: inputPath) {
- entries.append(contentsOf: try self.createEntries(inputURL.appendingPathComponent(subPath).relativePath,
- verbose))
- }
- }
-
- return entries
- }
-
}
diff --git a/Sources/swcomp/Containers/ZipCommand.swift b/Sources/swcomp/Containers/ZipCommand.swift
index f104b072..3e5a04ea 100644
--- a/Sources/swcomp/Containers/ZipCommand.swift
+++ b/Sources/swcomp/Containers/ZipCommand.swift
@@ -9,6 +9,8 @@ import SwiftCLI
class ZipCommand: ContainerCommand {
+ typealias ContainerType = ZipContainer
+
let name = "zip"
let shortDescription = "Extracts a ZIP container"
@@ -18,7 +20,4 @@ class ZipCommand: ContainerCommand {
let archive = Parameter()
- let openFunction: (Data) throws -> [ZipEntry] = ZipContainer.open
- let infoFunction: (Data) throws -> [ZipEntryInfo] = ZipContainer.info
-
}
diff --git a/Sources/swcomp/Extensions/TarEntry+Create.swift b/Sources/swcomp/Extensions/TarEntry+Create.swift
new file mode 100644
index 00000000..2e6ddcaa
--- /dev/null
+++ b/Sources/swcomp/Extensions/TarEntry+Create.swift
@@ -0,0 +1,96 @@
+// Copyright (c) 2021 Timofey Solomko
+// Licensed under MIT License
+//
+// See LICENSE for license information
+
+import Foundation
+import SWCompression
+import SwiftCLI
+
+extension TarEntry {
+
+ static func createEntries(_ inputPath: String, _ verbose: Bool) throws -> [TarEntry] {
+ let inputURL = URL(fileURLWithPath: inputPath)
+ let fileManager = FileManager.default
+
+ let fileAttributes = try fileManager.attributesOfItem(atPath: inputPath)
+
+ let name = inputURL.relativePath
+
+ let entryType: ContainerEntryType
+ if let typeFromAttributes = fileAttributes[.type] as? FileAttributeType {
+ switch typeFromAttributes {
+ case .typeBlockSpecial:
+ entryType = .blockSpecial
+ case .typeCharacterSpecial:
+ entryType = .characterSpecial
+ case .typeDirectory:
+ entryType = .directory
+ case .typeRegular:
+ entryType = .regular
+ case .typeSocket:
+ entryType = .socket
+ case .typeSymbolicLink:
+ entryType = .symbolicLink
+ case .typeUnknown:
+ entryType = .unknown
+ default:
+ entryType = .unknown
+ }
+ } else {
+ entryType = .unknown
+ }
+
+ var info = TarEntryInfo(name: name, type: entryType)
+ info.creationTime = fileAttributes[.creationDate] as? Date
+ info.groupID = (fileAttributes[.groupOwnerAccountID] as? NSNumber)?.intValue
+ info.ownerGroupName = fileAttributes[.groupOwnerAccountName] as? String
+ info.modificationTime = fileAttributes[.modificationDate] as? Date
+ info.ownerID = (fileAttributes[.ownerAccountID] as? NSNumber)?.intValue
+ info.ownerUserName = fileAttributes[.ownerAccountName] as? String
+ if let posixPermissions = (fileAttributes[.posixPermissions] as? NSNumber)?.intValue {
+ info.permissions = Permissions(rawValue: UInt32(truncatingIfNeeded: posixPermissions))
+ }
+
+ var entryData = Data()
+ if entryType == .symbolicLink {
+ info.linkName = try fileManager.destinationOfSymbolicLink(atPath: inputPath)
+ } else if entryType != .directory {
+ entryData = try Data(contentsOf: URL(fileURLWithPath: inputPath))
+ }
+
+ if verbose {
+ var log = ""
+ switch entryType {
+ case .regular:
+ log += "f: "
+ case .directory:
+ log += "d: "
+ case .symbolicLink:
+ log += "l:"
+ default:
+ log += "u: "
+ }
+ log += name
+ if entryType == .symbolicLink {
+ log += " -> " + info.linkName
+ }
+ print(log)
+ }
+
+ let entry = TarEntry(info: info, data: entryData)
+
+ var entries = [TarEntry]()
+ entries.append(entry)
+
+ if entryType == .directory {
+ for subPath in try fileManager.contentsOfDirectory(atPath: inputPath) {
+ entries.append(contentsOf: try self.createEntries(inputURL.appendingPathComponent(subPath).relativePath,
+ verbose))
+ }
+ }
+
+ return entries
+ }
+
+}
diff --git a/Sources/swcomp/main.swift b/Sources/swcomp/main.swift
index 4b329857..47c7ba8d 100644
--- a/Sources/swcomp/main.swift
+++ b/Sources/swcomp/main.swift
@@ -7,7 +7,7 @@ import Foundation
import SWCompression
import SwiftCLI
-let cli = CLI(name: "swcomp", version: "4.6.0",
+let cli = CLI(name: "swcomp", version: "4.6.1",
description: """
swcomp - a small command-line client for SWCompression framework.
Serves as an example of SWCompression usage.
diff --git a/Tests/BZip2Tests.swift b/Tests/BZip2Tests.swift
index 8fbf2594..e5b1e1a0 100644
--- a/Tests/BZip2Tests.swift
+++ b/Tests/BZip2Tests.swift
@@ -67,4 +67,8 @@ class BZip2Tests: XCTestCase {
XCTAssertThrowsError(try BZip2.decompress(data: testData))
}
+ func testEmptyData() throws {
+ XCTAssertThrowsError(try BZip2.decompress(data: Data()))
+ }
+
}
diff --git a/Tests/GzipTests.swift b/Tests/GzipTests.swift
index 3c350d74..cf829bb8 100644
--- a/Tests/GzipTests.swift
+++ b/Tests/GzipTests.swift
@@ -151,4 +151,8 @@ class GzipTests: XCTestCase {
XCTAssertThrowsError(try GzipArchive.multiUnarchive(archive: testData))
}
+ func testEmptyData() throws {
+ XCTAssertThrowsError(try GzipArchive.unarchive(archive: Data()))
+ }
+
}
diff --git a/Tests/LzmaTests.swift b/Tests/LzmaTests.swift
index 580b5bf9..acc26d88 100644
--- a/Tests/LzmaTests.swift
+++ b/Tests/LzmaTests.swift
@@ -51,5 +51,9 @@ class LzmaTests: XCTestCase {
XCTAssertThrowsError(try LZMA.decompress(data: testData))
}
+ func testEmptyData() throws {
+ XCTAssertThrowsError(try LZMA.decompress(data: Data()))
+ XCTAssertThrowsError(try LZMA2.decompress(data: Data()))
+ }
}
diff --git a/Tests/Results.md b/Tests/Results.md
index 4bc90a0a..5e99b1f6 100644
--- a/Tests/Results.md
+++ b/Tests/Results.md
@@ -1,18 +1,24 @@
# Test Results
-In this document you can find the results of benchmarking which was performed on Macbook Pro, Late 2011. The main
-purpose of these results is to track progress from version to version.
+In this document you can find the results of benchmarking which was performed on Macbook Air, Retina, 13-inch, Early
+2020 with 1,1 GHz Quad-Core Intel Core i5 CPU. The main purpose of these results is to track progress from version to
+version.
-__Note:__ Since 4.1.0 version of SWCompression internal functionality related to reading/writing bits and bytes
-is published as a separate framework, [BitByteData](https://github.com/tsolomko/BitByteData).
-The overall performance heavily depends on the speed of reading and writing, and thus BitByteData's version, which is
-specified in a separate column in the tables below, becomes relevant to benchmarking, since newer versions can contain
-performance improvements.
+## Changelog
-__Note:__ Since 4.3.0 version of SWCompression the first (zeroth, actually) iteration is excluded from averages
-calculation since this iteration has abnormally longer execution time than any of the following iterations. This
-exclusion led not only to (artificially) improved results, but also to the increased quality of the results by reducing
-calculated uncertainty.
+__September 2021.__ The results are now listed in terms of speed (e.g. MB/s); the benchmarks for Deflate, BZip2 compression and
+TAR container creation have been added; all previous results have been removed since newer hardware is now used; added
+results for the `-Ounchecked` compiler option; the macOS version is now listed for results.
+
+__April 2018.__ The first (zeroth, actually) iteration is now excluded from averages calculation since this iteration
+has abnormally longer execution time than any of the following iterations. This exclusion led not only to (artificially)
+improved results, but also to the increased quality of the results by reducing calculated uncertainty. In addition, the
+averages are now computed over 10 iterations instead of 6.
+
+__January 2018.__ SWCompression internal functionality related to reading/writing bits and bytes is published as a
+separate framework, [BitByteData](https://github.com/tsolomko/BitByteData). The overall performance heavily depends on
+the speed of reading and writing, and thus BitByteData's version, which is specified in a separate column in the tables
+below, becomes relevant to benchmarking, since newer versions can contain performance improvements.
## Tests description
@@ -29,64 +35,68 @@ using "Release" configuration.
__Note:__ External commands used to create compressed files were run using their default sets of options.
-__Note:__ All results are averages over 10 iterations (6 iterations until 4.3.0 version).
+__Note:__ All results are averages over 10 iterations. If the uncertainty is not listed it means that it is less than
+10% in terms of the units listed.
## BZip2 Decompress
-|SWCompression
version|BitByteData
version|Swift
version|Test 1|Test 2|Test 3|
-|:---:|:---:|:---:|---|---|---|
-|4.0.0|—|4.0.X|6.821 ± 0.042|54.214 ± 1.398|7.255 ± 0.117|
-|4.0.1|—|4.0.X|6.797 ± 0.080|54.046 ± 1.070|7.177 ± 0.029|
-|4.1.0|1.0.1|4.0.X|4.452 ± 0.125|36.768 ± 0.382|4.880 ± 0.094|
-|4.3.0|1.2.0|4.1.0|3.481 ± 0.038|27.187 ± 0.152|3.914 ± 0.091|
-|4.4.0|1.2.0|4.1.2|3.548 ± 0.037|27.950 ± 0.975|3.956 ± 0.063|
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|2.764 MB/s|2.973 MB/s|2.410 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|3.279 ± 0.429 MB/s|4.361 ± 0.306 MB/s|3.169 ± 0.180 MB/s|
## XZ Unarchive (LZMA/LZMA2 Decompress)
-|SWCompression
version|BitByteData
version|Swift
version|Test 1|Test 2|Test 3|
-|:---:|:---:|:---:|---|---|---|
-|4.0.0|—|4.0.X|error|24.663 ± 2.349|2.904 ± 0.076|
-|4.0.1|—|4.0.X|2.475 ± 0.067|23.507 ± 0.423|2.901 ± 0.049|
-|4.1.0|1.0.1|4.0.X|2.480 ± 0.091|24.126 ± 1.239|2.892 ± 0.052|
-|4.3.0|1.2.0|4.1.0|2.664 ± 0.031|26.030 ± 1.200|3.111 ± 0.053|
-|4.4.0|1.2.0|4.1.2|2.494 ± 0.038|23.773 ± 0.563|2.912 ± 0.018|
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|5.246 ± 0.279 MB/s|5.543 ± 0.143 MB/s|5.322 ± 0.26 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|6.015 ± 0.319 MB/s|6.374 ± 0.143 MB/s|5.841 ± 0.212 MB/s|
## GZip Unarchive (Deflate Decompress)
-|SWCompression
version|BitByteData
version|Swift
version|Test 1|Test 2|Test 3|
-|:---:|:---:|:---:|---|---|---|
-|4.0.0|—|4.0.X|4.007 ± 0.196|32.043 ± 0.581|4.303 ± 0.045|
-|4.0.1|—|4.0.X|3.886 ± 0.100|32.390 ± 0.896|4.295 ± 0.040|
-|4.1.0|1.0.1|4.0.X|2.886 ± 0.571|22.134 ± 1.473|2.700 ± 0.168|
-|4.3.0|1.2.0|4.1.0|1.622 ± 0.016|13.641 ± 0.069|1.804 ± 0.028|
-|4.4.0|1.2.0|4.1.2|1.665 ± 0.037|14.046 ± 0.093|1.858 ± 0.055|
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|5.946 ± 0.432 MB/s|6.034 ± 0.175 MB/s|6.071 ± 0.25 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|8.562 ± 0.388 MB/s|9.908 ± 0.204 MB/s|8.286 ± 0.250 MB/s|
+
+## BZip2 Compress
+
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|3.540 MB/s|2.862 MB/s|4.253 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|3.816 MB/s|3.060 MB/s|4.647 MB/s|
+
+## Deflate Compress
+
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|12.177 ± 0.259 MB/s|8.809 MB/s|13.594 ± 0.355 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|12.914 ± 0.355 MB/s|9.361 MB/s|15.020 ± 0.277 MB/s|
## 7-Zip Info Function
-|SWCompression
version|BitByteData
version|Swift
version|Test 1|Test 2|Test 3|
-|:---:|:---:|:---:|---|---|---|
-|4.0.0|—|4.0.X|0.270 ± 0.010|crash|0.601 ± 0.057|
-|4.0.1|—|4.0.X|0.258 ± 0.003|0.601 ± 0.010|0.473 ± 0.008|
-|4.1.0|1.0.1|4.0.X|0.062 ± 0.008|0.208 ± 0.010|0.122 ± 0.003|
-|4.3.0|1.2.0|4.1.0|0.060 ± 0.006|0.208 ± 0.008|0.123 ± 0.008|
-|4.4.0|1.2.0|4.1.2|0.062 ± 0.005|0.212 ± 0.008|0.122 ± 0.007|
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|77.072 ± 6.625 MB/s|111.246 ± 4.855 MB/s|38.721 ± 2.681 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|82.367 ± 7.381 MB/s|116.923 ± 3.812 MB/s|38.519 ± 2.988 MB/s|
## TAR Info Function
-|SWCompression
version|BitByteData
version|Swift
version|Test 1|Test 2|Test 3|
-|:---:|:---:|:---:|---|---|---|
-|4.0.0|—|4.0.X|0.248 ± 0.172|1.563 ± 0.442|1.254 ± 0.277|
-|4.0.1|—|4.0.X|0.187 ± 0.177|1.257 ± 0.404|1.016 ± 0.325|
-|4.1.0|1.0.1|4.0.X|0.194 ± 0.190|1.335 ± 0.475|1.062 ± 0.353|
-|4.3.0|1.2.0|4.1.0|0.111 ± 0.008|1.014 ± 0.016|0.813 ± 0.015|
-|4.4.0|1.2.0|4.1.2|0.095 ± 0.005|0.810 ± 0.025|0.680 ± 0.014|
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|967.792 ± 58.436 MB/s|1.006 GB/s|217.082 ± 19.783 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|1.073 ± 0.115 GB/s|1.053 GB/s|246.854 ± 6.763 MB/s|
## ZIP Info Function
-|SWCompression
version|BitByteData
version|Swift
version|Test 1|Test 2|Test 3|
-|:---:|:---:|:---:|---|---|---|
-|4.0.0|—|4.0.X|0.072 ± 0.065|0.669 ± 0.147|0.120 ± 0.081|
-|4.0.1|—|4.0.X|0.076 ± 0.064|0.670 ± 0.142|0.123 ± 0.080|
-|4.1.0|1.0.1|4.0.X|0.063 ± 0.076|0.148 ± 0.107|0.105 ± 0.089|
-|4.3.0|1.2.0|4.1.0|0.044 ± 0.007|0.122 ± 0.009|0.086 ± 0.008|
-|4.4.0|1.2.0|4.1.2|0.048 ± 0.005|0.125 ± 0.005|0.091 ± 0.010|
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|597.002 ± 75.017 MB/s|1.941 ± 0.135 GB/s|389.626 ± 22.006 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|685.266 ± 53.895 MB/s|2.147 GB/s|420.461 ± 15.156 MB/s|
+
+## TAR Create Function
+
+|SWCompression
version|BitByteData
version|macOS
version|Swift
version|Test 1|Test 2|Test 3|
+|:---:|:---:|:---:|:---:|---|---|---|
+|4.6.0|2.0.1|11.5.2|5.4.2|139.649 ± 8.310 MB/s|446.101 ± 21.476 MB/s|215.556 ± 17.5 MB/s|
+|4.6.0-unchecked|2.0.1|11.5.2|5.4.2|142.681 ± 5.664 MB/s|459.403 ± 17.862 MB/s|220.238 ± 3.476 MB/s|
diff --git a/Tests/SevenZipTests.swift b/Tests/SevenZipTests.swift
index d01c8cc0..e4d3bfa0 100644
--- a/Tests/SevenZipTests.swift
+++ b/Tests/SevenZipTests.swift
@@ -19,6 +19,11 @@ class SevenZipTests: XCTestCase {
XCTAssertThrowsError(try SevenZipContainer.open(container: testData))
}
+ func testEmptyData() throws {
+ XCTAssertThrowsError(try SevenZipContainer.info(container: Data()))
+ XCTAssertThrowsError(try SevenZipContainer.open(container: Data()))
+ }
+
func test1() throws {
let testData = try Constants.data(forTest: "test1", withType: SevenZipTests.testType)
let entries = try SevenZipContainer.open(container: testData)
@@ -388,4 +393,65 @@ class SevenZipTests: XCTestCase {
XCTAssertEqual(entries[0].data, answerData)
}
+ func testFormatMinorVersions() throws {
+ let answerData = try Constants.data(forAnswer: "test2")
+
+ var testData = try Constants.data(forTest: "test_minor_version_2", withType: SevenZipTests.testType)
+ var entries = try SevenZipContainer.open(container: testData)
+
+ XCTAssertEqual(entries.count, 1)
+ XCTAssertEqual(entries[0].info.name, "test2.answer")
+ XCTAssertEqual(entries[0].info.type, .regular)
+ XCTAssertEqual(entries[0].info.size, answerData.count)
+ XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 0))
+ XCTAssertEqual(entries[0].info.dosAttributes, DosAttributes(rawValue: 0x20))
+ // Checking times' values is a bit difficult since they are extremely precise.
+ XCTAssertNotNil(entries[0].info.modificationTime)
+ XCTAssertNil(entries[0].info.accessTime)
+ XCTAssertNil(entries[0].info.creationTime)
+ XCTAssertEqual(entries[0].info.hasStream, true)
+ XCTAssertEqual(entries[0].info.isEmpty, false)
+ XCTAssertEqual(entries[0].info.isAnti, false)
+ XCTAssertEqual(entries[0].info.crc, 4168830779)
+ XCTAssertEqual(entries[0].data, answerData)
+
+ testData = try Constants.data(forTest: "test_minor_version_3", withType: SevenZipTests.testType)
+ entries = try SevenZipContainer.open(container: testData)
+
+ XCTAssertEqual(entries.count, 1)
+ XCTAssertEqual(entries[0].info.name, "test2.answer")
+ XCTAssertEqual(entries[0].info.type, .regular)
+ XCTAssertEqual(entries[0].info.size, answerData.count)
+ XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 420))
+ XCTAssertEqual(entries[0].info.dosAttributes, DosAttributes(rawValue: 0x20))
+ // Checking times' values is a bit difficult since they are extremely precise.
+ XCTAssertNotNil(entries[0].info.modificationTime)
+ XCTAssertNotNil(entries[0].info.accessTime)
+ XCTAssertNotNil(entries[0].info.creationTime)
+ XCTAssertEqual(entries[0].info.hasStream, true)
+ XCTAssertEqual(entries[0].info.isEmpty, false)
+ XCTAssertEqual(entries[0].info.isAnti, false)
+ XCTAssertEqual(entries[0].info.crc, 4168830779)
+ XCTAssertEqual(entries[0].data, answerData)
+
+ testData = try Constants.data(forTest: "test_minor_version_4", withType: SevenZipTests.testType)
+ entries = try SevenZipContainer.open(container: testData)
+
+ XCTAssertEqual(entries.count, 1)
+ XCTAssertEqual(entries[0].info.name, "test2.answer")
+ XCTAssertEqual(entries[0].info.type, .regular)
+ XCTAssertEqual(entries[0].info.size, answerData.count)
+ XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 420))
+ XCTAssertEqual(entries[0].info.dosAttributes, DosAttributes(rawValue: 0x20))
+ // Checking times' values is a bit difficult since they are extremely precise.
+ XCTAssertNotNil(entries[0].info.modificationTime)
+ XCTAssertNotNil(entries[0].info.accessTime)
+ XCTAssertNotNil(entries[0].info.creationTime)
+ XCTAssertEqual(entries[0].info.hasStream, true)
+ XCTAssertEqual(entries[0].info.isEmpty, false)
+ XCTAssertEqual(entries[0].info.isAnti, false)
+ XCTAssertEqual(entries[0].info.crc, 4168830779)
+ XCTAssertEqual(entries[0].data, answerData)
+ }
+
}
diff --git a/Tests/Test Files b/Tests/Test Files
index fe35c32f..36e6d8fa 160000
--- a/Tests/Test Files
+++ b/Tests/Test Files
@@ -1 +1 @@
-Subproject commit fe35c32fdab1aab6becabc1ade18408a42e32113
+Subproject commit 36e6d8fa8e7468c4572206f40f6fe8c10fbd7a3e
diff --git a/Tests/ZipTests.swift b/Tests/ZipTests.swift
index 77aa05b9..5561d72a 100644
--- a/Tests/ZipTests.swift
+++ b/Tests/ZipTests.swift
@@ -18,6 +18,11 @@ class ZipTests: XCTestCase {
let testData = try Constants.data(forAnswer: "test6")
XCTAssertThrowsError(try ZipContainer.open(container: testData))
}
+
+ func testEmptyData() throws {
+ XCTAssertThrowsError(try ZipContainer.info(container: Data()))
+ XCTAssertThrowsError(try ZipContainer.open(container: Data()))
+ }
func testBigContainer() throws {
let testData = try Constants.data(forTest: "SWCompressionSourceCode", withType: ZipTests.testType)
diff --git a/Tests/ZlibTests.swift b/Tests/ZlibTests.swift
index d90369b3..273cb812 100644
--- a/Tests/ZlibTests.swift
+++ b/Tests/ZlibTests.swift
@@ -52,4 +52,8 @@ class ZlibTests: XCTestCase {
XCTAssertThrowsError(try ZlibArchive.unarchive(archive: testData))
}
+ func testEmptyData() throws {
+ XCTAssertThrowsError(try ZlibArchive.unarchive(archive: Data()))
+ }
+
}
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 24a89f58..2685906b 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -37,12 +37,18 @@ stages:
WATCHOS_ACTIONS: 'clean build'
WATCHOS_SIMULATOR: 'Apple Watch Series 4 - 44mm'
UTILS_PW_XCF_FLAG: '--xcf'
- # macosSwift54:
- # imageName: 'macOS-11.3'
- # DEVELOPER_DIR: '/Applications/Xcode_12.5.app'
- # WATCHOS_ACTIONS: 'clean test'
- # WATCHOS_SIMULATOR: 'Apple Watch Series 6 - 44mm'
- # UTILS_PW_XCF_FLAG: '--xcf'
+ macosSwift54:
+ imageName: 'macOS-11'
+ DEVELOPER_DIR: '/Applications/Xcode_12.5.1.app'
+ WATCHOS_ACTIONS: 'clean test'
+ WATCHOS_SIMULATOR: 'Apple Watch Series 6 - 44mm'
+ UTILS_PW_XCF_FLAG: '--xcf'
+ macosSwift55:
+ imageName: 'macOS-11'
+ DEVELOPER_DIR: '/Applications/Xcode_13.0.app'
+ WATCHOS_ACTIONS: 'clean test'
+ WATCHOS_SIMULATOR: 'Apple Watch Series 6 - 44mm'
+ UTILS_PW_XCF_FLAG: '--xcf'
pool:
vmImage: $(imageName)
steps:
@@ -74,7 +80,10 @@ stages:
containerImage: 'swift:5.3.3-bionic'
linuxSwift54:
imageName: 'ubuntu-18.04'
- containerImage: 'swift:5.4.2-bionic'
+ containerImage: 'swift:5.4.3-bionic'
+ linuxSwift55:
+ imageName: 'ubuntu-18.04'
+ containerImage: 'swift:5.5-bionic'
pool:
vmImage: $(imageName)
container: $[ variables['containerImage'] ]
@@ -90,7 +99,10 @@ stages:
matrix:
windowsSwift54:
imageName: 'windows-2019'
- SWIFT_VERSION: '5.4.2'
+ SWIFT_VERSION: '5.4.3'
+ windowsSwift55:
+ imageName: 'windows-2019'
+ SWIFT_VERSION: '5.5'
pool:
vmImage: $(imageName)
variables: