Browse Source

Frame initial unit tests pass

Pierre.Curto 5 years ago
parent
commit
ac61e7d85b
6 changed files with 35 additions and 27 deletions
  1. 15 13
      block.go
  2. 7 5
      frame.go
  3. 6 6
      frame_gen.go
  4. 4 0
      frame_test.go
  5. 2 2
      gen.go
  6. 1 1
      writer.go

+ 15 - 13
block.go

@@ -65,13 +65,6 @@ func CompressBlock(src, dst []byte, hashTable []int) (_ int, err error) {
 	// This significantly speeds up incompressible data and usually has very small impact on compression.
 	// bytes to skip =  1 + (bytes since last match >> adaptSkipLog)
 	const adaptSkipLog = 7
-	if cap(hashTable) < htSize {
-		hashTable = htPool.Get().([]int)
-		defer htPool.Put(hashTable)
-	} else {
-		hashTable = hashTable[:htSize]
-	}
-	_ = hashTable[htSize-1]
 
 	// si: Current position of the search.
 	// anchor: Position of the current literals.
@@ -81,6 +74,14 @@ func CompressBlock(src, dst []byte, hashTable []int) (_ int, err error) {
 		goto lastLiterals
 	}
 
+	if cap(hashTable) < htSize {
+		hashTable = htPool.Get().([]int)
+		defer htPool.Put(hashTable)
+	} else {
+		hashTable = hashTable[:htSize]
+	}
+	_ = hashTable[htSize-1]
+
 	// Fast scan strategy: the hash table only stores the last 4 bytes sequences.
 	for si < sn {
 		// Hash the next 6 bytes (sequence)...
@@ -261,10 +262,15 @@ func CompressBlockHC(src, dst []byte, depth CompressionLevel, hashTable []int) (
 	// bytes to skip =  1 + (bytes since last match >> adaptSkipLog)
 	const adaptSkipLog = 7
 
+	var chainTable []int
 	var si, di, anchor int
-
 	// hashTable: stores the last position found for a given hash
 	// chainTable: stores previous positions for a given hash
+	sn := len(src) - mfLimit
+	if sn <= 0 {
+		goto lastLiterals
+	}
+
 	if cap(hashTable) < htSize {
 		hashTable = htPool.Get().([]int)
 		defer htPool.Put(hashTable)
@@ -272,7 +278,7 @@ func CompressBlockHC(src, dst []byte, depth CompressionLevel, hashTable []int) (
 		hashTable = hashTable[:htSize]
 	}
 	_ = hashTable[htSize-1]
-	chainTable := htPool.Get().([]int)
+	chainTable = htPool.Get().([]int)
 	defer htPool.Put(chainTable)
 	_ = chainTable[htSize-1]
 
@@ -280,10 +286,6 @@ func CompressBlockHC(src, dst []byte, depth CompressionLevel, hashTable []int) (
 		depth = winSize
 	}
 
-	sn := len(src) - mfLimit
-	if sn <= 0 {
-		goto lastLiterals
-	}
 
 	for si < sn {
 		// Hash the next 4 bytes (sequence).

+ 7 - 5
frame.go

@@ -227,7 +227,7 @@ func (b *FrameDataBlock) closeW(w *Writer) {
 
 // Block compression errors are ignored since the buffer is sized appropriately.
 func (b *FrameDataBlock) compress(w *Writer, src []byte, ht []int) *FrameDataBlock {
-	dst := b.Data
+	dst := b.Data[:len(src)] // trigger the incompressible flag in CompressBlock
 	var n int
 	switch w.level {
 	case Fast:
@@ -236,10 +236,10 @@ func (b *FrameDataBlock) compress(w *Writer, src []byte, ht []int) *FrameDataBlo
 		n, _ = CompressBlockHC(src, dst, w.level, ht)
 	}
 	if n == 0 {
-		b.Size.compressedSet(false)
+		b.Size.uncompressedSet(true)
 		dst = src
 	} else {
-		b.Size.compressedSet(true)
+		b.Size.uncompressedSet(false)
 		dst = dst[:n]
 	}
 	b.Data = dst
@@ -286,14 +286,16 @@ func (b *FrameDataBlock) uncompress(r *Reader, dst []byte) (int, error) {
 		return 0, io.EOF
 	}
 
-	isCompressed := b.Size.compressed()
+	isCompressed := !b.Size.uncompressed()
+	size := b.Size.size()
 	var data []byte
 	if isCompressed {
 		data = b.Data
 	} else {
 		data = dst
 	}
-	if _, err := io.ReadFull(r.src, data[:b.Size.size()]); err != nil {
+	data = data[:size]
+	if _, err := io.ReadFull(r.src, data); err != nil {
 		return 0, err
 	}
 	if isCompressed {

+ 6 - 6
frame_gen.go

@@ -34,16 +34,16 @@ func (x *DescriptorFlags) BlockSizeIndexSet(v BlockSizeIndex) *DescriptorFlags {
 // Code generated by `gen.exe`. DO NOT EDIT.
 
 // DataBlockSize is defined as follow:
-//   field       bits
-//   -----       ----
-//   size        31
-//   compressed  1
+//   field         bits
+//   -----         ----
+//   size          31
+//   uncompressed  1
 type DataBlockSize uint32
 
 // Getters.
 func (x DataBlockSize) size() int { return int(x&0x7FFFFFFF) }
-func (x DataBlockSize) compressed() bool { return x>>31&1 != 0 }
+func (x DataBlockSize) uncompressed() bool { return x>>31&1 != 0 }
 
 // Setters.
 func (x *DataBlockSize) sizeSet(v int) *DataBlockSize { *x = *x&^0x7FFFFFFF | DataBlockSize(v)&0x7FFFFFFF; return x }
-func (x *DataBlockSize) compressedSet(v bool) *DataBlockSize { const b = 1<<31; if v { *x = *x&^b | b } else { *x &^= b }; return x }
+func (x *DataBlockSize) uncompressedSet(v bool) *DataBlockSize { const b = 1<<31; if v { *x = *x&^b | b } else { *x &^= b }; return x }

+ 4 - 0
frame_test.go

@@ -73,6 +73,10 @@ func TestFrameDataBlock(t *testing.T) {
 		{"", Block64Kb},
 		{sample, Block64Kb},
 		{strings.Repeat(sample, 10), Block64Kb},
+		{strings.Repeat(sample, 5000), Block256Kb},
+		{strings.Repeat(sample, 5000), Block1Mb},
+		{strings.Repeat(sample, 23000), Block1Mb},
+		{strings.Repeat(sample, 93000), Block4Mb},
 	} {
 		label := fmt.Sprintf("%s (%d)", tc.data[:min(len(tc.data), 10)], len(tc.data))
 		t.Run(label, func(t *testing.T) {

+ 2 - 2
gen.go

@@ -25,8 +25,8 @@ type DescriptorFlags struct {
 }
 
 type DataBlockSize struct {
-	size       [31]int
-	compressed bool
+	size         [31]int
+	uncompressed bool
 }
 
 func main() {

+ 1 - 1
writer.go

@@ -115,7 +115,7 @@ func (w *Writer) write() error {
 		c <- b.compress(w, data, nil)
 		// Wait for the compressed or uncompressed data to no longer be in use
 		// and free the allocated buffers
-		if !b.Size.compressed() {
+		if b.Size.uncompressed() {
 			zdata, data = data, zdata
 		}
 		size.put(data)