aboutsummaryrefslogtreecommitdiff
path: root/internal/flatex/window_decoder.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/flatex/window_decoder.go')
-rw-r--r--internal/flatex/window_decoder.go101
1 files changed, 101 insertions, 0 deletions
diff --git a/internal/flatex/window_decoder.go b/internal/flatex/window_decoder.go
new file mode 100644
index 00000000..492c6a96
--- /dev/null
+++ b/internal/flatex/window_decoder.go
@@ -0,0 +1,101 @@
+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
+}