Index: src/0dev.org/predictor/predictor.go ================================================================== --- src/0dev.org/predictor/predictor.go +++ src/0dev.org/predictor/predictor.go @@ -16,12 +16,12 @@ // The following hash code is the heart of the algorithm: // It builds a sliding hash sum of the previous 3-and-a-bit // characters which will be used to index the guess table. // A better hash function would result in additional compression, // at the expense of time. -func (ctx *context) update(val uint16) { - ctx.hash = (ctx.hash << 4) ^ val +func (ctx *context) update(val byte) { + ctx.hash = (ctx.hash << 4) ^ uint16(val) } type compressor func([]byte) error func (w compressor) Write(data []byte) (int, error) { @@ -92,11 +92,11 @@ } else { // Guess was wrong, output char ctx.table[ctx.hash] = current buf = append(buf, current) } - ctx.update(uint16(current)) + ctx.update(current) } if _, err := writer.Write(buf); err != nil { return err } @@ -148,10 +148,12 @@ if len(ctx.input) > 0 { rc = copy(output, ctx.input) // Check whether we still have leftover data in the buffer :) if rc < len(ctx.input) { + // Shift the remaining bytes at the start of the buffer + // and resize the buffer accordingly ctx.input = ctx.input[:copy(ctx.input, ctx.input[rc:])] } return rc, nil } @@ -190,36 +192,37 @@ for i, a := 0, predicted; i < rc; i++ { if (flags & (1 << uint(i))) > 0 { // Guess succeeded, fill in from the table ctx.input[i] = ctx.table[ctx.hash] } else { - // Relocate a read byte + // Relocate a read byte and advance the read byte index ctx.input[i], a = ctx.input[a], a+1 // Guess failed, update the table ctx.table[ctx.hash] = ctx.input[i] } // Update the hash - ctx.update(uint16(ctx.input[i])) + ctx.update(ctx.input[i]) } - // Copy the decompressed data to the output - ctx.input = ctx.input[:rc] - copied = copy(output, ctx.input) - + // Copy the decompressed data to the output and accumulate the count + copied = copy(output, ctx.input[:rc]) total += copied // Check for remaining bytes that dont fit in the output buffer if copied < rc { - ctx.input = ctx.input[:copy(ctx.input, ctx.input[copied:])] + // Shift the remaining bytes at the start of the buffer + // and resize the buffer accordingly + ctx.input = ctx.input[:copy(ctx.input, ctx.input[copied:rc])] } else { // Clear the buffer ctx.input = ctx.input[:0] + // Loop for another pass if there is available space in the output output = output[copied:] if len(output) > 0 && err == nil { goto readHeader } } return total, err }) }