Login
bitwriter.cr at tip
Login

File src/remilib/compression/bzip/bitwriter.cr from the latest check-in


     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
#### Bzip2 Implementation
#### Copyright (C) 2023-2024 Remilia Scarlet
#### Copyright (c) 2022 drone1400
#### Copyright (C) 2015 Jaime Olivares
#### Copyright (c) 2011 Matthew Francis
#### MIT License
####
#### Ported from the Java implementation by Matthew Francis:
#### https://github.com/MateuszBartosiewicz/bzip2.
####
#### Modified by drone1400
####
#### Ported by Remilia Scarlet from the C# implementation by Jamie Olivares:
#### http://github.com/jaime-olivares/bzip2

module RemiLib::Compression::BZip2
  private class BitWriter
    protected getter io : IO

    # A buffer of bits waiting to be written to the output stream.
    @bitBuffer : UInt32 = 0

    # The number of bits currently buffered in bitBuffer.
    @bitCount : Int32 = 0

    # Creates a new `BitWriter` instance that will write to the given `IO`.
    def initialize(@io : IO)
    end

    @[AlwaysInline]
    def writeBoolean(value : Bool) : Nil
      @bitCount += 1
      @bitBuffer |= (value ? 1u32 : 0u32) << (32 - @bitCount)

      if @bitCount == 8
        @io.write_byte((@bitBuffer >> 24).to_u8!)
        @bitBuffer = 0
        @bitCount = 0
      end
    end

    @[AlwaysInline]
    def writeUnary(value : Int) : Nil
      while value > 0
        writeBoolean(true)
        value -= 1
      end
      writeBoolean(false)
    end

    @[AlwaysInline]
    def writeBits(count : Int, value : Int32|UInt32)
      @bitBuffer |= (value.to_u32! << (32 - count)) >> @bitCount
      @bitCount += count

      while @bitCount >= 8
        @io.write_byte((@bitBuffer >> 24).to_u8!)
        @bitBuffer <<= 8
        @bitCount -= 8
      end
    end

    @[AlwaysInline]
    def writeInt32(value : Int32|UInt32) : Nil
      writeBits(16, (value.to_u32! >> 16) & 0xFFFF)
      writeBits(16, value.to_u32! & 0xFFFF)
    end

    @[AlwaysInline]
    def flush : Nil
      if @bitCount > 0
        writeBits(8 - @bitCount, 0)
      end
    end
  end
end