Hex dump: Difference between revisions

Content deleted Content added
PureFox (talk | contribs)
→‎{{header|Wren}}: Rewritten to cater for more bases.
Jgrprior (talk | contribs)
m →‎{{header|Python}}: Fix offset and final byte count when skipping bytes. Show example of using offset and length.
Line 571: Line 571:
import math
import math
from io import BufferedIOBase
from io import BufferedIOBase
from io import SEEK_END
from itertools import islice
from itertools import islice
from typing import Iterable
from typing import Iterable
Line 586: Line 587:


@abc.abstractmethod
@abc.abstractmethod
def __call__(self, data: Sequence[int]) -> str:
def format(self, data: Sequence[int]) -> str:
""""""
"""Return _data_ formatted for output on one line."""


@property
@property
@abc.abstractmethod
@abc.abstractmethod
def bytes_per_line(self) -> int:
def bytes_per_line(self) -> int:
""""""
"""The number of bytes to display per line of output."""




Line 598: Line 599:
bytes_per_line = 16
bytes_per_line = 16


def __call__(self, data: Sequence[int]) -> str:
def format(self, data: Sequence[int]) -> str:
assert len(data) <= 16
assert len(data) <= 16
hex = f"{bytes(data[:8]).hex(' ')} {bytes(data[8:]).hex(' ')}".ljust(48)
hex = f"{bytes(data[:8]).hex(' ')} {bytes(data[8:]).hex(' ')}".ljust(48)
Line 608: Line 609:
bytes_per_line = 6
bytes_per_line = 6


def __call__(self, data: Sequence[int]) -> str:
def format(self, data: Sequence[int]) -> str:
assert len(data) <= 6
assert len(data) <= 6
bits = " ".join(bin(b)[2:].rjust(8, "0") for b in data).ljust(53)
bits = " ".join(bin(b)[2:].rjust(8, "0") for b in data).ljust(53)
Line 639: Line 640:
skip: int = 0,
skip: int = 0,
length: int = math.inf, # type: ignore
length: int = math.inf, # type: ignore
format: Formatter = canonicalFormatter,
formatter: Formatter = canonicalFormatter,
) -> Iterator[str]:
) -> Iterator[str]:
"""Generate a textual representation of bytes in _f_, one line at a time."""
"""Generate a textual representation of bytes in _f_, one line at a time."""
f.seek(skip)
f.seek(skip)
offset = 0
offset = skip
byte_count = 0
byte_count = 0
previous_line = ""
previous_line = ""
squeezing = False # True if the last output line was squeezed
identical_chunk = False

assert length > 0


while byte_count < length:
while byte_count < length:
Line 661: Line 664:


# One line per chunk
# One line per chunk
for chunk in group(data, format.bytes_per_line):
for chunk in group(data, formatter.bytes_per_line):
line = format(chunk)
line = formatter.format(chunk)
if previous_line == line:
if previous_line == line:
if identical_chunk is False:
if squeezing is False:
identical_chunk = True
squeezing = True
yield "*"
yield "*"
else:
else:
previous_line = line
previous_line = line
identical_chunk = False
squeezing = False
yield f"{offset:0>8x} {line}"
yield f"{offset:0>8x} {line}"


offset += format.bytes_per_line
offset += formatter.bytes_per_line
byte_count += len(chunk)
byte_count += len(chunk)


# Final byte count
# Final byte count
bytes_in_f = f.seek(0, SEEK_END)
yield f"{byte_count:0>8x}"
yield f"{min(byte_count + skip, bytes_in_f):0>8x}"




Line 722: Line 726:
for line in hex_dump(
for line in hex_dump(
args.file,
args.file,
format=formatter,
formatter=formatter,
skip=args.skip,
skip=args.skip,
length=args.length,
length=args.length,
Line 740: Line 744:
00000060 20 00 3d d8 00 de 2e 00 | .=.....|
00000060 20 00 3d d8 00 de 2e 00 | .=.....|
00000068
00000068
</pre>
<pre>$ python hex_dump.py example_utf16.txt -s 20 -n 25</pre>
<pre>
00000014 6f 00 64 00 65 00 20 00 69 00 73 00 20 00 61 00 |o.d.e. .i.s. .a.|
00000024 20 00 70 00 72 00 6f 00 67 | .p.r.o.g|
0000002d
</pre>
</pre>
<pre>$ python hex_dump.py example_utf16.txt -b</pre>
<pre>$ python hex_dump.py example_utf16.txt -b</pre>