Class: Origami::Filter::Utils::BitReader

Inherits:
Object
  • Object
show all
Defined in:
lib/origami/filters.rb

Overview

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

Constant Summary collapse

BRUIJIN_TABLE =
::Array.new(32)

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ BitReader

Returns a new instance of BitReader.



146
147
148
149
# File 'lib/origami/filters.rb', line 146

def initialize(data)
    @data = data
    reset
end

Instance Method Details

#cloObject

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



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/origami/filters.rb', line 262

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

#clzObject

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



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/origami/filters.rb', line 235

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?Boolean

Returns true if end of data has been reached.

Returns:



162
163
164
# File 'lib/origami/filters.rb', line 162

def eod?
    @ptr_byte >= @data.size
end

#peek(length) ⇒ Object

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



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/origami/filters.rb', line 206

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

#posObject

Returns the read pointer position in bits.



169
170
171
# File 'lib/origami/filters.rb', line 169

def pos
    (@ptr_byte << 3) + @ptr_bit
end

#pos=(bits) ⇒ Object

Sets the read pointer position in bits.

Raises:



183
184
185
186
187
188
189
190
191
# File 'lib/origami/filters.rb', line 183

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

    bits
end

#read(length) ⇒ Object

Reads length bits as a Fixnum and advances read pointer.



196
197
198
199
200
201
# File 'lib/origami/filters.rb', line 196

def read(length)
    n = self.peek(length)
    self.pos += length

    n
end

#resetObject

Resets the read pointer.



154
155
156
157
# File 'lib/origami/filters.rb', line 154

def reset
    @ptr_byte, @ptr_bit = 0, 0
    self
end

#sizeObject

Returns the data size in bits.



176
177
178
# File 'lib/origami/filters.rb', line 176

def size
    @data.size << 3
end