class Origami::Filter::Utils::BitReader

Class used to read a String as a stream of bits. Internally used by some filters.

Constants

BRUIJIN_TABLE

Public Class Methods

new(data) click to toggle source
# File lib/origami/filters.rb, line 174
def initialize(data)
    @data = data
    reset
end

Public Instance Methods

clo() click to toggle source

Used for bit scanning. Count leading ones. Does not advance read pointer.

# File lib/origami/filters.rb, line 288
def clo
    count = 0
    if @ptr_bit != 0
        bits = peek(8 - @ptr_bit)
        count = clz32(~(bits << (32 - (8 - @ptr_bit))) & 0xff)

        return count if count < (8 - @ptr_bit)
    end

    delta = 0
    while @data.size > @ptr_byte + delta * 4
        word = @data[@ptr_byte + delta * 4, 4] # next 32 bits
        z = clz32(~((word << (4 - word.size)).unpack("N")[0]) & 0xffff_ffff)

        count += z
        delta += 1

        return count if z < 32 - ((4 - word.size) << 3)
    end

    count
end
clz() click to toggle source

Used for bit scanning. Counts leading zeros. Does not advance read pointer.

# File lib/origami/filters.rb, line 261
def clz
    count = 0
    if @ptr_bit != 0
        bits = peek(8 - @ptr_bit)
        count = clz32(bits << (32 - (8 - @ptr_bit)))

        return count if count < (8 - @ptr_bit)
    end

    delta = 0
    while @data.size > @ptr_byte + delta * 4
        word = @data[@ptr_byte + delta * 4, 4] # next 32 bits
        z = clz32((word << (4 - word.size)).unpack("N")[0])

        count += z
        delta += 1

        return count if z < 32 - ((4 - word.size) << 3)
    end

    count
end
eod?() click to toggle source

Returns true if end of data has been reached.

# File lib/origami/filters.rb, line 190
def eod?
    @ptr_byte >= @data.size
end
peek(length) click to toggle source

Reads length bits as a Fixnum. Does not advance read pointer.

# File lib/origami/filters.rb, line 232
def peek(length)
    return BitReaderError, "Invalid read length" unless length > 0
    return BitReaderError, "Insufficient data" if self.pos + length > self.size

    n = 0
    ptr_byte, ptr_bit = @ptr_byte, @ptr_bit

    while length > 0
        byte = @data[ptr_byte].ord

        if length > 8 - ptr_bit
            length -= 8 - ptr_bit
            n |= ( byte & ((1 << (8 - ptr_bit)) - 1) ) << length

            ptr_byte += 1
            ptr_bit = 0
        else
            n |= (byte >> (8 - ptr_bit - length)) & ((1 << length) - 1)
            length = 0
        end
    end

    n
end
pos() click to toggle source

Returns the read pointer position in bits.

# File lib/origami/filters.rb, line 197
def pos
    (@ptr_byte << 3) + @ptr_bit
end
pos=(bits) click to toggle source

Sets the read pointer position in bits.

# File lib/origami/filters.rb, line 211
def pos=(bits)
    raise BitReaderError, "Pointer position out of data" if bits > self.size

    pbyte = bits >> 3
    pbit = bits - (pbyte << 3)
    @ptr_byte, @ptr_bit = pbyte, pbit
end
read(length) click to toggle source

Reads length bits as a Fixnum and advances read pointer.

# File lib/origami/filters.rb, line 222
def read(length)
    n = self.peek(length)
    self.pos += length

    n
end
reset() click to toggle source

Resets the read pointer.

# File lib/origami/filters.rb, line 182
def reset
    @ptr_byte, @ptr_bit = 0, 0
    self
end
size() click to toggle source

Returns the data size in bits.

# File lib/origami/filters.rb, line 204
def size
    @data.size << 3
end

Private Instance Methods

bitswap8(i) click to toggle source
# File lib/origami/filters.rb, line 313
def bitswap8(i) #:nodoc
    ((i * 0x0202020202) & 0x010884422010) % 1023
end