@@ -182,34 +182,34 @@ end
182
182
-- =============================================================================
183
183
184
184
function KaitaiStream :align_to_byte ()
185
- self .bits = 0
186
185
self .bits_left = 0
186
+ self .bits = 0
187
187
end
188
188
189
189
function KaitaiStream :read_bits_int_be (n )
190
+ local res = 0
191
+
190
192
local bits_needed = n - self .bits_left
193
+ self .bits_left = - bits_needed % 8
194
+
191
195
if bits_needed > 0 then
192
196
-- 1 bit => 1 byte
193
197
-- 8 bits => 1 byte
194
198
-- 9 bits => 2 bytes
195
199
local bytes_needed = math.ceil (bits_needed / 8 )
196
- local buf = self ._io :read (bytes_needed )
197
- for i = 1 , # buf do
198
- local byte = buf :byte (i )
199
- self .bits = self .bits << 8
200
- self .bits = self .bits | byte
201
- self .bits_left = self .bits_left + 8
200
+ local buf = {self ._io :read (bytes_needed ):byte (1 , bytes_needed )}
201
+ for i = 1 , bytes_needed do
202
+ res = res << 8 | buf [i ]
202
203
end
204
+
205
+ local new_bits = res
206
+ res = res >> self .bits_left | self .bits << bits_needed
207
+ self .bits = new_bits -- will be masked at the end of the function
208
+ else
209
+ res = self .bits >> - bits_needed -- shift unneeded bits out
203
210
end
204
211
205
- -- Raw mask with required number of 1s, starting from lowest bit
206
- local mask = (1 << n ) - 1
207
- -- Shift self.bits to align the highest bits with the mask & derive reading result
208
- local shift_bits = self .bits_left - n
209
- local res = (self .bits >> shift_bits ) & mask
210
- -- Clear top bits that we've just read => AND with 1s
211
- self .bits_left = self .bits_left - n
212
- mask = (1 << self .bits_left ) - 1
212
+ local mask = (1 << self .bits_left ) - 1 -- `bits_left` is in range 0..7
213
213
self .bits = self .bits & mask
214
214
215
215
return res
@@ -225,28 +225,31 @@ function KaitaiStream:read_bits_int(n)
225
225
end
226
226
227
227
function KaitaiStream :read_bits_int_le (n )
228
+ local res = 0
228
229
local bits_needed = n - self .bits_left
230
+
229
231
if bits_needed > 0 then
230
232
-- 1 bit => 1 byte
231
233
-- 8 bits => 1 byte
232
234
-- 9 bits => 2 bytes
233
235
local bytes_needed = math.ceil (bits_needed / 8 )
234
- local buf = self ._io :read (bytes_needed )
235
- for i = 1 , # buf do
236
- local byte = buf :byte (i )
237
- self .bits = self .bits | (byte << self .bits_left )
238
- self .bits_left = self .bits_left + 8
236
+ local buf = {self ._io :read (bytes_needed ):byte (1 , bytes_needed )}
237
+ for i = 1 , bytes_needed do
238
+ res = res | buf [i ] << ((i - 1 ) * 8 ) -- NB: Lua uses 1-based indexing, but we need 0-based here
239
239
end
240
+
241
+ local new_bits = res >> bits_needed
242
+ res = res << self .bits_left | self .bits
243
+ self .bits = new_bits
244
+ else
245
+ res = self .bits
246
+ self .bits = self .bits >> n
240
247
end
241
248
242
- -- Raw mask with required number of 1s, starting from lowest bit
243
- local mask = (1 << n ) - 1
244
- -- Derive reading result
245
- local res = self .bits & mask
246
- -- Remove bottom bits that we've just read by shifting
247
- self .bits = self .bits >> n
248
- self .bits_left = self .bits_left - n
249
+ self .bits_left = - bits_needed % 8
249
250
251
+ local mask = (1 << n ) - 1 -- unlike some other languages, no problem with this in Lua
252
+ res = res & mask
250
253
return res
251
254
end
252
255
0 commit comments