From d581eea31388a0fdb37b2cdadf68414fd8ca10ff Mon Sep 17 00:00:00 2001 From: Andrea Zoppi Date: Sat, 2 Mar 2024 15:21:25 +0100 Subject: [PATCH] Improved integer suffix Signed-off-by: Andrea Zoppi --- .../hexrec.hexdump.CHAR_PRINTABLE.rst | 6 +++ .../hexrec.hexdump.CHAR_TOKENS.rst | 6 +++ .../hexrec.hexdump.DEFAULT_FORMAT_ORDER.rst | 6 +++ docs/_autosummary/hexrec.hexdump.hexdump.rst | 6 +++ docs/_autosummary/hexrec.hexdump.rst | 49 +++++++++++++++++++ .../hexrec.utils.SUFFIX_SCALE.rst | 6 +++ docs/_autosummary/hexrec.utils.rst | 1 + docs/reference.rst | 1 + src/hexrec/cli.py | 22 ++++----- src/hexrec/hexdump.py | 5 +- src/hexrec/utils.py | 45 ++++++++++++++--- tests/test_utils.py | 13 ++++- 12 files changed, 143 insertions(+), 23 deletions(-) create mode 100644 docs/_autosummary/hexrec.hexdump.CHAR_PRINTABLE.rst create mode 100644 docs/_autosummary/hexrec.hexdump.CHAR_TOKENS.rst create mode 100644 docs/_autosummary/hexrec.hexdump.DEFAULT_FORMAT_ORDER.rst create mode 100644 docs/_autosummary/hexrec.hexdump.hexdump.rst create mode 100644 docs/_autosummary/hexrec.hexdump.rst create mode 100644 docs/_autosummary/hexrec.utils.SUFFIX_SCALE.rst diff --git a/docs/_autosummary/hexrec.hexdump.CHAR_PRINTABLE.rst b/docs/_autosummary/hexrec.hexdump.CHAR_PRINTABLE.rst new file mode 100644 index 0000000..2fd0209 --- /dev/null +++ b/docs/_autosummary/hexrec.hexdump.CHAR_PRINTABLE.rst @@ -0,0 +1,6 @@ +CHAR\_PRINTABLE +=============== + +.. currentmodule:: hexrec.hexdump + +.. autodata:: CHAR_PRINTABLE \ No newline at end of file diff --git a/docs/_autosummary/hexrec.hexdump.CHAR_TOKENS.rst b/docs/_autosummary/hexrec.hexdump.CHAR_TOKENS.rst new file mode 100644 index 0000000..acedecd --- /dev/null +++ b/docs/_autosummary/hexrec.hexdump.CHAR_TOKENS.rst @@ -0,0 +1,6 @@ +CHAR\_TOKENS +============ + +.. currentmodule:: hexrec.hexdump + +.. autodata:: CHAR_TOKENS \ No newline at end of file diff --git a/docs/_autosummary/hexrec.hexdump.DEFAULT_FORMAT_ORDER.rst b/docs/_autosummary/hexrec.hexdump.DEFAULT_FORMAT_ORDER.rst new file mode 100644 index 0000000..7ee9d58 --- /dev/null +++ b/docs/_autosummary/hexrec.hexdump.DEFAULT_FORMAT_ORDER.rst @@ -0,0 +1,6 @@ +DEFAULT\_FORMAT\_ORDER +====================== + +.. currentmodule:: hexrec.hexdump + +.. autodata:: DEFAULT_FORMAT_ORDER \ No newline at end of file diff --git a/docs/_autosummary/hexrec.hexdump.hexdump.rst b/docs/_autosummary/hexrec.hexdump.hexdump.rst new file mode 100644 index 0000000..34107b3 --- /dev/null +++ b/docs/_autosummary/hexrec.hexdump.hexdump.rst @@ -0,0 +1,6 @@ +hexdump +======= + +.. currentmodule:: hexrec.hexdump + +.. autofunction:: hexdump \ No newline at end of file diff --git a/docs/_autosummary/hexrec.hexdump.rst b/docs/_autosummary/hexrec.hexdump.rst new file mode 100644 index 0000000..5568a50 --- /dev/null +++ b/docs/_autosummary/hexrec.hexdump.rst @@ -0,0 +1,49 @@ +hexdump +======= + +.. automodule:: hexrec.hexdump + + + + + .. rubric:: Attributes + + .. autosummary:: + :toctree: + :template: custom-base-template.rst + :nosignatures: + + ~CHAR_PRINTABLE + ~CHAR_TOKENS + ~DEFAULT_FORMAT_ORDER + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :template: custom-base-template.rst + :nosignatures: + + ~hexdump + + + + + + + + + + + + + + + + + diff --git a/docs/_autosummary/hexrec.utils.SUFFIX_SCALE.rst b/docs/_autosummary/hexrec.utils.SUFFIX_SCALE.rst new file mode 100644 index 0000000..13a5526 --- /dev/null +++ b/docs/_autosummary/hexrec.utils.SUFFIX_SCALE.rst @@ -0,0 +1,6 @@ +SUFFIX\_SCALE +============= + +.. currentmodule:: hexrec.utils + +.. autodata:: SUFFIX_SCALE \ No newline at end of file diff --git a/docs/_autosummary/hexrec.utils.rst b/docs/_autosummary/hexrec.utils.rst index fed9d59..9dd90b0 100644 --- a/docs/_autosummary/hexrec.utils.rst +++ b/docs/_autosummary/hexrec.utils.rst @@ -13,6 +13,7 @@ :template: custom-base-template.rst :nosignatures: + ~SUFFIX_SCALE ~DEFAULT_DELETE diff --git a/docs/reference.rst b/docs/reference.rst index 1c71b92..175bb4f 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -15,5 +15,6 @@ Reference hexrec.formats.srec hexrec.formats.titxt hexrec.formats.xtek + hexrec.hexdump hexrec.utils hexrec.xxd diff --git a/src/hexrec/cli.py b/src/hexrec/cli.py index b84137e..e3fab08 100644 --- a/src/hexrec/cli.py +++ b/src/hexrec/cli.py @@ -660,10 +660,10 @@ def flood( """) @click.option('-n', '--length', 'length', type=BASED_INT, help=""" Interpret only length bytes of input. -""") # FIXME: SUFFIXED_INT for hexdump compatible integers +""") @click.option('-s', '--skip', 'skip', type=BASED_INT, help=""" Skip offset bytes from the beginning of the input. -""") # FIXME: SUFFIXED_INT for hexdump compatible integers +""") @click.option('-v', '--no_squeezing', 'no_squeezing', is_flag=True, help=""" The -v option causes hexdump to display all input data. Without the -v option, any number of groups of output lines @@ -678,8 +678,8 @@ def flood( Forces the input file format. Required for the standard input. """) -@click.option('-V', '--version', is_flag=True, is_eager=True, expose_value=False, - callback=print_hexdump_version, help=""" +@click.option('-V', '--version', is_flag=True, is_eager=True, + expose_value=False, callback=print_hexdump_version, help=""" Print version and exit. """) @click.argument('infile', type=FILE_PATH_IN) @@ -698,7 +698,6 @@ def hexdump( upper: bool, input_format: Optional[str], # TODO: ) -> None: - # TODO: __doc__ r"""Display file contents in hexadecimal, decimal, octal, or ascii. The hexdump utility is a filter which displays the specified @@ -788,10 +787,10 @@ def hexdump( """) @click.option('-n', '--length', 'length', type=BASED_INT, help=""" Interpret only length bytes of input. -""") # FIXME: SUFFIXED_INT for hexdump compatible integers +""") @click.option('-s', '--skip', 'skip', type=BASED_INT, help=""" Skip offset bytes from the beginning of the input. -""") # FIXME: SUFFIXED_INT for hexdump compatible integers +""") @click.option('-v', '--no_squeezing', 'no_squeezing', is_flag=True, help=""" The -v option causes hexdump to display all input data. Without the -v option, any number of groups of output lines @@ -806,8 +805,8 @@ def hexdump( Forces the input file format. Required for the standard input. """) -@click.option('-V', '--version', is_flag=True, is_eager=True, expose_value=False, - callback=print_hexdump_version, help=""" +@click.option('-V', '--version', is_flag=True, is_eager=True, + expose_value=False, callback=print_hexdump_version, help=""" Print version and exit. """) @click.argument('infile', type=FILE_PATH_IN) @@ -825,7 +824,6 @@ def hd( upper: bool, input_format: Optional[str], # TODO: ) -> None: - # TODO: __doc__ r"""Display file contents in hexadecimal, decimal, octal, or ascii. The hexdump utility is a filter which displays the specified @@ -1199,8 +1197,8 @@ def del_header( @click.option('-u', '--upper', 'upper', is_flag=True, help=""" Uses upper case hex letters on data only. """) -@click.option('-v', '--version', is_flag=True, is_eager=True, expose_value=False, - callback=print_version, help=""" +@click.option('-v', '--version', is_flag=True, is_eager=True, + expose_value=False, callback=print_version, help=""" Prints the package version number. """) @click.argument('infile', type=FILE_PATH_IN) diff --git a/src/hexrec/hexdump.py b/src/hexrec/hexdump.py index 6ad09bb..15e77eb 100644 --- a/src/hexrec/hexdump.py +++ b/src/hexrec/hexdump.py @@ -523,13 +523,14 @@ def hexdump( offset = 0 last_chunk = None squeezing = False + read = instream.read write = outstream.write while True: if length is None: - chunk = instream.read(width) + chunk = read(width) else: - chunk = instream.read(min(width, length - offset)) + chunk = read(min(width, length - offset)) if not chunk: break diff --git a/src/hexrec/utils.py b/src/hexrec/utils.py index a6c25a0..2d25366 100644 --- a/src/hexrec/utils.py +++ b/src/hexrec/utils.py @@ -44,11 +44,45 @@ BIN8_TO_BYTES: List[bytes] = [bin(i)[2:].zfill(8).encode() for i in range(256)] BYTES_TO_BIN8: Mapping[bytes, int] = {s: i for i, s in enumerate(BIN8_TO_BYTES)} +SUFFIX_SCALE: Mapping[str, int] = { + 'k': 2**10, + 'm': 2**20, + 'g': 2**30, + 't': 2**40, + 'p': 2**50, + 'e': 2**60, + 'z': 2**70, + 'y': 2**80, + + 'kib': 2**10, + 'mib': 2**20, + 'gib': 2**30, + 'tib': 2**40, + 'pib': 2**50, + 'eib': 2**60, + 'zib': 2**70, + 'yib': 2**80, + + 'kb': 10**3, + 'mb': 10**6, + 'gb': 10**9, + 'tb': 10**12, + 'pb': 10**15, + 'eb': 10**18, + 'zb': 10**21, + 'yb': 10**24, +} +r"""Integer suffix to scale factor.""" + INT_REGEX = re.compile(r'^\s*(?P[+-]?)\s*' r'(?P(0x|0b|0o|0)?)' r'(?P[a-f0-9]+)' r'(?Ph?)' - r'(?P[km]?)\s*$') + r'\s*(?P(' + r'k|m|g|t|p|e|z|y|' + r'kib|mib|gib|tib|pib|eib|zib|yib|' + r'kb|mb|gb|tb|pb|eb|zb|yb' + r')?)\s*$') DEFAULT_DELETE: bytes = b' \t.-:\r\n' r"""Delete from hex strings. @@ -167,8 +201,8 @@ def parse_int( either prefixed with ``0x`` or postfixed with ``h`` to convert from a hexadecimal representation, or prefixed with ``0b`` from binary; a prefix of only ``0`` converts from octal. - A further suffix of ``k`` or ``m`` scales as *kibibyte* or - *mebibyte*. + A further suffix applies a scale factor as per + :data:`SUFFIX_SCALE`. A ``None`` value evaluates as ``None``. Any other object class will call the standard :func:`int`. @@ -214,10 +248,7 @@ def parse_int( else: i = int(value, 10) - if scale == 'k': - i <<= 10 - elif scale == 'm': - i <<= 20 + i *= SUFFIX_SCALE.get((scale or '').lower(), 1) if sign == '-': i = -i diff --git a/tests/test_utils.py b/tests/test_utils.py index b794157..6568689 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -31,8 +31,17 @@ '0o1234567': 0o1234567, '0O1234567': 0o1234567, - '1k': 1 << 10, - '1m': 1 << 20, + '1k': 2**10, + '1M': 2**20, + '1 G': 2**30, + + '1KiB': 2**10, + '1 mib': 2**20, + '1GiB': 2**30, + + '1 KB': 10**3, + '1MB': 10**6, + '1gb': 10**9, b'456': 456, 123: 123,