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.



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

def initialize(data)
    @data = data
    reset
end

Instance Method Details

#cloObject

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



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# 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

#clzObject

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



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# 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?Boolean

Returns true if end of data has been reached.

Returns:



190
191
192
# File 'lib/origami/filters.rb', line 190

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

#peek(length) ⇒ Object

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



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# 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

#posObject

Returns the read pointer position in bits.



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

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

#pos=(bits) ⇒ Object

Sets the read pointer position in bits.

Raises:



211
212
213
214
215
216
217
# 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) ⇒ Object

Reads length bits as a Fixnum and advances read pointer.



222
223
224
225
226
227
# File 'lib/origami/filters.rb', line 222

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

    n
end

#resetObject

Resets the read pointer.



182
183
184
185
# File 'lib/origami/filters.rb', line 182

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

#sizeObject

Returns the data size in bits.



204
205
206
# File 'lib/origami/filters.rb', line 204

def size
    @data.size << 3
end