Source file
src/compress/flate/huffman_bit_writer.go
1
2
3
4
5 package flate
6
7 import (
8 "io"
9 "math"
10 "sync"
11 )
12
13 const (
14
15 offsetCodeCount = 30
16
17
18 endBlockMarker = 256
19
20
21 lengthCodesStart = 257
22
23
24 codegenCodeCount = 19
25 badCode = 255
26
27
28
29 maxPredefinedTokens = 250
30
31
32
33
34
35
36 bufferFlushSize = 246
37 )
38
39
40
41 var lengthExtraBits = [32]uint8{
42 0, 0, 0,
43 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
44 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
45 4, 5, 5, 5, 5, 0,
46 }
47
48
49 var lengthBase = [32]uint8{
50 0, 1, 2, 3, 4, 5, 6, 7, 8, 10,
51 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
52 64, 80, 96, 112, 128, 160, 192, 224, 255,
53 }
54
55
56 var offsetExtraBits = [32]int8{
57 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
58 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
59 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
60
61 14, 14,
62 }
63
64
65
66
67
68 var offsetCombined = [32]uint32{
69 0x0, 0x100, 0x200, 0x300, 0x401, 0x601, 0x802, 0xc02,
70 0x1003, 0x1803, 0x2004, 0x3004, 0x4005, 0x6005,
71 0x8006, 0xc006, 0x10007, 0x18007, 0x20008, 0x30008,
72 0x40009, 0x60009, 0x8000a, 0xc000a, 0x10000b, 0x18000b,
73 0x20000c, 0x30000c, 0x40000d, 0x60000d, 0x0, 0x0}
74
75
76
77
78
79 var lengthCombined = func() (t [256]uint32) {
80 for i := range t {
81 code := lengthCodes[i]
82 t[i] = uint32(code) | uint32(lengthExtraBits[code])<<5 | uint32(uint8(i)-lengthBase[code])<<8
83 }
84 return t
85 }()
86
87
88 var codegenOrder = []uint32{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
89
90
91
92
93
94
95
96
97
98 type huffmanBitWriter struct {
99
100
101
102 writer io.Writer
103
104
105
106 bits uint64
107 nbits uint8
108 nbytes uint8
109
110
111
112 wroteHuffman bool
113 literalEncoding *huffmanEncoder
114 tmpLitEncoding *huffmanEncoder
115 offsetEncoding *huffmanEncoder
116 codegenEncoding *huffmanEncoder
117 err error
118
119
120
121
122 prevHeader int
123
124
125
126
127 logNewTablePenalty uint
128
129
130
131
132 bytes [(bufferFlushSize + 7 + 8 + 7) &^ 7]byte
133 literalFreq [lengthCodesStart + 32]uint16
134 offsetFreq [32]uint16
135 codegenFreq [codegenCodeCount]uint16
136
137
138 codegen [literalCount + offsetCodeCount + 1]uint8
139 }
140
141
142 func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
143 return &huffmanBitWriter{
144 writer: w,
145 literalEncoding: newHuffmanEncoder(literalCount),
146 tmpLitEncoding: newHuffmanEncoder(literalCount),
147 codegenEncoding: newHuffmanEncoder(codegenCodeCount),
148 offsetEncoding: newHuffmanEncoder(offsetCodeCount),
149 }
150 }
151
152
153 func (w *huffmanBitWriter) reset(writer io.Writer) {
154 w.writer = writer
155 w.bits, w.nbits, w.nbytes, w.err = 0, 0, 0, nil
156 w.prevHeader = 0
157 w.wroteHuffman = false
158 }
159
160
161
162 func (w *huffmanBitWriter) canReuse(t *tokens) (ok bool) {
163 a := t.offHist[:offsetCodeCount]
164 b := w.offsetEncoding.codes
165 b = b[:len(a)]
166 for i, v := range a {
167 if v != 0 && b[i].zero() {
168 return false
169 }
170 }
171
172 a = t.extraHist[:literalCount-256]
173 b = w.literalEncoding.codes[256:literalCount]
174 b = b[:len(a)]
175 for i, v := range a {
176 if v != 0 && b[i].zero() {
177 return false
178 }
179 }
180
181 a = t.litHist[:256]
182 b = w.literalEncoding.codes[:len(a)]
183 for i, v := range a {
184 if v != 0 && b[i].zero() {
185 return false
186 }
187 }
188 return true
189 }
190
191
192
193 func (w *huffmanBitWriter) flush() {
194 if w.err != nil {
195 w.nbits = 0
196 return
197 }
198 if w.prevHeader > 0 {
199
200 w.writeCode(w.literalEncoding.codes[endBlockMarker])
201 w.prevHeader = 0
202 }
203 n := w.nbytes
204 for w.nbits != 0 {
205 w.bytes[n] = byte(w.bits)
206 w.bits >>= 8
207 if w.nbits > 8 {
208 w.nbits -= 8
209 } else {
210 w.nbits = 0
211 }
212 n++
213 }
214 w.bits = 0
215 if n > 0 {
216 w.write(w.bytes[:n])
217 }
218 w.nbytes = 0
219 }
220
221
222
223 func (w *huffmanBitWriter) write(b []byte) {
224 if w.err != nil {
225 return
226 }
227 _, w.err = w.writer.Write(b)
228 }
229
230
231 func (w *huffmanBitWriter) writeBits(b int32, nb uint8) {
232 w.bits |= uint64(b) << (w.nbits & 63)
233 w.nbits += nb
234 if w.nbits >= 48 {
235 w.flushBits()
236 }
237 }
238
239
240 func (w *huffmanBitWriter) writeBytes(bytes []byte) {
241 if w.err != nil {
242 return
243 }
244 n := w.nbytes
245 if w.nbits&7 != 0 {
246 w.err = InternalError("writeBytes with unfinished bits")
247 return
248 }
249 for w.nbits != 0 {
250 w.bytes[n] = byte(w.bits)
251 w.bits >>= 8
252 w.nbits -= 8
253 n++
254 }
255 if n != 0 {
256 w.write(w.bytes[:n])
257 }
258 w.nbytes = 0
259 w.write(bytes)
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274 func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int, litEnc, offEnc *huffmanEncoder) {
275 clear(w.codegenFreq[:])
276
277
278
279
280 codegen := w.codegen[:]
281
282 cgnl := codegen[:numLiterals]
283 for i := range cgnl {
284 cgnl[i] = litEnc.codes[i].len()
285 }
286
287 cgnl = codegen[numLiterals : numLiterals+numOffsets]
288 for i := range cgnl {
289 cgnl[i] = offEnc.codes[i].len()
290 }
291 codegen[numLiterals+numOffsets] = badCode
292
293 size := codegen[0]
294 count := 1
295 outIndex := 0
296 for inIndex := 1; size != badCode; inIndex++ {
297
298
299 nextSize := codegen[inIndex]
300 if nextSize == size {
301 count++
302 continue
303 }
304
305 if size != 0 {
306 codegen[outIndex] = size
307 outIndex++
308 w.codegenFreq[size]++
309 count--
310 for count >= 3 {
311 n := min(6, count)
312 codegen[outIndex] = 16
313 outIndex++
314 codegen[outIndex] = uint8(n - 3)
315 outIndex++
316 w.codegenFreq[16]++
317 count -= n
318 }
319 } else {
320 for count >= 11 {
321 n := min(138, count)
322 codegen[outIndex] = 18
323 outIndex++
324 codegen[outIndex] = uint8(n - 11)
325 outIndex++
326 w.codegenFreq[18]++
327 count -= n
328 }
329 if count >= 3 {
330
331 codegen[outIndex] = 17
332 outIndex++
333 codegen[outIndex] = uint8(count - 3)
334 outIndex++
335 w.codegenFreq[17]++
336 count = 0
337 }
338 }
339 count--
340 for ; count >= 0; count-- {
341 codegen[outIndex] = size
342 outIndex++
343 w.codegenFreq[size]++
344 }
345
346 size = nextSize
347 count = 1
348 }
349
350 codegen[outIndex] = badCode
351 }
352
353
354 func (w *huffmanBitWriter) codegens() int {
355 numCodegens := len(w.codegenFreq)
356 for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 {
357 numCodegens--
358 }
359 return numCodegens
360 }
361
362
363 func (w *huffmanBitWriter) headerSize() (size, numCodegens int) {
364 numCodegens = len(w.codegenFreq)
365 for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 {
366 numCodegens--
367 }
368 return 3 + 5 + 5 + 4 + (3 * numCodegens) +
369 w.codegenEncoding.bitLength(w.codegenFreq[:]) +
370 int(w.codegenFreq[16])*2 +
371 int(w.codegenFreq[17])*3 +
372 int(w.codegenFreq[18])*7, numCodegens
373 }
374
375
376 func (w *huffmanBitWriter) dynamicReuseSize(litEnc, offEnc *huffmanEncoder) (size int) {
377 size = litEnc.bitLength(w.literalFreq[:]) +
378 offEnc.bitLength(w.offsetFreq[:])
379 return size
380 }
381
382
383 func (w *huffmanBitWriter) dynamicSize(litEnc, offEnc *huffmanEncoder, extraBits int) (size, numCodegens int) {
384 header, numCodegens := w.headerSize()
385 size = header +
386 litEnc.bitLength(w.literalFreq[:]) +
387 offEnc.bitLength(w.offsetFreq[:]) +
388 extraBits
389 return size, numCodegens
390 }
391
392
393
394 func (w *huffmanBitWriter) extraBitSize() int {
395 total := 0
396 for i, n := range w.literalFreq[257:literalCount] {
397 total += int(n) * int(lengthExtraBits[i&31])
398 }
399 for i, n := range w.offsetFreq[:offsetCodeCount] {
400 total += int(n) * int(offsetExtraBits[i&31])
401 }
402 return total
403 }
404
405
406 func (w *huffmanBitWriter) fixedSize(extraBits int) int {
407 return 3 +
408 fixedLiteralEncoding().bitLength(w.literalFreq[:]) +
409 fixedOffsetEncoding().bitLength(w.offsetFreq[:]) +
410 extraBits
411 }
412
413
414
415
416 func (w *huffmanBitWriter) storedSize(in []byte) (int, bool) {
417 if in == nil {
418 return 0, false
419 }
420 if len(in) <= maxStoreBlockSize {
421 return (len(in) + 5) * 8, true
422 }
423 return 0, false
424 }
425
426
427 func (w *huffmanBitWriter) writeCode(c hcode) {
428 w.bits |= c.code64() << (w.nbits & reg8SizeMask64)
429 w.nbits += c.len()
430 if w.nbits >= 48 {
431 w.flushBits()
432 }
433 }
434
435
436 func (w *huffmanBitWriter) flushBits() {
437 bits := w.bits
438 w.bits >>= 48
439 w.nbits -= 48
440 n := w.nbytes
441
442
443 storeLE64(w.bytes[n:], bits)
444 n += 6
445
446 if n >= bufferFlushSize {
447 if w.err != nil {
448 n = 0
449 return
450 }
451 w.write(w.bytes[:n])
452 n = 0
453 }
454
455 w.nbytes = n
456 }
457
458
459
460
461
462
463 func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, numCodegens int, isEof bool) {
464 if w.err != nil {
465 return
466 }
467 var firstBits int32 = 4
468 if isEof {
469 firstBits = 5
470 }
471 w.writeBits(firstBits, 3)
472 w.writeBits(int32(numLiterals-257), 5)
473 w.writeBits(int32(numOffsets-1), 5)
474 w.writeBits(int32(numCodegens-4), 4)
475
476 for i := range numCodegens {
477 value := uint(w.codegenEncoding.codes[codegenOrder[i]].len())
478 w.writeBits(int32(value), 3)
479 }
480
481 i := 0
482 for {
483 var codeWord = uint32(w.codegen[i])
484 i++
485 if codeWord == badCode {
486 break
487 }
488 w.writeCode(w.codegenEncoding.codes[codeWord])
489
490 switch codeWord {
491 case 16:
492 w.writeBits(int32(w.codegen[i]), 2)
493 i++
494 case 17:
495 w.writeBits(int32(w.codegen[i]), 3)
496 i++
497 case 18:
498 w.writeBits(int32(w.codegen[i]), 7)
499 i++
500 }
501 }
502 }
503
504
505
506
507 func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) {
508 if w.err != nil {
509 return
510 }
511 if w.prevHeader > 0 {
512
513 w.writeCode(w.literalEncoding.codes[endBlockMarker])
514 w.prevHeader = 0
515 }
516
517
518 if length == 0 && isEof {
519 w.writeFixedHeader(isEof)
520
521 w.writeBits(0, 7)
522 w.flush()
523 return
524 }
525
526 var flag int32
527 if isEof {
528 flag = 1
529 }
530 w.writeBits(flag, 3)
531 w.flush()
532 w.writeBits(int32(length), 16)
533 w.writeBits(int32(^uint16(length)), 16)
534 }
535
536
537 func (w *huffmanBitWriter) writeFixedHeader(isEof bool) {
538 if w.err != nil {
539 return
540 }
541 if w.prevHeader > 0 {
542
543 w.writeCode(w.literalEncoding.codes[endBlockMarker])
544 w.prevHeader = 0
545 }
546
547
548 var value int32 = 2
549 if isEof {
550 value = 3
551 }
552 w.writeBits(value, 3)
553 }
554
555
556
557
558
559
560 func (w *huffmanBitWriter) writeBlock(tokens *tokens, eof bool, input []byte) {
561 if w.err != nil {
562 return
563 }
564
565 tokens.AddEOB()
566 if w.prevHeader > 0 {
567
568 w.writeCode(w.literalEncoding.codes[endBlockMarker])
569 w.prevHeader = 0
570 }
571 numLiterals, numOffsets := w.indexTokens(tokens)
572 w.generate()
573 var extraBits int
574 storedSize, storable := w.storedSize(input)
575 if storable {
576 extraBits = w.extraBitSize()
577 }
578
579
580
581 var literalEncoding = fixedLiteralEncoding()
582 var offsetEncoding = fixedOffsetEncoding()
583 var size = math.MaxInt32
584 if tokens.n < maxPredefinedTokens {
585 size = w.fixedSize(extraBits)
586 }
587
588
589 var numCodegens int
590
591
592
593 w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding)
594 w.codegenEncoding.generate(w.codegenFreq[:], 7)
595 dynamicSize, numCodegens := w.dynamicSize(w.literalEncoding, w.offsetEncoding, extraBits)
596
597 if dynamicSize < size {
598 size = dynamicSize
599 literalEncoding = w.literalEncoding
600 offsetEncoding = w.offsetEncoding
601 }
602
603
604 if storable && storedSize <= size {
605 w.writeStoredHeader(len(input), eof)
606 w.writeBytes(input)
607 return
608 }
609
610
611 if literalEncoding == fixedLiteralEncoding() {
612 w.writeFixedHeader(eof)
613 } else {
614 w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof)
615 }
616
617
618 w.writeTokens(tokens.Slice(), literalEncoding.codes, offsetEncoding.codes)
619 }
620
621
622
623
624 func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []byte, sync bool) {
625 if w.err != nil {
626 return
627 }
628
629 sync = sync || eof
630 if sync {
631 tokens.AddEOB()
632 } else {
633
634 tokens.extraHist[0] = 1
635 }
636
637
638 if (w.wroteHuffman || eof) && w.prevHeader > 0 {
639
640 w.writeCode(w.literalEncoding.codes[endBlockMarker])
641 w.prevHeader = 0
642 w.wroteHuffman = false
643 }
644
645 if w.prevHeader > 0 && !w.canReuse(tokens) {
646 w.writeCode(w.literalEncoding.codes[endBlockMarker])
647 w.prevHeader = 0
648 }
649
650 numLiterals, numOffsets := w.indexTokens(tokens)
651 extraBits := 0
652 ssize, storable := w.storedSize(input)
653
654 if storable || w.prevHeader > 0 {
655 extraBits = w.extraBitSize()
656 }
657
658 var size int
659
660
661 if w.prevHeader > 0 {
662
663
664 newSize := w.prevHeader + tokens.EstimatedBits()
665
666
667
668 newSize += int(w.literalEncoding.codes[endBlockMarker].len()) + newSize>>w.logNewTablePenalty
669
670
671 reuseSize := w.dynamicReuseSize(w.literalEncoding, w.offsetEncoding) + extraBits
672
673
674 if newSize < reuseSize {
675
676 w.writeCode(w.literalEncoding.codes[endBlockMarker])
677 size = newSize
678 w.prevHeader = 0
679 } else {
680 size = reuseSize
681 }
682
683
684 if tokens.n < maxPredefinedTokens {
685 if preSize := w.fixedSize(extraBits) + 7; preSize < size {
686
687 if storable && ssize <= size {
688 w.writeStoredHeader(len(input), eof)
689 w.writeBytes(input)
690 return
691 }
692 w.writeFixedHeader(eof)
693 if !sync {
694 tokens.AddEOB()
695 }
696 w.writeTokens(tokens.Slice(), fixedLiteralEncoding().codes, fixedOffsetEncoding().codes)
697 return
698 }
699 }
700
701
702 if storable && ssize <= size {
703 w.writeStoredHeader(len(input), eof)
704 w.writeBytes(input)
705 return
706 }
707 }
708
709
710 if w.prevHeader == 0 {
711 w.literalFreq[endBlockMarker] = 1
712
713 w.generate()
714
715
716 w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding)
717 w.codegenEncoding.generate(w.codegenFreq[:], 7)
718
719 var numCodegens int
720 size, numCodegens = w.dynamicSize(w.literalEncoding, w.offsetEncoding, extraBits)
721
722
723 if tokens.n < maxPredefinedTokens {
724 if preSize := w.fixedSize(extraBits); preSize <= size {
725
726 if storable && ssize <= preSize {
727 w.writeStoredHeader(len(input), eof)
728 w.writeBytes(input)
729 return
730 }
731 w.writeFixedHeader(eof)
732 if !sync {
733 tokens.AddEOB()
734 }
735 w.writeTokens(tokens.Slice(), fixedLiteralEncoding().codes, fixedOffsetEncoding().codes)
736 return
737 }
738 }
739
740 if storable && ssize <= size {
741
742 w.writeStoredHeader(len(input), eof)
743 w.writeBytes(input)
744 return
745 }
746
747
748 w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof)
749 if !sync {
750 w.prevHeader, _ = w.headerSize()
751 }
752 w.wroteHuffman = false
753 }
754
755 if sync {
756 w.prevHeader = 0
757 }
758
759 w.writeTokens(tokens.Slice(), w.literalEncoding.codes, w.offsetEncoding.codes)
760 }
761
762
763
764
765 func (w *huffmanBitWriter) indexTokens(t *tokens) (numLiterals, numOffsets int) {
766 *(*[256]uint16)(w.literalFreq[:]) = t.litHist
767 *(*[32]uint16)(w.literalFreq[256:]) = t.extraHist
768 w.offsetFreq = t.offHist
769
770 if t.n == 0 {
771 return
772 }
773
774 numLiterals = len(w.literalFreq)
775 for w.literalFreq[numLiterals-1] == 0 {
776 numLiterals--
777 }
778
779 numOffsets = len(w.offsetFreq)
780 for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 {
781 numOffsets--
782 }
783 if numOffsets == 0 {
784
785
786 w.offsetFreq[0] = 1
787 numOffsets = 1
788 }
789 return
790 }
791
792
793 func (w *huffmanBitWriter) generate() {
794 w.literalEncoding.generate(w.literalFreq[:literalCount], 15)
795 w.offsetEncoding.generate(w.offsetFreq[:offsetCodeCount], 15)
796 }
797
798
799
800 func (w *huffmanBitWriter) writeTokens(tokens []token, lenCodes, offCodes []hcode) {
801 if w.err != nil {
802 return
803 }
804 if len(tokens) == 0 {
805 return
806 }
807
808
809 var deferEOB bool
810 if tokens[len(tokens)-1] == endBlockMarker {
811 tokens = tokens[:len(tokens)-1]
812 deferEOB = true
813 }
814
815
816 lits := lenCodes[:256]
817 offs := offCodes[:32]
818 lengths := lenCodes[lengthCodesStart:]
819 lengths = lengths[:32]
820
821
822 bits, nbits, nbytes := w.bits, w.nbits, w.nbytes
823
824
825 storeLE64(w.bytes[nbytes:], bits)
826 nbytes += nbits >> 3
827 bits >>= nbits & 56
828 nbits &= 7
829 if nbytes >= bufferFlushSize {
830 _, w.err = w.writer.Write(w.bytes[:nbytes])
831 nbytes = 0
832 if w.err != nil {
833 return
834 }
835 }
836
837
838
839
840
841
842
843
844 for i := 0; i < len(tokens); i++ {
845 t := tokens[i]
846 if t < 256 {
847 c := lits[t]
848 bits |= c.code64() << (nbits & 63)
849 nbits += c.len()
850
851 if i+1 < len(tokens) && tokens[i+1] < 256 {
852 i++
853 c := lits[tokens[i]]
854 bits |= c.code64() << (nbits & 63)
855 nbits += c.len()
856 if i+1 < len(tokens) && tokens[i+1] < 256 {
857 i++
858 c := lits[tokens[i]]
859 bits |= c.code64() << (nbits & 63)
860 nbits += c.len()
861 }
862 }
863 } else {
864
865 lc := lengthCombined[t.length()]
866 c := lengths[lc&31]
867 bits |= (c.code64() | uint64(lc>>8)<<(c.len()&63)) << (nbits & 63)
868 nbits += c.len() + uint8(lc>>5)&7
869
870
871 offset := t.offset()
872 offCode := (offset >> 16) & 31
873 c = offs[offCode]
874 offComb := offsetCombined[offCode]
875 extra := (offset - (offComb >> 8)) & matchOffsetOnlyMask
876 bits |= (c.code64() | uint64(extra)<<(c.len()&63)) << (nbits & 63)
877 nbits += c.len() + uint8(offComb)
878 }
879 storeLE64(w.bytes[nbytes:], bits)
880 nbytes += nbits >> 3
881 bits >>= nbits & 56
882 nbits &= 7
883 if nbytes >= bufferFlushSize {
884 if w.err != nil {
885 nbytes = 0
886 return
887 }
888 _, w.err = w.writer.Write(w.bytes[:nbytes])
889 nbytes = 0
890 }
891 }
892
893 w.bits, w.nbits, w.nbytes = bits, nbits, nbytes
894
895 if deferEOB {
896 w.writeCode(lenCodes[endBlockMarker])
897 }
898 }
899
900
901
902 var huffOffset = sync.OnceValue(func() *huffmanEncoder {
903 w := newHuffmanBitWriter(nil)
904 w.offsetFreq[0] = 1
905 h := newHuffmanEncoder(offsetCodeCount)
906 h.generate(w.offsetFreq[:offsetCodeCount], 15)
907 return h
908 })
909
910
911
912
913 func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) {
914 if w.err != nil {
915 return
916 }
917
918
919 clear(w.literalFreq[:])
920 if !w.wroteHuffman {
921 clear(w.offsetFreq[:])
922 }
923
924 const numLiterals = endBlockMarker + 1
925 const numOffsets = 1
926
927
928 const guessHeaderSizeBits = 70 * 8
929 histogram(input, w.literalFreq[:numLiterals])
930 ssize, storable := w.storedSize(input)
931 if storable && len(input) > 1024 {
932
933
934
935
936
937
938 abs := float64(0)
939 avg := float64(len(input)) / 256
940 max := float64(len(input) * 2)
941 for _, v := range w.literalFreq[:256] {
942 diff := float64(v) - avg
943 abs += diff * diff
944 if abs >= max {
945 break
946 }
947 }
948 if abs < max {
949
950 w.writeStoredHeader(len(input), eof)
951 w.writeBytes(input)
952 return
953 }
954 }
955 w.literalFreq[endBlockMarker] = 1
956 w.tmpLitEncoding.generate(w.literalFreq[:numLiterals], 15)
957 estBits := w.tmpLitEncoding.canEncodeLen(w.literalFreq[:numLiterals])
958 if estBits < math.MaxInt32 {
959 estBits += w.prevHeader
960 if w.prevHeader == 0 {
961 estBits += guessHeaderSizeBits
962 }
963 estBits += estBits >> w.logNewTablePenalty
964 }
965
966
967 if storable && ssize <= estBits {
968 w.writeStoredHeader(len(input), eof)
969 w.writeBytes(input)
970 return
971 }
972
973 if w.prevHeader > 0 {
974 reuseSize := w.literalEncoding.canEncodeLen(w.literalFreq[:256])
975 if estBits < reuseSize {
976
977 w.writeCode(w.literalEncoding.codes[endBlockMarker])
978 w.prevHeader = 0
979 }
980 }
981
982 if w.prevHeader == 0 {
983
984 w.literalEncoding, w.tmpLitEncoding = w.tmpLitEncoding, w.literalEncoding
985
986
987 w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, huffOffset())
988 w.codegenEncoding.generate(w.codegenFreq[:], 7)
989 numCodegens := w.codegens()
990
991
992 w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof)
993 w.wroteHuffman = true
994 w.prevHeader, _ = w.headerSize()
995 }
996
997 encoding := w.literalEncoding.codes[:256]
998
999 bits, nbits, nbytes := w.bits, w.nbits, w.nbytes
1000
1001
1002
1003 for len(input) > 3 {
1004
1005 if nbits >= 8 {
1006 n := nbits >> 3
1007 storeLE64(w.bytes[nbytes:], bits)
1008 bits >>= (n * 8) & 63
1009 nbits -= n * 8
1010 nbytes += n
1011 }
1012 if nbytes >= bufferFlushSize {
1013 if w.err != nil {
1014 nbytes = 0
1015 return
1016 }
1017 _, w.err = w.writer.Write(w.bytes[:nbytes])
1018 nbytes = 0
1019 }
1020 a, b := encoding[input[0]], encoding[input[1]]
1021 bits |= a.code64() << (nbits & 63)
1022 bits |= b.code64() << ((nbits + a.len()) & 63)
1023 c := encoding[input[2]]
1024 nbits += b.len() + a.len()
1025 bits |= c.code64() << (nbits & 63)
1026 nbits += c.len()
1027 input = input[3:]
1028 }
1029
1030
1031 for _, t := range input {
1032 if nbits >= 48 {
1033 storeLE64(w.bytes[nbytes:], bits)
1034 bits >>= 48
1035 nbits -= 48
1036 nbytes += 6
1037 if nbytes >= bufferFlushSize {
1038 if w.err != nil {
1039 nbytes = 0
1040 return
1041 }
1042 _, w.err = w.writer.Write(w.bytes[:nbytes])
1043 nbytes = 0
1044 }
1045 }
1046
1047 c := encoding[t]
1048 bits |= c.code64() << (nbits & 63)
1049
1050 nbits += c.len()
1051 }
1052
1053 w.bits, w.nbits, w.nbytes = bits, nbits, nbytes
1054
1055
1056 if w.nbits >= 48 {
1057 w.flushBits()
1058 }
1059
1060 if eof || sync {
1061 w.writeCode(w.literalEncoding.codes[endBlockMarker])
1062 w.prevHeader = 0
1063 w.wroteHuffman = false
1064 }
1065 }
1066
View as plain text