wip(0.S3): the runtime migrated - ludic migrate state --runtime <every program>: 331 vars into 25 states (RtInputState, RtGlState, ...), 2 lets; its states are made before it boots; no module-level var is let through outside --globals
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7b17b4a1b9
commit
02448e176c
38 changed files with 53877 additions and 53251 deletions
|
|
@ -17,32 +17,50 @@
|
|||
# ============================================================================
|
||||
|
||||
# ---- forward bit reader (LSB-first) — for FSE table descriptions -----------
|
||||
var zf_src: pointer = null
|
||||
var zf_pos: int = 0 # byte cursor
|
||||
var zf_bit: int = 0 # bit within the current byte (0 = LSB)
|
||||
export state RtZstdState {
|
||||
zf_src: pointer = null
|
||||
zf_pos: int = 0 # byte cursor
|
||||
zf_bit: int = 0 # bit within the current byte (0 = LSB)
|
||||
zb_src: pointer = null
|
||||
zb_s: int = 0 # first byte of the stream
|
||||
zb_L: int = 0 # stream length
|
||||
zb_skip: int = 0 # padding bits above the sentinel in the last byte
|
||||
zb_cur: int = 0 # data-bit index consumed so far
|
||||
fse_ncount_n: int = 0
|
||||
zstd_pll: SeqDT = null
|
||||
zstd_pof: SeqDT = null
|
||||
zstd_pml: SeqDT = null
|
||||
zstd_ll_base: words = null
|
||||
zstd_ll_bits: words = null
|
||||
zstd_ml_base: words = null
|
||||
zstd_ml_bits: words = null
|
||||
zstd_lit: pointer = null
|
||||
zstd_litn: int = 0
|
||||
zstd_huf_prev: HufDT = null
|
||||
zstd_rep0: int = 1
|
||||
zstd_rep1: int = 4
|
||||
zstd_rep2: int = 8
|
||||
zstd_seq_sp: int = 0
|
||||
zstd_err: int = 0
|
||||
}
|
||||
|
||||
function zf_init(src: pointer, at: int) -> void { zf_src = src; zf_pos = at; zf_bit = 0 }
|
||||
function zf_read(n: int) -> int {
|
||||
function zf_init(rt_zstd_st: mut RtZstdState, src: pointer, at: int) -> void { rt_zstd_st.zf_src = src; rt_zstd_st.zf_pos = at; rt_zstd_st.zf_bit = 0 }
|
||||
function zf_read(rt_zstd_st: mut RtZstdState, n: int) -> int {
|
||||
var v = 0
|
||||
var k = 0
|
||||
while k < n {
|
||||
let b = (zf_src[zf_pos] >> zf_bit) & 1
|
||||
let b = (rt_zstd_st.zf_src[rt_zstd_st.zf_pos] >> rt_zstd_st.zf_bit) & 1
|
||||
v = v | (b << k)
|
||||
zf_bit += 1
|
||||
if zf_bit == 8 { zf_bit = 0; zf_pos += 1 }
|
||||
rt_zstd_st.zf_bit += 1
|
||||
if rt_zstd_st.zf_bit == 8 { rt_zstd_st.zf_bit = 0; rt_zstd_st.zf_pos += 1 }
|
||||
k += 1
|
||||
}
|
||||
return v
|
||||
}
|
||||
# byte position just past the bits consumed (rounding up a partial byte).
|
||||
function zf_bytepos() -> int { if zf_bit == 0 { return zf_pos }; return zf_pos + 1 }
|
||||
function zf_bytepos(rt_zstd_st: RtZstdState) -> int { if rt_zstd_st.zf_bit == 0 { return rt_zstd_st.zf_pos }; return rt_zstd_st.zf_pos + 1 }
|
||||
|
||||
# ---- backward bit reader (MSB-first) — for FSE / Huffman streams ------------
|
||||
var zb_src: pointer = null
|
||||
var zb_s: int = 0 # first byte of the stream
|
||||
var zb_L: int = 0 # stream length
|
||||
var zb_skip: int = 0 # padding bits above the sentinel in the last byte
|
||||
var zb_cur: int = 0 # data-bit index consumed so far
|
||||
|
||||
function zstd_highbit(v: int) -> int {
|
||||
var r = -1
|
||||
|
|
@ -52,32 +70,32 @@ function zstd_highbit(v: int) -> int {
|
|||
}
|
||||
|
||||
# init over stream bytes [s, s+L); the sentinel is the top set bit of the last.
|
||||
function zb_init(src: pointer, s: int, L: int) -> int {
|
||||
zb_src = src; zb_s = s; zb_L = L; zb_cur = 0
|
||||
function zb_init(rt_zstd_st: mut RtZstdState, src: pointer, s: int, L: int) -> int {
|
||||
rt_zstd_st.zb_src = src; rt_zstd_st.zb_s = s; rt_zstd_st.zb_L = L; rt_zstd_st.zb_cur = 0
|
||||
if L <= 0 { return -1 }
|
||||
let hb = zstd_highbit(src[s + L - 1])
|
||||
if hb < 0 { return -1 } # a zero last byte is invalid
|
||||
zb_skip = 8 - hb # the sentinel bit + anything above it is padding
|
||||
rt_zstd_st.zb_skip = 8 - hb # the sentinel bit + anything above it is padding
|
||||
return 0
|
||||
}
|
||||
# one data bit (0/1), MSB-first from the end of the stream.
|
||||
function zb_bit() -> int {
|
||||
let j = zb_skip + zb_cur
|
||||
let byteidx = (zb_L - 1) - (j >> 3)
|
||||
function zb_bit(rt_zstd_st: mut RtZstdState) -> int {
|
||||
let j = rt_zstd_st.zb_skip + rt_zstd_st.zb_cur
|
||||
let byteidx = (rt_zstd_st.zb_L - 1) - (j >> 3)
|
||||
let bit = 7 - (j & 7)
|
||||
zb_cur += 1
|
||||
rt_zstd_st.zb_cur += 1
|
||||
if byteidx < 0 { return 0 }
|
||||
return (zb_src[zb_s + byteidx] >> bit) & 1
|
||||
return (rt_zstd_st.zb_src[rt_zstd_st.zb_s + byteidx] >> bit) & 1
|
||||
}
|
||||
# read n bits, first bit read = most-significant of the result.
|
||||
function zb_read(n: int) -> int {
|
||||
function zb_read(rt_zstd_st: mut RtZstdState, n: int) -> int {
|
||||
var v = 0
|
||||
var k = 0
|
||||
while k < n { v = (v << 1) | zb_bit(); k += 1 }
|
||||
while k < n { v = (v << 1) | zb_bit(rt_zstd_st); k += 1 }
|
||||
return v
|
||||
}
|
||||
function zb_total() -> int { return 8 * (zb_L - 1) + (8 - zb_skip) } # usable data bits
|
||||
function zb_done() -> int { if zb_cur >= zb_total() { return 1 }; return 0 }
|
||||
function zb_total(rt_zstd_st: RtZstdState) -> int { return 8 * (rt_zstd_st.zb_L - 1) + (8 - rt_zstd_st.zb_skip) } # usable data bits
|
||||
function zb_done(rt_zstd_st: RtZstdState) -> int { if rt_zstd_st.zb_cur >= zb_total(rt_zstd_st) { return 1 }; return 0 }
|
||||
|
||||
# ---- FSE decode table ------------------------------------------------------
|
||||
property FseDT {
|
||||
|
|
@ -152,9 +170,8 @@ function zstd_highbit32(v: int) -> int {
|
|||
|
||||
# read normalized counts (FSE_readNCount) forward from the current zf position.
|
||||
# fills `norm[0..*nsym)`, returns the tableLog; `outn` receives the symbol count.
|
||||
var fse_ncount_n: int = 0
|
||||
function fse_read_ncount(norm: words, maxsym: int) -> int {
|
||||
let accLog = zf_read(4) + 5
|
||||
function fse_read_ncount(rt_zstd_st: mut RtZstdState, norm: words, maxsym: int) -> int {
|
||||
let accLog = zf_read(rt_zstd_st, 4) + 5
|
||||
var remaining = (1 << accLog) + 1
|
||||
var threshold = 1 << accLog
|
||||
var bitsLeft = accLog + 1
|
||||
|
|
@ -165,10 +182,10 @@ function fse_read_ncount(norm: words, maxsym: int) -> int {
|
|||
# a run of zero-probability symbols, encoded in groups of 2 bits (0..3),
|
||||
# 3 meaning "continue"
|
||||
var n0 = sym
|
||||
var rep = zf_read(2)
|
||||
var rep = zf_read(rt_zstd_st, 2)
|
||||
while rep == 3 {
|
||||
n0 += 3
|
||||
rep = zf_read(2)
|
||||
rep = zf_read(rt_zstd_st, 2)
|
||||
}
|
||||
n0 += rep
|
||||
while sym < n0 { norm[sym] = 0; sym += 1 }
|
||||
|
|
@ -177,12 +194,12 @@ function fse_read_ncount(norm: words, maxsym: int) -> int {
|
|||
let maxv = (2 * threshold - 1) - remaining
|
||||
var count = 0
|
||||
# low bitsLeft-1 bits, then maybe one more (the "large" range)
|
||||
let low = zf_peek(bitsLeft - 1)
|
||||
let low = zf_peek(rt_zstd_st, bitsLeft - 1)
|
||||
if low < maxv {
|
||||
count = low
|
||||
zf_skip(bitsLeft - 1)
|
||||
zf_skip(rt_zstd_st, bitsLeft - 1)
|
||||
} else {
|
||||
count = zf_read(bitsLeft)
|
||||
count = zf_read(rt_zstd_st, bitsLeft)
|
||||
if count >= threshold { count -= maxv }
|
||||
}
|
||||
let val = count - 1 # -1 means low-prob (stored as -1)
|
||||
|
|
@ -199,36 +216,36 @@ function fse_read_ncount(norm: words, maxsym: int) -> int {
|
|||
}
|
||||
}
|
||||
while sym <= maxsym { norm[sym] = 0; sym += 1 }
|
||||
fse_ncount_n = sym
|
||||
rt_zstd_st.fse_ncount_n = sym
|
||||
return accLog
|
||||
}
|
||||
|
||||
# peek/skip helpers for the forward reader (the ncount "large range" needs a peek)
|
||||
function zf_peek(n: int) -> int {
|
||||
let sp = zf_pos; let sb = zf_bit
|
||||
let v = zf_read(n)
|
||||
zf_pos = sp; zf_bit = sb
|
||||
function zf_peek(rt_zstd_st: mut RtZstdState, n: int) -> int {
|
||||
let sp = rt_zstd_st.zf_pos; let sb = rt_zstd_st.zf_bit
|
||||
let v = zf_read(rt_zstd_st, n)
|
||||
rt_zstd_st.zf_pos = sp; rt_zstd_st.zf_bit = sb
|
||||
return v
|
||||
}
|
||||
function zf_skip(n: int) -> void { zf_read(n) }
|
||||
function zf_skip(rt_zstd_st: mut RtZstdState, n: int) -> void { zf_read(rt_zstd_st, n) }
|
||||
|
||||
# ---- FSE decompress (2 interleaved states) — Huffman weight stream ----------
|
||||
# decode symbols from a backward stream already init'd, using DTable `dt`, into
|
||||
# out[0..cap). Returns count. Two states advance alternately (FSE_decompress).
|
||||
function fse_decompress(dt: FseDT, out: words, cap: int) -> int {
|
||||
var s1 = zb_read(dt.log)
|
||||
var s2 = zb_read(dt.log)
|
||||
function fse_decompress(rt_zstd_st: mut RtZstdState, dt: FseDT, out: words, cap: int) -> int {
|
||||
var s1 = zb_read(rt_zstd_st, dt.log)
|
||||
var s2 = zb_read(rt_zstd_st, dt.log)
|
||||
var n = 0
|
||||
# two states alternate; when a state-advance read overruns the stream, the
|
||||
# other state's residual symbol is the final one (FSE_decompress tail).
|
||||
while true {
|
||||
out[n] = dt.sym[s1]; n += 1
|
||||
s1 = dt.ns[s1] + zb_read(dt.nb[s1])
|
||||
if zb_cur > zb_total() { out[n] = dt.sym[s2]; n += 1; return n }
|
||||
s1 = dt.ns[s1] + zb_read(rt_zstd_st, dt.nb[s1])
|
||||
if rt_zstd_st.zb_cur > zb_total(rt_zstd_st) { out[n] = dt.sym[s2]; n += 1; return n }
|
||||
if n >= cap { return n }
|
||||
out[n] = dt.sym[s2]; n += 1
|
||||
s2 = dt.ns[s2] + zb_read(dt.nb[s2])
|
||||
if zb_cur > zb_total() { out[n] = dt.sym[s1]; n += 1; return n }
|
||||
s2 = dt.ns[s2] + zb_read(rt_zstd_st, dt.nb[s2])
|
||||
if rt_zstd_st.zb_cur > zb_total(rt_zstd_st) { out[n] = dt.sym[s1]; n += 1; return n }
|
||||
if n >= cap { return n }
|
||||
}
|
||||
return n
|
||||
|
|
@ -262,51 +279,44 @@ function zstd_lits(s: pointer) -> words {
|
|||
return a
|
||||
}
|
||||
|
||||
var zstd_pll: SeqDT = null
|
||||
function zstd_predef_ll() -> SeqDT {
|
||||
if zstd_pll != null { return zstd_pll }
|
||||
function zstd_predef_ll(rt_zstd_st: mut RtZstdState) -> SeqDT {
|
||||
if rt_zstd_st.zstd_pll != null { return rt_zstd_st.zstd_pll }
|
||||
let dt = new SeqDT
|
||||
dt.log = 6
|
||||
dt.base = zstd_lits("0;0;1;3;4;6;7;9;10;12;14;16;20;22;28;32;48;64;128;256;1024;4096;0;1;2;4;5;7;8;10;11;13;16;18;22;24;32;40;64;64;128;512;2048;0;1;2;3;5;6;8;9;11;12;15;18;20;24;28;40;48;65536;32768;16384;8192")
|
||||
dt.addbits = zstd_lits("0;0;0;0;0;0;0;0;0;0;0;1;1;1;2;3;4;6;7;8;10;12;0;0;0;0;0;0;0;0;0;0;1;1;1;2;3;3;6;6;7;9;11;0;0;0;0;0;0;0;0;0;0;0;1;1;2;2;3;4;16;15;14;13")
|
||||
dt.nb = zstd_lits("4;4;5;5;5;5;5;5;5;5;6;5;5;5;5;5;5;5;5;6;6;6;4;4;5;5;5;5;5;5;5;6;5;5;5;5;5;5;4;4;5;6;6;4;4;5;5;5;5;5;5;5;5;6;5;5;5;5;5;5;6;6;6;6")
|
||||
dt.ns = zstd_lits("0;16;32;0;0;0;0;0;0;0;0;0;0;0;0;0;0;32;0;0;0;0;32;0;0;32;0;32;0;32;0;0;32;0;32;0;32;0;0;16;32;0;0;48;16;32;32;32;32;32;32;32;32;0;32;32;32;32;32;32;0;0;0;0")
|
||||
zstd_pll = dt
|
||||
rt_zstd_st.zstd_pll = dt
|
||||
return dt
|
||||
}
|
||||
|
||||
var zstd_pof: SeqDT = null
|
||||
function zstd_predef_of() -> SeqDT {
|
||||
if zstd_pof != null { return zstd_pof }
|
||||
function zstd_predef_of(rt_zstd_st: mut RtZstdState) -> SeqDT {
|
||||
if rt_zstd_st.zstd_pof != null { return rt_zstd_st.zstd_pof }
|
||||
let dt = new SeqDT
|
||||
dt.log = 5
|
||||
dt.base = zstd_lits("0;61;509;32765;2097149;5;125;4093;262141;8388605;29;253;16381;1048573;1;125;2045;131069;4194301;13;253;8189;524285;1;61;1021;65533;268435453;134217725;67108861;33554429;16777213")
|
||||
dt.addbits = zstd_lits("0;6;9;15;21;3;7;12;18;23;5;8;14;20;2;7;11;17;22;4;8;13;19;1;6;10;16;28;27;26;25;24")
|
||||
dt.nb = zstd_lits("5;4;5;5;5;5;4;5;5;5;5;4;5;5;5;4;5;5;5;5;4;5;5;5;4;5;5;5;5;5;5;5")
|
||||
dt.ns = zstd_lits("0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;16;0;0;0;0;16;0;0;0;16;0;0;0;0;0;0;0")
|
||||
zstd_pof = dt
|
||||
rt_zstd_st.zstd_pof = dt
|
||||
return dt
|
||||
}
|
||||
|
||||
var zstd_pml: SeqDT = null
|
||||
function zstd_predef_ml() -> SeqDT {
|
||||
if zstd_pml != null { return zstd_pml }
|
||||
function zstd_predef_ml(rt_zstd_st: mut RtZstdState) -> SeqDT {
|
||||
if rt_zstd_st.zstd_pml != null { return rt_zstd_st.zstd_pml }
|
||||
let dt = new SeqDT
|
||||
dt.log = 6
|
||||
dt.base = zstd_lits("3;4;5;6;8;9;11;13;16;19;22;25;28;31;34;37;41;47;59;83;131;515;4;5;6;7;9;10;12;15;18;21;24;27;30;33;35;39;43;51;67;99;259;4;4;5;7;8;10;11;14;17;20;23;26;29;32;65539;32771;16387;8195;4099;2051;1027")
|
||||
dt.addbits = zstd_lits("0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;2;3;4;7;9;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;2;3;4;5;8;0;0;0;0;0;0;0;0;0;0;0;0;0;0;16;15;14;13;12;11;10")
|
||||
dt.nb = zstd_lits("6;4;5;5;5;5;5;6;6;6;6;6;6;6;6;6;6;6;6;6;6;6;4;4;5;5;5;5;6;6;6;6;6;6;6;6;6;6;6;6;6;6;6;4;4;4;5;5;5;5;6;6;6;6;6;6;6;6;6;6;6;6;6;6")
|
||||
dt.ns = zstd_lits("0;0;32;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;16;0;32;0;32;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;32;48;16;32;32;32;32;0;0;0;0;0;0;0;0;0;0;0;0;0;0")
|
||||
zstd_pml = dt
|
||||
rt_zstd_st.zstd_pml = dt
|
||||
return dt
|
||||
}
|
||||
|
||||
var zstd_ll_base: words = null
|
||||
var zstd_ll_bits: words = null
|
||||
var zstd_ml_base: words = null
|
||||
var zstd_ml_bits: words = null
|
||||
function zstd_seq_tables_init() -> void {
|
||||
if zstd_ll_base != null { return }
|
||||
function zstd_seq_tables_init(rt_zstd_st: mut RtZstdState) -> void {
|
||||
if rt_zstd_st.zstd_ll_base != null { return }
|
||||
let llb = words(36)
|
||||
var i = 0
|
||||
while i < 16 { llb[i] = i; i += 1 }
|
||||
|
|
@ -335,7 +345,7 @@ function zstd_seq_tables_init() -> void {
|
|||
mlx[38] = 3; mlx[39] = 3; mlx[40] = 4; mlx[41] = 4; mlx[42] = 5; mlx[43] = 7
|
||||
mlx[44] = 8; mlx[45] = 9; mlx[46] = 10; mlx[47] = 11; mlx[48] = 12; mlx[49] = 13
|
||||
mlx[50] = 14; mlx[51] = 15; mlx[52] = 16
|
||||
zstd_ll_base = llb; zstd_ll_bits = llx; zstd_ml_base = mlb; zstd_ml_bits = mlx
|
||||
rt_zstd_st.zstd_ll_base = llb; rt_zstd_st.zstd_ll_bits = llx; rt_zstd_st.zstd_ml_base = mlb; rt_zstd_st.zstd_ml_bits = mlx
|
||||
}
|
||||
|
||||
# ---- Huffman literal decode ------------------------------------------------
|
||||
|
|
@ -384,63 +394,61 @@ function huf_build(weight: words, nweights: int) -> HufDT {
|
|||
|
||||
# parse a Huffman tree description at zf_pos (forward); returns the HufDT and
|
||||
# leaves zf_pos just past the description.
|
||||
function huf_read_tree() -> HufDT {
|
||||
let header = zf_src[zf_pos]
|
||||
zf_pos += 1
|
||||
function huf_read_tree(rt_zstd_st: mut RtZstdState) -> HufDT {
|
||||
let header = rt_zstd_st.zf_src[rt_zstd_st.zf_pos]
|
||||
rt_zstd_st.zf_pos += 1
|
||||
let weight = words(256)
|
||||
if header >= 128 { # direct: (header-127) 4-bit weights
|
||||
let n = header - 127
|
||||
var i = 0
|
||||
while i < n {
|
||||
let bpos = zf_pos + (i >> 1)
|
||||
let bpos = rt_zstd_st.zf_pos + (i >> 1)
|
||||
var w = 0
|
||||
if (i & 1) == 0 { w = zf_src[bpos] >> 4 } else { w = zf_src[bpos] & 15 }
|
||||
if (i & 1) == 0 { w = rt_zstd_st.zf_src[bpos] >> 4 } else { w = rt_zstd_st.zf_src[bpos] & 15 }
|
||||
weight[i] = w
|
||||
i += 1
|
||||
}
|
||||
zf_pos = zf_pos + ((n + 1) >> 1)
|
||||
rt_zstd_st.zf_pos = rt_zstd_st.zf_pos + ((n + 1) >> 1)
|
||||
return huf_build(weight, n)
|
||||
}
|
||||
# FSE-compressed weights: header = compressed size; decode via a fresh FSE.
|
||||
# This path is not yet bit-exact, so flag it and let z_zstd bail with -1 rather
|
||||
# than emit wrong literals (a low-entropy tilemap uses raw literals, not this).
|
||||
zstd_err = 1
|
||||
let cstart = zf_pos
|
||||
rt_zstd_st.zstd_err = 1
|
||||
let cstart = rt_zstd_st.zf_pos
|
||||
let norm = words(256)
|
||||
let log = fse_read_ncount(norm, 255) # forward table description
|
||||
let wt = fse_build(norm, fse_ncount_n, log)
|
||||
let log = fse_read_ncount(rt_zstd_st, norm, 255) # forward table description
|
||||
let wt = fse_build(norm, rt_zstd_st.fse_ncount_n, log)
|
||||
# the weight bitstream runs from the byte after the ncount to cstart+header
|
||||
zb_init(zf_src, zf_bytepos(), cstart + header - zf_bytepos())
|
||||
let n = fse_decompress(wt, weight, 256)
|
||||
zf_pos = cstart + header
|
||||
zb_init(rt_zstd_st, rt_zstd_st.zf_src, zf_bytepos(rt_zstd_st), cstart + header - zf_bytepos(rt_zstd_st))
|
||||
let n = fse_decompress(rt_zstd_st, wt, weight, 256)
|
||||
rt_zstd_st.zf_pos = cstart + header
|
||||
return huf_build(weight, n)
|
||||
}
|
||||
|
||||
# decode `n` Huffman symbols from a backward stream already init'd into out.
|
||||
function huf_decode_stream(dt: HufDT, out: pointer, at: int, n: int) -> void {
|
||||
function huf_decode_stream(rt_zstd_st: mut RtZstdState, dt: HufDT, out: pointer, at: int, n: int) -> void {
|
||||
var i = 0
|
||||
while i < n {
|
||||
let bits = zstd_peek_rev(dt.maxbits)
|
||||
let bits = zstd_peek_rev(rt_zstd_st, dt.maxbits)
|
||||
out[at + i] = dt.sym[bits]
|
||||
zb_cur += dt.nb[bits]
|
||||
rt_zstd_st.zb_cur += dt.nb[bits]
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
# peek maxbits bits (MSB-first) without consuming — for the Huffman table index.
|
||||
function zstd_peek_rev(n: int) -> int {
|
||||
let save = zb_cur
|
||||
let v = zb_read(n)
|
||||
zb_cur = save
|
||||
function zstd_peek_rev(rt_zstd_st: mut RtZstdState, n: int) -> int {
|
||||
let save = rt_zstd_st.zb_cur
|
||||
let v = zb_read(rt_zstd_st, n)
|
||||
rt_zstd_st.zb_cur = save
|
||||
return v
|
||||
}
|
||||
|
||||
# ---- literals section ------------------------------------------------------
|
||||
# decoded literals live here; zstd_lit_decode fills them and returns the byte
|
||||
# offset where the sequences section begins.
|
||||
var zstd_lit: pointer = null
|
||||
var zstd_litn: int = 0
|
||||
|
||||
function zstd_lit_decode(src: pointer, pos: int, blockend: int) -> int {
|
||||
function zstd_lit_decode(rt_zstd_st: mut RtZstdState, src: pointer, pos: int, blockend: int) -> int {
|
||||
let lb = src[pos]
|
||||
let ltype = lb & 3
|
||||
let sf = (lb >> 2) & 3
|
||||
|
|
@ -457,8 +465,8 @@ function zstd_lit_decode(src: pointer, pos: int, blockend: int) -> int {
|
|||
hdr = 3
|
||||
} }
|
||||
if ltype == 0 { # raw literals: copy regen bytes
|
||||
zstd_lit = offset(src, pos + hdr)
|
||||
zstd_litn = regen
|
||||
rt_zstd_st.zstd_lit = offset(src, pos + hdr)
|
||||
rt_zstd_st.zstd_litn = regen
|
||||
return pos + hdr + regen
|
||||
}
|
||||
if ltype == 1 { # RLE literals: one byte * regen
|
||||
|
|
@ -466,17 +474,16 @@ function zstd_lit_decode(src: pointer, pos: int, blockend: int) -> int {
|
|||
let b = src[pos + hdr]
|
||||
var i = 0
|
||||
while i < regen { buf[i] = b; i += 1 }
|
||||
zstd_lit = buf
|
||||
zstd_litn = regen
|
||||
rt_zstd_st.zstd_lit = buf
|
||||
rt_zstd_st.zstd_litn = regen
|
||||
return pos + hdr + 1
|
||||
}
|
||||
# Huffman literals (ltype 2 compressed, 3 treeless) — a 3/4/5-byte header with
|
||||
# regenerated + compressed sizes and 1 or 4 streams.
|
||||
return zstd_lit_huff(src, pos, ltype, sf)
|
||||
return zstd_lit_huff(rt_zstd_st, src, pos, ltype, sf)
|
||||
}
|
||||
|
||||
var zstd_huf_prev: HufDT = null
|
||||
function zstd_lit_huff(src: pointer, pos: int, ltype: int, sf: int) -> int {
|
||||
function zstd_lit_huff(rt_zstd_st: mut RtZstdState, src: pointer, pos: int, ltype: int, sf: int) -> int {
|
||||
var regen = 0
|
||||
var comp = 0
|
||||
var hdr = 0
|
||||
|
|
@ -497,22 +504,22 @@ function zstd_lit_huff(src: pointer, pos: int, ltype: int, sf: int) -> int {
|
|||
hdr = 5
|
||||
} } }
|
||||
let buf = bytes(regen + 4)
|
||||
zstd_lit = buf
|
||||
zstd_litn = regen
|
||||
rt_zstd_st.zstd_lit = buf
|
||||
rt_zstd_st.zstd_litn = regen
|
||||
var hs = pos + hdr # start of the Huffman payload
|
||||
var payn = comp
|
||||
var dt = zstd_huf_prev
|
||||
var dt = rt_zstd_st.zstd_huf_prev
|
||||
if ltype == 2 { # compressed: read the tree first
|
||||
zf_init(src, hs)
|
||||
dt = huf_read_tree()
|
||||
let treesize = zf_bytepos() - hs
|
||||
zf_init(rt_zstd_st, src, hs)
|
||||
dt = huf_read_tree(rt_zstd_st)
|
||||
let treesize = zf_bytepos(rt_zstd_st) - hs
|
||||
hs += treesize
|
||||
payn = comp - treesize
|
||||
zstd_huf_prev = dt
|
||||
rt_zstd_st.zstd_huf_prev = dt
|
||||
}
|
||||
if streams == 1 {
|
||||
zb_init(src, hs, payn)
|
||||
huf_decode_stream(dt, buf, 0, regen)
|
||||
zb_init(rt_zstd_st, src, hs, payn)
|
||||
huf_decode_stream(rt_zstd_st, dt, buf, 0, regen)
|
||||
} else {
|
||||
# 4 streams with a 6-byte jump table (three 16-bit sizes; the 4th is derived)
|
||||
let s1 = src[hs] | (src[hs + 1] << 8)
|
||||
|
|
@ -521,78 +528,74 @@ function zstd_lit_huff(src: pointer, pos: int, ltype: int, sf: int) -> int {
|
|||
let s4 = payn - 6 - s1 - s2 - s3
|
||||
let seg = (regen + 3) / 4
|
||||
var o = hs + 6
|
||||
zb_init(src, o, s1); huf_decode_stream(dt, buf, 0, seg)
|
||||
zb_init(rt_zstd_st, src, o, s1); huf_decode_stream(rt_zstd_st, dt, buf, 0, seg)
|
||||
o += s1
|
||||
zb_init(src, o, s2); huf_decode_stream(dt, buf, seg, seg)
|
||||
zb_init(rt_zstd_st, src, o, s2); huf_decode_stream(rt_zstd_st, dt, buf, seg, seg)
|
||||
o += s2
|
||||
zb_init(src, o, s3); huf_decode_stream(dt, buf, 2 * seg, seg)
|
||||
zb_init(rt_zstd_st, src, o, s3); huf_decode_stream(rt_zstd_st, dt, buf, 2 * seg, seg)
|
||||
o += s3
|
||||
zb_init(src, o, s4); huf_decode_stream(dt, buf, 3 * seg, regen - 3 * seg)
|
||||
zb_init(rt_zstd_st, src, o, s4); huf_decode_stream(rt_zstd_st, dt, buf, 3 * seg, regen - 3 * seg)
|
||||
}
|
||||
return pos + hdr + comp
|
||||
}
|
||||
|
||||
# ---- sequences + execution (exact port of ZSTD_decodeSequence) -------------
|
||||
var zstd_rep0: int = 1
|
||||
var zstd_rep1: int = 4
|
||||
var zstd_rep2: int = 8
|
||||
var zstd_seq_sp: int = 0
|
||||
|
||||
# build a sequence SeqDT for a symbol type from its compression mode:
|
||||
# 0 predefined, 1 RLE, 2 FSE-described (forward table desc), 3 repeat previous.
|
||||
# `kind` selects the baseline tables for RLE / mode-2: 0 = LL, 1 = OF, 2 = ML.
|
||||
function zstd_seq_table(src: pointer, sp: int, mode: int, kind: int, prev: SeqDT) -> SeqDT {
|
||||
function zstd_seq_table(rt_zstd_st: mut RtZstdState, src: pointer, sp: int, mode: int, kind: int, prev: SeqDT) -> SeqDT {
|
||||
if mode == 0 {
|
||||
zstd_seq_sp = sp
|
||||
if kind == 0 { return zstd_predef_ll() }
|
||||
if kind == 1 { return zstd_predef_of() }
|
||||
return zstd_predef_ml()
|
||||
rt_zstd_st.zstd_seq_sp = sp
|
||||
if kind == 0 { return zstd_predef_ll(rt_zstd_st) }
|
||||
if kind == 1 { return zstd_predef_of(rt_zstd_st) }
|
||||
return zstd_predef_ml(rt_zstd_st)
|
||||
}
|
||||
if mode == 3 { zstd_seq_sp = sp; return prev }
|
||||
if mode == 3 { rt_zstd_st.zstd_seq_sp = sp; return prev }
|
||||
if mode == 1 { # RLE: a single symbol byte
|
||||
let sym = src[sp]
|
||||
zstd_seq_sp = sp + 1
|
||||
rt_zstd_st.zstd_seq_sp = sp + 1
|
||||
let dt = new SeqDT
|
||||
dt.log = 0; dt.base = words(1); dt.addbits = words(1); dt.nb = words(1); dt.ns = words(1)
|
||||
dt.base[0] = zstd_seq_base(kind, sym); dt.addbits[0] = zstd_seq_bits(kind, sym)
|
||||
dt.base[0] = zstd_seq_base(rt_zstd_st, kind, sym); dt.addbits[0] = zstd_seq_bits(rt_zstd_st, kind, sym)
|
||||
dt.nb[0] = 0; dt.ns[0] = 0
|
||||
return dt
|
||||
}
|
||||
# mode 2: FSE table description (forward), build, then map base/addbits per symbol
|
||||
let norm = words(256)
|
||||
zf_init(src, sp)
|
||||
let log = fse_read_ncount(norm, 255)
|
||||
zstd_seq_sp = zf_bytepos()
|
||||
let ft = fse_build(norm, fse_ncount_n, log)
|
||||
zf_init(rt_zstd_st, src, sp)
|
||||
let log = fse_read_ncount(rt_zstd_st, norm, 255)
|
||||
rt_zstd_st.zstd_seq_sp = zf_bytepos(rt_zstd_st)
|
||||
let ft = fse_build(norm, rt_zstd_st.fse_ncount_n, log)
|
||||
let size = 1 << log
|
||||
let dt = new SeqDT
|
||||
dt.log = log; dt.base = words(size); dt.addbits = words(size); dt.nb = ft.nb; dt.ns = ft.ns
|
||||
var u = 0
|
||||
while u < size {
|
||||
dt.base[u] = zstd_seq_base(kind, ft.sym[u])
|
||||
dt.addbits[u] = zstd_seq_bits(kind, ft.sym[u])
|
||||
dt.base[u] = zstd_seq_base(rt_zstd_st, kind, ft.sym[u])
|
||||
dt.addbits[u] = zstd_seq_bits(rt_zstd_st, kind, ft.sym[u])
|
||||
u += 1
|
||||
}
|
||||
return dt
|
||||
}
|
||||
|
||||
# baseline / extra-bit tables per symbol type for RLE + FSE-described tables.
|
||||
function zstd_seq_base(kind: int, sym: int) -> int {
|
||||
if kind == 0 { return zstd_ll_base[sym] }
|
||||
if kind == 2 { return zstd_ml_base[sym] }
|
||||
function zstd_seq_base(rt_zstd_st: RtZstdState, kind: int, sym: int) -> int {
|
||||
if kind == 0 { return rt_zstd_st.zstd_ll_base[sym] }
|
||||
if kind == 2 { return rt_zstd_st.zstd_ml_base[sym] }
|
||||
return 1 << sym # OF: offset base = 1<<code
|
||||
}
|
||||
function zstd_seq_bits(kind: int, sym: int) -> int {
|
||||
if kind == 0 { return zstd_ll_bits[sym] }
|
||||
if kind == 2 { return zstd_ml_bits[sym] }
|
||||
function zstd_seq_bits(rt_zstd_st: RtZstdState, kind: int, sym: int) -> int {
|
||||
if kind == 0 { return rt_zstd_st.zstd_ll_bits[sym] }
|
||||
if kind == 2 { return rt_zstd_st.zstd_ml_bits[sym] }
|
||||
return sym # OF: extra bits = code
|
||||
}
|
||||
|
||||
# decode one compressed block's literals + sequences into out[opos..].
|
||||
function zstd_decomp_block(src: pointer, bstart: int, bsize: int, out: pointer, opos: int, cap: int) -> int {
|
||||
zstd_seq_tables_init()
|
||||
function zstd_decomp_block(rt_zstd_st: mut RtZstdState, src: pointer, bstart: int, bsize: int, out: pointer, opos: int, cap: int) -> int {
|
||||
zstd_seq_tables_init(rt_zstd_st)
|
||||
let blockend = bstart + bsize
|
||||
var sp = zstd_lit_decode(src, bstart, blockend)
|
||||
var sp = zstd_lit_decode(rt_zstd_st, src, bstart, blockend)
|
||||
var nseq = src[sp]
|
||||
if nseq < 128 { sp += 1 }
|
||||
else { if nseq < 255 { nseq = ((nseq - 128) << 8) + src[sp + 1]; sp += 2 }
|
||||
|
|
@ -601,21 +604,21 @@ function zstd_decomp_block(src: pointer, bstart: int, bsize: int, out: pointer,
|
|||
var litpos = 0
|
||||
if nseq == 0 {
|
||||
var i = 0
|
||||
while i < zstd_litn { out[op] = zstd_lit[i]; op += 1; i += 1 }
|
||||
while i < rt_zstd_st.zstd_litn { out[op] = rt_zstd_st.zstd_lit[i]; op += 1; i += 1 }
|
||||
return op
|
||||
}
|
||||
let modes = src[sp]; sp += 1
|
||||
let llmode = (modes >> 6) & 3
|
||||
let ofmode = (modes >> 4) & 3
|
||||
let mlmode = (modes >> 2) & 3
|
||||
let llt = zstd_seq_table(src, sp, llmode, 0, null); sp = zstd_seq_sp
|
||||
let oft = zstd_seq_table(src, sp, ofmode, 1, null); sp = zstd_seq_sp
|
||||
let mlt = zstd_seq_table(src, sp, mlmode, 2, null); sp = zstd_seq_sp
|
||||
zstd_rep0 = 1; zstd_rep1 = 4; zstd_rep2 = 8
|
||||
zb_init(src, sp, blockend - sp)
|
||||
var llstate = zb_read(llt.log)
|
||||
var ofstate = zb_read(oft.log)
|
||||
var mlstate = zb_read(mlt.log)
|
||||
let llt = zstd_seq_table(rt_zstd_st, src, sp, llmode, 0, null); sp = rt_zstd_st.zstd_seq_sp
|
||||
let oft = zstd_seq_table(rt_zstd_st, src, sp, ofmode, 1, null); sp = rt_zstd_st.zstd_seq_sp
|
||||
let mlt = zstd_seq_table(rt_zstd_st, src, sp, mlmode, 2, null); sp = rt_zstd_st.zstd_seq_sp
|
||||
rt_zstd_st.zstd_rep0 = 1; rt_zstd_st.zstd_rep1 = 4; rt_zstd_st.zstd_rep2 = 8
|
||||
zb_init(rt_zstd_st, src, sp, blockend - sp)
|
||||
var llstate = zb_read(rt_zstd_st, llt.log)
|
||||
var ofstate = zb_read(rt_zstd_st, oft.log)
|
||||
var mlstate = zb_read(rt_zstd_st, mlt.log)
|
||||
var q = 0
|
||||
while q < nseq {
|
||||
var matchLen = mlt.base[mlstate]
|
||||
|
|
@ -628,46 +631,45 @@ function zstd_decomp_block(src: pointer, bstart: int, bsize: int, out: pointer,
|
|||
if llt.base[llstate] == 0 { ll0 = 1 }
|
||||
var offset = 0
|
||||
if ofBits > 1 {
|
||||
offset = ofBase + zb_read(ofBits)
|
||||
zstd_rep2 = zstd_rep1; zstd_rep1 = zstd_rep0; zstd_rep0 = offset
|
||||
offset = ofBase + zb_read(rt_zstd_st, ofBits)
|
||||
rt_zstd_st.zstd_rep2 = rt_zstd_st.zstd_rep1; rt_zstd_st.zstd_rep1 = rt_zstd_st.zstd_rep0; rt_zstd_st.zstd_rep0 = offset
|
||||
} else {
|
||||
if ofBits == 0 {
|
||||
if ll0 == 1 { offset = zstd_rep1; zstd_rep1 = zstd_rep0; zstd_rep0 = offset }
|
||||
else { offset = zstd_rep0 }
|
||||
if ll0 == 1 { offset = rt_zstd_st.zstd_rep1; rt_zstd_st.zstd_rep1 = rt_zstd_st.zstd_rep0; rt_zstd_st.zstd_rep0 = offset }
|
||||
else { offset = rt_zstd_st.zstd_rep0 }
|
||||
} else {
|
||||
let ov = ofBase + ll0 + zb_read(1)
|
||||
let ov = ofBase + ll0 + zb_read(rt_zstd_st, 1)
|
||||
var temp = 0
|
||||
if ov == 1 { temp = zstd_rep1 }
|
||||
else { if ov == 3 { temp = zstd_rep0 - 1 }
|
||||
else { if ov >= 2 { temp = zstd_rep2 } else { temp = zstd_rep0 } } }
|
||||
if ov == 1 { temp = rt_zstd_st.zstd_rep1 }
|
||||
else { if ov == 3 { temp = rt_zstd_st.zstd_rep0 - 1 }
|
||||
else { if ov >= 2 { temp = rt_zstd_st.zstd_rep2 } else { temp = rt_zstd_st.zstd_rep0 } } }
|
||||
if temp == 0 { temp = -1 }
|
||||
if ov == 1 { } else { zstd_rep2 = zstd_rep1 }
|
||||
zstd_rep1 = zstd_rep0
|
||||
zstd_rep0 = temp
|
||||
if ov == 1 { } else { rt_zstd_st.zstd_rep2 = rt_zstd_st.zstd_rep1 }
|
||||
rt_zstd_st.zstd_rep1 = rt_zstd_st.zstd_rep0
|
||||
rt_zstd_st.zstd_rep0 = temp
|
||||
offset = temp
|
||||
}
|
||||
}
|
||||
if mlBits > 0 { matchLen += zb_read(mlBits) }
|
||||
if llBits > 0 { litLen += zb_read(llBits) }
|
||||
if mlBits > 0 { matchLen += zb_read(rt_zstd_st, mlBits) }
|
||||
if llBits > 0 { litLen += zb_read(rt_zstd_st, llBits) }
|
||||
var i = 0
|
||||
while i < litLen { out[op] = zstd_lit[litpos]; op += 1; litpos += 1; i += 1 }
|
||||
while i < litLen { out[op] = rt_zstd_st.zstd_lit[litpos]; op += 1; litpos += 1; i += 1 }
|
||||
var k = 0
|
||||
while k < matchLen { out[op] = out[op - offset]; op += 1; k += 1 }
|
||||
q += 1
|
||||
if q < nseq {
|
||||
llstate = llt.ns[llstate] + zb_read(llt.nb[llstate])
|
||||
mlstate = mlt.ns[mlstate] + zb_read(mlt.nb[mlstate])
|
||||
ofstate = oft.ns[ofstate] + zb_read(oft.nb[ofstate])
|
||||
llstate = llt.ns[llstate] + zb_read(rt_zstd_st, llt.nb[llstate])
|
||||
mlstate = mlt.ns[mlstate] + zb_read(rt_zstd_st, mlt.nb[mlstate])
|
||||
ofstate = oft.ns[ofstate] + zb_read(rt_zstd_st, oft.nb[ofstate])
|
||||
}
|
||||
}
|
||||
while litpos < zstd_litn { out[op] = zstd_lit[litpos]; op += 1; litpos += 1 }
|
||||
while litpos < rt_zstd_st.zstd_litn { out[op] = rt_zstd_st.zstd_lit[litpos]; op += 1; litpos += 1 }
|
||||
return op
|
||||
}
|
||||
|
||||
# ---- frame / block loop ----------------------------------------------------
|
||||
var zstd_err: int = 0
|
||||
# decompress a single zstd frame. Returns bytes written, or -1.
|
||||
function z_zstd(src: pointer, len: int, out: pointer, cap: int) -> int {
|
||||
function z_zstd(rt_zstd_st: mut RtZstdState, src: pointer, len: int, out: pointer, cap: int) -> int {
|
||||
if len < 6 { return -1 }
|
||||
if src[0] != '(' { return -1 } # 0x28
|
||||
if src[1] != 181 { return -1 } # 0xB5
|
||||
|
|
@ -687,9 +689,9 @@ function z_zstd(src: pointer, len: int, out: pointer, cap: int) -> int {
|
|||
if fcsFlag == 2 { pos += 4 }
|
||||
if fcsFlag == 3 { pos += 8 }
|
||||
# reset the repeat offsets per frame
|
||||
zstd_rep0 = 1; zstd_rep1 = 4; zstd_rep2 = 8
|
||||
zstd_huf_prev = null
|
||||
zstd_err = 0
|
||||
rt_zstd_st.zstd_rep0 = 1; rt_zstd_st.zstd_rep1 = 4; rt_zstd_st.zstd_rep2 = 8
|
||||
rt_zstd_st.zstd_huf_prev = null
|
||||
rt_zstd_st.zstd_err = 0
|
||||
var op = 0
|
||||
var last = 0
|
||||
while last == 0 {
|
||||
|
|
@ -709,11 +711,11 @@ function z_zstd(src: pointer, len: int, out: pointer, cap: int) -> int {
|
|||
while i < bsize { out[op] = b; op += 1; i += 1 }
|
||||
pos += 1
|
||||
} else { if btype == 2 { # compressed block
|
||||
op = zstd_decomp_block(src, pos, bsize, out, op, cap)
|
||||
op = zstd_decomp_block(rt_zstd_st, src, pos, bsize, out, op, cap)
|
||||
pos += bsize
|
||||
} else { return -1 } } } # reserved
|
||||
if op > cap { return -1 }
|
||||
if zstd_err != 0 { return -1 }
|
||||
if rt_zstd_st.zstd_err != 0 { return -1 }
|
||||
}
|
||||
return op
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue