Skip to content

Commit

Permalink
Factor out deflate.decoder.add_history
Browse files Browse the repository at this point in the history
  • Loading branch information
nigeltao committed Sep 28, 2019
1 parent 344efe7 commit 498e1f4
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 77 deletions.
93 changes: 59 additions & 34 deletions release/c/wuffs-unsupported-snapshot.c
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 //
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
89 changes: 46 additions & 43 deletions std/deflate/decode_deflate.wuffs
Expand Up @@ -132,18 +132,58 @@ 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,
max_incl:decoder_workbuf_len_max_incl_worst_case)
}

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()
Expand All @@ -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
}
}
Expand Down

0 comments on commit 498e1f4

Please sign in to comment.