Skip to content

Commit

Permalink
Gzip support, Update to Swift 4.1, checksum optimizations, version 3.…
Browse files Browse the repository at this point in the history
…0.0 release.
  • Loading branch information
mw99 committed Mar 7, 2019
1 parent 9b589b1 commit 3b9f23e
Show file tree
Hide file tree
Showing 6 changed files with 460 additions and 71 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
## Build generated
build/
DerivedData/
development/

## Various settings
*.pbxuser
Expand Down
8 changes: 5 additions & 3 deletions DataCompression.podspec
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
Pod::Spec.new do |s|
s.name = "DataCompression"
s.version = "2.0.1"
s.summary = "Swift libcompression wrapper as an extension for the Data type (ZLIB, LZFSE, LZMA, LZ4, deflate, RFC-1950, RFC-1951)"
s.authors = "Markus Wanke"
s.version = "3.0.0"
s.summary = "Swift libcompression wrapper as an extension for the Data type (GZIP, ZLIB, LZFSE, LZMA, LZ4, deflate, RFC-1950, RFC-1951, RFC-1952)"
s.authors = { "Markus Wanke" => "[email protected]" }
s.homepage = "https://github.com/mw99/DataCompression"
s.license = { :type => 'Apache 2.0', :file => 'LICENSE' }
s.source = { :git => "https://github.com/mw99/DataCompression.git", :tag => s.version }

s.swift_version = '4.1'

s.ios.deployment_target = '9.0'
s.osx.deployment_target = '10.11'
s.tvos.deployment_target = '9.0'
Expand Down
130 changes: 105 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,108 @@

### A libcompression wrapper extension for the `Data` type

##### Supported compression algorithms are:
#### Supported compression algorithms are:

