Browse Source

working Writer.ReadFrom and Reader.WriteTo methods

Pierre.Curto 5 years ago
parent
commit
7e4ed9edd7
4 changed files with 12 additions and 11 deletions
  1. 0 2
      internal/lz4block/blocks.go
  2. 9 7
      internal/lz4stream/frame.go
  3. 1 1
      reader.go
  4. 2 1
      state.go

+ 0 - 2
internal/lz4block/blocks.go

@@ -61,8 +61,6 @@ func (b BlockSizeIndex) Get() []byte {
 }
 
 func (b BlockSizeIndex) Put(buf []byte) {
-	//TODO disabled as releasing buffers introduces a bug in Reader.WriteTo and Writer.ReadFrom
-	return
 	switch b {
 	case 4:
 		BlockPool64K.Put(buf)

+ 9 - 7
internal/lz4stream/frame.go

@@ -230,29 +230,29 @@ func (b *Blocks) initR(f *Frame) {
 }
 
 func NewFrameDataBlock(size lz4block.BlockSizeIndex) *FrameDataBlock {
-	return &FrameDataBlock{Data: size.Get()}
+	buf := size.Get()
+	return &FrameDataBlock{Data: buf, data: buf}
 }
 
 type FrameDataBlock struct {
 	Size     DataBlockSize
-	Data     []byte // (un)compressed data
+	Data     []byte // compressed or uncompressed data (.data or .src)
 	Checksum uint32
-	ref      []byte
+	data     []byte // buffer for compressed data
 	src      []byte // uncompressed data
 }
 
 func (b *FrameDataBlock) CloseW(f *Frame) {
 	size := f.Descriptor.Flags.BlockSizeIndex()
-	size.Put(b.ref)
+	size.Put(b.data)
 	b.Data = nil
-	b.ref = nil
+	b.data = nil
 	b.src = nil
 }
 
 // Block compression errors are ignored since the buffer is sized appropriately.
 func (b *FrameDataBlock) Compress(f *Frame, src []byte, ht []int, level lz4block.CompressionLevel) *FrameDataBlock {
-	data := b.Data[:len(src)] // trigger the incompressible flag in CompressBlock
-	b.ref = data              // keep track of the allocated buffer so that it can be freed
+	data := b.data[:len(src)] // trigger the incompressible flag in CompressBlock
 	var n int
 	switch level {
 	case lz4block.Fast:
@@ -314,8 +314,10 @@ func (b *FrameDataBlock) Uncompress(f *Frame, src io.Reader, dst []byte) (int, e
 	size := b.Size.size()
 	var data []byte
 	if isCompressed {
+		// Data is first copied into b.Data and then it will get uncompressed into dst.
 		data = b.Data
 	} else {
+		// Data is directly copied into dst as it is not compressed.
 		data = dst
 	}
 	data = data[:size]

+ 1 - 1
reader.go

@@ -175,7 +175,7 @@ func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
 	block := r.frame.Blocks.Block
 	size := r.frame.Descriptor.Flags.BlockSizeIndex()
 	data := size.Get()
-	defer size.Put(r.data)
+	defer size.Put(data)
 	for {
 		switch bn, err = block.Uncompress(r.frame, r.src, data); err {
 		case nil:

+ 2 - 1
state.go

@@ -45,8 +45,9 @@ func (s *_State) next(err error) bool {
 	return false
 }
 
+// nextd is like next but for defers.
 func (s *_State) nextd(errp *error) bool {
-	return s.next(*errp)
+	return errp != nil && s.next(*errp)
 }
 
 // check sets s in error if not already in error and if the error is not nil or io.EOF,