Skip to content

Commit

Permalink
Optimised find/findall for byte aligned case.
Browse files Browse the repository at this point in the history
Bug #326.
  • Loading branch information
scott-griffiths committed May 10, 2024
1 parent c8c7f74 commit ce684cd
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 3 deletions.
18 changes: 18 additions & 0 deletions bitstring/bitstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,24 @@ def rfind(self, bs: BitStore, start: int, end: int, bytealigned: bool = False):
return -1

def findall_msb0(self, bs: BitStore, start: int, end: int, bytealigned: bool = False) -> Iterator[int]:
if bytealigned is True and len(bs) % 8 == 0:
# Special case, looking for whole bytes on whole byte boundaries
bytes_ = bs.tobytes()
# Round up start byte to next byte, and round end byte down.
# We're only looking for whole bytes, so can ignore bits at either end.
start_byte = (start + 7) // 8
end_byte = end // 8
b = self._bitarray[start_byte * 8: end_byte * 8].tobytes()
byte_pos = 0
bytes_to_search = end_byte - start_byte
while byte_pos < bytes_to_search:
byte_pos = b.find(bytes_, byte_pos)
if byte_pos == -1:
break
yield (byte_pos + start_byte) * 8
byte_pos = byte_pos + 1
return
# General case
i = self._bitarray.itersearch(bs._bitarray, start, end)
if not bytealigned:
for p in i:
Expand Down
1 change: 1 addition & 0 deletions release_notes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ A couple more minor bug fixes.
* Sometimes a ValueError was being raised instead of a ReadError. Bug #325.
* Initialising a bitstring from None now raises a TypeError rather than generating
an empty bitstring. Bug #323.
* Fixed performance regression for find/findall in some situations. Bug #326.

-------------------------
April 2024: version 4.2.1
Expand Down
6 changes: 3 additions & 3 deletions tests/test_bitstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ def test_find_corner_cases(self):

def test_find_bytes(self):
s = BitStream.fromstring('0x010203040102ff')
assert not s.find('0x05', bytealigned=True)
assert s.find('0x02', bytealigned=True)
assert s.find('0x05', bytealigned=True) ==()
assert s.find('0x02', bytealigned=True) == (8,)
assert s.read(16).hex == '0203'
assert s.find('0x02', start=s.bitpos, bytealigned=True)
assert s.find('0x02', start=s.bitpos, bytealigned=True) == (40,)
s.read(1)
assert not s.find('0x02', start=s.bitpos, bytealigned=True)

Expand Down

0 comments on commit ce684cd

Please sign in to comment.