From f892e8bfd2fca63d2651d3a9b66dbd259f30131d Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Mon, 18 Sep 2023 20:14:30 +0200 Subject: [PATCH 1/5] Have 'Segment.chunks' yield smaller 'Segment's --- bincopy.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/bincopy.py b/bincopy.py index a254133..f945d14 100755 --- a/bincopy.py +++ b/bincopy.py @@ -351,13 +351,8 @@ class Segment: """ - class Chunk(namedtuple("Chunk", ["address", "data"])): + _Chunk = namedtuple("Chunk", ["address", "data"]) - def __len___(self): - return len(self.data) - - _Chunk = Chunk - def __init__(self, minimum_address, maximum_address, data, word_size_bytes): self.minimum_address = minimum_address self.maximum_address = maximum_address @@ -389,16 +384,20 @@ def chunks(self, size=32, alignment=1): if chunk_offset != 0: first_chunk_size = (alignment - chunk_offset) - yield self.Chunk(address // self._word_size_bytes, - data[:first_chunk_size]) - address += (first_chunk_size // self._word_size_bytes) + yield Segment(address, + address + size, + data[:first_chunk_size], + self._word_size_bytes) + address += first_chunk_size data = data[first_chunk_size:] else: first_chunk_size = 0 for offset in range(0, len(data), size): - yield self.Chunk((address + offset) // self._word_size_bytes, - data[offset:offset + size]) + yield Segment(address + offset, + address + offset + size, + data[offset:offset + size], + self._word_size_bytes) def add_data(self, minimum_address, maximum_address, data, overwrite): """Add given data to this segment. The added data must be adjacent to From 7582b69b5d467e0f6c7b9a2356da659e97c4fddc Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Mon, 18 Sep 2023 21:39:52 +0200 Subject: [PATCH 2/5] Update docstrings referring to Chunk --- bincopy.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/bincopy.py b/bincopy.py index f945d14..48ac3bf 100755 --- a/bincopy.py +++ b/bincopy.py @@ -365,9 +365,8 @@ def address(self): def chunks(self, size=32, alignment=1): """Return chunks of the data aligned as given by `alignment`. `size` - must be a multiple of `alignment`. Each chunk is returned as a - named two-tuple of its address and data. Both `size` and - `alignment` are in words. + must be a multiple of `alignment`. Each chunk is itself a Segment. + Both `size` and `alignment` are in words. """ @@ -635,9 +634,8 @@ def remove(self, minimum_address, maximum_address): def chunks(self, size=32, alignment=1): """Iterate over all segments and return chunks of the data aligned as given by `alignment`. `size` must be a multiple of - `alignment`. Each chunk is returned as a named two-tuple of - its address and data. Both `size` and `alignment` are in - words. + `alignment`. Each chunk is in turn a smaller Segment. Both `size` and + `alignment` are in words. """ @@ -842,10 +840,10 @@ def segments(self): >>> for chunk in binfile.segments.chunks(2): ... print(chunk) ... - Chunk(address=0, data=bytearray(b'\\x00\\x01')) - Chunk(address=2, data=bytearray(b'\\x02')) - Chunk(address=10, data=bytearray(b'\\x03\\x04')) - Chunk(address=12, data=bytearray(b'\\x05')) + Segment(address=0, data=bytearray(b'\\x00\\x01')) + Segment(address=2, data=bytearray(b'\\x02')) + Segment(address=10, data=bytearray(b'\\x03\\x04')) + Segment(address=12, data=bytearray(b'\\x05')) Each segment can be split into smaller pieces using the `chunks(size=32, alignment=1)` method on a single segment. @@ -856,11 +854,11 @@ def segments(self): ... print(chunk) ... Segment(address=0, data=bytearray(b'\\x00\\x01\\x02')) - Chunk(address=0, data=bytearray(b'\\x00\\x01')) - Chunk(address=2, data=bytearray(b'\\x02')) + Segment(address=0, data=bytearray(b'\\x00\\x01')) + Segment(address=2, data=bytearray(b'\\x02')) Segment(address=10, data=bytearray(b'\\x03\\x04\\x05')) - Chunk(address=10, data=bytearray(b'\\x03\\x04')) - Chunk(address=12, data=bytearray(b'\\x05')) + Segment(address=10, data=bytearray(b'\\x03\\x04')) + Segment(address=12, data=bytearray(b'\\x05')) """ From 2c136438a172b431b74b1a9545fc11c803178947 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Wed, 20 Sep 2023 16:22:48 +0200 Subject: [PATCH 3/5] Remove _Chunk --- bincopy.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/bincopy.py b/bincopy.py index 48ac3bf..6318160 100755 --- a/bincopy.py +++ b/bincopy.py @@ -351,8 +351,6 @@ class Segment: """ - _Chunk = namedtuple("Chunk", ["address", "data"]) - def __init__(self, minimum_address, maximum_address, data, word_size_bytes): self.minimum_address = minimum_address self.maximum_address = maximum_address From 361578d9337ae4ed2f89e14332110005f9d77854 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Wed, 20 Sep 2023 16:23:21 +0200 Subject: [PATCH 4/5] Make Segment.word_size_bytes public --- bincopy.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bincopy.py b/bincopy.py index 6318160..223fdd8 100755 --- a/bincopy.py +++ b/bincopy.py @@ -355,11 +355,11 @@ def __init__(self, minimum_address, maximum_address, data, word_size_bytes): self.minimum_address = minimum_address self.maximum_address = maximum_address self.data = data - self._word_size_bytes = word_size_bytes + self.word_size_bytes = word_size_bytes @property def address(self): - return self.minimum_address // self._word_size_bytes + return self.minimum_address // self.word_size_bytes def chunks(self, size=32, alignment=1): """Return chunks of the data aligned as given by `alignment`. `size` @@ -371,8 +371,8 @@ def chunks(self, size=32, alignment=1): if (size % alignment) != 0: raise Error(f'size {size} is not a multiple of alignment {alignment}') - size *= self._word_size_bytes - alignment *= self._word_size_bytes + size *= self.word_size_bytes + alignment *= self.word_size_bytes address = self.minimum_address data = self.data @@ -384,7 +384,7 @@ def chunks(self, size=32, alignment=1): yield Segment(address, address + size, data[:first_chunk_size], - self._word_size_bytes) + self.word_size_bytes) address += first_chunk_size data = data[first_chunk_size:] else: @@ -394,7 +394,7 @@ def chunks(self, size=32, alignment=1): yield Segment(address + offset, address + offset + size, data[offset:offset + size], - self._word_size_bytes) + self.word_size_bytes) def add_data(self, minimum_address, maximum_address, data, overwrite): """Add given data to this segment. The added data must be adjacent to @@ -468,7 +468,7 @@ def remove_data(self, minimum_address, maximum_address): return Segment(maximum_address, maximum_address + len(part2_data), part2_data, - self._word_size_bytes) + self.word_size_bytes) else: # Update this segment. if len(part1_data) > 0: @@ -488,7 +488,7 @@ def __eq__(self, other): return ((self.minimum_address == other.minimum_address) and (self.maximum_address == other.maximum_address) and (self.data == other.data) - and (self._word_size_bytes == other._word_size_bytes)) + and (self.word_size_bytes == other.word_size_bytes)) else: return False @@ -510,7 +510,7 @@ class Segments: """ def __init__(self, word_size_bytes): - self._word_size_bytes = word_size_bytes + self.word_size_bytes = word_size_bytes self._current_segment = None self._current_segment_index = None self._list = [] From b96de41910a9f6c78b5f973a7cdd1380cbac15da Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Wed, 20 Sep 2023 16:37:00 +0200 Subject: [PATCH 5/5] Add Segment.__len__ --- bincopy.py | 3 +++ tests/test_bincopy.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/bincopy.py b/bincopy.py index 223fdd8..2ac967f 100755 --- a/bincopy.py +++ b/bincopy.py @@ -500,6 +500,9 @@ def __iter__(self): def __repr__(self): return f'Segment(address={self.address}, data={self.data})' + def __len__(self): + return len(self.data) // self.word_size_bytes + _Segment = Segment diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index 0df6241..fe183c4 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -1841,6 +1841,21 @@ def test_verilog_vmem(self): with open('tests/files/empty_main.bin', 'rb') as fin: self.assertEqual(binfile.as_binary(padding=b'\x00'), fin.read()) + def test_segment_len(self): + length = 0x100 + word_size_bytes = 1 + segment = bincopy.Segment(0, length, bytes(length), word_size_bytes) + self.assertAlmostEqual(length, len(segment)) + + def test_segment_len_16(self): + length = 0x100 + word_size_bytes = 2 + segment = bincopy.Segment(0, + length, + bytes(length * word_size_bytes), + word_size_bytes) + self.assertEqual(length, len(segment)) + if __name__ == '__main__': unittest.main()