From 32d591d4d02cd37979c2c17fb3c8db6d2a85e99e Mon Sep 17 00:00:00 2001 From: airuike Date: Sat, 11 Apr 2020 14:58:23 -0400 Subject: [PATCH] Remove io.Pipe --- cachedwriter.go | 27 ++++++++-------- decompressor.go | 84 ++++++++++++++++++++++++++++--------------------- go.mod | 2 +- lzfse_test.go | 4 +++ 4 files changed, 66 insertions(+), 51 deletions(-) diff --git a/cachedwriter.go b/cachedwriter.go index cf4f032..c91a8ca 100644 --- a/cachedwriter.go +++ b/cachedwriter.go @@ -1,30 +1,29 @@ package lzfse import ( - "io" + "bytes" ) type cachedWriter struct { - w io.Writer - buf []byte + buf * bytes.Buffer } -func newCachedWriter(w io.Writer) *cachedWriter { +func newCachedWriter() *cachedWriter { return &cachedWriter{ - w: w, - buf: make([]byte, 0, 1024), + buf: &bytes.Buffer{}, } } -func (cw *cachedWriter) Write(b []byte) (int, error) { - n, err := cw.w.Write(b) - if n > 0 { - cw.buf = append(cw.buf, b[:n]...) - } - return n, err +func (w *cachedWriter) Write(b []byte) (int, error) { + return w.buf.Write(b) } -func (cw *cachedWriter) ReadRelativeToEnd(b []byte, offset int64) (copied int, err error) { - copied = copy(b, cw.buf[int64(len(cw.buf))-offset:]) +func (w *cachedWriter) ReadRelativeToEnd(b []byte, offset int64) (copied int, err error) { + bb := w.buf.Bytes() + copied = copy(b, bb[int64(w.buf.Len())-offset:]) return } + +func (w *cachedWriter) Bytes() []byte { + return w.buf.Bytes() +} diff --git a/decompressor.go b/decompressor.go index 79ef647..cfa9a10 100644 --- a/decompressor.go +++ b/decompressor.go @@ -1,7 +1,9 @@ package lzfse import ( + "bytes" "encoding/binary" + "fmt" "io" ) @@ -20,9 +22,7 @@ const ( type decompressor struct { r *cachedReader w *cachedWriter - pipeR *io.PipeReader - pipeW *io.PipeWriter - handlerError error + payload io.Reader } func decodeUncompressedBlock(r *cachedReader, w *cachedWriter) (err error) { @@ -49,45 +49,57 @@ func (d *decompressor) handleBlock(handler blockHandler) (Magic, error) { } func (d *decompressor) Read(b []byte) (int, error) { - return d.pipeR.Read(b) + if payload, err := d.decompressedPayload(); err == nil { + return payload.Read(b) + } else { + return 0, err + } } -func NewReader(r io.Reader) *decompressor { - pipeR, pipeW := io.Pipe() - d := &decompressor{ - r: newCachedReader(r), - w: newCachedWriter(pipeW), - pipeR: pipeR, - pipeW: pipeW, +func (d *decompressor) decompressedPayload() (io.Reader, error) { + var err error + if d.payload == nil { + d.payload, err = d.decompressAll() } + return d.payload, err +} + +func (d *decompressor) decompressAll() (io.Reader, error) { + var err error + magic := LZFSE_NO_BLOCK_MAGIC - go func() { - var err error - magic := LZFSE_NO_BLOCK_MAGIC - - for nil == err { - switch magic { - case LZFSE_NO_BLOCK_MAGIC: - magic, err = readBlockMagic(d.r) - case LZFSE_UNCOMPRESSED_BLOCK_MAGIC: - magic, err = d.handleBlock(decodeUncompressedBlock) - case LZFSE_COMPRESSEDV1_BLOCK_MAGIC: - magic, err = d.handleBlock(decodeCompressedV1Block) - case LZFSE_COMPRESSEDV2_BLOCK_MAGIC: - magic, err = d.handleBlock(decodeCompressedV2Block) - case LZFSE_COMPRESSEDLZVN_BLOCK_MAGIC: - magic, err = d.handleBlock(decodeLZVNBlock) - case LZFSE_ENDOFSTREAM_BLOCK_MAGIC: - magic = LZFSE_ENDOFSTREAM_BLOCK_MAGIC - err = io.EOF - default: - panic("Bad magic") - } + for err == nil { + switch magic { + case LZFSE_NO_BLOCK_MAGIC: + magic, err = readBlockMagic(d.r) + case LZFSE_UNCOMPRESSED_BLOCK_MAGIC: + magic, err = d.handleBlock(decodeUncompressedBlock) + case LZFSE_COMPRESSEDV1_BLOCK_MAGIC: + magic, err = d.handleBlock(decodeCompressedV1Block) + case LZFSE_COMPRESSEDV2_BLOCK_MAGIC: + magic, err = d.handleBlock(decodeCompressedV2Block) + case LZFSE_COMPRESSEDLZVN_BLOCK_MAGIC: + magic, err = d.handleBlock(decodeLZVNBlock) + case LZFSE_ENDOFSTREAM_BLOCK_MAGIC: + magic, err = LZFSE_ENDOFSTREAM_BLOCK_MAGIC, io.EOF + default: + magic, err = INVALID, fmt.Errorf("Bad magic") } + } - d.handlerError = err - d.pipeW.Close() - }() + if err == io.EOF { + // @@@ try just reading from it.. not sure if that works correctly. + return bytes.NewReader(d.w.Bytes()), nil + } + + return nil, err +} + +func NewReader(r io.Reader) *decompressor { + d := &decompressor{ + r: newCachedReader(r), + w: newCachedWriter(), + } return d } diff --git a/go.mod b/go.mod index 5773b69..318b946 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/aixiansheng/go-pure-lzfse +module github.com/aixiansheng/lzfse go 1.14 diff --git a/lzfse_test.go b/lzfse_test.go index 0c113e3..17b66c2 100644 --- a/lzfse_test.go +++ b/lzfse_test.go @@ -16,6 +16,10 @@ func TestMedium(t *testing.T) { DoDecomp("cmp2.lz", "dec2", "dec2.err", t) } +func TestKern(t *testing.T) { + DoDecomp("kernel.lzfse", "kernel.dec", "kernel.err", t) +} + func DoDecomp(compressed, original, errorOutputFile string, t *testing.T) { cmp, err := os.Open(compressed) if err != nil {