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.

[View source]

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.

[View source]

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.

[View source]

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:

[View source]

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.

[View source]

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.

[View source]

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:

[View source]

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.

[View source]

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.

[View source]

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.

[View source]

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

def size
    @data.size << 3
end