/*
* Copyright (c) Huawei Technologies Co., Ltd. 2021-2025. All rights reserved.
*/
/**
* @file
*
* This is a class library that implements the function of decompressing data.
* Provides stream decompression interfaces such as inflateInit, inflate, inflateEnd, getGzipHeader, and setDictionary.
*/
package cangjie_tpc::zlib4cj
/* Some constants */
let ENOUGH_LENS: UInt32 = 852
let ENOUGH_DISTS: UInt32 = 592
let MAXBITS: Int64 = 15
let TYPE_CODES: UInt32 = 1
let TYPE_LENS: UInt32 = 2
let TYPE_DISTS: UInt32 = 3
/* Decompression status */
let HEAD: UInt32 = 0
let FLAGS: UInt32 = 1
let TIME: UInt32 = 2
let OS: UInt32 = 3
let EXLEN: UInt32 = 4
let EXTRA: UInt32 = 5
let NAME: UInt32 = 6
let COMMENT: UInt32 = 7
let HCRC: UInt32 = 8
let DICTID: UInt32 = 9
let DICT: UInt32 = 10
let TYPE: UInt32 = 11
let TYPEDO: UInt32 = 12
let STORED: UInt32 = 13
let COPY_: UInt32 = 14
let COPY: UInt32 = 15
let TABLE: UInt32 = 16
let LENLENS: UInt32 = 17
let CODELENS: UInt32 = 18
let LEN_: UInt32 = 19
let LEN: UInt32 = 20
let LENEXT: UInt32 = 21
let DIST: UInt32 = 22
let DISTEXT: UInt32 = 23
let MATCH: UInt32 = 24
let LIT: UInt32 = 25
let CHECK: UInt32 = 26
let LENGTH: UInt32 = 27
let DONE: UInt32 = 28
let BAD: UInt32 = 29
let MEM: UInt32 = 30
let SYNC: UInt32 = 31
struct Code {
/*
* Option value description:
* 00000000 - Original characters from 0 - 255
* 0000tttt - Level-2 table link. tttt != 0 indicates the start position of the level-2 table.
* 0001eeee - Length, distance, or eeee indicates the number of digits occupied by the extended value.
* 01100000 - block terminator
* 01000000 - Invalid value.
*/
public Code(var option: UInt8, var bits: UInt8, var value: UInt16) {}
}
/* Static decompression code table of the literal length */
let lenfix: Array<Code> = [
Code(96,7,0), Code(0,8,80), Code(0,8,16), Code(20,8,115), Code(18,7,31), Code(0,8,112), Code(0,8,48), Code(0,9,192),
Code(16,7,10), Code(0,8,96), Code(0,8,32), Code(0,9,160), Code(0,8,0), Code(0,8,128), Code(0,8,64), Code(0,9,224),
Code(16,7,6), Code(0,8,88), Code(0,8,24), Code(0,9,144), Code(19,7,59), Code(0,8,120), Code(0,8,56), Code(0,9,208),
Code(17,7,17), Code(0,8,104), Code(0,8,40), Code(0,9,176), Code(0,8,8), Code(0,8,136), Code(0,8,72), Code(0,9,240),
Code(16,7,4), Code(0,8,84), Code(0,8,20), Code(21,8,227), Code(19,7,43), Code(0,8,116), Code(0,8,52), Code(0,9,200),
Code(17,7,13), Code(0,8,100), Code(0,8,36), Code(0,9,168), Code(0,8,4), Code(0,8,132), Code(0,8,68), Code(0,9,232),
Code(16,7,8), Code(0,8,92), Code(0,8,28), Code(0,9,152), Code(20,7,83), Code(0,8,124), Code(0,8,60), Code(0,9,216),
Code(18,7,23), Code(0,8,108), Code(0,8,44), Code(0,9,184), Code(0,8,12), Code(0,8,140), Code(0,8,76), Code(0,9,248),
Code(16,7,3), Code(0,8,82), Code(0,8,18), Code(21,8,163), Code(19,7,35), Code(0,8,114), Code(0,8,50), Code(0,9,196),
Code(17,7,11), Code(0,8,98), Code(0,8,34), Code(0,9,164), Code(0,8,2), Code(0,8,130), Code(0,8,66), Code(0,9,228),
Code(16,7,7), Code(0,8,90), Code(0,8,26), Code(0,9,148), Code(20,7,67), Code(0,8,122), Code(0,8,58), Code(0,9,212),
Code(18,7,19), Code(0,8,106), Code(0,8,42), Code(0,9,180), Code(0,8,10), Code(0,8,138), Code(0,8,74), Code(0,9,244),
Code(16,7,5), Code(0,8,86), Code(0,8,22), Code(64,8,0), Code(19,7,51), Code(0,8,118), Code(0,8,54), Code(0,9,204),
Code(17,7,15), Code(0,8,102), Code(0,8,38), Code(0,9,172), Code(0,8,6), Code(0,8,134), Code(0,8,70), Code(0,9,236),
Code(16,7,9), Code(0,8,94), Code(0,8,30), Code(0,9,156), Code(20,7,99), Code(0,8,126), Code(0,8,62), Code(0,9,220),
Code(18,7,27), Code(0,8,110), Code(0,8,46), Code(0,9,188), Code(0,8,14), Code(0,8,142), Code(0,8,78), Code(0,9,252),
Code(96,7,0), Code(0,8,81), Code(0,8,17), Code(21,8,131), Code(18,7,31), Code(0,8,113), Code(0,8,49), Code(0,9,194),
Code(16,7,10), Code(0,8,97), Code(0,8,33), Code(0,9,162), Code(0,8,1), Code(0,8,129), Code(0,8,65), Code(0,9,226),
Code(16,7,6), Code(0,8,89), Code(0,8,25), Code(0,9,146), Code(19,7,59), Code(0,8,121), Code(0,8,57), Code(0,9,210),
Code(17,7,17), Code(0,8,105), Code(0,8,41), Code(0,9,178), Code(0,8,9), Code(0,8,137), Code(0,8,73), Code(0,9,242),
Code(16,7,4), Code(0,8,85), Code(0,8,21), Code(16,8,258), Code(19,7,43), Code(0,8,117), Code(0,8,53), Code(0,9,202),
Code(17,7,13), Code(0,8,101), Code(0,8,37), Code(0,9,170), Code(0,8,5), Code(0,8,133), Code(0,8,69), Code(0,9,234),
Code(16,7,8), Code(0,8,93), Code(0,8,29), Code(0,9,154), Code(20,7,83), Code(0,8,125), Code(0,8,61), Code(0,9,218),
Code(18,7,23), Code(0,8,109), Code(0,8,45), Code(0,9,186), Code(0,8,13), Code(0,8,141), Code(0,8,77), Code(0,9,250),
Code(16,7,3), Code(0,8,83), Code(0,8,19), Code(21,8,195), Code(19,7,35), Code(0,8,115), Code(0,8,51), Code(0,9,198),
Code(17,7,11), Code(0,8,99), Code(0,8,35), Code(0,9,166), Code(0,8,3), Code(0,8,131), Code(0,8,67), Code(0,9,230),
Code(16,7,7), Code(0,8,91), Code(0,8,27), Code(0,9,150), Code(20,7,67), Code(0,8,123), Code(0,8,59), Code(0,9,214),
Code(18,7,19), Code(0,8,107), Code(0,8,43), Code(0,9,182), Code(0,8,11), Code(0,8,139), Code(0,8,75), Code(0,9,246),
Code(16,7,5), Code(0,8,87), Code(0,8,23), Code(64,8,0), Code(19,7,51), Code(0,8,119), Code(0,8,55), Code(0,9,206),
Code(17,7,15), Code(0,8,103), Code(0,8,39), Code(0,9,174), Code(0,8,7), Code(0,8,135), Code(0,8,71), Code(0,9,238),
Code(16,7,9), Code(0,8,95), Code(0,8,31), Code(0,9,158), Code(20,7,99), Code(0,8,127), Code(0,8,63), Code(0,9,222),
Code(18,7,27), Code(0,8,111), Code(0,8,47), Code(0,9,190), Code(0,8,15), Code(0,8,143), Code(0,8,79), Code(0,9,254),
Code(96,7,0), Code(0,8,80), Code(0,8,16), Code(20,8,115), Code(18,7,31), Code(0,8,112), Code(0,8,48), Code(0,9,193),
Code(16,7,10), Code(0,8,96), Code(0,8,32), Code(0,9,161), Code(0,8,0), Code(0,8,128), Code(0,8,64), Code(0,9,225),
Code(16,7,6), Code(0,8,88), Code(0,8,24), Code(0,9,145), Code(19,7,59), Code(0,8,120), Code(0,8,56), Code(0,9,209),
Code(17,7,17), Code(0,8,104), Code(0,8,40), Code(0,9,177), Code(0,8,8), Code(0,8,136), Code(0,8,72), Code(0,9,241),
Code(16,7,4), Code(0,8,84), Code(0,8,20), Code(21,8,227), Code(19,7,43), Code(0,8,116), Code(0,8,52), Code(0,9,201),
Code(17,7,13), Code(0,8,100), Code(0,8,36), Code(0,9,169), Code(0,8,4), Code(0,8,132), Code(0,8,68), Code(0,9,233),
Code(16,7,8), Code(0,8,92), Code(0,8,28), Code(0,9,153), Code(20,7,83), Code(0,8,124), Code(0,8,60), Code(0,9,217),
Code(18,7,23), Code(0,8,108), Code(0,8,44), Code(0,9,185), Code(0,8,12), Code(0,8,140), Code(0,8,76), Code(0,9,249),
Code(16,7,3), Code(0,8,82), Code(0,8,18), Code(21,8,163), Code(19,7,35), Code(0,8,114), Code(0,8,50), Code(0,9,197),
Code(17,7,11), Code(0,8,98), Code(0,8,34), Code(0,9,165), Code(0,8,2), Code(0,8,130), Code(0,8,66), Code(0,9,229),
Code(16,7,7), Code(0,8,90), Code(0,8,26), Code(0,9,149), Code(20,7,67), Code(0,8,122), Code(0,8,58), Code(0,9,213),
Code(18,7,19), Code(0,8,106), Code(0,8,42), Code(0,9,181), Code(0,8,10), Code(0,8,138), Code(0,8,74), Code(0,9,245),
Code(16,7,5), Code(0,8,86), Code(0,8,22), Code(64,8,0), Code(19,7,51), Code(0,8,118), Code(0,8,54), Code(0,9,205),
Code(17,7,15), Code(0,8,102), Code(0,8,38), Code(0,9,173), Code(0,8,6), Code(0,8,134), Code(0,8,70), Code(0,9,237),
Code(16,7,9), Code(0,8,94), Code(0,8,30), Code(0,9,157), Code(20,7,99), Code(0,8,126), Code(0,8,62), Code(0,9,221),
Code(18,7,27), Code(0,8,110), Code(0,8,46), Code(0,9,189), Code(0,8,14), Code(0,8,142), Code(0,8,78), Code(0,9,253),
Code(96,7,0), Code(0,8,81), Code(0,8,17), Code(21,8,131), Code(18,7,31), Code(0,8,113), Code(0,8,49), Code(0,9,195),
Code(16,7,10), Code(0,8,97), Code(0,8,33), Code(0,9,163), Code(0,8,1), Code(0,8,129), Code(0,8,65), Code(0,9,227),
Code(16,7,6), Code(0,8,89), Code(0,8,25), Code(0,9,147), Code(19,7,59), Code(0,8,121), Code(0,8,57), Code(0,9,211),
Code(17,7,17), Code(0,8,105), Code(0,8,41), Code(0,9,179), Code(0,8,9), Code(0,8,137), Code(0,8,73), Code(0,9,243),
Code(16,7,4), Code(0,8,85), Code(0,8,21), Code(16,8,258), Code(19,7,43), Code(0,8,117), Code(0,8,53), Code(0,9,203),
Code(17,7,13), Code(0,8,101), Code(0,8,37), Code(0,9,171), Code(0,8,5), Code(0,8,133), Code(0,8,69), Code(0,9,235),
Code(16,7,8), Code(0,8,93), Code(0,8,29), Code(0,9,155), Code(20,7,83), Code(0,8,125), Code(0,8,61), Code(0,9,219),
Code(18,7,23), Code(0,8,109), Code(0,8,45), Code(0,9,187), Code(0,8,13), Code(0,8,141), Code(0,8,77), Code(0,9,251),
Code(16,7,3), Code(0,8,83), Code(0,8,19), Code(21,8,195), Code(19,7,35), Code(0,8,115), Code(0,8,51), Code(0,9,199),
Code(17,7,11), Code(0,8,99), Code(0,8,35), Code(0,9,167), Code(0,8,3), Code(0,8,131), Code(0,8,67), Code(0,9,231),
Code(16,7,7), Code(0,8,91), Code(0,8,27), Code(0,9,151), Code(20,7,67), Code(0,8,123), Code(0,8,59), Code(0,9,215),
Code(18,7,19), Code(0,8,107), Code(0,8,43), Code(0,9,183), Code(0,8,11), Code(0,8,139), Code(0,8,75), Code(0,9,247),
Code(16,7,5), Code(0,8,87), Code(0,8,23), Code(64,8,0), Code(19,7,51), Code(0,8,119), Code(0,8,55), Code(0,9,207),
Code(17,7,15), Code(0,8,103), Code(0,8,39), Code(0,9,175), Code(0,8,7), Code(0,8,135), Code(0,8,71), Code(0,9,239),
Code(16,7,9), Code(0,8,95), Code(0,8,31), Code(0,9,159), Code(20,7,99), Code(0,8,127), Code(0,8,63), Code(0,9,223),
Code(18,7,27), Code(0,8,111), Code(0,8,47), Code(0,9,191), Code(0,8,15), Code(0,8,143), Code(0,8,79), Code(0,9,255)
]
/* Distance static decompression code table */
let distfix: Array<Code> = [
Code(16,5,1), Code(23,5,257), Code(19,5,17), Code(27,5,4097), Code(17,5,5), Code(25,5,1025), Code(21,5,65), Code(29,5,16385),
Code(16,5,3), Code(24,5,513), Code(20,5,33), Code(28,5,8193), Code(18,5,9), Code(26,5,2049), Code(22,5,129), Code(64,5,0),
Code(16,5,2), Code(23,5,385), Code(19,5,25), Code(27,5,6145), Code(17,5,7), Code(25,5,1537), Code(21,5,97), Code(29,5,24577),
Code(16,5,4), Code(24,5,769), Code(20,5,49), Code(28,5,12289), Code(18,5,13), Code(26,5,3073), Code(22,5,193), Code(64,5,0)
]
let lbase: Array<UInt16> = [
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
]
let lext: Array<UInt16> = [
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 196
]
let dbase: Array<UInt16> = [
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0
]
let dext: Array<UInt16> = [
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64
]
public class Inflate <: Stream {
/* Current Decompression Status */
private var mode: UInt32 = HEAD
/* Last compressed block flag */
private var last: Bool = false
/* Data wrapper type: ZLIB, GZIP, or DEFLATE (without wrapper) */
private var wrap: Int64 = ZLIB
/* Whether a dictionary is required */
private var havedict: Bool = false
private var flags: Int32 = -1
private var dmax: UInt32 = 32768
private var check: UInt32 = 0
/* Check the verification value */
private var total: Int64 = 0
private var head: ?GZIPHeader = None
private var wbits: Int32 = 0
private var wsize: UInt32 = 0
private var whave: UInt32 = 0
private var wnext: UInt32 = 0
private var window: Array<UInt8> = NULL_ARR_UINT8
private var hold: UInt32 = 0
private var bits: UInt32 = 0
private var length: UInt32 = 0
private var offset: UInt32 = 0
private var extra: UInt32 = 0
private var lencodes: Array<Code> = NULL_ARR_Code
private var distcodes: Array<Code> = NULL_ARR_Code
private var lendyn: Array<Code> = NULL_ARR_Code
private var distdyn: Array<Code> = NULL_ARR_Code
private var lenbits: UInt32 = 0
private var distbits: UInt32 = 0
private var ncode: UInt32 = 0
private var nlen: UInt32 = 0
private var ndist: UInt32 = 0
private var have: UInt32 = 0
private var codelens: Array<UInt16> = NULL_ARR_UINT16
private var work: Array<UInt16> = NULL_ARR_UINT16
private var back: Int32 = -1
private var was: UInt32 = 0
private var hbuf: Array<UInt8> = Array<UInt8>(4, repeat: 0)
private var finished = false
var initout: Int64 = 0
public init (wrap: Int64) {
this(15, wrap)
}
@Frozen
public init (wbits: Int64, wrap: Int64) {
var nowrap = false
var w = wbits
if (wrap <= 0) {
nowrap = true
} else if (wrap == 1) {
} else if (wrap == 2) {
w = w + 16
} else {
nowrap = true
}
if (nowrap) {
this.inflateInit2(-Int32(w))
} else {
this.inflateInit2(Int32(w))
}
}
@Frozen
public init() {
}
@Frozen
public func end(): Unit {
finished = true;
this
}
@Frozen
public func inflateInit(): Int32 {
return inflateInit2(Int32(DEF_WINDOW_BITS))
}
@Frozen
public func inflateInit2(wbits: Int32): Int32 {
return inflateReset2(wbits)
}
@Frozen
func inflateReset2(wbits: Int32): Int32 {
var windowBits = wbits
var wraps = 0
if (windowBits < 0) {
if (windowBits < -15) {
return Z_STREAM_ERROR
}
wraps = 0;
windowBits = -windowBits
} else {
wraps = Int64((windowBits >> 4) + 5)
if (windowBits < 48) {
windowBits &= 15
}
}
if (windowBits != 0 && (windowBits < 8 || windowBits > 15)) {
return Z_STREAM_ERROR
}
this.wbits = windowBits
this.wrap = wraps
inflateReset()
try {
window = Array<UInt8>(Int64(wsize), repeat: 0)
lendyn = Array<Code>(Int64(ENOUGH_LENS), {_ => Code(0,0,0)})
distdyn = Array<Code>(Int64(ENOUGH_DISTS), {_ => Code(0,0,0)})
codelens = Array<UInt16>(320, repeat: 0)
work = Array<UInt16>(288, repeat: 0)
} catch (e: Exception) {
message = erroMsg(Z_MEM_ERROR)
return Z_MEM_ERROR
}
return Z_OK
}
@Frozen
func CRC2(check: UInt32, word: UInt32): UInt32 {
this.hbuf[0] = UInt8(word & 0xFF)
this.hbuf[1] = UInt8(((word) >> 8) & 0xFF)
return crc32(check, this.hbuf, 0, 2)
}
@Frozen
func CRC4(check: UInt32, word: UInt32): UInt32 {
this.hbuf[0] = UInt8(word & 0xFF)
this.hbuf[1] = UInt8(((word) >> 8) & 0xFF)
this.hbuf[2] = UInt8(((word) >> 16) & 0xFF)
this.hbuf[3] = UInt8(((word) >> 24) & 0xFF)
return crc32(check, this.hbuf, 0, 4)
}
/**
* Decompressing Data.
*
* @param flush Decompressing Data.
* @return UInt32 Returns a value of the UInt32 type.
*
* @since 0.24.2
*/
@Frozen
public func inflate(flush: Int32): Int32 {
message = ""
if (mode == TYPE) {
mode = TYPEDO
}
var ret: Int32 = Z_OK
var len: UInt32 = 0
var copy: Int64 = 0
var copyfrom: Int64 = 0
var copybuf: Array<UInt8> = NULL_ARR_UINT8
var here: Code = Code(0,0,0)
var link: Code = Code(0,0,0)
var buf: Array<UInt8>
var error: Bool
if (mode != CHECK) {
initout = avail_out
}
var initin: Int64 = avail_in
while (true) {
if(mode == HEAD) {
/* Format of the parsing header: zlib gzip deflate */
if (wrap == DEFLATE) {
mode = TYPEDO
continue
}
if (needBits(16)) {
return Z_BUF_ERROR
}
if ((wrap & 2) != 0 && hold == 0x8B1F) {
if (wbits == 0) {
wbits = 15
}
check = DEFAULT_CRC32
buf = [UInt8(hold & 0xFF), UInt8((hold >> 8) & 0xFF)]
check = CRC2(this.check, hold)
initBits()
mode = FLAGS
continue
}
if (let Some(v) <- head) {
v.done = -1
}
if ((wrap & 1) != 0) {
if ((((getBits(8) << 8) + (hold >> 8)) % 31) != 0) {
message = "incorrect header check"
mode = BAD
continue
}
if (getBits(4) != METHOD_DEFLATE) {
message = "unknown compression method"
mode = BAD
continue
}
}
dropBits(4)
len = getBits(4) + 8
if (wbits == 0) {
wbits = Int32(len)
}
if (len > 15 || Int32(len) > wbits) {
message = "invalid window size"
mode = BAD
continue
}
dmax = 1 << len
flags = 0 /* indicate zlib header */
check = DEFAULT_ADLER32
adler = check
mode = if ((hold & 0x200) != 0) {
DICTID
} else {
TYPE
}
initBits()
}
// #ifdef GUNZIP
if (mode == FLAGS) {
if (needBits(16)) {
return Z_BUF_ERROR
}
flags = Int32(hold)
if (UInt32(flags & 0xFF) != METHOD_DEFLATE) {
message = "unknown compression method"
mode = BAD
continue
}
if ((flags & 0xE000) != 0) {
message = "unknown header flags set"
mode = BAD
continue
}
if (let Some(v) <- head) {
v.text = Int32((hold >> 8) & 1)
}
if ((flags & 0x0200) != 0 && (this.wrap & 4) != 0) {
buf = [UInt8(hold & 0xFF), UInt8((hold >> 8) & 0xFF)]
check = CRC2(this.check, hold)
}
initBits()
mode = TIME
}
if (mode == TIME) {
if (needBits(32)) {
return Z_BUF_ERROR
}
if (let Some(v) <- head) {
v.time = Int64(hold)
}
if ((this.wrap & 4) != 0 && (flags & 0x0200) != 0) {
buf = [UInt8(hold & 0xFF), UInt8((hold >> 8) & 0xFF), UInt8((hold >> 16) & 0xFF), UInt8((hold >> 24) & 0xFF)]
check = CRC4(this.check, hold)
}
initBits()
mode = OS
}
if (mode == OS) {
if (needBits(16)) {
return Z_BUF_ERROR
}
if (let Some(v) <- head) {
v.xflags = Int32(hold & 0xFF)
v.os = Int32(hold >> 8)
}
if ((this.wrap & 4) != 0 && (flags & 0x0200) != 0) {
buf = [UInt8(hold & 0xFF), UInt8((hold >> 8) & 0xFF)]
check = CRC2(this.check, hold)
}
initBits()
mode = EXLEN
}
if (mode == EXLEN) {
if ((flags & 0x0400) != 0) {
if (needBits(16)) {
return Z_BUF_ERROR
}
length = hold
if (let Some(v) <- head) {
v.extra_len = hold
}
if ((this.wrap & 4) != 0 && (flags & 0x0200) != 0) {
buf = [UInt8(hold & 0xFF), UInt8((hold >> 8) & 0xFF)]
check = CRC2(this.check, hold)
}
initBits()
} else {
if (let Some(v) <- head) {
v.extra = NULL_ARR_UINT8
}
}
mode = EXTRA
}
if (mode == EXTRA) {
if ((flags & 0x0400) != 0) {
copy = Int64(length)
if (copy > avail_in) {
copy = avail_in
}
if (copy != 0) {
if (let Some(v) <- head) {
if (let Some(w) <- v.extra) {
let len = (v.extra_len) - (length)
if (len < v.extra_max) {
for (i in 0..copy) {
w[Int64(len) + i] = next_in[pos_in]
pos_in++
}
}
}
}
if ((this.wrap & 4) != 0 && (flags & 0x0200) != 0) {
check = crc32(check, next_in, pos_in - copy, copy)
}
avail_in -= copy
length -= UInt32(copy)
}
if (length != 0) {
break
}
}
length = 0
mode = NAME
}
if (mode == NAME) {
if ((flags & 0x0800) != 0) {
if (avail_in == 0) {
break // TODO
}
copy = 0
do {
len = UInt32(next_in[pos_in + copy])
copy++
if (let Some(v) <- head) {
if (let Some(w) <- v.name) {
w[Int64(this.length)] = UInt8(len & 0xFF)
this.length++
}
}
} while (len != 0 && copy < Int64(have))
if ((this.wrap & 4) != 0 && (flags & 0x0200) != 0) {
check = crc32(check, next_in, pos_in, copy)
}
avail_in -= copy
pos_in += copy
if (len != 0) {
break// TODO goto inf_leave
}
} else {
if (let Some(v) <- head) {
v.name = NULL_ARR_UINT8
}
}
length = 0
mode = COMMENT
}
if (mode == COMMENT) {
if ((flags & 0x1000) != 0) {
if (avail_in == 0) {
break // TODO
}
copy = 0
do {
len = UInt32(next_in[pos_in + copy])
copy++
if (let Some(v) <- head) {
if (let Some(w) <- v.comment) {
if (this.length < v.comm_max) {
w[Int64(this.length)] = UInt8(len & 0xFF)
this.length++
}
}
}
} while(len != 0 && copy < Int64(have))
if ((this.wrap & 4) != 0 && (flags & 0x0200) != 0) {
check = crc32(check, next_in, pos_in, copy)
}
avail_in -= copy
pos_in += copy
if (len != 0) {
break// TODO goto inf_leave
}
} else {
if (let Some(v) <- head) {
v.comment = NULL_ARR_UINT8
}
}
length = 0
mode = HCRC
}
if (mode == HCRC) {
if ((flags & 0x0200) != 0) {
if ( needBits(16)){
return Z_BUF_ERROR
}
if ((this.wrap & 4) != 0 && hold != (check & 0xFFFF)) {
message = "header crc mismatch"
mode = BAD
continue
}
initBits()
}
if (let Some(v) <- head) {
v.hcrc = (flags >> 9) & 1
v.done = 1
}
check = DEFAULT_CRC32
adler = check
mode = TYPE
}
// #ifdef GUNZIP end
if (mode == DICTID) {
/* Obtains the dictionary verification value. */
if (needBits(32)) {
break
}
check = ((hold >> 24) & 0xFF) + ((hold >> 8) & 0xFF00) + ((hold & 0xFF00) << 8) + ((hold & 0xFF) << 24)
adler = check
initBits()
mode = DICT
}
if (mode == DICT) {
/* Determines whether to set the dictionary. If the dictionary is not set, Z_NEED_DICT is returned. */
if (!havedict) {
return Z_NEED_DICT
}
check = DEFAULT_ADLER32
adler = check
mode = TYPE
}
if (mode == TYPE) {
if (flush == Z_BLOCK || flush == Z_TREES) {
break
}
mode = TYPEDO
}
if (mode == TYPEDO) {
/* Identify the compressed block type: direct storage, static huffman compression, and dynamic huffman compression. */
if (last) {
byteBits()
mode = CHECK
} else {
if (needBits(3)) {
break
}
last = if (getBits(1) != 0) { true } else { false }
dropBits(1)
match (getBits(2)) {
case 0 =>
mode = STORED
case 1 =>
mode = LEN_
lencodes = lenfix
lenbits = 9
distcodes = distfix
distbits = 5
if (flush == Z_TREES) {
dropBits(2)
break
}
case 2 =>
lencodes = lendyn
distcodes = distdyn
mode = TABLE
case _ =>
message = "invalid block type"
mode = BAD
}
dropBits(2)
}
}
if (mode == STORED) {
/* Decompress the compressed block in the storage format: Obtain the data length and check the correctness. */
byteBits()
if (needBits(32)) {
break
}
if ((hold & 0xFFFF) != ((hold >> 16) ^ 0xFFFF)) {
message = "invalid stored block lengths"
mode = BAD
continue
}
length = hold & 0xFFFF
initBits()
mode = COPY_
if (flush == Z_TREES) {
break // TODO goto inf_leave
}
this.mode = COPY_
}
if (mode == COPY_) {
mode = COPY
}
if (mode == COPY) {
/* Decompress Storage Format Compressed Blocks: Copying Data */
copy = Int64(length)
if (copy > 0) {
if (copy > avail_in) { copy = avail_in }
if (copy > avail_out) { copy = avail_out }
if (copy == 0) {
break // TODO goto inf_leave
}
for (i in 0..copy) {
next_out[pos_out] = next_in[pos_in]
pos_out++
pos_in++
}
avail_in -= copy
avail_out -= copy
length -= UInt32(copy)
continue
}
mode = TYPE
continue
}
if (mode == TABLE) {
/*
* Decompress the dynamic huffman tree:
* parse the code length sequence length corresponding to the three trees.
*/
if (needBits(14)) {
break
}
nlen = getBits(5) + 257
dropBits(5)
ndist = getBits(5) + 1
dropBits(5)
ncode = getBits(4) + 4
dropBits(4)
if (nlen > 286 || ndist > 30) {
message = "too many length or distance symbols"
mode = BAD
} else {
have = 0
mode = LENLENS
}
}
if (mode == LENLENS) {
/*
* Decompress the dynamic huffman tree:
* Obtain the code length sequence of the cl tree and construct the decompressed code table.
*/
var isbreak = false
while (have < ncode) {
if (needBits(3)) {
isbreak = true
break
}
codelens[bl_order[Int64(have)]] = UInt16(getBits(3))
have++
dropBits(3)
}
if (isbreak) {
break
}
while (have < 19) {
codelens[bl_order[Int64(have)]] = 0
have++
}
lenbits = 7
error = inflateTable(TYPE_CODES, lenbits, 19, codelens, lencodes)
if (error) {
message = "invalid code lengths set"
mode = BAD
} else {
have = 0
mode = CODELENS
}
}
if (mode == CODELENS) {
/*
* Decompress the dynamic huffman tree:
* Decompress the code length sequence of the literal/length and
* distance trees to construct the literal/length and distance decompression code table.
*/
var isbreak = false
while (have < nlen + ndist) {
while (true) {
here = lencodes[Int64(getBits(lenbits))]
if (UInt32(here.bits) <= bits) {
break
}
if (pullByte()) { // TODO BUG SEE
isbreak = true
break
}
}
if (isbreak) {
break
}
if (here.value < 16) {
dropBits(UInt32(here.bits))
codelens[Int64(have)] = here.value
have++
} else {
if (here.value == 16) {
if (needBits(UInt32(here.bits) + 2)) {
isbreak = true
break
}
dropBits(UInt32(here.bits))
if (have == 0) {
message = "invalid bit length repeat"
mode = BAD
continue
}
len = UInt32(codelens[Int64(have) - 1])
copy = 3 + Int64(getBits(2))
dropBits(2)
} else if (here.value == 17) {
if (needBits(UInt32(here.bits) + 3)) {
isbreak = true
break
}
dropBits(UInt32(here.bits))
len = 0
copy = 3 + Int64(getBits(3))
dropBits(3)
} else {
if (needBits(UInt32(here.bits) + 7)) {
isbreak = true
break
}
dropBits(UInt32(here.bits))
len = 0
copy = 11 + Int64(getBits(7))
dropBits(7)
}
if (have + UInt32(copy) > nlen + ndist) {
message = "invalid bit length repeat"
mode = BAD
continue
} else {
while (copy > 0) {
codelens[Int64(have)] = UInt16(len)
have++
copy--
}
}
}
}
if (isbreak) {
break
}
if (mode == BAD) { continue }
if (codelens[256] == 0) {
message = "invalid code -- missing end-of-block"
mode = BAD
continue
}
lenbits = 9
error = inflateTable(TYPE_LENS, lenbits, nlen, codelens, lencodes)
if (error) {
message = "invalid literal/lengths set"
mode = BAD
continue
}
distbits = 6
error = inflateTable(TYPE_DISTS, distbits, ndist, codelens, distcodes)
if (error) {
message = "invalid distances set"
mode = BAD
continue
} else {
mode = LEN_
if (flush == Z_TREES) {
break
}
}
}
if (mode == LEN_) {
mode = LEN
}
if (mode == LEN) {
/* Decompress compressed blocks: Decompress length or original characters. */
if (avail_in >= 6 && avail_out >= 258) {
inflateFast()
if (mode == TYPE) {
back = -1
}
continue
}
back = 0
var isbreak = false
while (true) {
here = lencodes[Int64(getBits(lenbits))] // 定位到这里hold的值不对了, 28 正确为15
if (UInt32(here.bits) <= bits) {
break
}
if (pullByte()) {
isbreak = true
break
}
}
if (isbreak) {
break
}
if (here.option != 0 && (here.option & 0xF0) == 0) {
/* here is the link node of the level-2 table. */
link = here
while (true) {
here = lencodes[Int64(link.value) + Int64(getBits(UInt32(link.bits + link.option)) >> UInt32(link.bits))]
if (UInt32(link.bits + here.bits) <= bits) {
break
}
if (pullByte()) {
isbreak = true
break
}
}
if (isbreak) {
break
}
dropBits(UInt32(link.bits))
back += Int32(link.bits)
}
dropBits(UInt32(here.bits))
back += Int32(here.bits)
length = UInt32(here.value)
if (here.option == 0) {
/* here is the original character. */
mode = LIT
} else if ((here.option & 32) != 0) {
/* here is a block terminator */
back = -1
mode = TYPE
} else if ((here.option & 64) != 0) {
/* here Invalid. */
message = "invalid literal/length code"
mode = BAD
} else {
/* here is length */
extra = UInt32(here.option & 0x0F)
mode = LENEXT
}
}
if (mode == LENEXT) {
/* Decompress the compressed block: Decompress the extension bit of the length. */
if (extra != 0) {
if (needBits(extra)) {
break
}
length += getBits(extra)
dropBits(extra)
back += Int32(extra)
}
was = length
mode = DIST
}
if (mode == DIST) {
/* Decompressing a compressed block: decompressing distance. */
var isbreak = false
while (true) {
here = distcodes[Int64(getBits(distbits))]
if (UInt32(here.bits) <= bits) {
break
}
if (pullByte()) {
isbreak = true
break
}
}
if (isbreak) {
break
}
if ((here.option & 0xF0) == 0) {
/* here is the link node of the level-2 table. */
link = here
while (true) {
here = distcodes[Int64(link.value) + Int64(getBits(UInt32(link.bits + link.option)) >> UInt32(link.bits))]
if (UInt32(link.bits + here.bits) < bits) {
break
}
if (pullByte()) {
isbreak = true
break
}
}
if (isbreak) {
break
}
dropBits(UInt32(link.bits))
back += Int32(link.bits)
}
dropBits(UInt32(here.bits))
back += Int32(here.bits)
if ((here.option & 64) != 0) {
/* here Invalid */
message = "invalid distance code"
mode = BAD
} else {
/* here is distance */
offset = UInt32(here.value)
extra = UInt32(here.option & 0x0F)
mode = DISTEXT
}
}
if (mode == DISTEXT) {
/* Decompress the compressed block: decompress the extended bit of the distance. */
if (extra != 0) {
if (needBits(extra)) {
break
}
offset += getBits(extra)
dropBits(extra)
back += Int32(extra)
}
if (offset > dmax) {
message = "invalid distance too far back1"
mode = BAD
} else {
mode = MATCH
}
}
if (mode == MATCH) {
/* Decompress compressed blocks: Copy matching data. */
if (avail_out == 0) {
break
}
copy = pos_out
/* The matching start position is in the window. */
if (Int64(offset) > copy) {
copy = Int64(offset) - copy
/* Remaining distance > Data size in the window, Error reporting. */
if (copy > Int64(whave)) {
message = "invalid distance too far back2"
mode = BAD
continue
} else if (copy > Int64(wnext)) {
/* The matching start position is in the [wnext, wsize) range. */
copy -= Int64(wnext)
copyfrom = Int64(wsize) - copy
} else {
/* The matching start position is in the range [0, wnext). */
copyfrom = Int64(wnext) - copy
}
if (copy > Int64(length)) {
copy = Int64(length)
}
copybuf = window
} else {
/* The match start position is in the output buffer and is copied directly. */
copyfrom = copy - Int64(offset)
copy = Int64(length)
copybuf = next_out
}
if (copy > avail_out) {
/* The output buffer is insufficient. Copy part of the buffer first. */
copy = avail_out
}
avail_out -= copy
length -= UInt32(copy)
for (i in copyfrom..copyfrom + copy) {
next_out[pos_out] = copybuf[i]
pos_out++
}
if (length == 0) {
mode = LEN
}
}
if (mode == LIT) {
/* Decompress compressed blocks: Copy original characters. */
if (avail_out == 0) {
break
}
next_out[pos_out] = UInt8(length & 0xFF)
avail_out--
pos_out++
mode = LEN
}
if (mode == CHECK) {
/* Check the verification value. */
if (this.wrap != DEFLATE) {
if (needBits(32)){
return Z_BUF_ERROR
}
var newdatalen: Int64 = initout - avail_out
initout = avail_out
total_out += newdatalen
total += newdatalen
if ((this.wrap & 4) != 0 && newdatalen > 0) {
if (flags != 0) {
check = crc32(check, next_out, pos_out - Int64(newdatalen), newdatalen)
} else {
check = adler32(check, next_out, pos_out - Int64(newdatalen), newdatalen)
}
adler = check
}
if ((this.wrap & 4) != 0) {
var realcheck: UInt32 = hold
if (flags == 0) {
realcheck = ((hold >> 24) & 0xFF) + ((hold >> 8) & 0xFF00) + ((hold & 0xFF00) << 8) + ((hold & 0xFF) << 24)
}
if (realcheck != check) {
message = "incorrect data check"
mode = BAD
continue
}
}
initBits()
}
if (this.wbits == 31) {
mode = LENGTH
} else{
mode = DONE
}
}
if (mode == LENGTH) {
/* Check Length */
if (flags != 0 && this.wrap != DEFLATE) {
if (needBits(32)) {
return Z_BUF_ERROR
}
if ((this.wrap & 4) != 0 && hold != UInt32(total & 0xFFFFFFFF)) {
message = "incorrect length check"
mode = BAD
continue
}
initBits()
}
mode = DONE
}
if (mode == DONE) {
message = "inflate completed"
ret = Z_STREAM_END
break // TODO inf_leave
}
if (mode == BAD) {
ret = Z_DATA_ERROR
break // TODO inf_leave
}
if (mode == MEM) { return Z_MEM_ERROR}
if (mode >= SYNC || mode < HEAD) {
return Z_STREAM_ERROR
}
}
if (this.wsize != 0 || initout != this.avail_out && mode < BAD && (mode < CHECK || flush != Z_FINISH)) {
updateWindow(next_out, pos_out, initout - this.avail_out)
}
initin -= avail_in
initout -= avail_out
total_in += initin
total_out += initout
total += initout
var outputstart: Int64 = pos_out - initout
if ((this.wrap & 4) != 0 && initout > 0) {
if (flags != 0) {
check = crc32(check, next_out, outputstart, initout)
} else {
check = adler32(check, next_out, outputstart, initout)
}
adler = check
}
data_type = Int32(bits)
if (last) {
data_type += 64
}
if (mode == TYPE) {
data_type += 128
}
if (mode == LEN_ || mode == COPY_) {
data_type += 256
}
if (((initin == 0 && initout == 0) || flush == Z_FINISH) && ret == Z_OK) {
ret = Z_BUF_ERROR
}
return ret
}
/**
* This command is invoked after the decompression is complete to check the decompression status.
*
* @return UInt32 Returns a value of the UInt32 type.
*
* @since 0.24.2
*/
@Frozen
public func inflateEnd(): Int32 {
this.window = NULL_ARR_UINT8
this.head = None
this.lencodes = NULL_ARR_Code
this.distcodes = NULL_ARR_Code
this.lendyn = NULL_ARR_Code
this.distdyn = NULL_ARR_Code
this.codelens = NULL_ARR_UINT16
this.work = NULL_ARR_UINT16
this.hbuf = NULL_ARR_UINT8
return Z_OK
}
/**
* Sets the decompression dictionary.
* This command is invoked when the inflate function returns Z_NEED_DICT.
* If a dictionary is set during compression, the same dictionary must be set before decompression.
*
* @param dict Dictionary data
* @return UInt32 Returns a value of the UInt32 type.
*
* @since 0.24.2
*/
@Frozen
public func setDictionary(dict: Array<UInt8>): Int32 {
if (mode < HEAD || mode > SYNC) {
message = erroMsg(Z_STREAM_ERROR)
return Z_STREAM_ERROR
}
if (this.wrap != DEFLATE && mode != DICT) {
message = erroMsg(Z_STREAM_ERROR)
return Z_STREAM_ERROR
}
/* check for correct dictionary identifier */
if (mode == DICT) {
var dictid: UInt32 = DEFAULT_ADLER32
dictid = adler32(dictid, dict, 0, dict.size)
if (dictid != check) {
message = "dictionary data error"
return Z_DATA_ERROR
}
}
updateWindow(dict, dict.size, dict.size)
havedict = true
message = ""
return Z_OK
}
/**
* This method is used to obtain the header information of the gzip file after the gzip file is decompressed.
*
* @param gzhead Header information in gzip format
*
* @since 0.24.2
*/
@Frozen
public func getGzipHeader(): ?GZIPHeader {
if (mode < HEAD || mode > SYNC) {
return None
}
if ((this.wrap & 2) == 0) {
return None
} else {
this.head?.done = 0
return this.head
}
}
/**
* During decompression, invalid compressed data is skipped and decompressed from the next full refresh point.
*
* @return UInt32 Returns a value of the UInt32 type.
*
* @since 0.24.2
*/
@OverflowWrapping
@Frozen
public func inflateSync(): Int32 {
/* Checking Parameters */
if (mode < HEAD || mode > SYNC) {
message = erroMsg(Z_STREAM_ERROR)
return Z_STREAM_ERROR
}
if (avail_in == 0 && bits < 8) {
return Z_BUF_ERROR
}
var len: Int64
var buf: Array<UInt8> = Array<UInt8>(4, repeat: 0)
/* if first time, start search in bit buffer */
if (mode != SYNC) {
mode = SYNC
hold <<= bits & 7
bits -= bits & 7
len = 0
while (bits >= 8) {
buf[len] = UInt8(hold)
len++
hold >>= 8
bits -= 8
}
have = 0
syncSearch(have, buf, len)
}
/* search available input */
len = syncSearch(have, next_in, avail_in)
avail_in -= len
pos_in += len
total_in += len
/* return no joy or set up to restart inflate() on a new block */
if (have != 4) {
return Z_DATA_ERROR
}
var t_in: Int64 = total_in
var t_out: Int64 = total_out
inflateReset()
total_in = t_in
total_out = t_out
mode = TYPE
return Z_OK
}
@Frozen
private func initBits(): Unit {
hold = 0
bits = 0
}
@Frozen
private func pullByte(): Bool {
if (avail_in == 0) {
return true
}
avail_in--
hold += UInt32(next_in[pos_in]) << bits
pos_in++
bits += 8
return false
}
@Frozen
private func needBits(n: UInt32): Bool {
while (bits < n) {
if (pullByte()) {
return true
}
}
return false
}
@Frozen
private func getBits(n: UInt32): UInt32 {
return hold & ((1 << n) - 1)
}
@Frozen
private func dropBits(n: UInt32): Unit {
hold >>= n
bits -= n
}
@Frozen
private func byteBits(): Unit {
hold >>= bits & 7
bits -= bits & 7
}
@Frozen
private func inflateTable(tabletype: UInt32, midcodelen: UInt32, symnums: UInt32, lens: Array<UInt16>, codetable: Array<Code>): Bool {
var here: Code = Code(0,0,0)
var left: Int32
var max: UInt32
var min: UInt32
var root: UInt32
var lstart: Int64 = 0
if (tabletype == TYPE_DISTS) {
lstart = Int64(nlen)
}
/* Counts the number of occurrences of each code length, which is stored in the count array. */
var count: Array<UInt16> = Array<UInt16>(MAXBITS + 1, repeat: 0)
for (i in lstart..lstart + Int64(symnums)) {
count[Int64(lens[i])]++
}
/* The maximum code length whose frequency is greater than 0 is found. */
max = UInt32(MAXBITS)
while (max > 0) {
if (count[Int64(max)] != 0) { break }
max--
}
if (max == 0) {
here = Code(64, 1, 0)
codetable[0] = here
if (tabletype == TYPE_DISTS) {
distbits = 1
} else {
lenbits = 1
}
return false
}
root = midcodelen
if (root > max) {
root = max
}
/* Find the minimum code length whose frequency is greater than 0. */
min = 1
while (min < max) {
if (count[Int64(min)] != 0) { break }
min++
}
if (root < min) {
root = min
}
/* Check the validity of the code length sequence. */
left = 1
for (i in 1..=MAXBITS) {
left <<= 1
left -= Int32(count[i])
if (left < 0) {
return true
}
}
if (left > 0 && (tabletype == TYPE_CODES || max != 1)) {
return true
}
/* Calculates the minimum code value corresponding to each code length and saves the value in the offs array. */
var offs = Array<UInt16>(MAXBITS + 1, repeat: 0)
for (i in 1..MAXBITS) {
offs[i + 1] = offs[i] + count[i]
}
/* Sorted by code length and symbol order and saved in the work array. */
for (i in lstart..lstart + Int64(symnums)) {
if (lens[i] != 0) {
work[Int64(offs[Int64(lens[i])])] = UInt16(i - lstart)
offs[Int64(lens[i])]++
}
}
var matchsym: UInt16
var base: Array<UInt16>
var extra: Array<UInt16>
match {
case tabletype == TYPE_CODES =>
base = NULL_ARR_UINT16
extra = NULL_ARR_UINT16
matchsym = 20
case tabletype == TYPE_LENS =>
base = lbase
extra = lext
matchsym = 257
case tabletype == TYPE_DISTS =>
base = dbase
extra = dext
matchsym = 0
case _ => return true
}
var used: UInt32 = 1 << root
if (tabletype == TYPE_LENS && used > ENOUGH_LENS ||
tabletype == TYPE_DISTS && used > ENOUGH_DISTS) {
return true
}
/* Work array subscript */
var sym: Int64 = 0
/* Code length */
var len: UInt32 = min
/* Start Code */
var huff: UInt32 = 0
/*
* When a level-1 table is created, the value is 0.
* When a level-2 table is created, the value is the maximum code length (threshold code length) of the level-1 table.
*/
var drop: UInt32 = 0
/*
* Maximum code length of the current table
* For the level-1 table, the code length threshold is midcodelen.
* For the level-2 table, the code length threshold is the maximum code length of the previous table minus the threshold midcodelen.
*/
var curr: UInt32 = root
/* Increment between multiple virtual code values when the real code value is extended to the maximum code length in the current table */
var incr: UInt32
/* Current Table Size */
var fill: UInt32
/* Location */
var pos: Int64
/* Start subscript of the current table (all tables are stored in the same array) */
var start: Int64 = 0
var mask: UInt32 = used - 1
var low: UInt32 = 0xFFFFFFFF
while (true) {
here.bits = UInt8((len - drop) & 0xFF)
/* Symbols of Code Length Trees or literal */
if (work[sym] + 1 < matchsym) {
here.option = 0
here.value = work[sym]
} else if (work[sym] >= matchsym) {
/* length or distance (Reference value + number of extended bit) */
pos = Int64(work[sym] - matchsym)
here.option = UInt8(extra[pos] & 0xFF)
here.value = base[pos]
} else {
/* Block end symbol */
here.option = 32 + 64
here.value = 0
}
/*
* When the code value is in the positive order, the increment is 1.
* However, the Huffman encoding saves the value in the reverse order.
* Therefore, the increment is 1 << len.
* In the level-2 table, the maximum code length of the level-1 table needs to be subtracted from the value drop.
*/
incr = 1 << (len - drop)
/* Size of the current code table */
fill = 1 << curr
/* Saves the size of the current code table, which will be used when calculating the start position of the next code table. */
min = fill
/* Save the encoding information to the code table (the subscript is the extended virtual code value). */
pos = start + Int64(huff >> drop)
do {
fill -= incr
codetable[pos + Int64(fill)] = here
} while (fill != 0)
/*
* Calculate the code value of the next character: In positive order, the code value of the current character plus 1 (huff + 1).
* However, the reverse order value is used here.
* The calculation logic is as follows: Find the first bit that is 0 from the most significant bit,
* set this bit to 1, and set the preceding bits (high bits) to 0.
* The search starts from the most significant bit.
* Therefore, you can set the most significant bit to 1 and set the other bits to 0.
* Then, you can determine whether the most significant bit is 0.
*/
incr = 1 << (len - 1)
/* Determine whether a bit is 0. */
while ((huff & incr) != 0) {
/* If the previous bit is 1, carry is generated. The next bit needs to be determined. */
incr >>= 1
}
if (incr != 0) {
/* High Position 0 (Because the most significant bits are all 1, add 1 and then carry it into 0.)
* The bit that does not carry is also set to 0.
*/
huff &= incr - 1
/* This position without carrying 1 */
huff += incr
} else {
huff = 0
}
sym++
/*
* Complete the construction of a character code table.
* The number of characters corresponding to the current code length decreases by one.
*/
count[Int64(len)]--
if (count[Int64(len)] == 0) {
/* End. Encoding information of all characters that appear has been saved to the code table. */
if (len == max) { break }
/* Obtains the code length of the next character. */
len = UInt32(lens[lstart + Int64(work[sym])])
}
/*
* When the code length exceeds the threshold code length,
* the level-2 code table is constructed and information about the level-2 code table is initialized.
*/
if (len > root && (huff & mask) != low) {
if (drop == 0) {
drop = root
}
/* Start subscript of the next table */
start += Int64(min)
/* Calculate the size of the level-2 table and save it in the left. */
curr = len - drop
left = Int32(1 << curr)
while (curr + drop < max) {
left -= Int32(count[Int64(curr + drop)])
/* left > 0 indicates that leaf nodes with longer code lengths are stored in the level-2 code table. */
if (left <= 0) { break }
curr++
left <<= 1
}
/* Check the size of the code table. */
used += 1 << curr
if ((tabletype == TYPE_LENS && used > ENOUGH_LENS) ||
(tabletype == TYPE_DISTS && used > ENOUGH_DISTS)) {
return true
}
/* The level-1 code table stores the information about the next level-2 code table. */
low = huff & mask
here.option = UInt8(curr & 0xFF)
here.bits = UInt8(root & 0xFF)
here.value = UInt16(start)
codetable[Int64(low)] = here
}
}
if (huff != 0) {
here.option = 64
here.bits = UInt8((len - drop) & 0xFF)
here.value = 0
codetable[Int64(huff)] = here
}
if (tabletype == TYPE_DISTS) {
distbits = root
} else {
lenbits = root
}
return false
}
@Frozen
private func inflateFast(): Unit {
var here: Code = Code(0, 0, 0)
var lmask: UInt32 = (1 << lenbits) - 1
var dmask: UInt32 = (1 << distbits) - 1
var len: UInt32 = 0
var dist: UInt32 = 0
var extra: UInt32 = 0
var stopError = 0
let last = this.avail_in - 5
let end = this.avail_out - 257
var copyfrom: UInt32 = 0
var copybuf: Array<UInt8> = NULL_ARR_UINT8
do {
if (bits < 15) {
try {
hold += UInt32(next_in[pos_in]) << bits
} catch (e: IndexOutOfBoundsException) {
throw e
}
pos_in++
avail_in--
bits += 8
hold += UInt32(next_in[pos_in]) << bits
pos_in++
avail_in--
bits += 8
}
here = lencodes[Int64(hold & lmask)]
hold >>= UInt32(here.bits)
bits -= UInt32(here.bits)
/* Link to the L2 code table of length */
if (here.option != 0 && (here.option & 0xF0) == 0) {
here = lencodes[Int64(here.value) + Int64(hold & ((1 << UInt32(here.option)) - 1))]
hold >>= UInt32(here.bits)
bits -= UInt32(here.bits)
}
/* Original character */
if (here.option == 0) {
next_out[pos_out] = UInt8(here.value & 0xFF)
pos_out++
avail_out--
} else if ((here.option & 16) != 0) {
/* length */
len = UInt32(here.value)
extra = UInt32(here.option & 0x0F)
if (extra != 0) {
if (bits < extra) {
hold += UInt32(next_in[pos_in]) << bits
pos_in++
avail_in--
bits += 8
}
len += hold & ((1 << extra) - 1)
hold >>= extra
bits -= extra
}
if (bits < 15) {
hold += UInt32(next_in[pos_in]) << bits
pos_in++
avail_in--
bits += 8
hold += UInt32(next_in[pos_in]) << bits
pos_in++
avail_in--
bits += 8
}
/* distances */
here = distcodes[Int64(hold & dmask)]
hold >>= UInt32(here.bits)
bits -= UInt32(here.bits)
if ((here.option & 0xF0) == 0) {
here = distcodes[Int64(here.value) + Int64(hold & ((1 << UInt32(here.option)) - 1))]
hold >>= UInt32(here.bits)
bits -= UInt32(here.bits)
}
if ((here.option & 16) != 0) {
dist = UInt32(here.value)
extra = UInt32(here.option & 0x0F)
if (bits < extra) {
hold += UInt32(next_in[pos_in]) << bits
pos_in++
avail_in--
bits += 8
if (bits < extra) {
hold += UInt32(next_in[pos_in]) << bits
pos_in++
avail_in--
bits += 8
}
}
dist += hold & ((1 << extra) - 1)
if (dist > dmax) {
message = "invalid distance too far back3"
mode = BAD
break
}
hold >>= extra
bits -= extra
/*
* Copy the matching data from the front (output buffer or loop array window).
* 1.Match start position exceeds output buffer
*/
if (dist > UInt32(pos_out)) {
extra = dist - UInt32(pos_out)
/* The match start position exceeds the window. */
if (extra > whave) { //TODO whave 1042 实际是2057
message = "invalid distance too far back4"
mode = BAD
break
}
/*
* 1.1 Copy the data in the window.
* wnext = 0: The data in the window is an entire segment and is directly copied.
*/
if (wnext == 0) {
/* Matching start position */
copyfrom = wsize - extra
if (len > extra) {
len -= extra
} else {
extra = len
len = 0
}
for (i in Int64(copyfrom)..Int64(copyfrom + extra)) {
next_out[pos_out] = window[i]
pos_out++
avail_out--
}
} else if (wnext < extra) {
/*
* If wnext is greater than 0 and the matching start position is after wnext,
* copy the data at the end of the window first.
*/
copyfrom = wsize + wnext - extra
extra -= wnext
if (extra < len) {
len -= extra
} else {
extra = len
len = 0
}
for (i in Int64(copyfrom)..Int64(copyfrom + extra)) {
next_out[pos_out] = window[i]
pos_out++
avail_out--
}
/* Copy the data at the beginning of the window. */
if (len > 0) {
copyfrom = 0
if (len > wnext) {
extra = wnext
len -= wnext
} else {
extra = len
len = 0
}
for (i in Int64(copyfrom)..Int64(copyfrom + extra)) {
next_out[pos_out] = window[i]
pos_out++
avail_out--
}
}
} else {
/* The matching start position is in front of wnext and is copied directly. */
copyfrom = wnext - extra
if (extra < len) {
len -= extra
} else {
extra = len
len = 0
}
for (i in Int64(copyfrom)..Int64(copyfrom + extra)) {
next_out[pos_out] = window[i]
pos_out++
avail_out--
}
}
/* 1.2 Copy the data on next_out. */
if (len > 0) {
copyfrom = 0
for (i in Int64(copyfrom)..Int64(copyfrom + len)) {
next_out[pos_out] = next_out[i]
pos_out++
avail_out--
}
}
/* 2. The matching start position is in the output buffer and is copied directly. */
} else {
copyfrom = UInt32(pos_out) - dist
for (i in Int64(copyfrom)..Int64(copyfrom + len)) {
next_out[pos_out] = next_out[i]
pos_out++
avail_out--
}
stopError = 0
}
} else {
message = "invalid distance code"
mode = BAD
break
}
} else if ((here.option & 32) != 0) {
mode = TYPE
break
} else {
message = "invalid literal/length code"
mode = BAD
break
}
} while (pos_out < end && pos_in < last)
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
len = bits >> 3
this.pos_in -= Int64(len)
this.avail_in += Int64(len)
this.bits -= len << 3
this.hold &= (1 << this.bits) - 1
}
@Frozen
@OverflowWrapping
private func updateWindow(buf: Array<UInt8>, start: Int64, length: Int64): Unit {
/* 1. If the amount of data to be updated is greater than wsize, copy the data at the end of wsize to the cyclic array window. */
if (this.window.size == 0) {
this.window = Array<Byte>(1 << this.wbits, repeat: 0)
}
if (this.wsize == 0) {
this.wsize = 1 << this.wbits
this.wnext = 0
this.whave = 0
}
if (length >= Int64(wsize)) {
let pos: Int64 = start - Int64(wsize) // TODO
for (i in 0..Int64(wsize)) {
window[i] = buf[pos + i]
}
wnext = 0
whave = wsize
} else {/* 2. The amount of data to be updated is less than wsize. */
/* 2.1 Copy data to the [wnext, wsize) range. */
var dist: UInt32 = wsize - wnext
if (Int64(dist) > length) {
dist = UInt32(length)
}
var pos: Int64 = start - length
for (i in Int64(wnext)..Int64(wnext + dist)) {
window[i] = buf[pos]
pos++
}
/* 2.2 The [wnext, wsize) range is insufficient. The remaining data is copied to [0,copy). */
var copy: Int64 = length - Int64(dist)
if (copy > 0) {
pos = start - copy
for (i in 0..copy) {
window[i] = buf[pos]
pos++
}
wnext = UInt32(copy)
whave = wsize
} else {/* 2.3 [wnext, wsize] is sufficient. You only need to update wnext and whave. */
wnext += dist
if (wnext == wsize) {
wnext = 0
}
if (whave < wsize) {
whave += dist
}
}
}
}
@Frozen
private func syncSearch(have: UInt32, buf: Array<UInt8>, length: Int64): Int64 {
var got: UInt32
got = have
var next: Int64 = 0
while (next < length && got < 4) {
let res: UInt8 = if (got < 2) { 0 } else { 0xFF }
if (buf[next] == res) {
got++
} else if (buf[next] != 0) {
got = 0
} else {
got = 4 - got
}
next++
}
this.have = got
return next
}
@Frozen
private func inflateReset(): Int32 {
if (mode < HEAD || mode > SYNC) {
return Z_STREAM_ERROR
}
wsize = 0
whave = 0
wnext = 0
total_in = 0
total_out = 0
total = 0
mode = HEAD
message = ""
last = false
havedict = false
dmax = 32768
head = None
hold = 0
bits = 0
lencodes = NULL_ARR_Code
distcodes = NULL_ARR_Code
back = -1
return Z_OK
}
}