Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,92 @@
|
||||
module lz
|
||||
|
||||
// compress_lzw compresses data using a pure-V LZW dictionary stream.
|
||||
pub fn compress_lzw(data []u8) ![]u8 {
|
||||
mut payload := []u8{}
|
||||
mut dict := map[string]int{}
|
||||
for i in 0 .. 256 {
|
||||
dict[[u8(i)].bytestr()] = i
|
||||
}
|
||||
mut next_code := 256
|
||||
mut word := ''
|
||||
|
||||
for b in data {
|
||||
symbol := [b].bytestr()
|
||||
candidate := word + symbol
|
||||
if candidate in dict {
|
||||
word = candidate
|
||||
continue
|
||||
}
|
||||
if word != '' {
|
||||
encode_uvarint(mut payload, u64(dict[word]))
|
||||
}
|
||||
dict[candidate] = next_code
|
||||
next_code++
|
||||
word = symbol
|
||||
}
|
||||
|
||||
if word != '' {
|
||||
encode_uvarint(mut payload, u64(dict[word]))
|
||||
}
|
||||
|
||||
return wrap_payload(.lzw, data, payload)
|
||||
}
|
||||
|
||||
// decompress_lzw decompresses data produced by compress_lzw.
|
||||
pub fn decompress_lzw(data []u8) ![]u8 {
|
||||
payload, expected_len := unwrap_payload(data, .lzw)!
|
||||
if payload.len == 0 {
|
||||
if expected_len == i64(0) {
|
||||
return []u8{}
|
||||
}
|
||||
return error('invalid lzw stream: missing codes')
|
||||
}
|
||||
|
||||
mut dict := map[int][]u8{}
|
||||
for i in 0 .. 256 {
|
||||
dict[i] = [u8(i)]
|
||||
}
|
||||
mut next_code := 256
|
||||
mut pos := 0
|
||||
|
||||
first_code, next_pos, ok := decode_uvarint(payload, pos)
|
||||
if !ok {
|
||||
return error('invalid lzw stream: bad initial code')
|
||||
}
|
||||
pos = next_pos
|
||||
if int(first_code) !in dict {
|
||||
return error('invalid lzw stream: unknown initial code')
|
||||
}
|
||||
mut word := dict[int(first_code)].clone()
|
||||
mut out := word.clone()
|
||||
|
||||
for pos < payload.len {
|
||||
code_u64, new_pos, ok_code := decode_uvarint(payload, pos)
|
||||
if !ok_code {
|
||||
return error('invalid lzw stream: bad code')
|
||||
}
|
||||
pos = new_pos
|
||||
code := int(code_u64)
|
||||
mut entry := []u8{}
|
||||
if code in dict {
|
||||
entry = dict[code].clone()
|
||||
} else if code == next_code {
|
||||
entry = word.clone()
|
||||
entry << word[0]
|
||||
} else {
|
||||
return error('invalid lzw stream: unknown code')
|
||||
}
|
||||
|
||||
out << entry
|
||||
mut new_entry := word.clone()
|
||||
new_entry << entry[0]
|
||||
dict[next_code] = new_entry
|
||||
next_code++
|
||||
word = entry.clone()
|
||||
}
|
||||
|
||||
if i64(out.len) != expected_len {
|
||||
return error('invalid lzw stream: length mismatch')
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in new issue
Block a user