-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathCompression.swift
148 lines (122 loc) · 3.89 KB
/
Compression.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: objc_interop
import StdlibUnittest
import Compression
import Foundation
// Read from Data
class DataSource {
private var _buf : Data
private var _bufSize : Int // total byte count
private var _pos : Int // next byte to read
public init(_ d: Data) {
_buf = d
_bufSize = d.count
_pos = 0
}
public func readData(ofLength len: Int) -> Data? {
let n = min(len,_bufSize - _pos)
if (n == 0) { return nil } // EOF
let d = _buf.subdata(in: _pos ..< _pos + n)
_pos += n
return d
}
}
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
func ofiltercompress_ifilterdecompress(
_ contents: Data, using algo: Algorithm
) throws -> Bool {
var payload = Data()
var decompressed = Data()
// Output filter compress
let f = DataSource(contents)
let ofilter = try OutputFilter(.compress, using: algo) { (x: Data?) -> () in
if let x = x { payload.append(x) }
}
while (true) {
let i = f.readData(ofLength: 900)
try ofilter.write(i) // will finalize when i is empty
if i == nil { break }
}
// Input filter decompress
let g = DataSource(payload)
let ifilter = try InputFilter(.decompress, using: algo) { (x: Int) -> Data? in
return g.readData(ofLength: x)
}
while let i = try ifilter.readData(ofLength: 400) {
decompressed.append(i)
}
print("ofilter | ifilter \(algo): \(contents.count) -> \(payload.count) -> \(decompressed.count)")
return contents == decompressed
}
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
func ifiltercompress_ofilterdecompress(
_ contents: Data, using algo: Algorithm
) throws -> Bool {
var payload = Data()
var decompressed = Data()
// Input filter compress
let f = DataSource(contents)
let ifilter = try InputFilter(.compress, using: algo) {(x: Int) -> Data? in
return f.readData(ofLength:x)
}
while let i = try ifilter.readData(ofLength: 400) {
payload.append(i)
}
// Output filter decompress
let g = DataSource(payload)
let ofilter = try OutputFilter(.decompress, using: algo) {(x: Data?) -> () in
if let x = x {
decompressed.append(x)
}
}
while (true) {
let i = g.readData(ofLength: 900)
try ofilter.write(i) // will finalize when i is empty
if i == nil { break }
}
print("ifilter | ofilter \(algo): \(contents.count) -> \(payload.count) -> \(decompressed.count)")
return contents == decompressed
}
func randomString(withBlockLength n: Int) -> String {
var strings = [String]()
for _ in 0 ..< n {
var s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
// Change some random chars
for _ in 1...10 {
let pos = Int.random(in: 0 ..< s.count)
let idx = s.index(s.startIndex, offsetBy: pos)
s = String(s[..<idx] + "#" + s[idx...])
}
strings.append(s)
}
return strings.joined(separator: "")
}
let tests = TestSuite("Compression")
if #available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *) {
do {
for blockLength in [0, 1, 2, 5, 10, 100] {
let testString = randomString(withBlockLength: blockLength)
let contents = testString.data(using: .utf8)!
for algo in Algorithm.allCases {
tests.test("OutputFilter/Compress/InputFilter/Decompress/\(algo)/\(blockLength)") {
expectDoesNotThrow({
expectTrue(
try ofiltercompress_ifilterdecompress(contents, using: algo),
"Failing input: \(testString)"
)
})
}
tests.test("InputFilter/Compress/OutputFilter/Decompress/\(algo)/\(blockLength)") {
expectDoesNotThrow({
expectTrue(
try ifiltercompress_ofilterdecompress(contents, using: algo),
"Failing input: \(testString)"
)
})
}
}
} // blockLength
}
}
runAllTests()