shithub: furgit

ref: d119343e8e7c83a56f87b05249ff0094aa2298a5
dir: /internal/flatex/window_decoder.go/

View raw version
package flatex

// windowDecoder implements the sliding window used in decompression.
type windowDecoder struct {
	hist []byte

	wrPos int
	rdPos int
	full  bool
}

func (wd *windowDecoder) init(size int) {
	*wd = windowDecoder{hist: wd.hist}

	if cap(wd.hist) < size {
		wd.hist = make([]byte, size)
	}
	wd.hist = wd.hist[:size]

	wd.wrPos = 0
	wd.rdPos = 0
	wd.full = false
}

func (wd *windowDecoder) histSize() int {
	if wd.full {
		return len(wd.hist)
	}
	return wd.wrPos
}

func (wd *windowDecoder) availRead() int {
	return wd.wrPos - wd.rdPos
}

func (wd *windowDecoder) availWrite() int {
	return len(wd.hist) - wd.wrPos
}

func (wd *windowDecoder) writeSlice() []byte {
	return wd.hist[wd.wrPos:]
}

func (wd *windowDecoder) writeMark(cnt int) {
	wd.wrPos += cnt
}

func (wd *windowDecoder) writeByte(c byte) {
	wd.hist[wd.wrPos] = c
	wd.wrPos++
}

func (wd *windowDecoder) writeCopy(dist, length int) int {
	dstBase := wd.wrPos
	dstPos := dstBase
	srcPos := dstPos - dist
	endPos := dstPos + length
	if endPos > len(wd.hist) {
		endPos = len(wd.hist)
	}

	if srcPos < 0 {
		srcPos += len(wd.hist)
		dstPos += copy(wd.hist[dstPos:endPos], wd.hist[srcPos:])
		srcPos = 0
	}

	for dstPos < endPos {
		dstPos += copy(wd.hist[dstPos:endPos], wd.hist[srcPos:dstPos])
	}

	wd.wrPos = dstPos
	return dstPos - dstBase
}

func (wd *windowDecoder) tryWriteCopy(dist, length int) int {
	dstPos := wd.wrPos
	endPos := dstPos + length
	if dstPos < dist || endPos > len(wd.hist) {
		return 0
	}
	dstBase := dstPos
	srcPos := dstPos - dist

	for dstPos < endPos {
		dstPos += copy(wd.hist[dstPos:endPos], wd.hist[srcPos:dstPos])
	}

	wd.wrPos = dstPos
	return dstPos - dstBase
}

func (wd *windowDecoder) readFlush() []byte {
	toRead := wd.hist[wd.rdPos:wd.wrPos]
	wd.rdPos = wd.wrPos
	if wd.wrPos == len(wd.hist) {
		wd.wrPos, wd.rdPos = 0, 0
		wd.full = true
	}
	return toRead
}