Index: src/0dev.org/predictor/predictor.go ================================================================== --- src/0dev.org/predictor/predictor.go +++ src/0dev.org/predictor/predictor.go @@ -122,13 +122,13 @@ var ctx context ctx.input = make([]byte, 0, 8) return decompressor(func(output []byte) (int, error) { var ( - err error - flags byte - rc, total int + err error + flags byte + i, rc, total int ) // Sanity check for space to read into if len(output) == 0 { return 0, nil @@ -143,22 +143,25 @@ ctx.input = ctx.input[:copy(ctx.input, ctx.input[rc:])] } return rc, nil } + loop: // Read the flags rc, err = reader.Read(ctx.input[:1]) - if rc == 0 || (err != nil && err != io.EOF) { - return rc, err + if err != nil && err != io.EOF { + return 0, err + } + if rc == 0 { + return total, err } ctx.input = ctx.input[:8] flags = ctx.input[0] - var i uint = 0 - for ; i < 8; i++ { - if flags&(1< 0 { + for i = 0; i < 8; i++ { + if flags&(1< 0 { // Guess was right ctx.input[i] = ctx.table[ctx.hash] } else { rc, err = reader.Read(ctx.input[i:(i + 1)]) @@ -165,11 +168,11 @@ if err == io.EOF { break } if err != nil { - return rc, err + return total, err } if rc == 0 { // treat as EoF break } @@ -179,18 +182,25 @@ ctx.hash = (ctx.hash << 4) ^ uint16(ctx.input[i]) } rc = copy(output, ctx.input[:i]) - total += rc // Place any remaining bytes in the buffer - if uint(rc) < i { + if rc < i { ctx.input = ctx.input[:copy(ctx.input, ctx.input[rc:i])] } else { + // Clear the buffer ctx.input = ctx.input[:0] + + // Advance the output buffer ... + output = output[i:] + // ... and decompress the next block if there is any space left + if len(output) > 0 && err != io.EOF { + goto loop + } } return total, err }) } Index: src/0dev.org/predictor/predictor_test.go ================================================================== --- src/0dev.org/predictor/predictor_test.go +++ src/0dev.org/predictor/predictor_test.go @@ -138,12 +138,12 @@ delta := diff.Diff(diff.D{len(input), len(decompressed), func(i, j int) bool { return input[i] == decompressed[j] }}) // Return a well-formated error if any differences are found if len(delta.Added) > 0 || len(delta.Removed) > 0 { - return fmt.Errorf("Unexpected decompressed output %v\ninput: %#x\ntrace: %#x\noutput: %#x\n", - delta, input, trace, decompressed) + return fmt.Errorf("Unexpected decompressed output %v\ninput: (%d) %#x\ntrace: (%d) %#x\noutput: (%d) %#x\n", + delta, len(input), input, len(trace), trace, len(decompressed), decompressed) } // All is good :) return nil }