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

     1  //go:build !amd64 || appengine || !gc || noasm
     2  // +build !amd64 appengine !gc noasm
     3  
     4  package zstd
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  )
    10  
    11  // decode sequences from the stream with the provided history but without dictionary.
    12  func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) {
    13  	return false, nil
    14  }
    15  
    16  // decode sequences from the stream without the provided history.
    17  func (s *sequenceDecs) decode(seqs []seqVals) error {
    18  	br := s.br
    19  
    20  	// Grab full sizes tables, to avoid bounds checks.
    21  	llTable, mlTable, ofTable := s.litLengths.fse.dt[:maxTablesize], s.matchLengths.fse.dt[:maxTablesize], s.offsets.fse.dt[:maxTablesize]
    22  	llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state
    23  	s.seqSize = 0
    24  	litRemain := len(s.literals)
    25  
    26  	maxBlockSize := maxCompressedBlockSize
    27  	if s.windowSize < maxBlockSize {
    28  		maxBlockSize = s.windowSize
    29  	}
    30  	for i := range seqs {
    31  		var ll, mo, ml int
    32  		if br.off > 4+((maxOffsetBits+16+16)>>3) {
    33  			// inlined function:
    34  			// ll, mo, ml = s.nextFast(br, llState, mlState, ofState)
    35  
    36  			// Final will not read from stream.
    37  			var llB, mlB, moB uint8
    38  			ll, llB = llState.final()
    39  			ml, mlB = mlState.final()
    40  			mo, moB = ofState.final()
    41  
    42  			// extra bits are stored in reverse order.
    43  			br.fillFast()
    44  			mo += br.getBits(moB)
    45  			if s.maxBits > 32 {
    46  				br.fillFast()
    47  			}
    48  			ml += br.getBits(mlB)
    49  			ll += br.getBits(llB)
    50  
    51  			if moB > 1 {
    52  				s.prevOffset[2] = s.prevOffset[1]
    53  				s.prevOffset[1] = s.prevOffset[0]
    54  				s.prevOffset[0] = mo
    55  			} else {
    56  				// mo = s.adjustOffset(mo, ll, moB)
    57  				// Inlined for rather big speedup
    58  				if ll == 0 {
    59  					// There is an exception though, when current sequence's literals_length = 0.
    60  					// In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2,
    61  					// an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte.
    62  					mo++
    63  				}
    64  
    65  				if mo == 0 {
    66  					mo = s.prevOffset[0]
    67  				} else {
    68  					var temp int
    69  					if mo == 3 {
    70  						temp = s.prevOffset[0] - 1
    71  					} else {
    72  						temp = s.prevOffset[mo]
    73  					}
    74  
    75  					if temp == 0 {
    76  						// 0 is not valid; input is corrupted; force offset to 1
    77  						println("WARNING: temp was 0")
    78  						temp = 1
    79  					}
    80  
    81  					if mo != 1 {
    82  						s.prevOffset[2] = s.prevOffset[1]
    83  					}
    84  					s.prevOffset[1] = s.prevOffset[0]
    85  					s.prevOffset[0] = temp
    86  					mo = temp
    87  				}
    88  			}
    89  			br.fillFast()
    90  		} else {
    91  			if br.overread() {
    92  				if debugDecoder {
    93  					printf("reading sequence %d, exceeded available data\n", i)
    94  				}
    95  				return io.ErrUnexpectedEOF
    96  			}
    97  			ll, mo, ml = s.next(br, llState, mlState, ofState)
    98  			br.fill()
    99  		}
   100  
   101  		if debugSequences {
   102  			println("Seq", i, "Litlen:", ll, "mo:", mo, "(abs) ml:", ml)
   103  		}
   104  		// Evaluate.
   105  		// We might be doing this async, so do it early.
   106  		if mo == 0 && ml > 0 {
   107  			return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml)
   108  		}
   109  		if ml > maxMatchLen {
   110  			return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
   111  		}
   112  		s.seqSize += ll + ml
   113  		if s.seqSize > maxBlockSize {
   114  			return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
   115  		}
   116  		litRemain -= ll
   117  		if litRemain < 0 {
   118  			return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, litRemain+ll)
   119  		}
   120  		seqs[i] = seqVals{
   121  			ll: ll,
   122  			ml: ml,
   123  			mo: mo,
   124  		}
   125  		if i == len(seqs)-1 {
   126  			// This is the last sequence, so we shouldn't update state.
   127  			break
   128  		}
   129  
   130  		// Manually inlined, ~ 5-20% faster
   131  		// Update all 3 states at once. Approx 20% faster.
   132  		nBits := llState.nbBits() + mlState.nbBits() + ofState.nbBits()
   133  		if nBits == 0 {
   134  			llState = llTable[llState.newState()&maxTableMask]
   135  			mlState = mlTable[mlState.newState()&maxTableMask]
   136  			ofState = ofTable[ofState.newState()&maxTableMask]
   137  		} else {
   138  			bits := br.get32BitsFast(nBits)
   139  			lowBits := uint16(bits >> ((ofState.nbBits() + mlState.nbBits()) & 31))
   140  			llState = llTable[(llState.newState()+lowBits)&maxTableMask]
   141  
   142  			lowBits = uint16(bits >> (ofState.nbBits() & 31))
   143  			lowBits &= bitMask[mlState.nbBits()&15]
   144  			mlState = mlTable[(mlState.newState()+lowBits)&maxTableMask]
   145  
   146  			lowBits = uint16(bits) & bitMask[ofState.nbBits()&15]
   147  			ofState = ofTable[(ofState.newState()+lowBits)&maxTableMask]
   148  		}
   149  	}
   150  	s.seqSize += litRemain
   151  	if s.seqSize > maxBlockSize {
   152  		return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
   153  	}
   154  	err := br.close()
   155  	if err != nil {
   156  		printf("Closing sequences: %v, %+v\n", err, *br)
   157  	}
   158  	return err
   159  }
   160  
   161  // executeSimple handles cases when a dictionary is not used.
   162  func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error {
   163  	// Ensure we have enough output size...
   164  	if len(s.out)+s.seqSize > cap(s.out) {
   165  		addBytes := s.seqSize + len(s.out)
   166  		s.out = append(s.out, make([]byte, addBytes)...)
   167  		s.out = s.out[:len(s.out)-addBytes]
   168  	}
   169  
   170  	if debugDecoder {
   171  		printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize)
   172  	}
   173  
   174  	var t = len(s.out)
   175  	out := s.out[:t+s.seqSize]
   176  
   177  	for _, seq := range seqs {
   178  		// Add literals
   179  		copy(out[t:], s.literals[:seq.ll])
   180  		t += seq.ll
   181  		s.literals = s.literals[seq.ll:]
   182  
   183  		// Malformed input
   184  		if seq.mo > t+len(hist) || seq.mo > s.windowSize {
   185  			return fmt.Errorf("match offset (%d) bigger than current history (%d)", seq.mo, t+len(hist))
   186  		}
   187  
   188  		// Copy from history.
   189  		if v := seq.mo - t; v > 0 {
   190  			// v is the start position in history from end.
   191  			start := len(hist) - v
   192  			if seq.ml > v {
   193  				// Some goes into the current block.
   194  				// Copy remainder of history
   195  				copy(out[t:], hist[start:])
   196  				t += v
   197  				seq.ml -= v
   198  			} else {
   199  				copy(out[t:], hist[start:start+seq.ml])
   200  				t += seq.ml
   201  				continue
   202  			}
   203  		}
   204  
   205  		// We must be in the current buffer now
   206  		if seq.ml > 0 {
   207  			start := t - seq.mo
   208  			if seq.ml <= t-start {
   209  				// No overlap
   210  				copy(out[t:], out[start:start+seq.ml])
   211  				t += seq.ml
   212  			} else {
   213  				// Overlapping copy
   214  				// Extend destination slice and copy one byte at the time.
   215  				src := out[start : start+seq.ml]
   216  				dst := out[t:]
   217  				dst = dst[:len(src)]
   218  				t += len(src)
   219  				// Destination is the space we just added.
   220  				for i := range src {
   221  					dst[i] = src[i]
   222  				}
   223  			}
   224  		}
   225  	}
   226  	// Add final literals
   227  	copy(out[t:], s.literals)
   228  	if debugDecoder {
   229  		t += len(s.literals)
   230  		if t != len(out) {
   231  			panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize))
   232  		}
   233  	}
   234  	s.out = out
   235  
   236  	return nil
   237  }