bitwriter.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright 2018 Klaus Post. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
  5. package huff0
  6. import "fmt"
  7. // bitWriter will write bits.
  8. // First bit will be LSB of the first byte of output.
  9. type bitWriter struct {
  10. bitContainer uint64
  11. nBits uint8
  12. out []byte
  13. }
  14. // bitMask16 is bitmasks. Has extra to avoid bounds check.
  15. var bitMask16 = [32]uint16{
  16. 0, 1, 3, 7, 0xF, 0x1F,
  17. 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
  18. 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF,
  19. 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  20. 0xFFFF, 0xFFFF} /* up to 16 bits */
  21. // addBits16NC will add up to 16 bits.
  22. // It will not check if there is space for them,
  23. // so the caller must ensure that it has flushed recently.
  24. func (b *bitWriter) addBits16NC(value uint16, bits uint8) {
  25. b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63)
  26. b.nBits += bits
  27. }
  28. // addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated.
  29. // It will not check if there is space for them, so the caller must ensure that it has flushed recently.
  30. func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
  31. b.bitContainer |= uint64(value) << (b.nBits & 63)
  32. b.nBits += bits
  33. }
  34. // encSymbol will add up to 16 bits. value may not contain more set bits than indicated.
  35. // It will not check if there is space for them, so the caller must ensure that it has flushed recently.
  36. func (b *bitWriter) encSymbol(ct cTable, symbol byte) {
  37. enc := ct[symbol]
  38. b.bitContainer |= uint64(enc.val) << (b.nBits & 63)
  39. b.nBits += enc.nBits
  40. }
  41. // encTwoSymbols will add up to 32 bits. value may not contain more set bits than indicated.
  42. // It will not check if there is space for them, so the caller must ensure that it has flushed recently.
  43. func (b *bitWriter) encTwoSymbols(ct cTable, av, bv byte) {
  44. encA := ct[av]
  45. encB := ct[bv]
  46. sh := b.nBits & 63
  47. combined := uint64(encA.val) | (uint64(encB.val) << (encA.nBits & 63))
  48. b.bitContainer |= combined << sh
  49. b.nBits += encA.nBits + encB.nBits
  50. }
  51. // addBits16ZeroNC will add up to 16 bits.
  52. // It will not check if there is space for them,
  53. // so the caller must ensure that it has flushed recently.
  54. // This is fastest if bits can be zero.
  55. func (b *bitWriter) addBits16ZeroNC(value uint16, bits uint8) {
  56. if bits == 0 {
  57. return
  58. }
  59. value <<= (16 - bits) & 15
  60. value >>= (16 - bits) & 15
  61. b.bitContainer |= uint64(value) << (b.nBits & 63)
  62. b.nBits += bits
  63. }
  64. // flush will flush all pending full bytes.
  65. // There will be at least 56 bits available for writing when this has been called.
  66. // Using flush32 is faster, but leaves less space for writing.
  67. func (b *bitWriter) flush() {
  68. v := b.nBits >> 3
  69. switch v {
  70. case 0:
  71. return
  72. case 1:
  73. b.out = append(b.out,
  74. byte(b.bitContainer),
  75. )
  76. b.bitContainer >>= 1 << 3
  77. case 2:
  78. b.out = append(b.out,
  79. byte(b.bitContainer),
  80. byte(b.bitContainer>>8),
  81. )
  82. b.bitContainer >>= 2 << 3
  83. case 3:
  84. b.out = append(b.out,
  85. byte(b.bitContainer),
  86. byte(b.bitContainer>>8),
  87. byte(b.bitContainer>>16),
  88. )
  89. b.bitContainer >>= 3 << 3
  90. case 4:
  91. b.out = append(b.out,
  92. byte(b.bitContainer),
  93. byte(b.bitContainer>>8),
  94. byte(b.bitContainer>>16),
  95. byte(b.bitContainer>>24),
  96. )
  97. b.bitContainer >>= 4 << 3
  98. case 5:
  99. b.out = append(b.out,
  100. byte(b.bitContainer),
  101. byte(b.bitContainer>>8),
  102. byte(b.bitContainer>>16),
  103. byte(b.bitContainer>>24),
  104. byte(b.bitContainer>>32),
  105. )
  106. b.bitContainer >>= 5 << 3
  107. case 6:
  108. b.out = append(b.out,
  109. byte(b.bitContainer),
  110. byte(b.bitContainer>>8),
  111. byte(b.bitContainer>>16),
  112. byte(b.bitContainer>>24),
  113. byte(b.bitContainer>>32),
  114. byte(b.bitContainer>>40),
  115. )
  116. b.bitContainer >>= 6 << 3
  117. case 7:
  118. b.out = append(b.out,
  119. byte(b.bitContainer),
  120. byte(b.bitContainer>>8),
  121. byte(b.bitContainer>>16),
  122. byte(b.bitContainer>>24),
  123. byte(b.bitContainer>>32),
  124. byte(b.bitContainer>>40),
  125. byte(b.bitContainer>>48),
  126. )
  127. b.bitContainer >>= 7 << 3
  128. case 8:
  129. b.out = append(b.out,
  130. byte(b.bitContainer),
  131. byte(b.bitContainer>>8),
  132. byte(b.bitContainer>>16),
  133. byte(b.bitContainer>>24),
  134. byte(b.bitContainer>>32),
  135. byte(b.bitContainer>>40),
  136. byte(b.bitContainer>>48),
  137. byte(b.bitContainer>>56),
  138. )
  139. b.bitContainer = 0
  140. b.nBits = 0
  141. return
  142. default:
  143. panic(fmt.Errorf("bits (%d) > 64", b.nBits))
  144. }
  145. b.nBits &= 7
  146. }
  147. // flush32 will flush out, so there are at least 32 bits available for writing.
  148. func (b *bitWriter) flush32() {
  149. if b.nBits < 32 {
  150. return
  151. }
  152. b.out = append(b.out,
  153. byte(b.bitContainer),
  154. byte(b.bitContainer>>8),
  155. byte(b.bitContainer>>16),
  156. byte(b.bitContainer>>24))
  157. b.nBits -= 32
  158. b.bitContainer >>= 32
  159. }
  160. // flushAlign will flush remaining full bytes and align to next byte boundary.
  161. func (b *bitWriter) flushAlign() {
  162. nbBytes := (b.nBits + 7) >> 3
  163. for i := uint8(0); i < nbBytes; i++ {
  164. b.out = append(b.out, byte(b.bitContainer>>(i*8)))
  165. }
  166. b.nBits = 0
  167. b.bitContainer = 0
  168. }
  169. // close will write the alignment bit and write the final byte(s)
  170. // to the output.
  171. func (b *bitWriter) close() error {
  172. // End mark
  173. b.addBits16Clean(1, 1)
  174. // flush until next byte.
  175. b.flushAlign()
  176. return nil
  177. }
  178. // reset and continue writing by appending to out.
  179. func (b *bitWriter) reset(out []byte) {
  180. b.bitContainer = 0
  181. b.nBits = 0
  182. b.out = out
  183. }