github.com/bir3/gocompiler@v0.9.2202/extra/compress/zstd/history.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  	"github.com/bir3/gocompiler/extra/compress/huff0"
     9  )
    10  
    11  // history contains the information transferred between blocks.
    12  type history struct {
    13  	// Literal decompression
    14  	huffTree *huff0.Scratch
    15  
    16  	// Sequence decompression
    17  	decoders      sequenceDecs
    18  	recentOffsets [3]int
    19  
    20  	// History buffer...
    21  	b []byte
    22  
    23  	// ignoreBuffer is meant to ignore a number of bytes
    24  	// when checking for matches in history
    25  	ignoreBuffer int
    26  
    27  	windowSize       int
    28  	allocFrameBuffer int // needed?
    29  	error            bool
    30  	dict             *dict
    31  }
    32  
    33  // reset will reset the history to initial state of a frame.
    34  // The history must already have been initialized to the desired size.
    35  func (h *history) reset() {
    36  	h.b = h.b[:0]
    37  	h.ignoreBuffer = 0
    38  	h.error = false
    39  	h.recentOffsets = [3]int{1, 4, 8}
    40  	h.decoders.freeDecoders()
    41  	h.decoders = sequenceDecs{br: h.decoders.br}
    42  	h.freeHuffDecoder()
    43  	h.huffTree = nil
    44  	h.dict = nil
    45  	//printf("history created: %+v (l: %d, c: %d)", *h, len(h.b), cap(h.b))
    46  }
    47  
    48  func (h *history) freeHuffDecoder() {
    49  	if h.huffTree != nil {
    50  		if h.dict == nil || h.dict.litEnc != h.huffTree {
    51  			huffDecoderPool.Put(h.huffTree)
    52  			h.huffTree = nil
    53  		}
    54  	}
    55  }
    56  
    57  func (h *history) setDict(dict *dict) {
    58  	if dict == nil {
    59  		return
    60  	}
    61  	h.dict = dict
    62  	h.decoders.litLengths = dict.llDec
    63  	h.decoders.offsets = dict.ofDec
    64  	h.decoders.matchLengths = dict.mlDec
    65  	h.decoders.dict = dict.content
    66  	h.recentOffsets = dict.offsets
    67  	h.huffTree = dict.litEnc
    68  }
    69  
    70  // append bytes to history.
    71  // This function will make sure there is space for it,
    72  // if the buffer has been allocated with enough extra space.
    73  func (h *history) append(b []byte) {
    74  	if len(b) >= h.windowSize {
    75  		// Discard all history by simply overwriting
    76  		h.b = h.b[:h.windowSize]
    77  		copy(h.b, b[len(b)-h.windowSize:])
    78  		return
    79  	}
    80  
    81  	// If there is space, append it.
    82  	if len(b) < cap(h.b)-len(h.b) {
    83  		h.b = append(h.b, b...)
    84  		return
    85  	}
    86  
    87  	// Move data down so we only have window size left.
    88  	// We know we have less than window size in b at this point.
    89  	discard := len(b) + len(h.b) - h.windowSize
    90  	copy(h.b, h.b[discard:])
    91  	h.b = h.b[:h.windowSize]
    92  	copy(h.b[h.windowSize-len(b):], b)
    93  }
    94  
    95  // ensureBlock will ensure there is space for at least one block...
    96  func (h *history) ensureBlock() {
    97  	if cap(h.b) < h.allocFrameBuffer {
    98  		h.b = make([]byte, 0, h.allocFrameBuffer)
    99  		return
   100  	}
   101  
   102  	avail := cap(h.b) - len(h.b)
   103  	if avail >= h.windowSize || avail > maxCompressedBlockSize {
   104  		return
   105  	}
   106  	// Move data down so we only have window size left.
   107  	// We know we have less than window size in b at this point.
   108  	discard := len(h.b) - h.windowSize
   109  	copy(h.b, h.b[discard:])
   110  	h.b = h.b[:h.windowSize]
   111  }
   112  
   113  // append bytes to history without ever discarding anything.
   114  func (h *history) appendKeep(b []byte) {
   115  	h.b = append(h.b, b...)
   116  }