github.com/bir3/gocompiler@v0.9.2202/extra/compress/zstd/seqdec.go (about)

     1  // Copyright 2019+ Klaus Post. All rights reserved.
     2  // License information can be found in the LICENSE file.
     3  // Based on work by Yann Collet, released under BSD License.
     4  
     5  package zstd
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"io"
    11  )
    12  
    13  type seq struct {
    14  	litLen   uint32
    15  	matchLen uint32
    16  	offset   uint32
    17  
    18  	// Codes are stored here for the encoder
    19  	// so they only have to be looked up once.
    20  	llCode, mlCode, ofCode uint8
    21  }
    22  
    23  type seqVals struct {
    24  	ll, ml, mo int
    25  }
    26  
    27  func (s seq) String() string {
    28  	if s.offset <= 3 {
    29  		if s.offset == 0 {
    30  			return fmt.Sprint("litLen:", s.litLen, ", matchLen:", s.matchLen+zstdMinMatch, ", offset: INVALID (0)")
    31  		}
    32  		return fmt.Sprint("litLen:", s.litLen, ", matchLen:", s.matchLen+zstdMinMatch, ", offset:", s.offset, " (repeat)")
    33  	}
    34  	return fmt.Sprint("litLen:", s.litLen, ", matchLen:", s.matchLen+zstdMinMatch, ", offset:", s.offset-3, " (new)")
    35  }
    36  
    37  type seqCompMode uint8
    38  
    39  const (
    40  	compModePredefined seqCompMode = iota
    41  	compModeRLE
    42  	compModeFSE
    43  	compModeRepeat
    44  )
    45  
    46  type sequenceDec struct {
    47  	// decoder keeps track of the current state and updates it from the bitstream.
    48  	fse    *fseDecoder
    49  	state  fseState
    50  	repeat bool
    51  }
    52  
    53  // init the state of the decoder with input from stream.
    54  func (s *sequenceDec) init(br *bitReader) error {
    55  	if s.fse == nil {
    56  		return errors.New("sequence decoder not defined")
    57  	}
    58  	s.state.init(br, s.fse.actualTableLog, s.fse.dt[:1<<s.fse.actualTableLog])
    59  	return nil
    60  }
    61  
    62  // sequenceDecs contains all 3 sequence decoders and their state.
    63  type sequenceDecs struct {
    64  	litLengths   sequenceDec
    65  	offsets      sequenceDec
    66  	matchLengths sequenceDec
    67  	prevOffset   [3]int
    68  	dict         []byte
    69  	literals     []byte
    70  	out          []byte
    71  	nSeqs        int
    72  	br           *bitReader
    73  	seqSize      int
    74  	windowSize   int
    75  	maxBits      uint8
    76  	maxSyncLen   uint64
    77  }
    78  
    79  // initialize all 3 decoders from the stream input.
    80  func (s *sequenceDecs) initialize(br *bitReader, hist *history, out []byte) error {
    81  	if err := s.litLengths.init(br); err != nil {
    82  		return errors.New("litLengths:" + err.Error())
    83  	}
    84  	if err := s.offsets.init(br); err != nil {
    85  		return errors.New("offsets:" + err.Error())
    86  	}
    87  	if err := s.matchLengths.init(br); err != nil {
    88  		return errors.New("matchLengths:" + err.Error())
    89  	}
    90  	s.br = br
    91  	s.prevOffset = hist.recentOffsets
    92  	s.maxBits = s.litLengths.fse.maxBits + s.offsets.fse.maxBits + s.matchLengths.fse.maxBits
    93  	s.windowSize = hist.windowSize
    94  	s.out = out
    95  	s.dict = nil
    96  	if hist.dict != nil {
    97  		s.dict = hist.dict.content
    98  	}
    99  	return nil
   100  }
   101  
   102  func (s *sequenceDecs) freeDecoders() {
   103  	if f := s.litLengths.fse; f != nil && !f.preDefined {
   104  		fseDecoderPool.Put(f)
   105  		s.litLengths.fse = nil
   106  	}
   107  	if f := s.offsets.fse; f != nil && !f.preDefined {
   108  		fseDecoderPool.Put(f)
   109  		s.offsets.fse = nil
   110  	}
   111  	if f := s.matchLengths.fse; f != nil && !f.preDefined {
   112  		fseDecoderPool.Put(f)
   113  		s.matchLengths.fse = nil
   114  	}
   115  }
   116  
   117  // execute will execute the decoded sequence with the provided history.
   118  // The sequence must be evaluated before being sent.
   119  func (s *sequenceDecs) execute(seqs []seqVals, hist []byte) error {
   120  	if len(s.dict) == 0 {
   121  		return s.executeSimple(seqs, hist)
   122  	}
   123  
   124  	// Ensure we have enough output size...
   125  	if len(s.out)+s.seqSize > cap(s.out) {
   126  		addBytes := s.seqSize + len(s.out)
   127  		s.out = append(s.out, make([]byte, addBytes)...)
   128  		s.out = s.out[:len(s.out)-addBytes]
   129  	}
   130  
   131  	if debugDecoder {
   132  		printf("Execute %d seqs with hist %d, dict %d, literals: %d into %d bytes\n", len(seqs), len(hist), len(s.dict), len(s.literals), s.seqSize)
   133  	}
   134  
   135  	var t = len(s.out)
   136  	out := s.out[:t+s.seqSize]
   137  
   138  	for _, seq := range seqs {
   139  		// Add literals
   140  		copy(out[t:], s.literals[:seq.ll])
   141  		t += seq.ll
   142  		s.literals = s.literals[seq.ll:]
   143  
   144  		// Copy from dictionary...
   145  		if seq.mo > t+len(hist) || seq.mo > s.windowSize {
   146  			if len(s.dict) == 0 {
   147  				return fmt.Errorf("match offset (%d) bigger than current history (%d)", seq.mo, t+len(hist))
   148  			}
   149  
   150  			// we may be in dictionary.
   151  			dictO := len(s.dict) - (seq.mo - (t + len(hist)))
   152  			if dictO < 0 || dictO >= len(s.dict) {
   153  				return fmt.Errorf("match offset (%d) bigger than current history+dict (%d)", seq.mo, t+len(hist)+len(s.dict))
   154  			}
   155  			end := dictO + seq.ml
   156  			if end > len(s.dict) {
   157  				n := len(s.dict) - dictO
   158  				copy(out[t:], s.dict[dictO:])
   159  				t += n
   160  				seq.ml -= n
   161  			} else {
   162  				copy(out[t:], s.dict[dictO:end])
   163  				t += end - dictO
   164  				continue
   165  			}
   166  		}
   167  
   168  		// Copy from history.
   169  		if v := seq.mo - t; v > 0 {
   170  			// v is the start position in history from end.
   171  			start := len(hist) - v
   172  			if seq.ml > v {
   173  				// Some goes into current block.
   174  				// Copy remainder of history
   175  				copy(out[t:], hist[start:])
   176  				t += v
   177  				seq.ml -= v
   178  			} else {
   179  				copy(out[t:], hist[start:start+seq.ml])
   180  				t += seq.ml
   181  				continue
   182  			}
   183  		}
   184  		// We must be in current buffer now
   185  		if seq.ml > 0 {
   186  			start := t - seq.mo
   187  			if seq.ml <= t-start {
   188  				// No overlap
   189  				copy(out[t:], out[start:start+seq.ml])
   190  				t += seq.ml
   191  				continue
   192  			} else {
   193  				// Overlapping copy
   194  				// Extend destination slice and copy one byte at the time.
   195  				src := out[start : start+seq.ml]
   196  				dst := out[t:]
   197  				dst = dst[:len(src)]
   198  				t += len(src)
   199  				// Destination is the space we just added.
   200  				for i := range src {
   201  					dst[i] = src[i]
   202  				}
   203  			}
   204  		}
   205  	}
   206  
   207  	// Add final literals
   208  	copy(out[t:], s.literals)
   209  	if debugDecoder {
   210  		t += len(s.literals)
   211  		if t != len(out) {
   212  			panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize))
   213  		}
   214  	}
   215  	s.out = out
   216  
   217  	return nil
   218  }
   219  
   220  // decode sequences from the stream with the provided history.
   221  func (s *sequenceDecs) decodeSync(hist []byte) error {
   222  	supported, err := s.decodeSyncSimple(hist)
   223  	if supported {
   224  		return err
   225  	}
   226  
   227  	br := s.br
   228  	seqs := s.nSeqs
   229  	startSize := len(s.out)
   230  	// Grab full sizes tables, to avoid bounds checks.
   231  	llTable, mlTable, ofTable := s.litLengths.fse.dt[:maxTablesize], s.matchLengths.fse.dt[:maxTablesize], s.offsets.fse.dt[:maxTablesize]
   232  	llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state
   233  	out := s.out
   234  	maxBlockSize := maxCompressedBlockSize
   235  	if s.windowSize < maxBlockSize {
   236  		maxBlockSize = s.windowSize
   237  	}
   238  
   239  	if debugDecoder {
   240  		println("decodeSync: decoding", seqs, "sequences", br.remain(), "bits remain on stream")
   241  	}
   242  	for i := seqs - 1; i >= 0; i-- {
   243  		if br.overread() {
   244  			printf("reading sequence %d, exceeded available data. Overread by %d\n", seqs-i, -br.remain())
   245  			return io.ErrUnexpectedEOF
   246  		}
   247  		var ll, mo, ml int
   248  		if br.off > 4+((maxOffsetBits+16+16)>>3) {
   249  			// inlined function:
   250  			// ll, mo, ml = s.nextFast(br, llState, mlState, ofState)
   251  
   252  			// Final will not read from stream.
   253  			var llB, mlB, moB uint8
   254  			ll, llB = llState.final()
   255  			ml, mlB = mlState.final()
   256  			mo, moB = ofState.final()
   257  
   258  			// extra bits are stored in reverse order.
   259  			br.fillFast()
   260  			mo += br.getBits(moB)
   261  			if s.maxBits > 32 {
   262  				br.fillFast()
   263  			}
   264  			ml += br.getBits(mlB)
   265  			ll += br.getBits(llB)
   266  
   267  			if moB > 1 {
   268  				s.prevOffset[2] = s.prevOffset[1]
   269  				s.prevOffset[1] = s.prevOffset[0]
   270  				s.prevOffset[0] = mo
   271  			} else {
   272  				// mo = s.adjustOffset(mo, ll, moB)
   273  				// Inlined for rather big speedup
   274  				if ll == 0 {
   275  					// There is an exception though, when current sequence's literals_length = 0.
   276  					// In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2,
   277  					// an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte.
   278  					mo++
   279  				}
   280  
   281  				if mo == 0 {
   282  					mo = s.prevOffset[0]
   283  				} else {
   284  					var temp int
   285  					if mo == 3 {
   286  						temp = s.prevOffset[0] - 1
   287  					} else {
   288  						temp = s.prevOffset[mo]
   289  					}
   290  
   291  					if temp == 0 {
   292  						// 0 is not valid; input is corrupted; force offset to 1
   293  						println("WARNING: temp was 0")
   294  						temp = 1
   295  					}
   296  
   297  					if mo != 1 {
   298  						s.prevOffset[2] = s.prevOffset[1]
   299  					}
   300  					s.prevOffset[1] = s.prevOffset[0]
   301  					s.prevOffset[0] = temp
   302  					mo = temp
   303  				}
   304  			}
   305  			br.fillFast()
   306  		} else {
   307  			ll, mo, ml = s.next(br, llState, mlState, ofState)
   308  			br.fill()
   309  		}
   310  
   311  		if debugSequences {
   312  			println("Seq", seqs-i-1, "Litlen:", ll, "mo:", mo, "(abs) ml:", ml)
   313  		}
   314  
   315  		if ll > len(s.literals) {
   316  			return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, len(s.literals))
   317  		}
   318  		size := ll + ml + len(out)
   319  		if size-startSize > maxBlockSize {
   320  			return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
   321  		}
   322  		if size > cap(out) {
   323  			// Not enough size, which can happen under high volume block streaming conditions
   324  			// but could be if destination slice is too small for sync operations.
   325  			// over-allocating here can create a large amount of GC pressure so we try to keep
   326  			// it as contained as possible
   327  			used := len(out) - startSize
   328  			addBytes := 256 + ll + ml + used>>2
   329  			// Clamp to max block size.
   330  			if used+addBytes > maxBlockSize {
   331  				addBytes = maxBlockSize - used
   332  			}
   333  			out = append(out, make([]byte, addBytes)...)
   334  			out = out[:len(out)-addBytes]
   335  		}
   336  		if ml > maxMatchLen {
   337  			return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
   338  		}
   339  
   340  		// Add literals
   341  		out = append(out, s.literals[:ll]...)
   342  		s.literals = s.literals[ll:]
   343  
   344  		if mo == 0 && ml > 0 {
   345  			return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml)
   346  		}
   347  
   348  		if mo > len(out)+len(hist) || mo > s.windowSize {
   349  			if len(s.dict) == 0 {
   350  				return fmt.Errorf("match offset (%d) bigger than current history (%d)", mo, len(out)+len(hist)-startSize)
   351  			}
   352  
   353  			// we may be in dictionary.
   354  			dictO := len(s.dict) - (mo - (len(out) + len(hist)))
   355  			if dictO < 0 || dictO >= len(s.dict) {
   356  				return fmt.Errorf("match offset (%d) bigger than current history (%d)", mo, len(out)+len(hist)-startSize)
   357  			}
   358  			end := dictO + ml
   359  			if end > len(s.dict) {
   360  				out = append(out, s.dict[dictO:]...)
   361  				ml -= len(s.dict) - dictO
   362  			} else {
   363  				out = append(out, s.dict[dictO:end]...)
   364  				mo = 0
   365  				ml = 0
   366  			}
   367  		}
   368  
   369  		// Copy from history.
   370  		// TODO: Blocks without history could be made to ignore this completely.
   371  		if v := mo - len(out); v > 0 {
   372  			// v is the start position in history from end.
   373  			start := len(hist) - v
   374  			if ml > v {
   375  				// Some goes into current block.
   376  				// Copy remainder of history
   377  				out = append(out, hist[start:]...)
   378  				ml -= v
   379  			} else {
   380  				out = append(out, hist[start:start+ml]...)
   381  				ml = 0
   382  			}
   383  		}
   384  		// We must be in current buffer now
   385  		if ml > 0 {
   386  			start := len(out) - mo
   387  			if ml <= len(out)-start {
   388  				// No overlap
   389  				out = append(out, out[start:start+ml]...)
   390  			} else {
   391  				// Overlapping copy
   392  				// Extend destination slice and copy one byte at the time.
   393  				out = out[:len(out)+ml]
   394  				src := out[start : start+ml]
   395  				// Destination is the space we just added.
   396  				dst := out[len(out)-ml:]
   397  				dst = dst[:len(src)]
   398  				for i := range src {
   399  					dst[i] = src[i]
   400  				}
   401  			}
   402  		}
   403  		if i == 0 {
   404  			// This is the last sequence, so we shouldn't update state.
   405  			break
   406  		}
   407  
   408  		// Manually inlined, ~ 5-20% faster
   409  		// Update all 3 states at once. Approx 20% faster.
   410  		nBits := llState.nbBits() + mlState.nbBits() + ofState.nbBits()
   411  		if nBits == 0 {
   412  			llState = llTable[llState.newState()&maxTableMask]
   413  			mlState = mlTable[mlState.newState()&maxTableMask]
   414  			ofState = ofTable[ofState.newState()&maxTableMask]
   415  		} else {
   416  			bits := br.get32BitsFast(nBits)
   417  
   418  			lowBits := uint16(bits >> ((ofState.nbBits() + mlState.nbBits()) & 31))
   419  			llState = llTable[(llState.newState()+lowBits)&maxTableMask]
   420  
   421  			lowBits = uint16(bits >> (ofState.nbBits() & 31))
   422  			lowBits &= bitMask[mlState.nbBits()&15]
   423  			mlState = mlTable[(mlState.newState()+lowBits)&maxTableMask]
   424  
   425  			lowBits = uint16(bits) & bitMask[ofState.nbBits()&15]
   426  			ofState = ofTable[(ofState.newState()+lowBits)&maxTableMask]
   427  		}
   428  	}
   429  
   430  	if size := len(s.literals) + len(out) - startSize; size > maxBlockSize {
   431  		return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
   432  	}
   433  
   434  	// Add final literals
   435  	s.out = append(out, s.literals...)
   436  	return br.close()
   437  }
   438  
   439  var bitMask [16]uint16
   440  
   441  func init() {
   442  	for i := range bitMask[:] {
   443  		bitMask[i] = uint16((1 << uint(i)) - 1)
   444  	}
   445  }
   446  
   447  func (s *sequenceDecs) next(br *bitReader, llState, mlState, ofState decSymbol) (ll, mo, ml int) {
   448  	// Final will not read from stream.
   449  	ll, llB := llState.final()
   450  	ml, mlB := mlState.final()
   451  	mo, moB := ofState.final()
   452  
   453  	// extra bits are stored in reverse order.
   454  	br.fill()
   455  	if s.maxBits <= 32 {
   456  		mo += br.getBits(moB)
   457  		ml += br.getBits(mlB)
   458  		ll += br.getBits(llB)
   459  	} else {
   460  		mo += br.getBits(moB)
   461  		br.fill()
   462  		// matchlength+literal length, max 32 bits
   463  		ml += br.getBits(mlB)
   464  		ll += br.getBits(llB)
   465  
   466  	}
   467  	mo = s.adjustOffset(mo, ll, moB)
   468  	return
   469  }
   470  
   471  func (s *sequenceDecs) adjustOffset(offset, litLen int, offsetB uint8) int {
   472  	if offsetB > 1 {
   473  		s.prevOffset[2] = s.prevOffset[1]
   474  		s.prevOffset[1] = s.prevOffset[0]
   475  		s.prevOffset[0] = offset
   476  		return offset
   477  	}
   478  
   479  	if litLen == 0 {
   480  		// There is an exception though, when current sequence's literals_length = 0.
   481  		// In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2,
   482  		// an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte.
   483  		offset++
   484  	}
   485  
   486  	if offset == 0 {
   487  		return s.prevOffset[0]
   488  	}
   489  	var temp int
   490  	if offset == 3 {
   491  		temp = s.prevOffset[0] - 1
   492  	} else {
   493  		temp = s.prevOffset[offset]
   494  	}
   495  
   496  	if temp == 0 {
   497  		// 0 is not valid; input is corrupted; force offset to 1
   498  		println("temp was 0")
   499  		temp = 1
   500  	}
   501  
   502  	if offset != 1 {
   503  		s.prevOffset[2] = s.prevOffset[1]
   504  	}
   505  	s.prevOffset[1] = s.prevOffset[0]
   506  	s.prevOffset[0] = temp
   507  	return temp
   508  }