247 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import math
 | 
						|
 | 
						|
 | 
						|
class FlexBuffer():
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
 | 
						|
        self.blockSize = None
 | 
						|
        self.c = None
 | 
						|
        self.l = None
 | 
						|
        self.buf = None
 | 
						|
 | 
						|
    def require(self, n):
 | 
						|
        
 | 
						|
        r = self.c - self.l + n
 | 
						|
        if r > 0:
 | 
						|
            self.l = self.l + self.blockSize * math.ceil(r / self.blockSize)
 | 
						|
            #tmp = bytearray(self.l)
 | 
						|
            #for i in len(self.buf):
 | 
						|
            #    tmp[i] = self.buf[i]
 | 
						|
            #self.buf = tmp
 | 
						|
            self.buf = self.buf + bytearray(self.l - len(self.buf))
 | 
						|
        self.c = self.c + n
 | 
						|
        return self.buf
 | 
						|
 | 
						|
    def alloc(self, initSize, blockSize):
 | 
						|
        
 | 
						|
        if blockSize:
 | 
						|
            sz = blockSize
 | 
						|
        else:
 | 
						|
            sz = 4096
 | 
						|
        self.blockSize = self.roundUp(sz)
 | 
						|
        self.c = 0
 | 
						|
        self.l = self.roundUp(initSize) | 0
 | 
						|
        self.l += self.blockSize - (self.l % self.blockSize)
 | 
						|
        self.buf = bytearray(self.l)
 | 
						|
        return self.buf
 | 
						|
 | 
						|
    def roundUp(self, n):
 | 
						|
        
 | 
						|
        r = n % 4
 | 
						|
        if r == 0:
 | 
						|
            return n
 | 
						|
        else:
 | 
						|
            return n + 4 - r
 | 
						|
 | 
						|
    def reset(self):
 | 
						|
 | 
						|
        self.c = 0
 | 
						|
        self.l = len(self.buf)
 | 
						|
 | 
						|
    def pack(self, size):
 | 
						|
        
 | 
						|
        return self.buf[0:size]
 | 
						|
 | 
						|
