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.



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

def initialize(data)
  @data = data
  reset
end

Instance Method Details

#cloObject

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



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/origami/filters.rb', line 283

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)).unpack1("N") & 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.



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/origami/filters.rb', line 256

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)).unpack1("N"))

    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:



185
186
187
# File 'lib/origami/filters.rb', line 185

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

#peek(length) ⇒ Object

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



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/origami/filters.rb', line 227

def peek(length)
  return BitReaderError, "Invalid read length" unless length > 0
  return BitReaderError, "Insufficient data" if self.pos + length > 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.



192
193
194
# File 'lib/origami/filters.rb', line 192

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

#pos=(bits) ⇒ Object

Sets the read pointer position in bits.

Raises:



206
207
208
209
210
211
212
# File 'lib/origami/filters.rb', line 206

def pos=(bits)
  raise BitReaderError, "Pointer position out of data" if bits > 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.



217
218
219
220
221
222
# File 'lib/origami/filters.rb', line 217

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

  n
end

#resetObject

Resets the read pointer.



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

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

#sizeObject

Returns the data size in bits.



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

def size
  @data.size << 3
end