decompress_generic.go 7.5 KB

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