writer.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright 2019 The Go Authors. 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. package ccitt
  5. import (
  6. "encoding/binary"
  7. "io"
  8. )
  9. type bitWriter struct {
  10. w io.Writer
  11. // order is whether to process w's bytes LSB first or MSB first.
  12. order Order
  13. // The high nBits bits of the bits field hold encoded bits to be written to w.
  14. bits uint64
  15. nBits uint32
  16. // bytes[:bw] holds encoded bytes not yet written to w.
  17. // Overflow protection is ensured by using a multiple of 8 as bytes length.
  18. bw uint32
  19. bytes [1024]uint8
  20. }
  21. // flushBits copies 64 bits from b.bits to b.bytes. If b.bytes is then full, it
  22. // is written to b.w.
  23. func (b *bitWriter) flushBits() error {
  24. binary.BigEndian.PutUint64(b.bytes[b.bw:], b.bits)
  25. b.bits = 0
  26. b.nBits = 0
  27. b.bw += 8
  28. if b.bw < uint32(len(b.bytes)) {
  29. return nil
  30. }
  31. b.bw = 0
  32. if b.order != MSB {
  33. reverseBitsWithinBytes(b.bytes[:])
  34. }
  35. _, err := b.w.Write(b.bytes[:])
  36. return err
  37. }
  38. // close finalizes a bitcode stream by writing any
  39. // pending bits to bitWriter's underlying io.Writer.
  40. func (b *bitWriter) close() error {
  41. // Write any encoded bits to bytes.
  42. if b.nBits > 0 {
  43. binary.BigEndian.PutUint64(b.bytes[b.bw:], b.bits)
  44. b.bw += (b.nBits + 7) >> 3
  45. }
  46. if b.order != MSB {
  47. reverseBitsWithinBytes(b.bytes[:b.bw])
  48. }
  49. // Write b.bw bytes to b.w.
  50. _, err := b.w.Write(b.bytes[:b.bw])
  51. return err
  52. }
  53. // alignToByteBoundary rounds b.nBits up to a multiple of 8.
  54. // If all 64 bits are used, flush them to bitWriter's bytes.
  55. func (b *bitWriter) alignToByteBoundary() error {
  56. if b.nBits = (b.nBits + 7) &^ 7; b.nBits == 64 {
  57. return b.flushBits()
  58. }
  59. return nil
  60. }
  61. // writeCode writes a variable length bitcode to b's underlying io.Writer.
  62. func (b *bitWriter) writeCode(bs bitString) error {
  63. bits := bs.bits
  64. nBits := bs.nBits
  65. if 64-b.nBits >= nBits {
  66. // b.bits has sufficient room for storing nBits bits.
  67. b.bits |= uint64(bits) << (64 - nBits - b.nBits)
  68. b.nBits += nBits
  69. if b.nBits == 64 {
  70. return b.flushBits()
  71. }
  72. return nil
  73. }
  74. // Number of leading bits that fill b.bits.
  75. i := 64 - b.nBits
  76. // Fill b.bits then flush and write remaining bits.
  77. b.bits |= uint64(bits) >> (nBits - i)
  78. b.nBits = 64
  79. if err := b.flushBits(); err != nil {
  80. return err
  81. }
  82. nBits -= i
  83. b.bits = uint64(bits) << (64 - nBits)
  84. b.nBits = nBits
  85. return nil
  86. }