1 QuestHelper_File
["collect_lzw.lua"] = "Development Version"
2 QuestHelper_Loadtime
["collect_lzw.lua"] = GetTime()
7 local function QH_LZW_Decompress(input
, tokens
, outbits
)
10 for i
= 0, tokens
-1 do
11 d
[i
] = {[0] = string.char(i
)}
14 local dsize
= tokens
+ 1 -- we use the "tokens" value as an EOF marker
19 while nextbits
< dsize
do bits
= bits
+ 1; nextbits
= nextbits
* 2 end
21 local i
= Bitstream
.Input(input
, outbits
)
26 local tok
= i
:depend(bits
)
27 if tok
== tokens
then return "" end -- Okay. There's nothing. We get it.
29 Merger
.Add(rv
, d
[bit
.mod(tok
, tokens
)][math
.floor(tok
/ tokens
)])
30 local w
= d
[bit
.mod(tok
, tokens
)][math
.floor(tok
/ tokens
)]
39 dsize
= dsize
+ 1 -- We haven't actually added the next element yet. However, we could in theory include it in the stream, so we need to adjust the number of bits properly.
40 if dsize
> nextbits
then
42 nextbits
= nextbits
* 2
46 if tok
== tokens
then break end -- we're done!
49 if d
[bit
.mod(tok
, tokens
)][math
.floor(tok
/ tokens
)] then
50 entry
= d
[bit
.mod(tok
, tokens
)][math
.floor(tok
/ tokens
)]
51 elseif tok
== dsize
- 1 then
52 entry
= w
.. w
:sub(1, 1)
54 QuestHelper
: Assert(false, "faaaail")
58 d
[bit
.mod(dsize
- 1, tokens
)][math
.floor((dsize
- 1) / tokens
)] = w
.. entry
:sub(1, 1) -- Naturally, we're writing to one *less* than dsize, since we already incremented.
63 return Merger
.Finish(rv
)
66 local function QH_LZW_Compress(input
, tokens
, outbits
)
70 for i
= 0, tokens
-1 do
71 d
[string.char(i
)] = {[""] = i
}
74 local dsize
= tokens
+ 1 -- we use the "tokens" value as an EOF marker
79 while nextbits
< dsize
do bits
= bits
+ 1; nextbits
= nextbits
* 2 end
81 local r
= Bitstream
.Output(outbits
)
94 local c
= input
:sub(ci
, ci
)
96 if d
[wcp
:sub(1, 1)][wcp
:sub(2)] then
99 r
:append(d
[w
:sub(1, 1)][w
:sub(2)], bits
)
100 d
[wcp
:sub(1, 1)][wcp
:sub(2)] = dsize
102 if dsize
> nextbits
then
104 nextbits
= nextbits
* 2
109 if w
~= "" then r
:append(d
[w
:sub(1, 1)][w
:sub(2)], bits
) end
111 dsize
= dsize
+ 1 -- Our decompressor doesn't realize we're ending here, so it will have added a table entry for that last token. Sigh.
112 if dsize
> nextbits
then
114 nextbits
= nextbits
* 2
116 r
:append(tokens
, bits
)
118 local rst
= r
:finish()
119 QuestHelper
: Assert(QH_LZW_Decompress(rst
, tokens
, outbits
) == input
) -- yay
124 local function QH_LZW_Compress_Dicts(input
, inputdict
, outputdict
)
128 for i
= 1, #inputdict
do idc
[inputdict
:sub(i
, i
)] = strchar(i
- 1) end
130 for i
= 1, #input
do Merger
.Add(im
, idc
[input
:sub(i
, i
)]) end
131 inproc
= Merger
.Finish(im
)
134 local bits
, dsize
= 1, 2
135 if not outputdict
then bits
= 8 else while dsize
< #outputdict
do bits
= bits
+ 1 ; dsize
= dsize
* 2 end end
136 QuestHelper
: Assert(not outputdict
or #outputdict
== dsize
)
138 local comp
= QH_LZW_Compress(inproc
, inputdict
and #inputdict
or 256, bits
)
141 local origcomp
= comp
143 for i
= 1, #origcomp
do Merger
.Add(im
, outputdict
:sub(strbyte(origcomp
:sub(i
, i
)) + 1)) end
144 comp
= Merger
.Finish(im
)
150 function QH_Collect_LZW_Init(_
, API
)
151 Merger
= API
.Utility_Merger
152 QuestHelper
: Assert(Merger
)
154 Bitstream
= API
.Utility_Bitstream
155 QuestHelper
: Assert(Bitstream
)
157 API
.Utility_LZW
= {Compress
= QH_LZW_Compress
, Decompress
= QH_LZW_Decompress
, Compress_Dicts
= QH_LZW_Compress_Dicts
}
165 QH_LZW_Compress("TOBEORNOTTOBEORTOBEORNOT", 256, 8)
169 QuestHelper:TextOut("lulz")
171 local inq = "ABABABABA"
175 str = QH_LZW_Compress(inq, alpha, bits)
178 tvr = tvr .. string.format("%d ", strbyte(str, i))
180 QuestHelper:TextOut(tvr)
182 ret = QH_LZW_Decompress(str, alpha, bits)
183 QuestHelper:TextOut(ret)
185 QuestHelper: Assert(inq == ret)