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.



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/origami/filters.rb', line 290

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.



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

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.



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

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
218
219
# 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

    bits
end

#read(length) ⇒ Object

Reads length bits as a Fixnum and advances read pointer.



224
225
226
227
228
229
# File 'lib/origami/filters.rb', line 224

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