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