mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
Merge branch 'hotfix-4.5.10'
This commit is contained in:
+2
-2
@@ -3,11 +3,11 @@ sourcekitten_sourcefile: docs.json
|
||||
clean: true
|
||||
author: Timofey Solomko
|
||||
module: SWCompression
|
||||
module_version: 4.5.9
|
||||
module_version: 4.5.10
|
||||
copyright: '© 2021 Timofey Solomko'
|
||||
readme: README.md
|
||||
github_url: https://github.com/tsolomko/SWCompression
|
||||
github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.5.9
|
||||
github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.5.10
|
||||
theme: fullwidth
|
||||
|
||||
custom_categories:
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"MD007": { "indent": 4 },
|
||||
"MD013": { "line_length": 120 },
|
||||
"MD024": false,
|
||||
"MD026": { "punctuation": ".,;:!"},
|
||||
"MD029": { "style": "ordered" }
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
excluded:
|
||||
- .build/
|
||||
- Package.swift
|
||||
- Carthage/
|
||||
disabled_rules:
|
||||
- cyclomatic_complexity
|
||||
- file_length
|
||||
- for_where
|
||||
- function_body_length
|
||||
- identifier_name
|
||||
- type_body_length
|
||||
opt_in_rules:
|
||||
- array_init
|
||||
- block_based_kvo
|
||||
- conditional_returns_on_newline
|
||||
- contains_over_first_not_nil
|
||||
- discouraged_direct_init
|
||||
- discouraged_object_literal
|
||||
- discouraged_optional_boolean
|
||||
- explicit_init
|
||||
- fatal_error_message
|
||||
- first_where
|
||||
- implicit_return
|
||||
- implicitly_unwrapped_optional
|
||||
- joined_default_parameter
|
||||
- literal_expression_end_indentation
|
||||
- operator_usage_whitespace
|
||||
- pattern_matching_keywords
|
||||
- redundant_nil_coalescing
|
||||
- single_test_class
|
||||
- sorted_first_last
|
||||
- switch_case_on_newline
|
||||
- trailing_closure
|
||||
@@ -3,6 +3,10 @@ git:
|
||||
depth: 1
|
||||
submodules: false
|
||||
jobs:
|
||||
allow_failures:
|
||||
# There is an issue with Swift 5.4 on Linux which fails the build. See https://bugs.swift.org/browse/SR-14594.
|
||||
env:
|
||||
- SWIFT_VERSION=5.4
|
||||
include:
|
||||
# We test only building using SPM with Swift 4.2 on macos since Carthage doesn't support multiple Swift language versions.
|
||||
- stage: test
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## 4.5.10
|
||||
|
||||
- Fixed compilation issues on Windows (PR #22 by @trametheka).
|
||||
- Performed minor optimizations to BZip2 and Deflate compression functionality.
|
||||
- Increased the lowest required version of BitByteData dependency to 1.4.4.
|
||||
|
||||
## 4.5.9
|
||||
|
||||
- Improved performance of LZMA/LZMA2 and, consequently, of XZ.
|
||||
|
||||
@@ -1 +1 @@
|
||||
github "tsolomko/BitByteData" ~> 1.4.3
|
||||
github "tsolomko/BitByteData" ~> 1.4.4
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ let package = Package(
|
||||
// .package(url: "https://github.com/jakeheis/SwiftCLI",
|
||||
// from: "5.2.0"),
|
||||
.package(url: "https://github.com/tsolomko/BitByteData",
|
||||
from: "1.4.3"),
|
||||
from: "1.4.4"),
|
||||
],
|
||||
targets: [
|
||||
// SWCOMP: Uncomment the lines below to build swcomp example program.
|
||||
|
||||
@@ -13,7 +13,7 @@ let package = Package(
|
||||
// .package(url: "https://github.com/jakeheis/SwiftCLI",
|
||||
// from: "5.2.0"),
|
||||
.package(url: "https://github.com/tsolomko/BitByteData",
|
||||
from: "1.4.3"),
|
||||
from: "1.4.4"),
|
||||
],
|
||||
targets: [
|
||||
// SWCOMP: Uncomment the lines below to build swcomp example program.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "SWCompression"
|
||||
s.version = "4.5.9"
|
||||
s.version = "4.5.10"
|
||||
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."
|
||||
@@ -22,7 +22,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.swift_versions = ["4", "5"]
|
||||
|
||||
s.dependency "BitByteData", "~> 1.4.3"
|
||||
s.dependency "BitByteData", "~> 1.4.4"
|
||||
|
||||
s.subspec "Deflate" do |sp|
|
||||
sp.source_files = "Sources/{Deflate/*,Common/*,Common/CodingTree/*}.swift"
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.5.9</string>
|
||||
<string>4.5.10</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>76</string>
|
||||
<string>77</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2021 Timofey Solomko</string>
|
||||
</dict>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.5.9</string>
|
||||
<string>4.5.10</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>76</string>
|
||||
<string>77</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1258,7 +1258,7 @@
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
CURRENT_PROJECT_VERSION = 77;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -1339,7 +1339,7 @@
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
CURRENT_PROJECT_VERSION = 77;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
"FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = (
|
||||
@@ -1400,7 +1400,7 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 76;
|
||||
DYLIB_CURRENT_VERSION = 77;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
@@ -1427,7 +1427,7 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 76;
|
||||
DYLIB_CURRENT_VERSION = 77;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
|
||||
@@ -79,10 +79,8 @@ extension BZip2: CompressionAlgorithm {
|
||||
(out, pointer) = BurrowsWheeler.transform(bytes: out)
|
||||
|
||||
let usedBytes = Set(out).sorted()
|
||||
out = mtf(out, characters: usedBytes)
|
||||
|
||||
var maxSymbol = 0
|
||||
(out, maxSymbol) = rleOfMtf(out)
|
||||
(out, maxSymbol) = mtfRle(out, characters: usedBytes)
|
||||
|
||||
// First, we analyze data and create Huffman trees and selectors.
|
||||
// Then we will perform encoding itself.
|
||||
@@ -258,16 +256,23 @@ extension BZip2: CompressionAlgorithm {
|
||||
return out
|
||||
}
|
||||
|
||||
private static func rleOfMtf(_ array: [Int]) -> ([Int], Int) {
|
||||
private static func mtfRle(_ array: [Int], characters: [Int]) -> ([Int], Int) {
|
||||
var out = [Int]()
|
||||
/// Mutable copy of `characters`.
|
||||
var dictionary = characters
|
||||
var lengthOfZerosRun = 0
|
||||
var maxSymbol = 1
|
||||
for i in 0..<array.count {
|
||||
let byte = array[i]
|
||||
let byte = dictionary.firstIndex(of: array[i])!
|
||||
|
||||
// Run length encoding of zeros.
|
||||
if byte == 0 {
|
||||
lengthOfZerosRun += 1
|
||||
}
|
||||
if (byte == 0 && i == array.count - 1) || byte != 0 {
|
||||
// Runs of zeros are represented using a modified binary system with two "digits", RUNA and RUNB, where
|
||||
// RUNA represents 1 and RUNB represents 2 (whereas in the usual base-2 system the digits are 0 and 1).
|
||||
// (We don't need a digit for zero since we can't get a run of length 0 by definition.)
|
||||
if lengthOfZerosRun > 0 {
|
||||
let digitsNumber = Int(floor(log2(Double(lengthOfZerosRun) + 1)))
|
||||
var remainder = lengthOfZerosRun
|
||||
@@ -285,16 +290,19 @@ extension BZip2: CompressionAlgorithm {
|
||||
}
|
||||
}
|
||||
if byte != 0 {
|
||||
// We add one, because 1 is used as RUNB.
|
||||
let newSymbol = byte + 1
|
||||
// We add one because, 1 is used as RUNB.
|
||||
// We don't add two instead, because 0 is never encountered as separate symbol, without RUNA meaning.
|
||||
out.append(newSymbol)
|
||||
if newSymbol > maxSymbol {
|
||||
maxSymbol = newSymbol
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the front.
|
||||
let old = dictionary.remove(at: byte)
|
||||
dictionary.insert(old, at: 0)
|
||||
}
|
||||
// Add 'end of stream' symbol.
|
||||
// Add the 'end of stream' symbol.
|
||||
out.append(maxSymbol + 1)
|
||||
return (out, maxSymbol)
|
||||
}
|
||||
|
||||
@@ -6,22 +6,29 @@
|
||||
import Foundation
|
||||
import BitByteData
|
||||
|
||||
fileprivate struct CodingIndex {
|
||||
|
||||
let treeCode: Int
|
||||
let bitSize: Int
|
||||
|
||||
}
|
||||
|
||||
final class EncodingTree {
|
||||
|
||||
private let bitWriter: BitWriter
|
||||
|
||||
private let codingIndices: [[Int]]
|
||||
private let codingIndices: [CodingIndex]
|
||||
|
||||
init(codes: [Code], _ bitWriter: BitWriter, reverseCodes: Bool = false) {
|
||||
self.bitWriter = bitWriter
|
||||
|
||||
var codingIndices = Array(repeating: [-1, -1], count: codes.count)
|
||||
var codingIndices = Array(repeating: CodingIndex(treeCode: -1, bitSize: -1), count: codes.count)
|
||||
|
||||
for code in codes {
|
||||
// Codes have already been reversed.
|
||||
// TODO: This assumption may be only correct for Huffman codes.
|
||||
let treeCode = reverseCodes ? code.code : code.code.reversed(bits: code.bits)
|
||||
codingIndices[code.symbol] = [treeCode, code.bits]
|
||||
codingIndices[code.symbol] = CodingIndex(treeCode: treeCode, bitSize: code.bits)
|
||||
}
|
||||
self.codingIndices = codingIndices
|
||||
|
||||
@@ -33,10 +40,10 @@ final class EncodingTree {
|
||||
|
||||
let codingIndex = self.codingIndices[symbol]
|
||||
|
||||
guard codingIndex[0] > -1
|
||||
guard codingIndex.treeCode > -1
|
||||
else { fatalError("Symbol is not found.") }
|
||||
|
||||
self.bitWriter.write(number: codingIndex[0], bitsCount: codingIndex[1])
|
||||
self.bitWriter.write(number: codingIndex.treeCode, bitsCount: codingIndex.bitSize)
|
||||
}
|
||||
|
||||
func bitSize(for stats: [Int]) -> Int {
|
||||
@@ -45,10 +52,10 @@ final class EncodingTree {
|
||||
guard symbol < self.codingIndices.count
|
||||
else { fatalError("Symbol is not found.") }
|
||||
let codingIndex = self.codingIndices[symbol]
|
||||
guard codingIndex[0] > -1
|
||||
guard codingIndex.treeCode > -1
|
||||
else { fatalError("Symbol is not found.") }
|
||||
|
||||
totalSize += count * codingIndex[1]
|
||||
totalSize += count * codingIndex.bitSize
|
||||
}
|
||||
return totalSize
|
||||
}
|
||||
|
||||
@@ -21,8 +21,12 @@ extension ByteReader {
|
||||
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)
|
||||
}
|
||||
@@ -39,6 +43,10 @@ fileprivate extension String {
|
||||
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)
|
||||
|
||||
@@ -75,7 +75,7 @@ struct ZipLocalHeader {
|
||||
case 0x0001: // Zip64
|
||||
// Zip64 extra field is a special case, because it requires knowledge about local header fields,
|
||||
// in particular, uncompressed and compressed sizes.
|
||||
// In local header both uncompressed size and compressed size fields are required.
|
||||
// In the local header both uncompressed size and compressed size fields are required.
|
||||
self.uncompSize = byteReader.uint64()
|
||||
self.compSize = byteReader.uint64()
|
||||
self.zip64FieldsArePresent = true
|
||||
|
||||
@@ -7,7 +7,7 @@ import Foundation
|
||||
import SWCompression
|
||||
import SwiftCLI
|
||||
|
||||
let cli = CLI(name: "swcomp", version: "4.5.9",
|
||||
let cli = CLI(name: "swcomp", version: "4.5.10",
|
||||
description: """
|
||||
swcomp - small command-line client for SWCompression framework.
|
||||
Serves as an example of SWCompression usage.
|
||||
|
||||
Reference in New Issue
Block a user