def _decompress(inBuf, outBuf):
 | 
						|
 | 
						|
    c_top_loop = 1
 | 
						|
    c_first_literal_run = 2
 | 
						|
    c_match = 3
 | 
						|
    c_copy_match = 4
 | 
						|
    c_match_done = 5
 | 
						|
    c_match_next = 6
 | 
						|
 | 
						|
    out = outBuf.buf
 | 
						|
    op = 0
 | 
						|
    ip = 0
 | 
						|
    t = inBuf[ip]
 | 
						|
    state = c_top_loop
 | 
						|
    m_pos = 0
 | 
						|
    ip_end = len(inBuf)
 | 
						|
 | 
						|
    if t > 17:
 | 
						|
        ip = ip + 1
 | 
						|
        t = t - 17
 | 
						|
        if t < 4:
 | 
						|
            state = c_match_next
 | 
						|
        else:
 | 
						|
            out = outBuf.require(t)
 | 
						|
            while True:
 | 
						|
                out[op] = inBuf[ip]
 | 
						|
                op = op + 1
 | 
						|
                ip = ip + 1
 | 
						|
                t = t - 1
 | 
						|
                if not t > 0: break
 | 
						|
            state = c_first_literal_run
 | 
						|
 | 
						|
    while True:
 | 
						|
        if_block = False
 | 
						|
 | 
						|
        ##
 | 
						|
        if state == c_top_loop:
 | 
						|
            t = inBuf[ip]
 | 
						|
            ip = ip + 1
 | 
						|
            if t >= 16:
 | 
						|
                state = c_match
 | 
						|
                continue
 | 
						|
            if t == 0:
 | 
						|
                while inBuf[ip] == 0:
 | 
						|
                    t = t + 255
 | 
						|
                    ip = ip + 1
 | 
						|
                t = t + 15 + inBuf[ip]
 | 
						|
                ip = ip + 1
 | 
						|
 | 
						|
            t = t + 3
 | 
						|
            out = outBuf.require(t)
 | 
						|
            while True:
 | 
						|
                out[op] = inBuf[ip]
 | 
						|
                op = op + 1
 | 
						|
                ip = ip + 1
 | 
						|
                t = t - 1
 | 
						|
                if not t > 0: break
 | 
						|
            # emulate c switch
 | 
						|
            state = c_first_literal_run
 | 
						|
 | 
						|
        ##
 | 
						|
        if state == c_first_literal_run:
 | 
						|
            t = inBuf[ip]
 | 
						|
            ip = ip + 1
 | 
						|
            if t >= 16:
 | 
						|
                state = c_match
 | 
						|
                continue
 | 
						|
            m_pos = op - 0x801 - (t >> 2) - (inBuf[ip] << 2)
 | 
						|
            ip = ip + 1
 | 
						|
            out = outBuf.require(3)
 | 
						|
            out[op] = out[m_pos]
 | 
						|
            op = op + 1
 | 
						|
            m_pos = m_pos + 1
 | 
						|
            out[op] = out[m_pos]
 | 
						|
            op = op + 1
 | 
						|
            m_pos = m_pos + 1
 | 
						|
            out[op] = out[m_pos]
 | 
						|
            op = op + 1
 | 
						|
 | 
						|
            state = c_match_done
 | 
						|
            continue
 | 
						|
 | 
						|
        ##
 | 
						|
        if state == c_match:
 | 
						|
            if t >= 64:
 | 
						|
                m_pos = op - 1 - ((t >> 2) & 7) - (inBuf[ip] << 3)
 | 
						|
                ip = ip + 1
 | 
						|
                t = (t >> 5) - 1
 | 
						|
                state = c_copy_match
 | 
						|
                continue
 | 
						|
            elif t >= 32:
 | 
						|
                t = t & 31
 | 
						|
                if t == 0:
 | 
						|
                    while inBuf[ip] == 0:
 | 
						|
                        t = t + 255
 | 
						|
                        ip = ip + 1
 | 
						|
                    t = t + 31 + inBuf[ip]
 | 
						|
                    ip = ip + 1
 | 
						|
                m_pos = op - 1 - ((inBuf[ip] + (inBuf[ip + 1] << 8)) >> 2)
 | 
						|
                ip = ip + 2
 | 
						|
            elif t >= 16:
 | 
						|
                m_pos = op - ((t & 8) << 11)
 | 
						|
                t = t & 7
 | 
						|
                if t == 0:
 | 
						|
                    while inBuf[ip] == 0:
 | 
						|
                        t = t + 255
 | 
						|
                        ip = ip + 1
 | 
						|
                    t = t + 7 + inBuf[ip]
 | 
						|
                    ip = ip + 1
 | 
						|
                m_pos = m_pos - ((inBuf[ip] + (inBuf[ip + 1] << 8)) >> 2)
 | 
						|
                ip = ip + 2
 | 
						|
                if m_pos == op:
 | 
						|
                    break
 | 
						|
                m_pos = m_pos - 0x4000
 | 
						|
            else:
 | 
						|
                m_pos = op - 1 - (t >> 2) - (inBuf[ip] << 2);
 | 
						|
                ip = ip + 1
 | 
						|
                out = outBuf.require(2)
 | 
						|
                out[op] = out[m_pos]
 | 
						|
                op = op + 1
 | 
						|
                m_pos = m_pos + 1
 | 
						|
                out[op] = out[m_pos]
 | 
						|
                op = op + 1
 | 
						|
                state = c_match_done
 | 
						|
                continue
 | 
						|
 | 
						|
            if t >= 6 and (op - m_pos) >= 4:
 | 
						|
                if_block = True
 | 
						|
                t += 2
 | 
						|
                out = outBuf.require(t)
 | 
						|
                while True:
 | 
						|
                    out[op] = out[m_pos]
 | 
						|
                    op += 1
 | 
						|
                    m_pos += 1
 | 
						|
                    t -= 1
 | 
						|
                    if not t > 0: break
 | 
						|
            #emulate c switch
 | 
						|
            state = c_copy_match
 | 
						|
        
 | 
						|
        ##
 | 
						|
        if state == c_copy_match:
 | 
						|
            if not if_block:
 | 
						|
                t += 2
 | 
						|
                out = outBuf.require(t)
 | 
						|
                while True:
 | 
						|
                    out[op] = out[m_pos]
 | 
						|
                    op += 1
 | 
						|
                    m_pos += 1
 | 
						|
                    t -= 1
 | 
						|
                    if not t > 0: break
 | 
						|
            #emulating c switch
 | 
						|
            state = c_match_done
 | 
						|
 
 | 
						|
        ##
 | 
						|
        if state == c_match_done:
 | 
						|
            t = inBuf[ip - 2] & 3
 | 
						|
            if t == 0:
 | 
						|
                state = c_top_loop
 | 
						|
                continue
 | 
						|
            #emulate c switch
 | 
						|
            state = c_match_next
 | 
						|
 | 
						|
        ##
 | 
						|
        if state == c_match_next:
 | 
						|
            out = outBuf.require(1)
 | 
						|
            out[op] = inBuf[ip]
 | 
						|
            op += 1
 | 
						|
            ip += 1
 | 
						|
            if t > 1:
 | 
						|
                out = outBuf.require(1)
 | 
						|
                out[op] = inBuf[ip]
 | 
						|
                op += 1
 | 
						|
                ip += 1
 | 
						|
                if t > 2:
 | 
						|
                    out = outBuf.require(1)
 | 
						|
                    out[op] = inBuf[ip]
 | 
						|
                    op += 1
 | 
						|
                    ip += 1
 | 
						|
            t = inBuf[ip]
 | 
						|
            ip += 1
 | 
						|
            state = c_match
 | 
						|
            continue
 | 
						|
 | 
						|
    return bytes(outBuf.pack(op))
 | 
						|
 | 
						|
def decompress(input, initSize = 16000, blockSize = 8192):
 | 
						|
    output = FlexBuffer()
 | 
						|
    output.alloc(initSize, blockSize)
 | 
						|
    return _decompress(bytearray(input), output)
 | 
						|
 | 
						|
 |