Files
aptly/vendor/github.com/kjk/lzma/lz_window.go
2018-06-22 12:44:23 -04:00

194 lines
4.0 KiB
Go

// Copyright (c) 2010, Andrei Vieru. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package lzma
import "io"
type lzOutWindow struct {
w io.Writer
buf []byte
winSize uint32
pos uint32
streamPos uint32
//unpacked uint32 // counter of unpacked bytes
}
func newLzOutWindow(w io.Writer, windowSize uint32) *lzOutWindow {
return &lzOutWindow{
w: w,
buf: make([]byte, windowSize),
winSize: windowSize,
pos: 0,
streamPos: 0,
//unpacked: 0,
}
}
func (ow *lzOutWindow) flush() {
size := ow.pos - ow.streamPos
if size == 0 {
return
}
n, err := ow.w.Write(ow.buf[ow.streamPos : ow.streamPos+size])
if err != nil {
throw(err)
}
if uint32(n) != size {
throw(nWriteError)
}
//unpacked += size
if ow.pos >= ow.winSize {
ow.pos = 0
}
ow.streamPos = ow.pos
}
func (ow *lzOutWindow) copyBlock(distance, length uint32) {
pos := ow.pos - distance - 1
if pos >= ow.winSize {
pos += ow.winSize
}
for ; length != 0; length-- {
if pos >= ow.winSize {
pos = 0
}
ow.buf[ow.pos] = ow.buf[pos]
ow.pos++
pos++
if ow.pos >= ow.winSize {
ow.flush()
}
}
}
func (ow *lzOutWindow) putByte(b byte) {
ow.buf[ow.pos] = b
ow.pos++
if ow.pos >= ow.winSize {
ow.flush()
}
}
func (ow *lzOutWindow) getByte(distance uint32) byte {
pos := ow.pos - distance - 1
if pos >= ow.winSize {
pos += ow.winSize
}
return ow.buf[pos]
}
type lzInWindow struct {
r io.Reader
buf []byte
posLimit uint32
lastSafePos uint32
bufOffset uint32
blockSize uint32
pos uint32
keepSizeBefore uint32
keepSizeAfter uint32
streamPos uint32
streamEnd bool
}
func newLzInWindow(r io.Reader, keepSizeBefore, keepSizeAfter, keepSizeReserv uint32) *lzInWindow {
blockSize := keepSizeBefore + keepSizeAfter + keepSizeReserv
iw := &lzInWindow{
r: r,
buf: make([]byte, blockSize),
lastSafePos: blockSize - keepSizeAfter,
bufOffset: 0,
blockSize: blockSize,
pos: 0,
keepSizeBefore: keepSizeBefore,
keepSizeAfter: keepSizeAfter,
streamPos: 0,
streamEnd: false,
}
iw.readBlock()
return iw
}
func (iw *lzInWindow) moveBlock() {
offset := iw.bufOffset + iw.pos - iw.keepSizeBefore
if offset > 0 {
offset--
}
numBytes := iw.bufOffset + iw.streamPos - offset
for i := uint32(0); i < numBytes; i++ {
iw.buf[i] = iw.buf[offset+i]
}
iw.bufOffset -= offset
}
func (iw *lzInWindow) readBlock() {
if iw.streamEnd {
return
}
for {
if iw.blockSize-iw.bufOffset-iw.streamPos == 0 {
return
}
n, err := iw.r.Read(iw.buf[iw.bufOffset+iw.streamPos : iw.blockSize])
if err != nil && err != io.EOF {
throw(err)
}
if n == 0 && err == io.EOF {
iw.posLimit = iw.streamPos
ptr := iw.bufOffset + iw.posLimit
if ptr > iw.lastSafePos {
iw.posLimit = iw.lastSafePos - iw.bufOffset
}
iw.streamEnd = true
return
}
iw.streamPos += uint32(n)
if iw.streamPos >= iw.pos+iw.keepSizeAfter {
iw.posLimit = iw.streamPos - iw.keepSizeAfter
}
}
}
func (iw *lzInWindow) movePos() {
iw.pos++
if iw.pos > iw.posLimit {
ptr := iw.bufOffset + iw.pos
if ptr > iw.lastSafePos {
iw.moveBlock()
}
iw.readBlock()
}
}
func (iw *lzInWindow) getIndexByte(index int32) byte {
return iw.buf[int32(iw.bufOffset+iw.pos)+index]
}
func (iw *lzInWindow) getMatchLen(index int32, distance, limit uint32) (res uint32) {
uIndex := uint32(index)
if iw.streamEnd == true {
if iw.pos+uIndex+limit > iw.streamPos {
limit = iw.streamPos - (iw.pos + uIndex)
}
}
distance++
pby := iw.bufOffset + iw.pos + uIndex
for res = uint32(0); res < limit && iw.buf[pby+res] == iw.buf[pby+res-distance]; res++ {
// empty body
}
return
}
func (iw *lzInWindow) getNumAvailableBytes() uint32 {
return iw.streamPos - iw.pos
}
func (iw *lzInWindow) reduceOffsets(subValue uint32) {
iw.bufOffset += subValue
iw.posLimit -= subValue
iw.pos -= subValue
iw.streamPos -= subValue
}