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.



138
139
140
141
# File 'lib/origami/filters.rb', line 138

def initialize(data)
  @data = data
  reset
end

Instance Method Details

#cloObject

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



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

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.



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

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:



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

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

#peek(length) ⇒ Object

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



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/origami/filters.rb', line 198

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.



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

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

#pos=(bits) ⇒ Object

Sets the read pointer position in bits.

Raises:



175
176
177
178
179
180
181
182
183
# File 'lib/origami/filters.rb', line 175

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.



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

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

  n
end

#resetObject

Resets the read pointer.



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

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

#sizeObject

Returns the data size in bits.



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

def size
  @data.size << 3
end