Factor out std/bzip2/decode_flush_slow.wuffs
diff --git a/std/bzip2/decode_bzip2.wuffs b/std/bzip2/decode_bzip2.wuffs index 177f281..64350c6 100644 --- a/std/bzip2/decode_bzip2.wuffs +++ b/std/bzip2/decode_bzip2.wuffs
@@ -698,69 +698,6 @@ } endwhile } -pri func decoder.flush_block?(dst: base.io_writer) { - var i : base.u32[..= 1_048575] - var n : base.u32 - var entry : base.u32 - var repeat_count : base.u32[..= 255] - var block_checksum_have : base.u32 - var prev : base.u8 - var curr : base.u8 - - if this.original_pointer >= this.block_size { - return "#bad block length" - } - assert this.original_pointer < 900000 via "a < b: a < c; c <= b"(c: this.block_size) - i = this.bwt[this.original_pointer] >> 12 - - block_checksum_have = 0xFFFF_FFFF - - n = 0 - while n < this.block_size { - assert n < 900000 via "a < b: a < c; c <= b"(c: this.block_size) - entry = this.bwt[i] - curr = (entry & 0xFF) as base.u8 - i = entry >> 12 - - if repeat_count >= 4 { - repeat_count = curr as base.u32 - while repeat_count > 0, - inv n < 900000, - { - block_checksum_have = - REV_CRC32_TABLE[((block_checksum_have >> 24) as base.u8) ^ prev] ^ - (block_checksum_have ~mod<< 8) - args.dst.write_u8?(a: prev) - repeat_count -= 1 - } endwhile - repeat_count = 0 - } else if curr <> prev { - repeat_count = 1 - block_checksum_have = - REV_CRC32_TABLE[((block_checksum_have >> 24) as base.u8) ^ curr] ^ - (block_checksum_have ~mod<< 8) - args.dst.write_u8?(a: curr) - } else { - repeat_count += 1 - block_checksum_have = - REV_CRC32_TABLE[((block_checksum_have >> 24) as base.u8) ^ curr] ^ - (block_checksum_have ~mod<< 8) - args.dst.write_u8?(a: curr) - } - - prev = curr - n += 1 - } endwhile - - block_checksum_have ^= 0xFFFF_FFFF - if block_checksum_have <> this.block_checksum_want { - return "#bad checksum" - } - this.final_checksum_have = block_checksum_have ^ ( - (this.final_checksum_have >> 31) | - (this.final_checksum_have ~mod<< 1)) -} - // The table below was created by script/print-crc32-magic-numbers.go with the // -reverse flag set.
diff --git a/std/bzip2/decode_flush_slow.wuffs b/std/bzip2/decode_flush_slow.wuffs new file mode 100644 index 0000000..33b21d2 --- /dev/null +++ b/std/bzip2/decode_flush_slow.wuffs
@@ -0,0 +1,76 @@ +// Copyright 2022 The Wuffs Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pri func decoder.flush_block?(dst: base.io_writer) { + var i : base.u32[..= 1_048575] + var n : base.u32 + var entry : base.u32 + var repeat_count : base.u32[..= 255] + var block_checksum_have : base.u32 + var prev : base.u8 + var curr : base.u8 + + if this.original_pointer >= this.block_size { + return "#bad block length" + } + assert this.original_pointer < 900000 via "a < b: a < c; c <= b"(c: this.block_size) + i = this.bwt[this.original_pointer] >> 12 + + block_checksum_have = 0xFFFF_FFFF + + n = 0 + while n < this.block_size { + assert n < 900000 via "a < b: a < c; c <= b"(c: this.block_size) + entry = this.bwt[i] + curr = (entry & 0xFF) as base.u8 + i = entry >> 12 + + if repeat_count >= 4 { + repeat_count = curr as base.u32 + while repeat_count > 0, + inv n < 900000, + { + block_checksum_have = + REV_CRC32_TABLE[((block_checksum_have >> 24) as base.u8) ^ prev] ^ + (block_checksum_have ~mod<< 8) + args.dst.write_u8?(a: prev) + repeat_count -= 1 + } endwhile + repeat_count = 0 + } else if curr <> prev { + repeat_count = 1 + block_checksum_have = + REV_CRC32_TABLE[((block_checksum_have >> 24) as base.u8) ^ curr] ^ + (block_checksum_have ~mod<< 8) + args.dst.write_u8?(a: curr) + } else { + repeat_count += 1 + block_checksum_have = + REV_CRC32_TABLE[((block_checksum_have >> 24) as base.u8) ^ curr] ^ + (block_checksum_have ~mod<< 8) + args.dst.write_u8?(a: curr) + } + + prev = curr + n += 1 + } endwhile + + block_checksum_have ^= 0xFFFF_FFFF + if block_checksum_have <> this.block_checksum_want { + return "#bad checksum" + } + this.final_checksum_have = block_checksum_have ^ ( + (this.final_checksum_have >> 31) | + (this.final_checksum_have ~mod<< 1)) +}