decompress_generic.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. //go:build !amd64 || appengine || !gc || noasm
  2. // +build !amd64 appengine !gc noasm
  3. // This file contains a generic implementation of Decoder.Decompress4X.
  4. package huff0
  5. import (
  6. "errors"
  7. "fmt"
  8. )
  9. // Decompress4X will decompress a 4X encoded stream.
  10. // The length of the supplied input must match the end of a block exactly.
  11. // The *capacity* of the dst slice must match the destination size of
  12. // the uncompressed data exactly.
  13. func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
  14. if len(d.dt.single) == 0 {
  15. return nil, errors.New("no table loaded")
  16. }
  17. if len(src) < 6+(4*1) {
  18. return nil, errors.New("input too small")
  19. }
  20. if use8BitTables && d.actualTableLog <= 8 {
  21. return d.decompress4X8bit(dst, src)
  22. }
  23. var br [4]bitReaderShifted
  24. // Decode "jump table"
  25. start := 6
  26. for i := 0; i < 3; i++ {
  27. length := int(src[i*2]) | (int(src[i*2+1]) << 8)
  28. if start+length >= len(src) {
  29. return nil, errors.New("truncated input (or invalid offset)")
  30. }
  31. err := br[i].init(src[start : start+length])
  32. if err != nil {
  33. return nil, err
  34. }
  35. start += length
  36. }
  37. err := br[3].init(src[start:])
  38. if err != nil {
  39. return nil, err
  40. }
  41. // destination, offset to match first output
  42. dstSize := cap(dst)
  43. dst = dst[:dstSize]
  44. out := dst
  45. dstEvery := (dstSize + 3) / 4
  46. const tlSize = 1 << tableLogMax
  47. const tlMask = tlSize - 1
  48. single := d.dt.single[:tlSize]
  49. // Use temp table to avoid bound checks/append penalty.
  50. buf := d.buffer()
  51. var off uint8
  52. var decoded int
  53. // Decode 2 values from each decoder/loop.
  54. const bufoff = 256
  55. for {
  56. if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 {
  57. break
  58. }
  59. {
  60. const stream = 0
  61. const stream2 = 1
  62. br[stream].fillFast()
  63. br[stream2].fillFast()
  64. val := br[stream].peekBitsFast(d.actualTableLog)
  65. val2 := br[stream2].peekBitsFast(d.actualTableLog)
  66. v := single[val&tlMask]
  67. v2 := single[val2&tlMask]
  68. br[stream].advance(uint8(v.entry))
  69. br[stream2].advance(uint8(v2.entry))
  70. buf[stream][off] = uint8(v.entry >> 8)
  71. buf[stream2][off] = uint8(v2.entry >> 8)
  72. val = br[stream].peekBitsFast(d.actualTableLog)
  73. val2 = br[stream2].peekBitsFast(d.actualTableLog)
  74. v = single[val&tlMask]
  75. v2 = single[val2&tlMask]
  76. br[stream].advance(uint8(v.entry))
  77. br[stream2].advance(uint8(v2.entry))
  78. buf[stream][off+1] = uint8(v.entry >> 8)
  79. buf[stream2][off+1] = uint8(v2.entry >> 8)
  80. }
  81. {
  82. const stream = 2
  83. const stream2 = 3
  84. br[stream].fillFast()
  85. br[stream2].fillFast()
  86. val := br[stream].peekBitsFast(d.actualTableLog)
  87. val2 := br[stream2].peekBitsFast(d.actualTableLog)
  88. v := single[val&tlMask]
  89. v2 := single[val2&tlMask]
  90. br[stream].advance(uint8(v.entry))
  91. br[stream2].advance(uint8(v2.entry))
  92. buf[stream][off] = uint8(v.entry >> 8)
  93. buf[stream2][off] = uint8(v2.entry >> 8)
  94. val = br[stream].peekBitsFast(d.actualTableLog)
  95. val2 = br[stream2].peekBitsFast(d.actualTableLog)
  96. v = single[val&tlMask]
  97. v2 = single[val2&tlMask]
  98. br[stream].advance(uint8(v.entry))
  99. br[stream2].advance(uint8(v2.entry))
  100. buf[stream][off+1] = uint8(v.entry >> 8)
  101. buf[stream2][off+1] = uint8(v2.entry >> 8)
  102. }
  103. off += 2
  104. if off == 0 {
  105. if bufoff > dstEvery {
  106. d.bufs.Put(buf)
  107. return nil, errors.New("corruption detected: stream overrun 1")
  108. }
  109. // There must at least be 3 buffers left.
  110. if len(out)-bufoff < dstEvery*3 {
  111. d.bufs.Put(buf)
  112. return nil, errors.New("corruption detected: stream overrun 2")
  113. }
  114. //copy(out, buf[0][:])
  115. //copy(out[dstEvery:], buf[1][:])
  116. //copy(out[dstEvery*2:], buf[2][:])
  117. //copy(out[dstEvery*3:], buf[3][:])
  118. *(*[bufoff]byte)(out) = buf[0]
  119. *(*[bufoff]byte)(out[dstEvery:]) = buf[1]
  120. *(*[bufoff]byte)(out[dstEvery*2:]) = buf[2]
  121. *(*[bufoff]byte)(out[dstEvery*3:]) = buf[3]
  122. out = out[bufoff:]
  123. decoded += bufoff * 4
  124. }
  125. }
  126. if off > 0 {
  127. ioff := int(off)
  128. if len(out) < dstEvery*3+ioff {
  129. d.bufs.Put(buf)
  130. return nil, errors.New("corruption detected: stream overrun 3")
  131. }
  132. copy(out, buf[0][:off])
  133. copy(out[dstEvery:], buf[1][:off])
  134. copy(out[dstEvery*2:], buf[2][:off])
  135. copy(out[dstEvery*3:], buf[3][:off])
  136. decoded += int(off) * 4
  137. out = out[off:]
  138. }
  139. // Decode remaining.
  140. remainBytes := dstEvery - (decoded / 4)
  141. for i := range br {
  142. offset := dstEvery * i
  143. endsAt := offset + remainBytes
  144. if endsAt > len(out) {
  145. endsAt = len(out)
  146. }
  147. br := &br[i]
  148. bitsLeft := br.remaining()
  149. for bitsLeft > 0 {
  150. br.fill()
  151. if offset >= endsAt {
  152. d.bufs.Put(buf)
  153. return nil, errors.New("corruption detected: stream overrun 4")
  154. }
  155. // Read value and increment offset.
  156. val := br.peekBitsFast(d.actualTableLog)
  157. v := single[val&tlMask].entry
  158. nBits := uint8(v)
  159. br.advance(nBits)
  160. bitsLeft -= uint(nBits)
  161. out[offset] = uint8(v >> 8)
  162. offset++
  163. }
  164. if offset != endsAt {
  165. d.bufs.Put(buf)
  166. return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt)
  167. }
  168. decoded += offset - dstEvery*i
  169. err = br.close()
  170. if err != nil {
  171. return nil, err
  172. }
  173. }
  174. d.bufs.Put(buf)
  175. if dstSize != decoded {
  176. return nil, errors.New("corruption detected: short output block")
  177. }
  178. return dst, nil
  179. }
  180. // Decompress1X will decompress a 1X encoded stream.
  181. // The cap of the output buffer will be the maximum decompressed size.
  182. // The length of the supplied input must match the end of a block exactly.
  183. func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
  184. if len(d.dt.single) == 0 {
  185. return nil, errors.New("no table loaded")
  186. }
  187. if use8BitTables && d.actualTableLog <= 8 {
  188. return d.decompress1X8Bit(dst, src)
  189. }
  190. var br bitReaderShifted
  191. err := br.init(src)
  192. if err != nil {
  193. return dst, err
  194. }
  195. maxDecodedSize := cap(dst)
  196. dst = dst[:0]
  197. // Avoid bounds check by always having full sized table.
  198. const tlSize = 1 << tableLogMax
  199. const tlMask = tlSize - 1
  200. dt := d.dt.single[:tlSize]
  201. // Use temp table to avoid bound checks/append penalty.
  202. bufs := d.buffer()
  203. buf := &bufs[0]
  204. var off uint8
  205. for br.off >= 8 {
  206. br.fillFast()
  207. v := dt[br.peekBitsFast(d.actualTableLog)&tlMask]
  208. br.advance(uint8(v.entry))
  209. buf[off+0] = uint8(v.entry >> 8)
  210. v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
  211. br.advance(uint8(v.entry))
  212. buf[off+1] = uint8(v.entry >> 8)
  213. // Refill
  214. br.fillFast()
  215. v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
  216. br.advance(uint8(v.entry))
  217. buf[off+2] = uint8(v.entry >> 8)
  218. v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
  219. br.advance(uint8(v.entry))
  220. buf[off+3] = uint8(v.entry >> 8)
  221. off += 4
  222. if off == 0 {
  223. if len(dst)+256 > maxDecodedSize {
  224. br.close()
  225. d.bufs.Put(bufs)
  226. return nil, ErrMaxDecodedSizeExceeded
  227. }
  228. dst = append(dst, buf[:]...)
  229. }
  230. }
  231. if len(dst)+int(off) > maxDecodedSize {
  232. d.bufs.Put(bufs)
  233. br.close()
  234. return nil, ErrMaxDecodedSizeExceeded
  235. }
  236. dst = append(dst, buf[:off]...)
  237. // br < 8, so uint8 is fine
  238. bitsLeft := uint8(br.off)*8 + 64 - br.bitsRead
  239. for bitsLeft > 0 {
  240. br.fill()
  241. if false && br.bitsRead >= 32 {
  242. if br.off >= 4 {
  243. v := br.in[br.off-4:]
  244. v = v[:4]
  245. low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
  246. br.value = (br.value << 32) | uint64(low)
  247. br.bitsRead -= 32
  248. br.off -= 4
  249. } else {
  250. for br.off > 0 {
  251. br.value = (br.value << 8) | uint64(br.in[br.off-1])
  252. br.bitsRead -= 8
  253. br.off--
  254. }
  255. }
  256. }
  257. if len(dst) >= maxDecodedSize {
  258. d.bufs.Put(bufs)
  259. br.close()
  260. return nil, ErrMaxDecodedSizeExceeded
  261. }
  262. v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask]
  263. nBits := uint8(v.entry)
  264. br.advance(nBits)
  265. bitsLeft -= nBits
  266. dst = append(dst, uint8(v.entry>>8))
  267. }
  268. d.bufs.Put(bufs)
  269. return dst, br.close()
  270. }