@@ -218,31 +218,33 @@ def read_f8le(self):
218218 # ========================================================================
219219
220220 def align_to_byte (self ):
221- self .bits = 0
222221 self .bits_left = 0
222+ self .bits = 0
223223
224224 def read_bits_int_be (self , n ):
225+ res = 0
226+
225227 bits_needed = n - self .bits_left
228+ self .bits_left = - bits_needed % 8
229+
226230 if bits_needed > 0 :
227231 # 1 bit => 1 byte
228232 # 8 bits => 1 byte
229233 # 9 bits => 2 bytes
230- bytes_needed = ((bits_needed - 1 ) // 8 ) + 1
234+ bytes_needed = ((bits_needed - 1 ) // 8 ) + 1 # `ceil(bits_needed / 8)`
231235 buf = self .read_bytes (bytes_needed )
236+ if PY2 :
237+ buf = bytearray (buf )
232238 for byte in buf :
233- byte = KaitaiStream .int_from_byte (byte )
234- self .bits <<= 8
235- self .bits |= byte
236- self .bits_left += 8
237-
238- # raw mask with required number of 1s, starting from lowest bit
239- mask = (1 << n ) - 1
240- # shift self.bits to align the highest bits with the mask & derive reading result
241- shift_bits = self .bits_left - n
242- res = (self .bits >> shift_bits ) & mask
243- # clear top bits that we've just read => AND with 1s
244- self .bits_left -= n
245- mask = (1 << self .bits_left ) - 1
239+ res = res << 8 | byte
240+
241+ new_bits = res
242+ res = res >> self .bits_left | self .bits << bits_needed
243+ self .bits = new_bits # will be masked at the end of the function
244+ else :
245+ res = self .bits >> - bits_needed # shift unneeded bits out
246+
247+ mask = (1 << self .bits_left ) - 1 # `bits_left` is in range 0..7
246248 self .bits &= mask
247249
248250 return res
@@ -253,26 +255,31 @@ def read_bits_int(self, n):
253255 return self .read_bits_int_be (n )
254256
255257 def read_bits_int_le (self , n ):
258+ res = 0
256259 bits_needed = n - self .bits_left
260+
257261 if bits_needed > 0 :
258262 # 1 bit => 1 byte
259263 # 8 bits => 1 byte
260264 # 9 bits => 2 bytes
261- bytes_needed = ((bits_needed - 1 ) // 8 ) + 1
265+ bytes_needed = ((bits_needed - 1 ) // 8 ) + 1 # `ceil(bits_needed / 8)`
262266 buf = self .read_bytes (bytes_needed )
263- for byte in buf :
264- byte = KaitaiStream .int_from_byte (byte )
265- self .bits |= (byte << self .bits_left )
266- self .bits_left += 8
267-
268- # raw mask with required number of 1s, starting from lowest bit
269- mask = (1 << n ) - 1
270- # derive reading result
271- res = self .bits & mask
272- # remove bottom bits that we've just read by shifting
273- self .bits >>= n
274- self .bits_left -= n
267+ if PY2 :
268+ buf = bytearray (buf )
269+ for i , byte in enumerate (buf ):
270+ res |= byte << (i * 8 )
271+
272+ new_bits = res >> bits_needed
273+ res = res << self .bits_left | self .bits
274+ self .bits = new_bits
275+ else :
276+ res = self .bits
277+ self .bits >>= n
278+
279+ self .bits_left = - bits_needed % 8
275280
281+ mask = (1 << n ) - 1 # no problem with this in Python (arbitrary precision integers)
282+ res &= mask
276283 return res
277284
278285 # ========================================================================
0 commit comments