diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c index 761ff3f3d..04f91d03d 100644 --- a/release/c/wuffs-unsupported-snapshot.c +++ b/release/c/wuffs-unsupported-snapshot.c @@ -2965,6 +2965,10 @@ sizeof__wuffs_deflate__decoder(); // ---------------- Public Function Prototypes +WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct // +wuffs_deflate__decoder__add_history(wuffs_deflate__decoder* self, + wuffs_base__slice_u8 a_hist); + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 // wuffs_deflate__decoder__workbuf_len(const wuffs_deflate__decoder* self); @@ -3083,6 +3087,11 @@ struct wuffs_deflate__decoder__struct { wuffs_version, initialize_flags); } + inline wuffs_base__empty_struct // + add_history(wuffs_base__slice_u8 a_hist) { + return wuffs_deflate__decoder__add_history(this, a_hist); + } + inline wuffs_base__range_ii_u64 // workbuf_len() const { return wuffs_deflate__decoder__workbuf_len(this); @@ -6373,6 +6382,53 @@ sizeof__wuffs_deflate__decoder() { // ---------------- Function Implementations +// -------- func deflate.decoder.add_history + +WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct // +wuffs_deflate__decoder__add_history(wuffs_deflate__decoder* self, + wuffs_base__slice_u8 a_hist) { + if (!self) { + return wuffs_base__make_empty_struct(); + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { + return wuffs_base__make_empty_struct(); + } + + wuffs_base__slice_u8 v_s = {0}; + uint64_t v_n_copied = 0; + uint32_t v_already_full = 0; + + v_s = a_hist; + if (((uint64_t)(v_s.len)) >= 32768) { + v_s = wuffs_base__slice_u8__suffix(v_s, 32768); + wuffs_base__slice_u8__copy_from_slice( + wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s); + self->private_impl.f_history_index = 32768; + } else { + v_n_copied = wuffs_base__slice_u8__copy_from_slice( + wuffs_base__slice_u8__subslice_i( + wuffs_base__make_slice_u8(self->private_data.f_history, 32768), + (self->private_impl.f_history_index & 32767)), + v_s); + if (v_n_copied < ((uint64_t)(v_s.len))) { + v_s = wuffs_base__slice_u8__subslice_i(v_s, v_n_copied); + v_n_copied = wuffs_base__slice_u8__copy_from_slice( + wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s); + self->private_impl.f_history_index = + (((uint32_t)((v_n_copied & 32767))) + 32768); + } else { + v_already_full = 0; + if (self->private_impl.f_history_index >= 32768) { + v_already_full = 32768; + } + self->private_impl.f_history_index = + ((self->private_impl.f_history_index & 32767) + + ((uint32_t)((v_n_copied & 32767))) + v_already_full); + } + } + return wuffs_base__make_empty_struct(); +} + // -------- func deflate.decoder.workbuf_len WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 // @@ -6417,9 +6473,6 @@ wuffs_deflate__decoder__decode_io_writer(wuffs_deflate__decoder* self, uint64_t v_mark = 0; wuffs_base__status v_status = NULL; - wuffs_base__slice_u8 v_written = {0}; - uint64_t v_n_copied = 0; - uint32_t v_already_full = 0; uint8_t* iop_a_dst = NULL; uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; @@ -6464,37 +6517,9 @@ wuffs_deflate__decoder__decode_io_writer(wuffs_deflate__decoder* self, } goto ok; } - v_written = wuffs_base__io__since( - v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst); - if (((uint64_t)(v_written.len)) >= 32768) { - v_written = wuffs_base__slice_u8__suffix(v_written, 32768); - wuffs_base__slice_u8__copy_from_slice( - wuffs_base__make_slice_u8(self->private_data.f_history, 32768), - v_written); - self->private_impl.f_history_index = 32768; - } else { - v_n_copied = wuffs_base__slice_u8__copy_from_slice( - wuffs_base__slice_u8__subslice_i( - wuffs_base__make_slice_u8(self->private_data.f_history, 32768), - (self->private_impl.f_history_index & 32767)), - v_written); - if (v_n_copied < ((uint64_t)(v_written.len))) { - v_written = wuffs_base__slice_u8__subslice_i(v_written, v_n_copied); - v_n_copied = wuffs_base__slice_u8__copy_from_slice( - wuffs_base__make_slice_u8(self->private_data.f_history, 32768), - v_written); - self->private_impl.f_history_index = - (((uint32_t)((v_n_copied & 32767))) + 32768); - } else { - v_already_full = 0; - if (self->private_impl.f_history_index >= 32768) { - v_already_full = 32768; - } - self->private_impl.f_history_index = - ((self->private_impl.f_history_index & 32767) + - ((uint32_t)((v_n_copied & 32767))) + v_already_full); - } - } + wuffs_deflate__decoder__add_history( + self, wuffs_base__io__since( + v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); status = v_status; WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); } diff --git a/std/deflate/decode_deflate.wuffs b/std/deflate/decode_deflate.wuffs index 89117ab52..fa3cc06a6 100644 --- a/std/deflate/decode_deflate.wuffs +++ b/std/deflate/decode_deflate.wuffs @@ -132,6 +132,49 @@ pub struct decoder?( code_lengths array[320] base.u8, ) +pub func decoder.add_history!(hist slice base.u8) { + var s slice base.u8 + var n_copied base.u64 + var already_full base.u32[..0x8000] + + s = args.hist + if s.length() >= 0x8000 { + // If s is longer than the ringbuffer, we can ignore the previous value + // of history_index, as we will overwrite the whole ringbuffer. + s = s.suffix(up_to:0x8000) + this.history[:].copy_from_slice!(s:s) + this.history_index = 0x8000 + } else { + // Otherwise, append s to the history ringbuffer starting at the + // previous history_index (modulo 0x8000). + n_copied = this.history[this.history_index & 0x7FFF:].copy_from_slice!(s:s) + if n_copied < s.length() { + // a_slice.copy_from(s:b_slice) returns the minimum of the two + // slice lengths. If that value is less than b_slice.length(), then + // not all of b_slice was copied. + // + // In terms of the history ringbuffer, that means that we have to + // wrap around and copy the remainder of s over the start of the + // history ringbuffer. + s = s[n_copied:] + n_copied = this.history[:].copy_from_slice!(s:s) + // Set history_index (modulo 0x8000) to the length of this + // remainder. The &0x7FFF is redundant, but proves to the compiler + // that the conversion to u32 will not overflow. The +0x8000 is to + // maintain that the history ringbuffer is full if and only if + // history_index >= 0x8000. + this.history_index = ((n_copied & 0x7FFF) as base.u32) + 0x8000 + } else { + // We didn't need to wrap around. + already_full = 0 + if this.history_index >= 0x8000 { + already_full = 0x8000 + } + this.history_index = (this.history_index & 0x7FFF) + ((n_copied & 0x7FFF) as base.u32) + already_full + } + } +} + pub func decoder.workbuf_len() base.range_ii_u64 { return this.util.make_range_ii_u64( min_incl:decoder_workbuf_len_max_incl_worst_case, @@ -139,11 +182,8 @@ pub func decoder.workbuf_len() base.range_ii_u64 { } pub func decoder.decode_io_writer?(dst base.io_writer, src base.io_reader, workbuf slice base.u8) { - var mark base.u64 - var status base.status - var written slice base.u8 - var n_copied base.u64 - var already_full base.u32[..0x8000] + var mark base.u64 + var status base.status while true { mark = args.dst.mark() @@ -154,44 +194,7 @@ pub func decoder.decode_io_writer?(dst base.io_writer, src base.io_reader, workb // TODO: should "since" be "since!", as the return value lets you // modify the state of args.dst, so future mutations (via the slice) // can change the veracity of any args.dst assertions? - written = args.dst.since(mark:mark) - // Append written, the decoded output, to the history ringbuffer. - if written.length() >= 0x8000 { - // If written is longer than the ringbuffer, we can ignore the - // previous value of history_index, as we will overwrite the whole - // ringbuffer. - written = written.suffix(up_to:0x8000) - this.history[:].copy_from_slice!(s:written) - this.history_index = 0x8000 - } else { - // Otherwise, append written to the history ringbuffer starting at - // the previous history_index (modulo 0x8000). - n_copied = this.history[this.history_index & 0x7FFF:].copy_from_slice!(s:written) - if n_copied < written.length() { - // a_slice.copy_from(s:b_slice) returns the minimum of the two - // slice lengths. If that value is less than b_slice.length(), - // then not all of b_slice was copied. - // - // In terms of the history ringbuffer, that means that we have - // to wrap around and copy the remainder of written over the - // start of the history ringbuffer. - written = written[n_copied:] - n_copied = this.history[:].copy_from_slice!(s:written) - // Set history_index (modulo 0x8000) to the length of this - // remainder. The &0x7FFF is redundant, but proves to the - // compiler that the conversion to u32 will not overflow. The - // +0x8000 is to maintain that the history ringbuffer is full - // if and only if history_index >= 0x8000. - this.history_index = ((n_copied & 0x7FFF) as base.u32) + 0x8000 - } else { - // We didn't need to wrap around. - already_full = 0 - if this.history_index >= 0x8000 { - already_full = 0x8000 - } - this.history_index = (this.history_index & 0x7FFF) + ((n_copied & 0x7FFF) as base.u32) + already_full - } - } + this.add_history!(hist:args.dst.since(mark:mark)) yield? status } }