1
2
3
4
5 package zstd
6
7 import (
8 "errors"
9 "fmt"
10 "math"
11 "math/bits"
12
13 "github.com/klauspost/compress/huff0"
14 )
15
16 type blockEnc struct {
17 size int
18 literals []byte
19 sequences []seq
20 coders seqCoders
21 litEnc *huff0.Scratch
22 dictLitEnc *huff0.Scratch
23 wr bitWriter
24
25 extraLits int
26 output []byte
27 recentOffsets [3]uint32
28 prevRecentOffsets [3]uint32
29
30 last bool
31 lowMem bool
32 }
33
34
35
36 func (b *blockEnc) init() {
37 if b.lowMem {
38
39 if cap(b.literals) < 1<<10 {
40 b.literals = make([]byte, 0, 1<<10)
41 }
42 const defSeqs = 20
43 if cap(b.sequences) < defSeqs {
44 b.sequences = make([]seq, 0, defSeqs)
45 }
46
47 if cap(b.output) < 1<<10 {
48 b.output = make([]byte, 0, 1<<10)
49 }
50 } else {
51 if cap(b.literals) < maxCompressedBlockSize {
52 b.literals = make([]byte, 0, maxCompressedBlockSize)
53 }
54 const defSeqs = 2000
55 if cap(b.sequences) < defSeqs {
56 b.sequences = make([]seq, 0, defSeqs)
57 }
58 if cap(b.output) < maxCompressedBlockSize {
59 b.output = make([]byte, 0, maxCompressedBlockSize)
60 }
61 }
62
63 if b.coders.mlEnc == nil {
64 b.coders.mlEnc = &fseEncoder{}
65 b.coders.mlPrev = &fseEncoder{}
66 b.coders.ofEnc = &fseEncoder{}
67 b.coders.ofPrev = &fseEncoder{}
68 b.coders.llEnc = &fseEncoder{}
69 b.coders.llPrev = &fseEncoder{}
70 }
71 b.litEnc = &huff0.Scratch{WantLogLess: 4}
72 b.reset(nil)
73 }
74
75
76 func (b *blockEnc) initNewEncode() {
77 b.recentOffsets = [3]uint32{1, 4, 8}
78 b.litEnc.Reuse = huff0.ReusePolicyNone
79 b.coders.setPrev(nil, nil, nil)
80 }
81
82
83
84
85 func (b *blockEnc) reset(prev *blockEnc) {
86 b.extraLits = 0
87 b.literals = b.literals[:0]
88 b.size = 0
89 b.sequences = b.sequences[:0]
90 b.output = b.output[:0]
91 b.last = false
92 if prev != nil {
93 b.recentOffsets = prev.prevRecentOffsets
94 }
95 b.dictLitEnc = nil
96 }
97
98
99
100
101 func (b *blockEnc) swapEncoders(prev *blockEnc) {
102 b.coders.swap(&prev.coders)
103 b.litEnc, prev.litEnc = prev.litEnc, b.litEnc
104 }
105
106
107 type blockHeader uint32
108
109
110 func (h *blockHeader) setLast(b bool) {
111 if b {
112 *h = *h | 1
113 } else {
114 const mask = (1 << 24) - 2
115 *h = *h & mask
116 }
117 }
118
119
120 func (h *blockHeader) setSize(v uint32) {
121 const mask = 7
122 *h = (*h)&mask | blockHeader(v<<3)
123 }
124
125
126 func (h *blockHeader) setType(t blockType) {
127 const mask = 1 | (((1 << 24) - 1) ^ 7)
128 *h = (*h & mask) | blockHeader(t<<1)
129 }
130
131
132 func (h blockHeader) appendTo(b []byte) []byte {
133 return append(b, uint8(h), uint8(h>>8), uint8(h>>16))
134 }
135
136
137 func (h blockHeader) String() string {
138 return fmt.Sprintf("Type: %d, Size: %d, Last:%t", (h>>1)&3, h>>3, h&1 == 1)
139 }
140
141
142 type literalsHeader uint64
143
144
145 func (h *literalsHeader) setType(t literalsBlockType) {
146 const mask = math.MaxUint64 - 3
147 *h = (*h & mask) | literalsHeader(t)
148 }
149
150
151 func (h *literalsHeader) setSize(regenLen int) {
152 inBits := bits.Len32(uint32(regenLen))
153
154 const mask = 3
155 lh := uint64(*h & mask)
156 switch {
157 case inBits < 5:
158 lh |= (uint64(regenLen) << 3) | (1 << 60)
159 if debugEncoder {
160 got := int(lh>>3) & 0xff
161 if got != regenLen {
162 panic(fmt.Sprint("litRegenSize = ", regenLen, "(want) != ", got, "(got)"))
163 }
164 }
165 case inBits < 12:
166 lh |= (1 << 2) | (uint64(regenLen) << 4) | (2 << 60)
167 case inBits < 20:
168 lh |= (3 << 2) | (uint64(regenLen) << 4) | (3 << 60)
169 default:
170 panic(fmt.Errorf("internal error: block too big (%d)", regenLen))
171 }
172 *h = literalsHeader(lh)
173 }
174
175
176 func (h *literalsHeader) setSizes(compLen, inLen int, single bool) {
177 compBits, inBits := bits.Len32(uint32(compLen)), bits.Len32(uint32(inLen))
178
179 const mask = 3
180 lh := uint64(*h & mask)
181 switch {
182 case compBits <= 10 && inBits <= 10:
183 if !single {
184 lh |= 1 << 2
185 }
186 lh |= (uint64(inLen) << 4) | (uint64(compLen) << (10 + 4)) | (3 << 60)
187 if debugEncoder {
188 const mmask = (1 << 24) - 1
189 n := (lh >> 4) & mmask
190 if int(n&1023) != inLen {
191 panic(fmt.Sprint("regensize:", int(n&1023), "!=", inLen, inBits))
192 }
193 if int(n>>10) != compLen {
194 panic(fmt.Sprint("compsize:", int(n>>10), "!=", compLen, compBits))
195 }
196 }
197 case compBits <= 14 && inBits <= 14:
198 lh |= (2 << 2) | (uint64(inLen) << 4) | (uint64(compLen) << (14 + 4)) | (4 << 60)
199 if single {
200 panic("single stream used with more than 10 bits length.")
201 }
202 case compBits <= 18 && inBits <= 18:
203 lh |= (3 << 2) | (uint64(inLen) << 4) | (uint64(compLen) << (18 + 4)) | (5 << 60)
204 if single {
205 panic("single stream used with more than 10 bits length.")
206 }
207 default:
208 panic("internal error: block too big")
209 }
210 *h = literalsHeader(lh)
211 }
212
213
214 func (h literalsHeader) appendTo(b []byte) []byte {
215 size := uint8(h >> 60)
216 switch size {
217 case 1:
218 b = append(b, uint8(h))
219 case 2:
220 b = append(b, uint8(h), uint8(h>>8))
221 case 3:
222 b = append(b, uint8(h), uint8(h>>8), uint8(h>>16))
223 case 4:
224 b = append(b, uint8(h), uint8(h>>8), uint8(h>>16), uint8(h>>24))
225 case 5:
226 b = append(b, uint8(h), uint8(h>>8), uint8(h>>16), uint8(h>>24), uint8(h>>32))
227 default:
228 panic(fmt.Errorf("internal error: literalsHeader has invalid size (%d)", size))
229 }
230 return b
231 }
232
233
234 func (h literalsHeader) size() int {
235 return int(h >> 60)
236 }
237
238 func (h literalsHeader) String() string {
239 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)
240 }
241
242
243 func (b *blockEnc) pushOffsets() {
244 b.prevRecentOffsets = b.recentOffsets
245 }
246
247
248 func (b *blockEnc) popOffsets() {
249 b.recentOffsets = b.prevRecentOffsets
250 }
251
252
253
254 func (b *blockEnc) matchOffset(offset, lits uint32) uint32 {
255
256
257
258 if true {
259 if lits > 0 {
260 switch offset {
261 case b.recentOffsets[0]:
262 offset = 1
263 case b.recentOffsets[1]:
264 b.recentOffsets[1] = b.recentOffsets[0]
265 b.recentOffsets[0] = offset
266 offset = 2
267 case b.recentOffsets[2]:
268 b.recentOffsets[2] = b.recentOffsets[1]
269 b.recentOffsets[1] = b.recentOffsets[0]
270 b.recentOffsets[0] = offset
271 offset = 3
272 default:
273 b.recentOffsets[2] = b.recentOffsets[1]
274 b.recentOffsets[1] = b.recentOffsets[0]
275 b.recentOffsets[0] = offset
276 offset += 3
277 }
278 } else {
279 switch offset {
280 case b.recentOffsets[1]:
281 b.recentOffsets[1] = b.recentOffsets[0]
282 b.recentOffsets[0] = offset
283 offset = 1
284 case b.recentOffsets[2]:
285 b.recentOffsets[2] = b.recentOffsets[1]
286 b.recentOffsets[1] = b.recentOffsets[0]
287 b.recentOffsets[0] = offset
288 offset = 2
289 case b.recentOffsets[0] - 1:
290 b.recentOffsets[2] = b.recentOffsets[1]
291 b.recentOffsets[1] = b.recentOffsets[0]
292 b.recentOffsets[0] = offset
293 offset = 3
294 default:
295 b.recentOffsets[2] = b.recentOffsets[1]
296 b.recentOffsets[1] = b.recentOffsets[0]
297 b.recentOffsets[0] = offset
298 offset += 3
299 }
300 }
301 } else {
302 offset += 3
303 }
304 return offset
305 }
306
307
308 func (b *blockEnc) encodeRaw(a []byte) {
309 var bh blockHeader
310 bh.setLast(b.last)
311 bh.setSize(uint32(len(a)))
312 bh.setType(blockTypeRaw)
313 b.output = bh.appendTo(b.output[:0])
314 b.output = append(b.output, a...)
315 if debugEncoder {
316 println("Adding RAW block, length", len(a), "last:", b.last)
317 }
318 }
319
320
321 func (b *blockEnc) encodeRawTo(dst, src []byte) []byte {
322 var bh blockHeader
323 bh.setLast(b.last)
324 bh.setSize(uint32(len(src)))
325 bh.setType(blockTypeRaw)
326 dst = bh.appendTo(dst)
327 dst = append(dst, src...)
328 if debugEncoder {
329 println("Adding RAW block, length", len(src), "last:", b.last)
330 }
331 return dst
332 }
333
334
335 func (b *blockEnc) encodeLits(lits []byte, raw bool) error {
336 var bh blockHeader
337 bh.setLast(b.last)
338 bh.setSize(uint32(len(lits)))
339
340
341 if len(lits) < 8 || (len(lits) < 32 && b.dictLitEnc == nil) || raw {
342 if debugEncoder {
343 println("Adding RAW block, length", len(lits), "last:", b.last)
344 }
345 bh.setType(blockTypeRaw)
346 b.output = bh.appendTo(b.output)
347 b.output = append(b.output, lits...)
348 return nil
349 }
350
351 var (
352 out []byte
353 reUsed, single bool
354 err error
355 )
356 if b.dictLitEnc != nil {
357 b.litEnc.TransferCTable(b.dictLitEnc)
358 b.litEnc.Reuse = huff0.ReusePolicyAllow
359 b.dictLitEnc = nil
360 }
361 if len(lits) >= 1024 {
362
363 out, reUsed, err = huff0.Compress4X(lits, b.litEnc)
364 } else if len(lits) > 16 {
365
366 single = true
367 out, reUsed, err = huff0.Compress1X(lits, b.litEnc)
368 } else {
369 err = huff0.ErrIncompressible
370 }
371 if err == nil && len(out)+5 > len(lits) {
372
373 var lh literalsHeader
374 lh.setSizes(len(out), len(lits), single)
375 if len(out)+lh.size() >= len(lits) {
376 err = huff0.ErrIncompressible
377 }
378 }
379 switch err {
380 case huff0.ErrIncompressible:
381 if debugEncoder {
382 println("Adding RAW block, length", len(lits), "last:", b.last)
383 }
384 bh.setType(blockTypeRaw)
385 b.output = bh.appendTo(b.output)
386 b.output = append(b.output, lits...)
387 return nil
388 case huff0.ErrUseRLE:
389 if debugEncoder {
390 println("Adding RLE block, length", len(lits))
391 }
392 bh.setType(blockTypeRLE)
393 b.output = bh.appendTo(b.output)
394 b.output = append(b.output, lits[0])
395 return nil
396 case nil:
397 default:
398 return err
399 }
400
401
402 b.litEnc.Reuse = huff0.ReusePolicyAllow
403 bh.setType(blockTypeCompressed)
404 var lh literalsHeader
405 if reUsed {
406 if debugEncoder {
407 println("Reused tree, compressed to", len(out))
408 }
409 lh.setType(literalsBlockTreeless)
410 } else {
411 if debugEncoder {
412 println("New tree, compressed to", len(out), "tree size:", len(b.litEnc.OutTable))
413 }
414 lh.setType(literalsBlockCompressed)
415 }
416
417 lh.setSizes(len(out), len(lits), single)
418 bh.setSize(uint32(len(out) + lh.size() + 1))
419
420
421 b.output = bh.appendTo(b.output)
422 b.output = lh.appendTo(b.output)
423
424 b.output = append(b.output, out...)
425
426 b.output = append(b.output, 0)
427 return nil
428 }
429
430
431 func (b *blockEnc) encodeRLE(val byte, length uint32) {
432 var bh blockHeader
433 bh.setLast(b.last)
434 bh.setSize(length)
435 bh.setType(blockTypeRLE)
436 b.output = bh.appendTo(b.output)
437 b.output = append(b.output, val)
438 }
439
440
441 func fuzzFseEncoder(data []byte) int {
442 if len(data) > maxSequences || len(data) < 2 {
443 return 0
444 }
445 enc := fseEncoder{}
446 hist := enc.Histogram()
447 maxSym := uint8(0)
448 for i, v := range data {
449 v = v & 63
450 data[i] = v
451 hist[v]++
452 if v > maxSym {
453 maxSym = v
454 }
455 }
456 if maxSym == 0 {
457
458 return 0
459 }
460 maxCount := func(a []uint32) int {
461 var max uint32
462 for _, v := range a {
463 if v > max {
464 max = v
465 }
466 }
467 return int(max)
468 }
469 cnt := maxCount(hist[:maxSym])
470 if cnt == len(data) {
471
472 return 0
473 }
474 enc.HistogramFinished(maxSym, cnt)
475 err := enc.normalizeCount(len(data))
476 if err != nil {
477 return 0
478 }
479 _, err = enc.writeCount(nil)
480 if err != nil {
481 panic(err)
482 }
483 return 1
484 }
485
486
487
488 func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error {
489 if len(b.sequences) == 0 {
490 return b.encodeLits(b.literals, rawAllLits)
491 }
492 if len(b.sequences) == 1 && len(org) > 0 && len(b.literals) <= 1 {
493
494 seq := b.sequences[0]
495 if seq.litLen == uint32(len(b.literals)) && seq.offset-3 == 1 {
496
497 b.encodeRLE(org[0], b.sequences[0].matchLen+zstdMinMatch+seq.litLen)
498 return nil
499 }
500 }
501
502
503 saved := b.size - len(b.literals) - (b.size >> 6)
504 if saved < 16 {
505 if org == nil {
506 return errIncompressible
507 }
508 b.popOffsets()
509 return b.encodeLits(org, rawAllLits)
510 }
511
512 var bh blockHeader
513 var lh literalsHeader
514 bh.setLast(b.last)
515 bh.setType(blockTypeCompressed)
516
517 bhOffset := len(b.output)
518 b.output = bh.appendTo(b.output)
519
520 var (
521 out []byte
522 reUsed, single bool
523 err error
524 )
525 if b.dictLitEnc != nil {
526 b.litEnc.TransferCTable(b.dictLitEnc)
527 b.litEnc.Reuse = huff0.ReusePolicyAllow
528 b.dictLitEnc = nil
529 }
530 if len(b.literals) >= 1024 && !raw {
531
532 out, reUsed, err = huff0.Compress4X(b.literals, b.litEnc)
533 } else if len(b.literals) > 16 && !raw {
534
535 single = true
536 out, reUsed, err = huff0.Compress1X(b.literals, b.litEnc)
537 } else {
538 err = huff0.ErrIncompressible
539 }
540
541 if err == nil && len(out)+5 > len(b.literals) {
542
543 var lh literalsHeader
544 lh.setSize(len(b.literals))
545 szRaw := lh.size()
546 lh.setSizes(len(out), len(b.literals), single)
547 szComp := lh.size()
548 if len(out)+szComp >= len(b.literals)+szRaw {
549 err = huff0.ErrIncompressible
550 }
551 }
552 switch err {
553 case huff0.ErrIncompressible:
554 lh.setType(literalsBlockRaw)
555 lh.setSize(len(b.literals))
556 b.output = lh.appendTo(b.output)
557 b.output = append(b.output, b.literals...)
558 if debugEncoder {
559 println("Adding literals RAW, length", len(b.literals))
560 }
561 case huff0.ErrUseRLE:
562 lh.setType(literalsBlockRLE)
563 lh.setSize(len(b.literals))
564 b.output = lh.appendTo(b.output)
565 b.output = append(b.output, b.literals[0])
566 if debugEncoder {
567 println("Adding literals RLE")
568 }
569 case nil:
570
571 if reUsed {
572 if debugEncoder {
573 println("reused tree")
574 }
575 lh.setType(literalsBlockTreeless)
576 } else {
577 if debugEncoder {
578 println("new tree, size:", len(b.litEnc.OutTable))
579 }
580 lh.setType(literalsBlockCompressed)
581 if debugEncoder {
582 _, _, err := huff0.ReadTable(out, nil)
583 if err != nil {
584 panic(err)
585 }
586 }
587 }
588 lh.setSizes(len(out), len(b.literals), single)
589 if debugEncoder {
590 printf("Compressed %d literals to %d bytes", len(b.literals), len(out))
591 println("Adding literal header:", lh)
592 }
593 b.output = lh.appendTo(b.output)
594 b.output = append(b.output, out...)
595 b.litEnc.Reuse = huff0.ReusePolicyAllow
596 if debugEncoder {
597 println("Adding literals compressed")
598 }
599 default:
600 if debugEncoder {
601 println("Adding literals ERROR:", err)
602 }
603 return err
604 }
605
606
607
608 switch {
609 case len(b.sequences) < 128:
610 b.output = append(b.output, uint8(len(b.sequences)))
611 case len(b.sequences) < 0x7f00:
612 n := len(b.sequences)
613 b.output = append(b.output, 128+uint8(n>>8), uint8(n))
614 default:
615 n := len(b.sequences) - 0x7f00
616 b.output = append(b.output, 255, uint8(n), uint8(n>>8))
617 }
618 if debugEncoder {
619 println("Encoding", len(b.sequences), "sequences")
620 }
621 b.genCodes()
622 llEnc := b.coders.llEnc
623 ofEnc := b.coders.ofEnc
624 mlEnc := b.coders.mlEnc
625 err = llEnc.normalizeCount(len(b.sequences))
626 if err != nil {
627 return err
628 }
629 err = ofEnc.normalizeCount(len(b.sequences))
630 if err != nil {
631 return err
632 }
633 err = mlEnc.normalizeCount(len(b.sequences))
634 if err != nil {
635 return err
636 }
637
638
639
640 chooseComp := func(cur, prev, preDef *fseEncoder) (*fseEncoder, seqCompMode) {
641
642 hist := cur.count[:cur.symbolLen]
643 nSize := cur.approxSize(hist) + cur.maxHeaderSize()
644 predefSize := preDef.approxSize(hist)
645 prevSize := prev.approxSize(hist)
646
647
648
649 nSize = nSize + (nSize+2*8*16)>>4
650 switch {
651 case predefSize <= prevSize && predefSize <= nSize || forcePreDef:
652 if debugEncoder {
653 println("Using predefined", predefSize>>3, "<=", nSize>>3)
654 }
655 return preDef, compModePredefined
656 case prevSize <= nSize:
657 if debugEncoder {
658 println("Using previous", prevSize>>3, "<=", nSize>>3)
659 }
660 return prev, compModeRepeat
661 default:
662 if debugEncoder {
663 println("Using new, predef", predefSize>>3, ". previous:", prevSize>>3, ">", nSize>>3, "header max:", cur.maxHeaderSize()>>3, "bytes")
664 println("tl:", cur.actualTableLog, "symbolLen:", cur.symbolLen, "norm:", cur.norm[:cur.symbolLen], "hist", cur.count[:cur.symbolLen])
665 }
666 return cur, compModeFSE
667 }
668 }
669
670
671 var mode uint8
672 if llEnc.useRLE {
673 mode |= uint8(compModeRLE) << 6
674 llEnc.setRLE(b.sequences[0].llCode)
675 if debugEncoder {
676 println("llEnc.useRLE")
677 }
678 } else {
679 var m seqCompMode
680 llEnc, m = chooseComp(llEnc, b.coders.llPrev, &fsePredefEnc[tableLiteralLengths])
681 mode |= uint8(m) << 6
682 }
683 if ofEnc.useRLE {
684 mode |= uint8(compModeRLE) << 4
685 ofEnc.setRLE(b.sequences[0].ofCode)
686 if debugEncoder {
687 println("ofEnc.useRLE")
688 }
689 } else {
690 var m seqCompMode
691 ofEnc, m = chooseComp(ofEnc, b.coders.ofPrev, &fsePredefEnc[tableOffsets])
692 mode |= uint8(m) << 4
693 }
694
695 if mlEnc.useRLE {
696 mode |= uint8(compModeRLE) << 2
697 mlEnc.setRLE(b.sequences[0].mlCode)
698 if debugEncoder {
699 println("mlEnc.useRLE, code: ", b.sequences[0].mlCode, "value", b.sequences[0].matchLen)
700 }
701 } else {
702 var m seqCompMode
703 mlEnc, m = chooseComp(mlEnc, b.coders.mlPrev, &fsePredefEnc[tableMatchLengths])
704 mode |= uint8(m) << 2
705 }
706 b.output = append(b.output, mode)
707 if debugEncoder {
708 printf("Compression modes: 0b%b", mode)
709 }
710 b.output, err = llEnc.writeCount(b.output)
711 if err != nil {
712 return err
713 }
714 start := len(b.output)
715 b.output, err = ofEnc.writeCount(b.output)
716 if err != nil {
717 return err
718 }
719 if false {
720 println("block:", b.output[start:], "tablelog", ofEnc.actualTableLog, "maxcount:", ofEnc.maxCount)
721 fmt.Printf("selected TableLog: %d, Symbol length: %d\n", ofEnc.actualTableLog, ofEnc.symbolLen)
722 for i, v := range ofEnc.norm[:ofEnc.symbolLen] {
723 fmt.Printf("%3d: %5d -> %4d \n", i, ofEnc.count[i], v)
724 }
725 }
726 b.output, err = mlEnc.writeCount(b.output)
727 if err != nil {
728 return err
729 }
730
731
732 wr := &b.wr
733 wr.reset(b.output)
734
735 var ll, of, ml cState
736
737
738 seq := len(b.sequences) - 1
739 s := b.sequences[seq]
740 llEnc.setBits(llBitsTable[:])
741 mlEnc.setBits(mlBitsTable[:])
742 ofEnc.setBits(nil)
743
744 llTT, ofTT, mlTT := llEnc.ct.symbolTT[:256], ofEnc.ct.symbolTT[:256], mlEnc.ct.symbolTT[:256]
745
746
747
748 llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
749 ll.init(wr, &llEnc.ct, llB)
750 of.init(wr, &ofEnc.ct, ofB)
751 wr.flush32()
752 ml.init(wr, &mlEnc.ct, mlB)
753
754
755 wr.addBits32NC(s.litLen, llB.outBits)
756 wr.addBits32NC(s.matchLen, mlB.outBits)
757 wr.flush32()
758 wr.addBits32NC(s.offset, ofB.outBits)
759 if debugSequences {
760 println("Encoded seq", seq, s, "codes:", s.llCode, s.mlCode, s.ofCode, "states:", ll.state, ml.state, of.state, "bits:", llB, mlB, ofB)
761 }
762 seq--
763
764 for seq >= 0 {
765 s = b.sequences[seq]
766
767 ofB := ofTT[s.ofCode]
768 wr.flush32()
769
770 nbBitsOut := (uint32(of.state) + ofB.deltaNbBits) >> 16
771 dstState := int32(of.state>>(nbBitsOut&15)) + int32(ofB.deltaFindState)
772 wr.addBits16NC(of.state, uint8(nbBitsOut))
773 of.state = of.stateTable[dstState]
774
775
776 outBits := ofB.outBits & 31
777 extraBits := uint64(s.offset & bitMask32[outBits])
778 extraBitsN := outBits
779
780 mlB := mlTT[s.mlCode]
781
782 nbBitsOut = (uint32(ml.state) + mlB.deltaNbBits) >> 16
783 dstState = int32(ml.state>>(nbBitsOut&15)) + int32(mlB.deltaFindState)
784 wr.addBits16NC(ml.state, uint8(nbBitsOut))
785 ml.state = ml.stateTable[dstState]
786
787 outBits = mlB.outBits & 31
788 extraBits = extraBits<<outBits | uint64(s.matchLen&bitMask32[outBits])
789 extraBitsN += outBits
790
791 llB := llTT[s.llCode]
792
793 nbBitsOut = (uint32(ll.state) + llB.deltaNbBits) >> 16
794 dstState = int32(ll.state>>(nbBitsOut&15)) + int32(llB.deltaFindState)
795 wr.addBits16NC(ll.state, uint8(nbBitsOut))
796 ll.state = ll.stateTable[dstState]
797
798 outBits = llB.outBits & 31
799 extraBits = extraBits<<outBits | uint64(s.litLen&bitMask32[outBits])
800 extraBitsN += outBits
801
802 wr.flush32()
803 wr.addBits64NC(extraBits, extraBitsN)
804
805 if debugSequences {
806 println("Encoded seq", seq, s)
807 }
808
809 seq--
810 }
811 ml.flush(mlEnc.actualTableLog)
812 of.flush(ofEnc.actualTableLog)
813 ll.flush(llEnc.actualTableLog)
814 wr.close()
815 b.output = wr.out
816
817
818 if len(b.output)-3-bhOffset >= b.size {
819
820 b.output = b.encodeRawTo(b.output[:bhOffset], org)
821 b.popOffsets()
822 b.litEnc.Reuse = huff0.ReusePolicyNone
823 return nil
824 }
825
826
827 bh.setSize(uint32(len(b.output)-bhOffset) - 3)
828 if debugEncoder {
829 println("Rewriting block header", bh)
830 }
831 _ = bh.appendTo(b.output[bhOffset:bhOffset])
832 b.coders.setPrev(llEnc, mlEnc, ofEnc)
833 return nil
834 }
835
836 var errIncompressible = errors.New("incompressible")
837
838 func (b *blockEnc) genCodes() {
839 if len(b.sequences) == 0 {
840
841 return
842 }
843 if len(b.sequences) > math.MaxUint16 {
844 panic("can only encode up to 64K sequences")
845 }
846
847 llH := b.coders.llEnc.Histogram()
848 ofH := b.coders.ofEnc.Histogram()
849 mlH := b.coders.mlEnc.Histogram()
850 for i := range llH {
851 llH[i] = 0
852 }
853 for i := range ofH {
854 ofH[i] = 0
855 }
856 for i := range mlH {
857 mlH[i] = 0
858 }
859
860 var llMax, ofMax, mlMax uint8
861 for i := range b.sequences {
862 seq := &b.sequences[i]
863 v := llCode(seq.litLen)
864 seq.llCode = v
865 llH[v]++
866 if v > llMax {
867 llMax = v
868 }
869
870 v = ofCode(seq.offset)
871 seq.ofCode = v
872 ofH[v]++
873 if v > ofMax {
874 ofMax = v
875 }
876
877 v = mlCode(seq.matchLen)
878 seq.mlCode = v
879 mlH[v]++
880 if v > mlMax {
881 mlMax = v
882 if debugAsserts && mlMax > maxMatchLengthSymbol {
883 panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d), matchlen: %d", mlMax, seq.matchLen))
884 }
885 }
886 }
887 maxCount := func(a []uint32) int {
888 var max uint32
889 for _, v := range a {
890 if v > max {
891 max = v
892 }
893 }
894 return int(max)
895 }
896 if debugAsserts && mlMax > maxMatchLengthSymbol {
897 panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d)", mlMax))
898 }
899 if debugAsserts && ofMax > maxOffsetBits {
900 panic(fmt.Errorf("ofMax > maxOffsetBits (%d)", ofMax))
901 }
902 if debugAsserts && llMax > maxLiteralLengthSymbol {
903 panic(fmt.Errorf("llMax > maxLiteralLengthSymbol (%d)", llMax))
904 }
905
906 b.coders.mlEnc.HistogramFinished(mlMax, maxCount(mlH[:mlMax+1]))
907 b.coders.ofEnc.HistogramFinished(ofMax, maxCount(ofH[:ofMax+1]))
908 b.coders.llEnc.HistogramFinished(llMax, maxCount(llH[:llMax+1]))
909 }
910
View as plain text