Schneemann

inflate.lua

Sep 15th, 2021
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.41 KB | None | 0 0
  1. local sysnative = not not package.loadlib
  2. local datacard = nil
  3. if not sysnative then
  4. local component = require("component")
  5. if component.isAvailable("data") then
  6. datacard = component.data
  7. end
  8. end
  9.  
  10. local inflate = {}
  11.  
  12. function inflate.inflate(data)
  13. if datacard ~= nil then
  14. return datacard.inflate(data)
  15. end
  16.  
  17. -- we aren't using data cards here
  18. -- anyhow, skip the first 2 bytes because i cannot be fucked with the header
  19. local pos = 2*8
  20. local ret = ""
  21. local retcomb = ""
  22.  
  23. local function get(sz)
  24. if (pos>>3) >= #data then error("unexpected EOF in deflate stream") end
  25. local v = data:byte((pos>>3)+1) >> (pos&7)
  26. local boffs = 0
  27. if sz < 8-(pos&7) then
  28. pos = pos + sz
  29. else
  30. local boffs = (8-(pos&7))
  31. local brem = sz - boffs
  32. pos = pos + boffs
  33.  
  34. while brem > 8 do
  35. if (pos>>3) >= #data then error("unexpected EOF in deflate stream") end
  36. v = v | (data:byte((pos>>3)+1)<<boffs)
  37. boffs = boffs + 8
  38. brem = brem - 8
  39. pos = pos + 8
  40. end
  41.  
  42. if (pos>>3) >= #data then error("unexpected EOF in deflate stream") end
  43. v = v | (data:byte((pos>>3)+1)<<boffs)
  44. pos = pos + brem
  45. end
  46.  
  47. return v & ((1<<sz)-1)
  48. end
  49.  
  50. local function buildhuff(tab, tablen)
  51. local i
  52. local lsort = {}
  53.  
  54. -- categorise by length
  55. for i=1,15 do lsort[i] = {} end
  56. for i=1,tablen do
  57. if tab[i] ~= 0 then
  58. table.insert(lsort[tab[i]], i-1)
  59. end
  60. end
  61.  
  62. -- sort each by index
  63. for i=1,15 do table.sort(lsort[i]) end
  64.  
  65. -- build bit selection table
  66. local llim = {}
  67. local v = 0
  68. for i=1,15 do
  69. v = (v << 1) + #lsort[i]
  70. --print(i, v)
  71. llim[i] = v
  72. assert(v <= (1<<i))
  73. end
  74. assert(v == (1<<15))
  75.  
  76. return function()
  77. local v = 0
  78. local i
  79. for i=1,15 do
  80. v = (v<<1) + get(1)
  81. if v < llim[i] then
  82. return (lsort[i][1+(v-llim[i]+#lsort[i])] or
  83. error("lookup overflow"))
  84. end
  85. end
  86.  
  87. error("we seem to have an issue with this huffman tree")
  88. end
  89. end
  90.  
  91. local bfinal = false
  92. local btype
  93.  
  94. local decoders = {}
  95. decoders[1+1] = function()
  96. local i
  97.  
  98. -- literals
  99. local hltab = {}
  100. for i=0,143 do hltab[i+1] = 8 end
  101. for i=144,255 do hltab[i+1] = 9 end
  102. for i=256,279 do hltab[i+1] = 7 end
  103. for i=280,287 do hltab[i+1] = 8 end
  104.  
  105. -- distances
  106. local hdtab = {}
  107. for i=0,32-1 do hdtab[i+1] = 5 end
  108.  
  109. -- build and return
  110. local hltree = buildhuff(hltab, 288)
  111. local hdtree = buildhuff(hdtab, 32)
  112.  
  113. return hltree, hdtree
  114. end
  115. decoders[2+1] = function()
  116. local i, j
  117.  
  118. local hlit = get(5)+257
  119. local hdist = get(5)+1
  120. local hclen = get(4)+4
  121. --print(hlit, hdist, hclen)
  122.  
  123. local HCMAP = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
  124. local hctab = {}
  125.  
  126. -- code lengths
  127. for i=0,18 do hctab[i+1] = 0 end
  128. for i=1,hclen do
  129. hctab[HCMAP[i]+1] = get(3)
  130. --print(HCMAP[i], hctab[HCMAP[i]+1])
  131. end
  132. local hctree = buildhuff(hctab, 19)
  133.  
  134. -- literals
  135. local hltab = {}
  136. i = 1
  137. while i <= hlit do
  138. local v = hctree()
  139. if v <= 15 then
  140. hltab[i] = v
  141. i = i + 1
  142. elseif v == 16 then
  143. assert(i >= 2)
  144. for j=1,get(2)+3 do
  145. hltab[i] = hltab[i-1]
  146. i = i + 1
  147. end
  148. elseif v == 17 then
  149. for j=1,get(3)+3 do
  150. hltab[i] = 0
  151. i = i + 1
  152. end
  153. elseif v == 18 then
  154. for j=1,get(7)+11 do
  155. hltab[i] = 0
  156. i = i + 1
  157. end
  158. else
  159. error("hctree decoding issue")
  160. end
  161. end
  162. assert(i == hlit+1)
  163.  
  164. local hdtab = {}
  165. i = 1
  166. while i <= hdist do
  167. local v = hctree()
  168. if v <= 15 then
  169. hdtab[i] = v
  170. i = i + 1
  171. elseif v == 16 then
  172. assert(i >= 2)
  173. for j=1,get(2)+3 do
  174. hdtab[i] = hdtab[i-1]
  175. i = i + 1
  176. end
  177. elseif v == 17 then
  178. for j=1,get(3)+3 do
  179. hdtab[i] = 0
  180. i = i + 1
  181. end
  182. elseif v == 18 then
  183. for j=1,get(7)+11 do
  184. hdtab[i] = 0
  185. i = i + 1
  186. end
  187. else
  188. error("hctree decoding issue")
  189. end
  190. end
  191. assert(i == hdist+1)
  192.  
  193. local hltree = buildhuff(hltab, hlit)
  194. local hdtree = buildhuff(hdtab, hdist)
  195.  
  196. return hltree, hdtree
  197. --error("TODO: dynamic huffman deflate block")
  198. end
  199.  
  200. local function lzss(len, dist)
  201. if dist <= 3 then
  202. dist = dist + 1
  203. elseif dist <= 29 then
  204. -- i refuse to type this whole thing out
  205. local subdist = ((dist-4)>>1)
  206. --print(dist)
  207. local nd = get(subdist+1)
  208. dist = 1 + (1<<(subdist+2)) + ((dist&1)<<(subdist+1)) + nd
  209. --print(dist, nd)
  210. else
  211. print(dist)
  212. error("invalid deflate distance table code")
  213. end
  214.  
  215. -- TODO: optimise
  216. assert(dist >= 1)
  217. local i
  218. local idx = #ret-dist+1
  219. if idx < 1 then
  220. -- pull back from combined return
  221. ret = retcomb:sub(#retcomb+idx) .. ret
  222. retcomb = retcomb:sub(1,#retcomb+idx-1)
  223. idx = 1
  224. end
  225. assert(idx >= 1)
  226. assert(idx <= #ret)
  227. for i=1,len do
  228. ret = ret .. ret:sub(idx, idx)
  229. idx = idx + 1
  230. end
  231. end
  232.  
  233. while not bfinal do
  234. ret = ""
  235. bfinal = (get(1) ~= 0)
  236. btype = get(2)
  237. if btype == 3 then error("invalid block mode") end
  238. if sysnative then print("block", btype, bfinal) end
  239.  
  240. if btype == 0 then
  241. pos = (pos + 7) & (~7)
  242. local lpos = pos >> 3
  243. local len = data:byte(lpos+1)
  244. len = len + (data:byte(lpos+2) << 8)
  245. local nlen = data:byte(lpos+3)
  246. nlen = nlen + (data:byte(lpos+4) << 8)
  247. if (len ^ nlen) ~= 0xFFFF then
  248. error("stored block complement check failed")
  249. end
  250. ret = data:sub(lpos+4+1, lpos+4+1+len-1)
  251. assert(#ret == len)
  252. pos = pos + ((4+len)<<3)
  253. else
  254. local tfetch, tgetdist = decoders[btype+1]()
  255.  
  256. while true do
  257. local v = tfetch()
  258. if v <= 255 then
  259. ret = ret .. string.char(v)
  260. elseif v == 256 then
  261. break
  262. elseif v >= 257 and v <= 264 then
  263. lzss(v-257 + 3, tgetdist())
  264. elseif v >= 265 and v <= 268 then
  265. lzss((v-265)*2 + 11 + get(1), tgetdist())
  266. elseif v >= 269 and v <= 272 then
  267. lzss((v-269)*4 + 19 + get(2), tgetdist())
  268. elseif v >= 273 and v <= 276 then
  269. lzss((v-273)*8 + 35 + get(3), tgetdist())
  270. elseif v >= 277 and v <= 280 then
  271. lzss((v-277)*16 + 67 + get(4), tgetdist())
  272. elseif v >= 281 and v <= 284 then
  273. lzss((v-281)*32 + 131 + get(5), tgetdist())
  274. elseif v >= 285 then
  275. lzss(258, tgetdist())
  276. else
  277. print(v)
  278. error("invalid deflate literal table code")
  279. end
  280. end
  281. end
  282.  
  283. retcomb = retcomb .. ret
  284. if not sysnative then os.sleep(0) end
  285. end
  286.  
  287. --print(#ret)
  288. return retcomb
  289. end
  290.  
  291. return inflate
Add Comment
Please, Sign In to add comment