@@ -84,74 +84,73 @@ // Returns an io.Reader implementation that wraps the provided io.Reader // and decompresses data according to the predictor algorithm func Decompressor(reader io.Reader) io.Reader { var dcmp decompressor dcmp.source = reader - dcmp.input = make([]byte, 8) return iou.SizedReader(&dcmp, 8) } type decompressor struct { context source io.Reader - input []byte } // Note: this method does not implement the full io.Reader's Read() semantics func (ctx *decompressor) Read(output []byte) (int, error) { var ( - err error - flags, predicted byte - rc, total, copied int + err error + buffer []byte = make([]byte, 8) + flags byte + predicted, rc, total, copied int ) // Read the next prediction header readHeader: - rc, err = ctx.source.Read(ctx.input[:1]) + rc, err = ctx.source.Read(buffer[:1]) // Fail on error unless it is EOF if err != nil && err != io.EOF { return total, err } else if rc == 0 { return total, err } // Copy the prediction header and calculate the number of subsequent bytes to read - flags = ctx.input[0] + flags = buffer[0] predicted = bits.Hamming(flags) // Read the non-predicted bytes and place them in the end of the buffer - rc, err = ctx.source.Read(ctx.input[predicted:]) + rc, err = ctx.source.Read(buffer[predicted:]) retryData: - if rc < int(8-predicted) && err == nil { + if (rc < (8 - predicted)) && err == nil { // Retry the read if we have fewer bytes than what the prediction header indicates var r int - r, err = ctx.source.Read(ctx.input[int(predicted)+rc:]) + r, err = ctx.source.Read(buffer[predicted+rc:]) rc += r goto retryData } // Continue on any error, try to decompress and return it along the result // rc now contains the amount of actual bytes in this cycle (usually 8) - rc += int(predicted) + rc += predicted // Walk the buffer, filling in the predicted blanks, // relocating read bytes and and updating the guess table 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] + buffer[i] = ctx.table[ctx.hash] } else { // Relocate a read byte and advance the read byte index - ctx.input[i], a = ctx.input[a], a+1 + buffer[i], a = buffer[a], a+1 // Guess failed, update the table - ctx.table[ctx.hash] = ctx.input[i] + ctx.table[ctx.hash] = buffer[i] } // Update the hash - ctx.update(ctx.input[i]) + ctx.update(buffer[i]) } // Copy the decompressed data to the output and accumulate the count - copied = copy(output, ctx.input[:rc]) + copied = copy(output, buffer[:rc]) total += copied // Loop for another pass if there is available space in the output output = output[copied:] if len(output) > 0 && err == nil {