anki-word-query/addons21/fastwq/libs/mdict/lzo.py

247 lines
6.4 KiB
Python
Raw Permalink Normal View History

2018-07-01 10:55:30 +08:00
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)