func xzDecBCJRun(s *xzDecBCJ, b *xzBuf, chain func(*xzBuf) xzRet) xzRet {
	var outStart int
	if s.temp.filtered > 0 {
		bcjFlush(s, b)
		if s.temp.filtered > 0 {
			return xzOK
		}
		if s.ret == xzStreamEnd {
			return xzStreamEnd
		}
	}
	if len(s.temp.buf) < len(b.out)-b.outPos || len(s.temp.buf) == 0 {
		outStart = b.outPos
		copy(b.out[b.outPos:], s.temp.buf)
		b.outPos += len(s.temp.buf)
		s.ret = chain(b)
		if s.ret != xzStreamEnd && s.ret != xzOK {
			return s.ret
		}
		bcjApply(s, b.out[:b.outPos], &outStart)
		if s.ret == xzStreamEnd {
			return xzStreamEnd
		}
		s.temp.buf = s.temp.bufArray[:b.outPos-outStart]
		b.outPos -= len(s.temp.buf)
		copy(s.temp.buf, b.out[b.outPos:])
		if b.outPos+len(s.temp.buf) < len(b.out) {
			return xzOK
		}
	}
	if b.outPos < len(b.out) {
		s.out = b.out
		s.outPos = b.outPos
		b.out = s.temp.bufArray[:]
		b.outPos = len(s.temp.buf)
		s.ret = chain(b)
		s.temp.buf = s.temp.bufArray[:b.outPos]
		b.out = s.out
		b.outPos = s.outPos
		if s.ret != xzOK && s.ret != xzStreamEnd {
			return s.ret
		}
		bcjApply(s, s.temp.buf, &s.temp.filtered)
		if s.ret == xzStreamEnd {
			s.temp.filtered = len(s.temp.buf)
		}
		bcjFlush(s, b)
		if s.temp.filtered > 0 {
			return xzOK
		}
	}
	return s.ret
}
/*
Decode raw stream which has a BCJ filter as the first filter.

The BCJ filter functions are primitive in sense that they process the
data in chunks of 1-16 bytes. To hide this issue, this function does
some buffering.
package xz
type xzDecBCJ struct {
	typ xzFilterID
	ret xzRet
	pos int
	x86PrevMask uint32
	out    []byte
	outPos int
	temp   struct {
		filtered int
		buf      []byte  
		bufArray [16]byte
	}
}
func bcjX86TestMSByte(b byte) bool {
	return b == 0x00 || b == 0xff
}
func bcjX86Filter(s *xzDecBCJ, buf []byte) int {
	var maskToAllowedStatus = []bool{
		true, true, true, false, true, false, false, false,
	}
	var maskToBitNum = []byte{0, 1, 2, 2, 3, 3, 3, 3}
	var i int
	var prevPos int = -1
	var prevMask uint32 = s.x86PrevMask
	var src uint32
	var dest uint32
	var j uint32
	var b byte
	if len(buf) <= 4 {
		return 0
	}
	for i = 0; i < len(buf)-4; i++ {
		if buf[i]&0xfe != 0xe8 {
			continue
		}
		prevPos = i - prevPos
		if prevPos > 3 {
			prevMask = 0
		} else {
			prevMask = (prevMask << (uint(prevPos) - 1)) & 7
			if prevMask != 0 {
				b = buf[i+4-int(maskToBitNum[prevMask])]
				if !maskToAllowedStatus[prevMask] || bcjX86TestMSByte(b) {
					prevPos = i
					prevMask = prevMask<<1 | 1
					continue
				}
			}
		}
		prevPos = i
		if bcjX86TestMSByte(buf[i+4]) {
			src = getLE32(buf[i+1:])
			for {
				dest = src - uint32(s.pos+i+5)
				if prevMask == 0 {
					break
				}
				j = uint32(maskToBitNum[prevMask]) * 8
				b = byte(dest >> (24 - j))
				if !bcjX86TestMSByte(b) {
					break
				}
				src = dest ^ (1<<(32-j) - 1)
			}
			dest &= 0x01FFFFFF
			dest |= 0 - dest&0x01000000
			putLE32(dest, buf[i+1:])
			i += 4
		} else {
			prevMask = prevMask<<1 | 1
		}
	}
	prevPos = i - prevPos
	if prevPos > 3 {
		s.x86PrevMask = 0
	} else {
		s.x86PrevMask = prevMask << (uint(prevPos) - 1)
	}
	return i
}
func bcjPowerPCFilter(s *xzDecBCJ, buf []byte) int {
	var i int
	var instr uint32
	for i = 0; i+4 <= len(buf); i += 4 {
		instr = getBE32(buf[i:])
		if instr&0xFC000003 == 0x48000001 {
			instr &= 0x03FFFFFC
			instr -= uint32(s.pos + i)
			instr &= 0x03FFFFFC
			instr |= 0x48000001
			putBE32(instr, buf[i:])
		}
	}
	return i
}
var bcjIA64BranchTable = [...]byte{
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	4, 4, 6, 6, 0, 0, 7, 7,
	4, 4, 0, 0, 4, 4, 0, 0,
}
func bcjIA64Filter(s *xzDecBCJ, buf []byte) int {
	var branchTable = bcjIA64BranchTable[:]
	var i int
	var j int
	var slot uint32
	var bitPos uint32
	var bytePos uint32
	var bitRes uint32
	var addr uint32
	var mask uint32
	var instr uint64
	var norm uint64
	for i = 0; i+16 <= len(buf); i += 16 {
		mask = uint32(branchTable[buf[i]&0x1f])
		for slot, bitPos = 0, 5; slot < 3; slot, bitPos = slot+1, bitPos+41 {
			if (mask>>slot)&1 == 0 {
				continue
			}
			bytePos = bitPos >> 3
			bitRes = bitPos & 7
			instr = 0
			for j = 0; j < 6; j++ {
				instr |= uint64(buf[i+j+int(bytePos)]) << (8 * uint(j))
			}
			norm = instr >> bitRes
			if (norm>>37)&0x0f == 0x05 && (norm>>9)&0x07 == 0 {
				addr = uint32((norm >> 13) & 0x0fffff)
				addr |= (uint32(norm>>36) & 1) << 20
				addr <<= 4
				addr -= uint32(s.pos + i)
				addr >>= 4
				norm &= ^(uint64(0x8fffff) << 13)
				norm |= uint64(addr&0x0fffff) << 13
				norm |= uint64(addr&0x100000) << (36 - 20)
				instr &= 1<<bitRes - 1
				instr |= norm << bitRes
				for j = 0; j < 6; j++ {
					buf[i+j+int(bytePos)] = byte(instr >> (8 * uint(j)))
				}
			}
		}
	}
	return i
}
func bcjARMFilter(s *xzDecBCJ, buf []byte) int {
	var i int
	var addr uint32
	for i = 0; i+4 <= len(buf); i += 4 {
		if buf[i+3] == 0xeb {
			addr = uint32(buf[i]) | uint32(buf[i+1])<<8 |
				uint32(buf[i+2])<<16
			addr <<= 2
			addr -= uint32(s.pos + i + 8)
			addr >>= 2
			buf[i] = byte(addr)
			buf[i+1] = byte(addr >> 8)
			buf[i+2] = byte(addr >> 16)
		}
	}
	return i
}
func bcjARMThumbFilter(s *xzDecBCJ, buf []byte) int {
	var i int
	var addr uint32
	for i = 0; i+4 <= len(buf); i += 2 {
		if buf[i+1]&0xf8 == 0xf0 && buf[i+3]&0xf8 == 0xf8 {
			addr = uint32(buf[i+1]&0x07)<<19 |
				uint32(buf[i])<<11 |
				uint32(buf[i+3]&0x07)<<8 |
				uint32(buf[i+2])
			addr <<= 1
			addr -= uint32(s.pos + i + 4)
			addr >>= 1
			buf[i+1] = byte(0xf0 | (addr>>19)&0x07)
			buf[i] = byte(addr >> 11)
			buf[i+3] = byte(0xf8 | (addr>>8)&0x07)
			buf[i+2] = byte(addr)
			i += 2
		}
	}
	return i
}
func bcjSPARCFilter(s *xzDecBCJ, buf []byte) int {
	var i int
	var instr uint32
	for i = 0; i+4 <= len(buf); i += 4 {
		instr = getBE32(buf[i:])
		if instr>>22 == 0x100 || instr>>22 == 0x1ff {
			instr <<= 2
			instr -= uint32(s.pos + i)
			instr >>= 2
			instr = (0x40000000 - instr&0x400000) |
				0x40000000 | (instr & 0x3FFFFF)
			putBE32(instr, buf[i:])
		}
	}
	return i
}
func bcjApply(s *xzDecBCJ, buf []byte, pos *int) {
	var filtered int
	buf = buf[*pos:]
	switch s.typ {
	case idBCJX86:
		filtered = bcjX86Filter(s, buf)
	case idBCJPowerPC:
		filtered = bcjPowerPCFilter(s, buf)
	case idBCJIA64:
		filtered = bcjIA64Filter(s, buf)
	case idBCJARM:
		filtered = bcjARMFilter(s, buf)
	case idBCJARMThumb:
		filtered = bcjARMThumbFilter(s, buf)
	case idBCJSPARC:
		filtered = bcjSPARCFilter(s, buf)
	default:
	}
	*pos += filtered
	s.pos += filtered
}
func bcjFlush(s *xzDecBCJ, b *xzBuf) {
	var copySize int
	copySize = len(b.out) - b.outPos
	if copySize > s.temp.filtered {
		copySize = s.temp.filtered
	}
	copy(b.out[b.outPos:], s.temp.buf[:copySize])
	b.outPos += copySize
	s.temp.filtered -= copySize
	copy(s.temp.buf, s.temp.buf[copySize:])
	s.temp.buf = s.temp.buf[:len(s.temp.buf)-copySize]
}