blockenc.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. // Copyright 2019+ Klaus Post. All rights reserved.
  2. // License information can be found in the LICENSE file.
  3. // Based on work by Yann Collet, released under BSD License.
  4. package zstd
  5. import (
  6. "errors"
  7. "fmt"
  8. "math"
  9. "math/bits"
  10. "github.com/klauspost/compress/huff0"
  11. )
  12. type blockEnc struct {
  13. size int
  14. literals []byte
  15. sequences []seq
  16. coders seqCoders
  17. litEnc *huff0.Scratch
  18. wr bitWriter
  19. extraLits int
  20. last bool
  21. output []byte
  22. recentOffsets [3]uint32
  23. prevRecentOffsets [3]uint32
  24. }
  25. // init should be used once the block has been created.
  26. // If called more than once, the effect is the same as calling reset.
  27. func (b *blockEnc) init() {
  28. if cap(b.literals) < maxCompressedLiteralSize {
  29. b.literals = make([]byte, 0, maxCompressedLiteralSize)
  30. }
  31. const defSeqs = 200
  32. b.literals = b.literals[:0]
  33. if cap(b.sequences) < defSeqs {
  34. b.sequences = make([]seq, 0, defSeqs)
  35. }
  36. if cap(b.output) < maxCompressedBlockSize {
  37. b.output = make([]byte, 0, maxCompressedBlockSize)
  38. }
  39. if b.coders.mlEnc == nil {
  40. b.coders.mlEnc = &fseEncoder{}
  41. b.coders.mlPrev = &fseEncoder{}
  42. b.coders.ofEnc = &fseEncoder{}
  43. b.coders.ofPrev = &fseEncoder{}
  44. b.coders.llEnc = &fseEncoder{}
  45. b.coders.llPrev = &fseEncoder{}
  46. }
  47. b.litEnc = &huff0.Scratch{WantLogLess: 4}
  48. b.reset(nil)
  49. }
  50. // initNewEncode can be used to reset offsets and encoders to the initial state.
  51. func (b *blockEnc) initNewEncode() {
  52. b.recentOffsets = [3]uint32{1, 4, 8}
  53. b.litEnc.Reuse = huff0.ReusePolicyNone
  54. b.coders.setPrev(nil, nil, nil)
  55. }
  56. // reset will reset the block for a new encode, but in the same stream,
  57. // meaning that state will be carried over, but the block content is reset.
  58. // If a previous block is provided, the recent offsets are carried over.
  59. func (b *blockEnc) reset(prev *blockEnc) {
  60. b.extraLits = 0
  61. b.literals = b.literals[:0]
  62. b.size = 0
  63. b.sequences = b.sequences[:0]
  64. b.output = b.output[:0]
  65. b.last = false
  66. if prev != nil {
  67. b.recentOffsets = prev.prevRecentOffsets
  68. }
  69. }
  70. // reset will reset the block for a new encode, but in the same stream,
  71. // meaning that state will be carried over, but the block content is reset.
  72. // If a previous block is provided, the recent offsets are carried over.
  73. func (b *blockEnc) swapEncoders(prev *blockEnc) {
  74. b.coders.swap(&prev.coders)
  75. b.litEnc, prev.litEnc = prev.litEnc, b.litEnc
  76. }
  77. // blockHeader contains the information for a block header.
  78. type blockHeader uint32
  79. // setLast sets the 'last' indicator on a block.
  80. func (h *blockHeader) setLast(b bool) {
  81. if b {
  82. *h = *h | 1
  83. } else {
  84. const mask = (1 << 24) - 2
  85. *h = *h & mask
  86. }
  87. }
  88. // setSize will store the compressed size of a block.
  89. func (h *blockHeader) setSize(v uint32) {
  90. const mask = 7
  91. *h = (*h)&mask | blockHeader(v<<3)
  92. }
  93. // setType sets the block type.
  94. func (h *blockHeader) setType(t blockType) {
  95. const mask = 1 | (((1 << 24) - 1) ^ 7)
  96. *h = (*h & mask) | blockHeader(t<<1)
  97. }
  98. // appendTo will append the block header to a slice.
  99. func (h blockHeader) appendTo(b []byte) []byte {
  100. return append(b, uint8(h), uint8(h>>8), uint8(h>>16))
  101. }
  102. // String returns a string representation of the block.
  103. func (h blockHeader) String() string {
  104. return fmt.Sprintf("Type: %d, Size: %d, Last:%t", (h>>1)&3, h>>3, h&1 == 1)
  105. }
  106. // literalsHeader contains literals header information.
  107. type literalsHeader uint64
  108. // setType can be used to set the type of literal block.
  109. func (h *literalsHeader) setType(t literalsBlockType) {
  110. const mask = math.MaxUint64 - 3
  111. *h = (*h & mask) | literalsHeader(t)
  112. }
  113. // setSize can be used to set a single size, for uncompressed and RLE content.
  114. func (h *literalsHeader) setSize(regenLen int) {
  115. inBits := bits.Len32(uint32(regenLen))
  116. // Only retain 2 bits
  117. const mask = 3
  118. lh := uint64(*h & mask)
  119. switch {
  120. case inBits < 5:
  121. lh |= (uint64(regenLen) << 3) | (1 << 60)
  122. if debug {
  123. got := int(lh>>3) & 0xff
  124. if got != regenLen {
  125. panic(fmt.Sprint("litRegenSize = ", regenLen, "(want) != ", got, "(got)"))
  126. }
  127. }
  128. case inBits < 12:
  129. lh |= (1 << 2) | (uint64(regenLen) << 4) | (2 << 60)
  130. case inBits < 20:
  131. lh |= (3 << 2) | (uint64(regenLen) << 4) | (3 << 60)
  132. default:
  133. panic(fmt.Errorf("internal error: block too big (%d)", regenLen))
  134. }
  135. *h = literalsHeader(lh)
  136. }
  137. // setSizes will set the size of a compressed literals section and the input length.
  138. func (h *literalsHeader) setSizes(compLen, inLen int, single bool) {
  139. compBits, inBits := bits.Len32(uint32(compLen)), bits.Len32(uint32(inLen))
  140. // Only retain 2 bits
  141. const mask = 3
  142. lh := uint64(*h & mask)
  143. switch {
  144. case compBits <= 10 && inBits <= 10:
  145. if !single {
  146. lh |= 1 << 2
  147. }
  148. lh |= (uint64(inLen) << 4) | (uint64(compLen) << (10 + 4)) | (3 << 60)
  149. if debug {
  150. const mmask = (1 << 24) - 1
  151. n := (lh >> 4) & mmask
  152. if int(n&1023) != inLen {
  153. panic(fmt.Sprint("regensize:", int(n&1023), "!=", inLen, inBits))
  154. }
  155. if int(n>>10) != compLen {
  156. panic(fmt.Sprint("compsize:", int(n>>10), "!=", compLen, compBits))
  157. }
  158. }
  159. case compBits <= 14 && inBits <= 14:
  160. lh |= (2 << 2) | (uint64(inLen) << 4) | (uint64(compLen) << (14 + 4)) | (4 << 60)
  161. if single {
  162. panic("single stream used with more than 10 bits length.")
  163. }
  164. case compBits <= 18 && inBits <= 18:
  165. lh |= (3 << 2) | (uint64(inLen) << 4) | (uint64(compLen) << (18 + 4)) | (5 << 60)
  166. if single {
  167. panic("single stream used with more than 10 bits length.")
  168. }
  169. default:
  170. panic("internal error: block too big")
  171. }
  172. *h = literalsHeader(lh)
  173. }
  174. // appendTo will append the literals header to a byte slice.
  175. func (h literalsHeader) appendTo(b []byte) []byte {
  176. size := uint8(h >> 60)
  177. switch size {
  178. case 1:
  179. b = append(b, uint8(h))
  180. case 2:
  181. b = append(b, uint8(h), uint8(h>>8))
  182. case 3:
  183. b = append(b, uint8(h), uint8(h>>8), uint8(h>>16))
  184. case 4:
  185. b = append(b, uint8(h), uint8(h>>8), uint8(h>>16), uint8(h>>24))
  186. case 5:
  187. b = append(b, uint8(h), uint8(h>>8), uint8(h>>16), uint8(h>>24), uint8(h>>32))
  188. default:
  189. panic(fmt.Errorf("internal error: literalsHeader has invalid size (%d)", size))
  190. }
  191. return b
  192. }
  193. // size returns the output size with currently set values.
  194. func (h literalsHeader) size() int {
  195. return int(h >> 60)
  196. }
  197. func (h literalsHeader) String() string {
  198. return fmt.Sprintf("Type: %d, SizeFormat: %d, Size: 0x%d, Bytes:%d", literalsBlockType(h&3), (h>>2)&3, h&((1<<60)-1)>>4, h>>60)
  199. }
  200. // pushOffsets will push the recent offsets to the backup store.
  201. func (b *blockEnc) pushOffsets() {
  202. b.prevRecentOffsets = b.recentOffsets
  203. }
  204. // pushOffsets will push the recent offsets to the backup store.
  205. func (b *blockEnc) popOffsets() {
  206. b.recentOffsets = b.prevRecentOffsets
  207. }
  208. // matchOffset will adjust recent offsets and return the adjusted one,
  209. // if it matches a previous offset.
  210. func (b *blockEnc) matchOffset(offset, lits uint32) uint32 {
  211. // Check if offset is one of the recent offsets.
  212. // Adjusts the output offset accordingly.
  213. // Gives a tiny bit of compression, typically around 1%.
  214. if true {
  215. if lits > 0 {
  216. switch offset {
  217. case b.recentOffsets[0]:
  218. offset = 1
  219. case b.recentOffsets[1]:
  220. b.recentOffsets[1] = b.recentOffsets[0]
  221. b.recentOffsets[0] = offset
  222. offset = 2
  223. case b.recentOffsets[2]:
  224. b.recentOffsets[2] = b.recentOffsets[1]
  225. b.recentOffsets[1] = b.recentOffsets[0]
  226. b.recentOffsets[0] = offset
  227. offset = 3
  228. default:
  229. b.recentOffsets[2] = b.recentOffsets[1]
  230. b.recentOffsets[1] = b.recentOffsets[0]
  231. b.recentOffsets[0] = offset
  232. offset += 3
  233. }
  234. } else {
  235. switch offset {
  236. case b.recentOffsets[1]:
  237. b.recentOffsets[1] = b.recentOffsets[0]
  238. b.recentOffsets[0] = offset
  239. offset = 1
  240. case b.recentOffsets[2]:
  241. b.recentOffsets[2] = b.recentOffsets[1]
  242. b.recentOffsets[1] = b.recentOffsets[0]
  243. b.recentOffsets[0] = offset
  244. offset = 2
  245. case b.recentOffsets[0] - 1:
  246. b.recentOffsets[2] = b.recentOffsets[1]
  247. b.recentOffsets[1] = b.recentOffsets[0]
  248. b.recentOffsets[0] = offset
  249. offset = 3
  250. default:
  251. b.recentOffsets[2] = b.recentOffsets[1]
  252. b.recentOffsets[1] = b.recentOffsets[0]
  253. b.recentOffsets[0] = offset
  254. offset += 3
  255. }
  256. }
  257. } else {
  258. offset += 3
  259. }
  260. return offset
  261. }
  262. // encodeRaw can be used to set the output to a raw representation of supplied bytes.
  263. func (b *blockEnc) encodeRaw(a []byte) {
  264. var bh blockHeader
  265. bh.setLast(b.last)
  266. bh.setSize(uint32(len(a)))
  267. bh.setType(blockTypeRaw)
  268. b.output = bh.appendTo(b.output[:0])
  269. b.output = append(b.output, a...)
  270. if debug {
  271. println("Adding RAW block, length", len(a))
  272. }
  273. }
  274. // encodeRaw can be used to set the output to a raw representation of supplied bytes.
  275. func (b *blockEnc) encodeRawTo(dst, src []byte) []byte {
  276. var bh blockHeader
  277. bh.setLast(b.last)
  278. bh.setSize(uint32(len(src)))
  279. bh.setType(blockTypeRaw)
  280. dst = bh.appendTo(dst)
  281. dst = append(dst, src...)
  282. if debug {
  283. println("Adding RAW block, length", len(src))
  284. }
  285. return dst
  286. }
  287. // encodeLits can be used if the block is only litLen.
  288. func (b *blockEnc) encodeLits(raw bool) error {
  289. var bh blockHeader
  290. bh.setLast(b.last)
  291. bh.setSize(uint32(len(b.literals)))
  292. // Don't compress extremely small blocks
  293. if len(b.literals) < 32 || raw {
  294. if debug {
  295. println("Adding RAW block, length", len(b.literals))
  296. }
  297. bh.setType(blockTypeRaw)
  298. b.output = bh.appendTo(b.output)
  299. b.output = append(b.output, b.literals...)
  300. return nil
  301. }
  302. var (
  303. out []byte
  304. reUsed, single bool
  305. err error
  306. )
  307. if len(b.literals) >= 1024 {
  308. // Use 4 Streams.
  309. out, reUsed, err = huff0.Compress4X(b.literals, b.litEnc)
  310. } else if len(b.literals) > 32 {
  311. // Use 1 stream
  312. single = true
  313. out, reUsed, err = huff0.Compress1X(b.literals, b.litEnc)
  314. } else {
  315. err = huff0.ErrIncompressible
  316. }
  317. switch err {
  318. case huff0.ErrIncompressible:
  319. if debug {
  320. println("Adding RAW block, length", len(b.literals))
  321. }
  322. bh.setType(blockTypeRaw)
  323. b.output = bh.appendTo(b.output)
  324. b.output = append(b.output, b.literals...)
  325. return nil
  326. case huff0.ErrUseRLE:
  327. if debug {
  328. println("Adding RLE block, length", len(b.literals))
  329. }
  330. bh.setType(blockTypeRLE)
  331. b.output = bh.appendTo(b.output)
  332. b.output = append(b.output, b.literals[0])
  333. return nil
  334. default:
  335. return err
  336. case nil:
  337. }
  338. // Compressed...
  339. // Now, allow reuse
  340. b.litEnc.Reuse = huff0.ReusePolicyAllow
  341. bh.setType(blockTypeCompressed)
  342. var lh literalsHeader
  343. if reUsed {
  344. if debug {
  345. println("Reused tree, compressed to", len(out))
  346. }
  347. lh.setType(literalsBlockTreeless)
  348. } else {
  349. if debug {
  350. println("New tree, compressed to", len(out), "tree size:", len(b.litEnc.OutTable))
  351. }
  352. lh.setType(literalsBlockCompressed)
  353. }
  354. // Set sizes
  355. lh.setSizes(len(out), len(b.literals), single)
  356. bh.setSize(uint32(len(out) + lh.size() + 1))
  357. // Write block headers.
  358. b.output = bh.appendTo(b.output)
  359. b.output = lh.appendTo(b.output)
  360. // Add compressed data.
  361. b.output = append(b.output, out...)
  362. // No sequences.
  363. b.output = append(b.output, 0)
  364. return nil
  365. }
  366. // fuzzFseEncoder can be used to fuzz the FSE encoder.
  367. func fuzzFseEncoder(data []byte) int {
  368. if len(data) > maxSequences || len(data) < 2 {
  369. return 0
  370. }
  371. enc := fseEncoder{}
  372. hist := enc.Histogram()[:256]
  373. maxSym := uint8(0)
  374. for i, v := range data {
  375. v = v & 63
  376. data[i] = v
  377. hist[v]++
  378. if v > maxSym {
  379. maxSym = v
  380. }
  381. }
  382. if maxSym == 0 {
  383. // All 0
  384. return 0
  385. }
  386. maxCount := func(a []uint32) int {
  387. var max uint32
  388. for _, v := range a {
  389. if v > max {
  390. max = v
  391. }
  392. }
  393. return int(max)
  394. }
  395. cnt := maxCount(hist[:maxSym])
  396. if cnt == len(data) {
  397. // RLE
  398. return 0
  399. }
  400. enc.HistogramFinished(maxSym, cnt)
  401. err := enc.normalizeCount(len(data))
  402. if err != nil {
  403. return 0
  404. }
  405. _, err = enc.writeCount(nil)
  406. if err != nil {
  407. panic(err)
  408. }
  409. return 1
  410. }
  411. // encode will encode the block and append the output in b.output.
  412. func (b *blockEnc) encode(raw bool) error {
  413. if len(b.sequences) == 0 {
  414. return b.encodeLits(raw)
  415. }
  416. // We want some difference
  417. if len(b.literals) > (b.size - (b.size >> 5)) {
  418. return errIncompressible
  419. }
  420. var bh blockHeader
  421. var lh literalsHeader
  422. bh.setLast(b.last)
  423. bh.setType(blockTypeCompressed)
  424. // Store offset of the block header. Needed when we know the size.
  425. bhOffset := len(b.output)
  426. b.output = bh.appendTo(b.output)
  427. var (
  428. out []byte
  429. reUsed, single bool
  430. err error
  431. )
  432. if len(b.literals) >= 1024 && !raw {
  433. // Use 4 Streams.
  434. out, reUsed, err = huff0.Compress4X(b.literals, b.litEnc)
  435. } else if len(b.literals) > 32 && !raw {
  436. // Use 1 stream
  437. single = true
  438. out, reUsed, err = huff0.Compress1X(b.literals, b.litEnc)
  439. } else {
  440. err = huff0.ErrIncompressible
  441. }
  442. switch err {
  443. case huff0.ErrIncompressible:
  444. lh.setType(literalsBlockRaw)
  445. lh.setSize(len(b.literals))
  446. b.output = lh.appendTo(b.output)
  447. b.output = append(b.output, b.literals...)
  448. if debug {
  449. println("Adding literals RAW, length", len(b.literals))
  450. }
  451. case huff0.ErrUseRLE:
  452. lh.setType(literalsBlockRLE)
  453. lh.setSize(len(b.literals))
  454. b.output = lh.appendTo(b.output)
  455. b.output = append(b.output, b.literals[0])
  456. if debug {
  457. println("Adding literals RLE")
  458. }
  459. default:
  460. if debug {
  461. println("Adding literals ERROR:", err)
  462. }
  463. return err
  464. case nil:
  465. // Compressed litLen...
  466. if reUsed {
  467. if debug {
  468. println("reused tree")
  469. }
  470. lh.setType(literalsBlockTreeless)
  471. } else {
  472. if debug {
  473. println("new tree, size:", len(b.litEnc.OutTable))
  474. }
  475. lh.setType(literalsBlockCompressed)
  476. if debug {
  477. _, _, err := huff0.ReadTable(out, nil)
  478. if err != nil {
  479. panic(err)
  480. }
  481. }
  482. }
  483. lh.setSizes(len(out), len(b.literals), single)
  484. if debug {
  485. printf("Compressed %d literals to %d bytes", len(b.literals), len(out))
  486. println("Adding literal header:", lh)
  487. }
  488. b.output = lh.appendTo(b.output)
  489. b.output = append(b.output, out...)
  490. b.litEnc.Reuse = huff0.ReusePolicyAllow
  491. if debug {
  492. println("Adding literals compressed")
  493. }
  494. }
  495. // Sequence compression
  496. // Write the number of sequences
  497. switch {
  498. case len(b.sequences) < 128:
  499. b.output = append(b.output, uint8(len(b.sequences)))
  500. case len(b.sequences) < 0x7f00: // TODO: this could be wrong
  501. n := len(b.sequences)
  502. b.output = append(b.output, 128+uint8(n>>8), uint8(n))
  503. default:
  504. n := len(b.sequences) - 0x7f00
  505. b.output = append(b.output, 255, uint8(n), uint8(n>>8))
  506. }
  507. if debug {
  508. println("Encoding", len(b.sequences), "sequences")
  509. }
  510. b.genCodes()
  511. llEnc := b.coders.llEnc
  512. ofEnc := b.coders.ofEnc
  513. mlEnc := b.coders.mlEnc
  514. err = llEnc.normalizeCount(len(b.sequences))
  515. if err != nil {
  516. return err
  517. }
  518. err = ofEnc.normalizeCount(len(b.sequences))
  519. if err != nil {
  520. return err
  521. }
  522. err = mlEnc.normalizeCount(len(b.sequences))
  523. if err != nil {
  524. return err
  525. }
  526. // Choose the best compression mode for each type.
  527. // Will evaluate the new vs predefined and previous.
  528. chooseComp := func(cur, prev, preDef *fseEncoder) (*fseEncoder, seqCompMode) {
  529. // See if predefined/previous is better
  530. hist := cur.count[:cur.symbolLen]
  531. nSize := cur.approxSize(hist) + cur.maxHeaderSize()
  532. predefSize := preDef.approxSize(hist)
  533. prevSize := prev.approxSize(hist)
  534. // Add a small penalty for new encoders.
  535. // Don't bother with extremely small (<2 byte gains).
  536. nSize = nSize + (nSize+2*8*16)>>4
  537. switch {
  538. case predefSize <= prevSize && predefSize <= nSize || forcePreDef:
  539. if debug {
  540. println("Using predefined", predefSize>>3, "<=", nSize>>3)
  541. }
  542. return preDef, compModePredefined
  543. case prevSize <= nSize:
  544. if debug {
  545. println("Using previous", prevSize>>3, "<=", nSize>>3)
  546. }
  547. return prev, compModeRepeat
  548. default:
  549. if debug {
  550. println("Using new, predef", predefSize>>3, ". previous:", prevSize>>3, ">", nSize>>3, "header max:", cur.maxHeaderSize()>>3, "bytes")
  551. println("tl:", cur.actualTableLog, "symbolLen:", cur.symbolLen, "norm:", cur.norm[:cur.symbolLen], "hist", cur.count[:cur.symbolLen])
  552. }
  553. return cur, compModeFSE
  554. }
  555. }
  556. // Write compression mode
  557. var mode uint8
  558. if llEnc.useRLE {
  559. mode |= uint8(compModeRLE) << 6
  560. llEnc.setRLE(b.sequences[0].llCode)
  561. if debug {
  562. println("llEnc.useRLE")
  563. }
  564. } else {
  565. var m seqCompMode
  566. llEnc, m = chooseComp(llEnc, b.coders.llPrev, &fsePredefEnc[tableLiteralLengths])
  567. mode |= uint8(m) << 6
  568. }
  569. if ofEnc.useRLE {
  570. mode |= uint8(compModeRLE) << 4
  571. ofEnc.setRLE(b.sequences[0].ofCode)
  572. if debug {
  573. println("ofEnc.useRLE")
  574. }
  575. } else {
  576. var m seqCompMode
  577. ofEnc, m = chooseComp(ofEnc, b.coders.ofPrev, &fsePredefEnc[tableOffsets])
  578. mode |= uint8(m) << 4
  579. }
  580. if mlEnc.useRLE {
  581. mode |= uint8(compModeRLE) << 2
  582. mlEnc.setRLE(b.sequences[0].mlCode)
  583. if debug {
  584. println("mlEnc.useRLE, code: ", b.sequences[0].mlCode, "value", b.sequences[0].matchLen)
  585. }
  586. } else {
  587. var m seqCompMode
  588. mlEnc, m = chooseComp(mlEnc, b.coders.mlPrev, &fsePredefEnc[tableMatchLengths])
  589. mode |= uint8(m) << 2
  590. }
  591. b.output = append(b.output, mode)
  592. if debug {
  593. printf("Compression modes: 0b%b", mode)
  594. }
  595. b.output, err = llEnc.writeCount(b.output)
  596. if err != nil {
  597. return err
  598. }
  599. start := len(b.output)
  600. b.output, err = ofEnc.writeCount(b.output)
  601. if err != nil {
  602. return err
  603. }
  604. if false {
  605. println("block:", b.output[start:], "tablelog", ofEnc.actualTableLog, "maxcount:", ofEnc.maxCount)
  606. fmt.Printf("selected TableLog: %d, Symbol length: %d\n", ofEnc.actualTableLog, ofEnc.symbolLen)
  607. for i, v := range ofEnc.norm[:ofEnc.symbolLen] {
  608. fmt.Printf("%3d: %5d -> %4d \n", i, ofEnc.count[i], v)
  609. }
  610. }
  611. b.output, err = mlEnc.writeCount(b.output)
  612. if err != nil {
  613. return err
  614. }
  615. // Maybe in block?
  616. wr := &b.wr
  617. wr.reset(b.output)
  618. var ll, of, ml cState
  619. // Current sequence
  620. seq := len(b.sequences) - 1
  621. s := b.sequences[seq]
  622. llEnc.setBits(llBitsTable[:])
  623. mlEnc.setBits(mlBitsTable[:])
  624. ofEnc.setBits(nil)
  625. llTT, ofTT, mlTT := llEnc.ct.symbolTT[:256], ofEnc.ct.symbolTT[:256], mlEnc.ct.symbolTT[:256]
  626. // We have 3 bounds checks here (and in the loop).
  627. // Since we are iterating backwards it is kinda hard to avoid.
  628. llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
  629. ll.init(wr, &llEnc.ct, llB)
  630. of.init(wr, &ofEnc.ct, ofB)
  631. wr.flush32()
  632. ml.init(wr, &mlEnc.ct, mlB)
  633. // Each of these lookups also generates a bounds check.
  634. wr.addBits32NC(s.litLen, llB.outBits)
  635. wr.addBits32NC(s.matchLen, mlB.outBits)
  636. wr.flush32()
  637. wr.addBits32NC(s.offset, ofB.outBits)
  638. if debugSequences {
  639. println("Encoded seq", seq, s, "codes:", s.llCode, s.mlCode, s.ofCode, "states:", ll.state, ml.state, of.state, "bits:", llB, mlB, ofB)
  640. }
  641. seq--
  642. if llEnc.maxBits+mlEnc.maxBits+ofEnc.maxBits <= 32 {
  643. // No need to flush (common)
  644. for seq >= 0 {
  645. s = b.sequences[seq]
  646. wr.flush32()
  647. llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
  648. // tabelog max is 8 for all.
  649. of.encode(ofB)
  650. ml.encode(mlB)
  651. ll.encode(llB)
  652. wr.flush32()
  653. // We checked that all can stay within 32 bits
  654. wr.addBits32NC(s.litLen, llB.outBits)
  655. wr.addBits32NC(s.matchLen, mlB.outBits)
  656. wr.addBits32NC(s.offset, ofB.outBits)
  657. if debugSequences {
  658. println("Encoded seq", seq, s)
  659. }
  660. seq--
  661. }
  662. } else {
  663. for seq >= 0 {
  664. s = b.sequences[seq]
  665. wr.flush32()
  666. llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
  667. // tabelog max is below 8 for each.
  668. of.encode(ofB)
  669. ml.encode(mlB)
  670. ll.encode(llB)
  671. wr.flush32()
  672. // ml+ll = max 32 bits total
  673. wr.addBits32NC(s.litLen, llB.outBits)
  674. wr.addBits32NC(s.matchLen, mlB.outBits)
  675. wr.flush32()
  676. wr.addBits32NC(s.offset, ofB.outBits)
  677. if debugSequences {
  678. println("Encoded seq", seq, s)
  679. }
  680. seq--
  681. }
  682. }
  683. ml.flush(mlEnc.actualTableLog)
  684. of.flush(ofEnc.actualTableLog)
  685. ll.flush(llEnc.actualTableLog)
  686. err = wr.close()
  687. if err != nil {
  688. return err
  689. }
  690. b.output = wr.out
  691. if len(b.output)-3-bhOffset >= b.size {
  692. // Maybe even add a bigger margin.
  693. b.litEnc.Reuse = huff0.ReusePolicyNone
  694. return errIncompressible
  695. }
  696. // Size is output minus block header.
  697. bh.setSize(uint32(len(b.output)-bhOffset) - 3)
  698. if debug {
  699. println("Rewriting block header", bh)
  700. }
  701. _ = bh.appendTo(b.output[bhOffset:bhOffset])
  702. b.coders.setPrev(llEnc, mlEnc, ofEnc)
  703. return nil
  704. }
  705. var errIncompressible = errors.New("incompressible")
  706. func (b *blockEnc) genCodes() {
  707. if len(b.sequences) == 0 {
  708. // nothing to do
  709. return
  710. }
  711. if len(b.sequences) > math.MaxUint16 {
  712. panic("can only encode up to 64K sequences")
  713. }
  714. // No bounds checks after here:
  715. llH := b.coders.llEnc.Histogram()[:256]
  716. ofH := b.coders.ofEnc.Histogram()[:256]
  717. mlH := b.coders.mlEnc.Histogram()[:256]
  718. for i := range llH {
  719. llH[i] = 0
  720. }
  721. for i := range ofH {
  722. ofH[i] = 0
  723. }
  724. for i := range mlH {
  725. mlH[i] = 0
  726. }
  727. var llMax, ofMax, mlMax uint8
  728. for i, seq := range b.sequences {
  729. v := llCode(seq.litLen)
  730. seq.llCode = v
  731. llH[v]++
  732. if v > llMax {
  733. llMax = v
  734. }
  735. v = ofCode(seq.offset)
  736. seq.ofCode = v
  737. ofH[v]++
  738. if v > ofMax {
  739. ofMax = v
  740. }
  741. v = mlCode(seq.matchLen)
  742. seq.mlCode = v
  743. mlH[v]++
  744. if v > mlMax {
  745. mlMax = v
  746. if debugAsserts && mlMax > maxMatchLengthSymbol {
  747. panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d), matchlen: %d", mlMax, seq.matchLen))
  748. }
  749. }
  750. b.sequences[i] = seq
  751. }
  752. maxCount := func(a []uint32) int {
  753. var max uint32
  754. for _, v := range a {
  755. if v > max {
  756. max = v
  757. }
  758. }
  759. return int(max)
  760. }
  761. if debugAsserts && mlMax > maxMatchLengthSymbol {
  762. panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d)", mlMax))
  763. }
  764. if debugAsserts && ofMax > maxOffsetBits {
  765. panic(fmt.Errorf("ofMax > maxOffsetBits (%d)", ofMax))
  766. }
  767. if debugAsserts && llMax > maxLiteralLengthSymbol {
  768. panic(fmt.Errorf("llMax > maxLiteralLengthSymbol (%d)", llMax))
  769. }
  770. b.coders.mlEnc.HistogramFinished(mlMax, maxCount(mlH[:mlMax+1]))
  771. b.coders.ofEnc.HistogramFinished(ofMax, maxCount(ofH[:ofMax+1]))
  772. b.coders.llEnc.HistogramFinished(llMax, maxCount(llH[:llMax+1]))
  773. }