11#! /usr/bin/env lua
22
3- -- nbs = new bit stream
4- local function nbs (reader )
3+ --- New bit stream
4+ local function nbs (r )
55
66 -- b = buffer
77 -- p = position
88 -- bb = bit buffer
99 -- bc = bit count
1010 local b , p , bb , bc = " " , 1 , 0 , 0
1111
12- local function fill ()
12+ --- Fill
13+ local function F ()
1314 if p > # b then
14- b = reader ()
15+ b = r ()
1516 if not b or # b == 0 then return false end
1617 p = 1
1718 end
1819 return true
1920 end
2021
21- -- nb = need bits
22+ --- Need bits
2223 local function nb (n )
2324 while bc < n do
2425 if p > # b then
25- if not fill () then error (" Unexpected EOF" ) end
26+ if not F () then error (" Unexpected EOF" ) end
2627 end
2728 bb = bb + (b :byte (p ) << bc )
2829 p = p + 1
2930 bc = bc + 8
3031 end
3132 end
3233
33- -- rb = read bits
34+ --- Read bits
3435 local function rb (n )
3536 nb (n )
3637 local v = bb & ((1 << n ) - 1 )
3738 bb , bc = (bb >> n ), bc - n
3839 return v
3940 end
4041
41- -- ab = align byte
42+ --- Align byte
4243 local function ab () bb , bc = 0 , 0 end
4344
44- -- raw = read raw bytes
45- local function raw (n )
45+ --- Read raw bytes
46+ local function ra (n )
4647 ab ()
47- local out , got = {}, 0
48- while got < n do
48+
49+ -- o = out
50+ -- g = got
51+ local o , g = {}, 0
52+ while g < n do
4953 if p > # b then
50- if not fill () then error (" Unexpected EOF" ) end
54+ if not F () then error (" Unexpected EOF" ) end
5155 end
52- local take = math.min (n - got , # b - p + 1 )
53- out [ # out + 1 ] = b :sub (p , p + take - 1 )
56+ local take = math.min (n - g , # b - p + 1 )
57+ o [ # o + 1 ] = b :sub (p , p + take - 1 )
5458 p = p + take
55- got = got + take
59+ g = g + take
5660 end
57- return table.concat (out )
61+ return table.concat (o )
5862 end
5963
60- return { r = rb , a = ab , raw = raw }
64+ return { r = rb , a = ab , raw = ra }
6165end
6266
63- -- rv = revbits
67+ --- Reverse bits
6468local function rv (x , bits )
6569 local y = 0
6670
@@ -72,7 +76,7 @@ local function rv(x, bits)
7276 return y
7377end
7478
75- -- mh = make huff
79+ --- Make huffman
7680local function mh (lengths )
7781
7882 -- m = maximum length
@@ -108,7 +112,7 @@ local function mh(lengths)
108112 return { tab = t , max = m }
109113end
110114
111- -- rh = read huff
115+ --- Read huffman
112116local function rh (bs , h )
113117
114118 -- c = code
@@ -124,38 +128,41 @@ local function rh(bs, h)
124128 error (" invalid Huffman code" )
125129end
126130
127- local function inflate (reader , writer )
131+ --- Inflate a deflated file inside a zip
132+ --- @param r function The reader function
133+ --- @param w function The writer function
134+ local function inf (r , w )
128135
129136 -- bs = bit stream
130137 -- op = output position
131138 -- kg = keep going (in a loop)
132- -- win = sliding window (32KB circular buffer)
139+ -- sw = sliding window (32KB circular buffer)
133140 -- wp = window pointer
134- -- out = output chunk buffer
135- local bs , op , kg , win , wp , out = nbs (reader ), 0 , true , {}, 0 , {}
136-
137- -- flush = write to sink
138- local function flush ()
139- if # out > 0 then
140- writer (table.concat (out ))
141- out = {}
141+ -- o = output chunk buffer
142+ local bs , op , kg , sw , wp , o = nbs (r ), 0 , true , {}, 0 , {}
143+
144+ --- Flush all unwritten data to the output file
145+ local function F ()
146+ if # o > 0 then
147+ w (table.concat (o ))
148+ o = {}
142149 end
143150 end
144151
145- -- ab = append byte
152+ --- Append byte
146153 local function ab (byte )
147154 op = op + 1
148155
149156 -- Add to output chunk
150- out [ # out + 1 ] = string.char (byte )
151- if # out >= 4096 then flush () end
157+ o [ # o + 1 ] = string.char (byte )
158+ if # o >= 4096 then F () end
152159
153160 -- Add to history window
154- win [wp ] = byte
161+ sw [wp ] = byte
155162 wp = (wp + 1 ) % 32768
156163 end
157164
158- -- as = append string
165+ --- Append string
159166 local function as (s ) for i = 1 , # s do ab (s :byte (i )) end end
160167
161168 while kg do
@@ -166,9 +173,9 @@ local function inflate(reader, writer)
166173
167174 if t == 0 then
168175 -- uncompressed block: align, then read LEN, NLEN from byte stream
169- local h , len , s = bs .raw (4 )
176+ local h , len , s = bs .ra (4 )
170177 len = h :byte (1 ) + h :byte (2 )* 256
171- s = bs .raw (len )
178+ s = bs .ra (len )
172179 as (s )
173180
174181 elseif t == 1 or t == 2 then
@@ -206,15 +213,15 @@ local function inflate(reader, writer)
206213 if s <= 15 then
207214 le [# le + 1 ] = s
208215 elseif s == 16 then
209- local r , l = bs .r (2 ) + 3 , le [# le ]
210- for _ = 1 , r do le [# le + 1 ] = l
216+ local x , l = bs .r (2 ) + 3 , le [# le ]
217+ for _ = 1 , x do le [# le + 1 ] = l
211218 end
212219 elseif s == 17 then
213- local r = bs .r (3 ) + 3
214- for _ = 1 , r do le [# le + 1 ] = 0 end
220+ local x = bs .r (3 ) + 3
221+ for _ = 1 , x do le [# le + 1 ] = 0 end
215222 elseif s == 18 then
216- local r = bs .r (7 ) + 11
217- for _ = 1 , r do le [# le + 1 ] = 0 end
223+ local x = bs .r (7 ) + 11
224+ for _ = 1 , x do le [# le + 1 ] = 0 end
218225 end
219226 end
220227 for i = 1 , hl do ll [i ] = le [i ] end
@@ -274,7 +281,7 @@ local function inflate(reader, writer)
274281 -- Read from window history
275282 for _ = 1 , l do
276283 local p = (wp - dv ) % 32768
277- ab (win [p ] or 0 )
284+ ab (sw [p ] or 0 )
278285 end
279286 end
280287 end
@@ -285,7 +292,7 @@ local function inflate(reader, writer)
285292 if f == 1 then kg = false end
286293 end
287294
288- flush ()
295+ F ()
289296end
290297
291298local function crc32 (s , c )
@@ -303,13 +310,13 @@ local function crc32(s, c)
303310 return c ~ x
304311end
305312
306- local function unzip (path )
313+ local function unzip (p )
307314
308315 -- C = read chunk size
309316 -- f = file
310317 local C , f = 4096
311318
312- f , E = io.open (path , " rb" )
319+ f , E = io.open (p , " rb" )
313320 if E then print (E ) os.exit (1 ) end
314321
315322 -- R = read bytes
@@ -321,8 +328,11 @@ local function unzip(path)
321328
322329 local function S (n ) f :seek (" cur" , n ) end
323330
324- local function le16 () local a , b = R (2 ):byte (1 , 2 ) return a + b * 256 end
325- local function le32 () local a , b , c , d = R (4 ):byte (1 , 4 ) return a + b * 256 + c * 65536 + d * 16777216 end
331+ --- Read the next 2 bytes in the file as a 16-bit little endian number
332+ local function R16 () local a , b = R (2 ):byte (1 , 2 ) return a + b * 256 end
333+
334+ --- Read the next 4 bytes in the file as a 32-bit little endian number
335+ local function R32 () local a , b , c , d = R (4 ):byte (1 , 4 ) return a + b * 256 + c * 65536 + d * 16777216 end
326336
327337 while true do
328338
@@ -340,19 +350,19 @@ local function unzip(path)
340350 -- of = output file
341351 -- re = remaining bytes
342352 -- cr = crc32 checksum
343- local s , v , fl , cm , cr , cs , us , nl , el , fn , os , di , of , re , cr = f :read (4 )
353+ local s , v , fl , cm , cr , cs , us , nl , el , fn , os , di , of , re = f :read (4 )
344354 if not s or # s < 4 then break end
345355 if s ~= " PK\3\4 " then break end
346356
347- v , E = le16 () if not v then break end -- version
348- fl , E = le16 () if not fl then break end -- flags
349- cm , E = le16 () if not cm then break end -- method
357+ v , E = R16 () if not v then break end -- version
358+ fl , E = R16 () if not fl then break end -- flags
359+ cm , E = R16 () if not cm then break end -- method
350360 S (4 ) -- skip modification time and date
351- cr , E = le32 () if not cr then break end -- crc32
352- cs , E = le32 () if not cs then break end -- compressed size
353- us , E = le32 () if not us then break end -- uncompressed size
354- nl , E = le16 () if not nl then break end -- name length
355- el , E = le16 () if not el then break end -- extra name length
361+ cr , E = R32 () if not cr then break end -- crc32
362+ cs , E = R32 () if not cs then break end -- compressed size
363+ us , E = R32 () if not us then break end -- uncompressed size
364+ nl , E = R16 () if not nl then break end -- name length
365+ el , E = R16 () if not el then break end -- extra name length
356366
357367 fn , E = R (nl ) if not fn then break end -- filename
358368 if el > 0 then S (el ) end
@@ -361,12 +371,14 @@ local function unzip(path)
361371
362372 re , cr = cs , 0
363373
364- -- reader = read compressed data in chunks
365- local function reader ()
374+ --- Read compressed data in chunks
375+ local function RC ()
366376 if re <= 0 then return nil end
367- local chunk = f :read (math.min (C , re ))
368- if chunk then re = re - # chunk end
369- return chunk
377+
378+ -- c = chunk
379+ local c = f :read (math.min (C , re ))
380+ if c then re = re - # c end
381+ return c
370382 end
371383
372384 -- Setup output file
@@ -379,22 +391,21 @@ local function unzip(path)
379391 if not of then
380392 print (E )
381393 else
382- -- writer = write decompressed data and update CRC
383- local function writer (chunk )
384- cr = crc32 (chunk , cr )
385- of :write (chunk )
394+ --- Write decompressed data and update CRC
395+ --- @param c string The chunk of decompressed data to write to the file
396+ local function W (c )
397+ cr = crc32 (c , cr )
398+ of :write (c )
386399 end
387400
388- if cm == 0 then
389- -- no compression
401+ if cm == 0 then -- uncompressed file
390402 while re > 0 do
391- local chunk = reader ()
392- if not chunk then break end
393- writer ( chunk )
403+ local c = RC ()
404+ if not c then break end
405+ W ( c )
394406 end
395- elseif cm == 8 then
396- -- deflate
397- inflate (reader , writer )
407+ elseif cm == 8 then -- deflated file
408+ inf (RC , W )
398409 else
399410 print (" Unsupported compression" )
400411 end
0 commit comments