* GZIP format (.gz files) [RFC-1952](https://www.ietf.org/rfc/rfc1952.txt)
* ZLIB deflate stream [RFC-1950](https://www.ietf.org/rfc/rfc1950.txt)
* ZLIB deflate raw [RFC-1951](https://www.ietf.org/rfc/rfc1951.txt)
* [LZMA](https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm)
* [LZFSE](https://github.com/lzfse/lzfse)
* [LZ4](https://en.wikipedia.org/wiki/LZ4_(compression_algorithm))

##### Requirements
* iOS deployment target >= **9.0**
* macOS deployment target >= **10.11**
* tvOS deployment target >= **9.0**
* watchOS deployment target >= **2.0**
#### Requirements
* iOS deployment target **>= 9.0**
* macOS deployment target **>= 10.11**
* tvOS deployment target **>= 9.0**
* watchOS deployment target **>= 2.0**


## Usage example

### Try all algorithms and compare the compression ratio
```swift
let s = "A string that really needs to loose some weight..."
var res: Data? = s.data(using: .utf8)
let raw: Data! = String(repeating: "There is no place like 127.0.0.1", count: 25).data(using: .utf8)

res = res?.deflate()
res = res?.inflate()
print("raw => \(raw.count) bytes")

res = res?.zip()
res = res?.unzip()
for algo: Data.CompressionAlgorithm in [.zlib, .lzfse, .lz4, .lzma] {
let compressedData: Data! = raw.compress(withAlgorithm: algo)

res = res?.compress(withAlgorithm: .LZFSE)
res = res?.decompress(withAlgorithm: .LZFSE)
let ratio = Double(raw.count) / Double(compressedData.count)
print("\(algo) => \(compressedData.count) bytes, ratio: \(ratio)")

assert(compressedData.decompress(withAlgorithm: algo)! == raw)
}
```

res = res?.compress(withAlgorithm: .LZ4)
res = res?.decompress(withAlgorithm: .LZ4)
Will print something like:
```
raw => 800 bytes
zlib => 40 bytes, ratio: 20.00
lzfse => 69 bytes, ratio: 11.59
lz4 => 181 bytes, ratio: 4.42
lzma => 100 bytes, ratio: 8.00
```

res = res?.compress(withAlgorithm: .LZMA)
res = res?.decompress(withAlgorithm: .LZMA)
### Container formats

res = res?.compress(withAlgorithm: .ZLIB)
res = res?.decompress(withAlgorithm: .ZLIB)

assert(res != nil)
let t = String(data: res!, encoding: .utf8)
assert(s == t)
##### The famous zlib deflate algorithm ([RFC-1951](https://www.ietf.org/rfc/rfc1951.txt)) can also be used with the shortcuts `.deflate()` and `.inflate()`
```
let data: Data! = "https://www.ietf.org/rfc/rfc1951.txt".data(using: .utf8)
let deflated: Data! = data.deflate()
let inflated: Data? = deflated?.inflate()
assert(data == inflated)
```

##### Data in gzip format ([RFC-1952](https://www.ietf.org/rfc/rfc1952.txt)) can be handled with `.gzip()` and `.gunzip()`
```
let data: Data! = "https://www.ietf.org/rfc/rfc1952.txt".data(using: .utf8)
let gzipped: Data! = data.zip()
let gunzipped: Data? = gzipped.unzip()
assert(data == gunzipped)
```
*Note: Compressed data in gzip format will always be 18 bytes larger than raw deflated data and will append/perform a crc32 checksum based data integrity test .*

##### Data in zip format ([RFC-1950](https://www.ietf.org/rfc/rfc1950.txt)) can be handled with `.zip()` and `.unzip()`
```
let data: Data! = "https://www.ietf.org/rfc/rfc1950.txt".data(using: .utf8)
let zipped: Data! = data.zip()
let unzipped: Data? = zipped.unzip()
assert(data == unzipped)
```
*Note: Compressed data in zip format will always be 6 bytes larger than raw deflated data and will append/perform a adler32 checksum based data integrity test .*


### Compress a file on the command line and decompress it in Swift
The easiest way is using the already installed **gzip** command line tool. Assuming you have a file called **file.txt**, after calling
```bash
gzip -9 file.txt
```
the file should have been compressed to **file.txt.gz**. You can now load and uncompress the contents of your file with:
```
let compressedData = try? Data(contentsOf: URL(fileURLWithPath: "/path/to/your/file.txt.gz"))
if let uncompressedData = compressedData?.gunzip() {
print(String(data: uncompressedData, encoding: .utf8) ?? "Can't decode UTF-8")
}
```

### Checksum extensions
Unrelated to compression but for convenience **Crc32** and **Adler32** methods are also exposed on the `Data` type which may come in handy.
```
let classicExample = "The quick brown fox jumps over the lazy dog".data(using: .utf8)!
let crc32 = classicExample.crc32()
let adler32 = classicExample.adler32()
print("crc32: \(crc32), adler32: \(adler32)")
```
Will print:
```
crc32: 414fa339, adler32: 5bdc0fda
```



## Install

#### Cocoa Pods
Expand Down Expand Up @@ -77,7 +135,7 @@ import PackageDescription
let package = Package(
name: "<your_package_name>",
dependencies: [
.Package(url: "https://github.com/mw99/DataCompression.git", majorVersion: 2)
.Package(url: "https://github.com/mw99/DataCompression.git", majorVersion: 3)
]
)
```
Expand All @@ -93,7 +151,29 @@ $ swift build -Xswiftc -target -Xswiftc x86_64-apple-macosx10.11

#### Or just copy the file into your project

You only need one file located in `Sources/DataCompression.swift`. Drag and drop it into the Xcode project navigator.
You only need one file located at `Sources/DataCompression.swift`. Drag and drop it into the Xcode project navigator.


## Change log / Upgrading guide

##### Version `2.0.X` to `3.0.0`

- The encoded data in zip format is not copied anymore, which should improve performance.
- Checksum validation is now always performed with libz and way faster.
- The `skipCheckSumValidation:` parameter of `.unzip()` was removed.
- Items of the algorithm enum type are now Swift like lowercase, e.g. `.LZMA``.lzma`


## License


##### Apache License, Version 2.0

##### Copyright 2016, Markus Wanke

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Loading

0 comments on commit 3b9f23e

Please sign in to comment.