diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4383f2d..8a231c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: [push, pull_request] jobs: macOS: name: Test on macOS - runs-on: macOS-latest + runs-on: macOS-12 steps: - uses: actions/checkout@v1 - name: Show environments @@ -23,15 +23,15 @@ jobs: run: pod lib lint --quick linux: runs-on: ubuntu-latest - container: swift:5.4-focal + container: swift:latest steps: - uses: actions/checkout@v2 - name: Unit Test - run: swift test --enable-test-discovery + run: swift test xcode: name: Test with Xcode - runs-on: macOS-latest + runs-on: macos-12 strategy: matrix: name: [macOS, iOS, tvOS] @@ -47,7 +47,7 @@ jobs: - name: tvOS scheme: Gzip tvOS sdk: appletvsimulator - destination: 'platform=tvOS Simulator,name=Apple TV 4K' + destination: 'platform=tvOS Simulator,name=Apple TV' steps: - uses: actions/checkout@v1 - name: Test diff --git a/.swiftlint.yml b/.swiftlint.yml index 9018928..54c6dd5 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,7 +1,4 @@ -excluded: - - Tests/GzipTests - opt_in_rules: - attributes - closure_end_indentation @@ -11,12 +8,10 @@ opt_in_rules: - explicit_init - fatal_error_message - first_where - - implicit_return - implicitly_unwrapped_optional - let_var_whitespace - multiline_parameters - nimble_operator - - no_extension_access_modifier - number_separator - object_literal - operator_usage_whitespace @@ -24,7 +19,6 @@ opt_in_rules: - redundant_nil_coalescing - strict_fileprivate - switch_case_on_newline - - unneeded_parentheses_in_closure_argument - vertical_parameter_alignment_on_call trailing_comma: @@ -34,6 +28,6 @@ trailing_whitespace: ignores_empty_lines: true vertical_whitespace: - max_empty_lines: 2 + max_empty_lines: 3 line_length: 200 diff --git a/CHANGELOG.md b/CHANGELOG.md index cde2c08..d30584b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ Change Log ========================== +5.3.0 +-------------------------- + +### Changes + +- add `wBits` optional parameter to `gzipped(level:)` and `.gunzipped()` to support managing the size of the history buffer. + + + 5.2.0 -------------------------- diff --git a/Gzip.xcodeproj/project.pbxproj b/Gzip.xcodeproj/project.pbxproj index 15cac13..2680342 100644 --- a/Gzip.xcodeproj/project.pbxproj +++ b/Gzip.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 55; objects = { /* Begin PBXAggregateTarget section */ @@ -367,7 +367,7 @@ attributes = { LastSwiftMigration = 0700; LastSwiftUpdateCheck = 1120; - LastUpgradeCheck = 1330; + LastUpgradeCheck = 1400; TargetAttributes = { 2A2CCF79238127CB00FAC851 = { CreatedOnToolsVersion = 11.2.1; @@ -407,7 +407,7 @@ }; }; buildConfigurationList = 2A58A7501B00F3A2005FBBC2 /* Build configuration list for PBXProject "Gzip" */; - compatibilityVersion = "Xcode 10.0"; + compatibilityVersion = "Xcode 13.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -461,6 +461,7 @@ /* Begin PBXShellScriptBuildPhase section */ 2ACC21C31E54BB9D0078241F /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -471,7 +472,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -563,6 +564,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.wolfrosch.Test-tvOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; @@ -579,6 +581,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.wolfrosch.Test-tvOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; @@ -609,6 +612,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.2.0; OTHER_CFLAGS = "-fembed-bitcode-marker"; PRODUCT_BUNDLE_IDENTIFIER = com.wolfrosch.Gzip; @@ -640,6 +644,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.2.0; OTHER_CFLAGS = "-fembed-bitcode"; PRODUCT_BUNDLE_IDENTIFIER = com.wolfrosch.Gzip; @@ -674,6 +679,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.2.0; OTHER_CFLAGS = "-fembed-bitcode-marker"; PRODUCT_BUNDLE_IDENTIFIER = com.wolfrosch.Gzip; @@ -705,6 +711,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.2.0; OTHER_CFLAGS = "-fembed-bitcode"; PRODUCT_BUNDLE_IDENTIFIER = com.wolfrosch.Gzip; @@ -748,6 +755,7 @@ COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 4; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -765,7 +773,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = "© 2014-2022 1024jp"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.1.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -808,6 +816,7 @@ COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 4; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -820,7 +829,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = "© 2014-2022 1024jp"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.1.1; MTL_ENABLE_DEBUG_INFO = NO; SWIFT_COMPILATION_MODE = wholemodule; @@ -833,6 +842,7 @@ 2A58A75F1B00F414005FBBC2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", @@ -844,6 +854,7 @@ "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.wolfrosch.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; @@ -853,6 +864,7 @@ 2A58A7601B00F414005FBBC2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", @@ -863,6 +875,7 @@ "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.wolfrosch.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; @@ -878,6 +891,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.wolfrosch.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -893,6 +907,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.wolfrosch.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -903,6 +918,8 @@ 2ACC21C11E54BB920078241F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -910,6 +927,8 @@ 2ACC21C21E54BB920078241F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -919,6 +938,7 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CURRENT_PROJECT_VERSION = 5; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; @@ -935,6 +955,7 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.wolfrosch.Gzip; PRODUCT_NAME = Gzip; @@ -948,6 +969,7 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CURRENT_PROJECT_VERSION = 5; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; @@ -962,6 +984,7 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.wolfrosch.Gzip; PRODUCT_NAME = Gzip; @@ -991,6 +1014,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.2.0; OTHER_CFLAGS = "-fembed-bitcode-marker"; PRODUCT_BUNDLE_IDENTIFIER = com.wolfrosch.Gzip; @@ -1020,6 +1044,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; MARKETING_VERSION = 5.2.0; OTHER_CFLAGS = "-fembed-bitcode"; PRODUCT_BUNDLE_IDENTIFIER = com.wolfrosch.Gzip; diff --git a/Gzip.xcodeproj/xcshareddata/xcschemes/Gzip iOS.xcscheme b/Gzip.xcodeproj/xcshareddata/xcschemes/Gzip iOS.xcscheme index 69da53c..23d47ae 100644 --- a/Gzip.xcodeproj/xcshareddata/xcschemes/Gzip iOS.xcscheme +++ b/Gzip.xcodeproj/xcshareddata/xcschemes/Gzip iOS.xcscheme @@ -1,6 +1,6 @@ Data { + public func gzipped(level: CompressionLevel = .defaultCompression, wBits: Int32 = Gzip.maxWindowBits + 16) throws -> Data { guard !self.isEmpty else { return Data() @@ -160,7 +175,7 @@ extension Data { var stream = z_stream() var status: Int32 - status = deflateInit2_(&stream, level.rawValue, Z_DEFLATED, MAX_WBITS + 16, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY, ZLIB_VERSION, Int32(DataSize.stream)) + status = deflateInit2_(&stream, level.rawValue, Z_DEFLATED, wBits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY, ZLIB_VERSION, Int32(DataSize.stream)) guard status == Z_OK else { // deflateInit2 returns: @@ -211,9 +226,18 @@ extension Data { /// Create a new `Data` instance by decompressing the receiver using zlib. /// Throws an error if decompression failed. /// + /// The `wBits` parameter allows for managing the size of the history buffer. The possible values are: + /// + /// Value Window size logarithm Input + /// +8 to +15 Base 2 Includes zlib header and trailer + /// -8 to -15 Absolute value of wbits Raw stream with no header and trailer + /// +24 to +31 = 16 + (8 to 15) Low 4 bits of the value Includes gzip header and trailer + /// +40 to +47 = 32 + (8 to 15) Low 4 bits of the value zlib or gzip format + /// + /// - Parameter wBits: Manage the size of the history buffer. /// - Returns: Gzip-decompressed `Data` instance. /// - Throws: `GzipError` - public func gunzipped() throws -> Data { + public func gunzipped(wBits: Int32 = Gzip.maxWindowBits + 32) throws -> Data { guard !self.isEmpty else { return Data() @@ -227,7 +251,7 @@ extension Data { var stream = z_stream() var status: Int32 - status = inflateInit2_(&stream, MAX_WBITS + 32, ZLIB_VERSION, Int32(DataSize.stream)) + status = inflateInit2_(&stream, wBits, ZLIB_VERSION, Int32(DataSize.stream)) guard status == Z_OK else { // inflateInit2 returns: diff --git a/Tests/GzipTests/GzipTests.swift b/Tests/GzipTests/GzipTests.swift index ff9ba43..721d321 100644 --- a/Tests/GzipTests/GzipTests.swift +++ b/Tests/GzipTests/GzipTests.swift @@ -69,7 +69,9 @@ final class GzipTests: XCTestCase { let data = "testString".data(using: .utf8)! XCTAssertThrowsError(try data.gunzipped()) { error in - guard let gzipError = error as? GzipError else { return XCTFail("Caught incorrect error.") } + guard let gzipError = error as? GzipError else { + return XCTFail("Caught incorrect error.") + } XCTAssertEqual(gzipError.kind, .data) XCTAssertEqual(gzipError.message, "incorrect header check") @@ -97,6 +99,22 @@ final class GzipTests: XCTestCase { XCTAssertEqual(String(data: uncompressed, encoding: .utf8), "test") } + func testDecompressionWithNoHeaderAndTrailer() throws { + + let encoded = """ + 7ZOxCsIwEIbf5ea0JNerqdmdFeygFYciHYK0lTZOIe9u9AXMTTpkOQ\ + h8hLv/7vNwmFfr7DyBuXho7Tisrh8fYAAlYiF1oWSr0EgyhCWRrpsa\ + OxCwm9xihxWMB/UuR9e7Z3zCfmqX/naPyAmMFHD+1C7WIKBKRykdrd\ + PRTTqqJINlZKAYkylOv006i4zZEBksY8HIyKFi5EuMf0kzroxzZowc\ + dHIPIYjvjjbRUSTKjmZHs6N/6WhVStS01VnRrGhW9BeKXsML + """ + let data = try XCTUnwrap(Data(base64Encoded: encoded)) + let uncompressed = try data.gunzipped(wBits: -Gzip.maxWindowBits) + let json = String(data: uncompressed, encoding: .utf8) + + XCTAssertEqual(json?.first, "{") + XCTAssertEqual(json?.last, "}") + } func testMultipleDecompression() throws { let firstData = try "test".data(using: .utf8)!.gzipped()