From a4ef9ba4acc24313618106389da0678f93eb24ec Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 23 Oct 2020 14:26:47 +0000 Subject: [PATCH] tool: add 'to_bytespec' command; minor changes --- mmgen/exception.py | 2 ++ mmgen/tool.py | 8 ++++++++ mmgen/util.py | 51 ++++++++++++++++++++++++++++++++++------------ test/tooltest2.py | 30 +++++++++++++++++++++------ 4 files changed, 72 insertions(+), 19 deletions(-) diff --git a/mmgen/exception.py b/mmgen/exception.py index 83e8a2bf..a274df7b 100755 --- a/mmgen/exception.py +++ b/mmgen/exception.py @@ -34,6 +34,8 @@ class InvalidPasswdFormat(Exception): mmcode = 1 class CfgFileParseError(Exception): mmcode = 1 class UserOptError(Exception): mmcode = 1 class NoLEDSupport(Exception): mmcode = 1 +class NotAnInteger(Exception): mmcode = 1 +class IntegerOutOfRange(Exception): mmcode = 1 # 2: yellow hl, message only class InvalidTokenAddress(Exception): mmcode = 2 diff --git a/mmgen/tool.py b/mmgen/tool.py index 77831648..8bb305a3 100755 --- a/mmgen/tool.py +++ b/mmgen/tool.py @@ -310,6 +310,14 @@ class MMGenToolCmdUtil(MMGenToolCmds): "convert a byte specifier such as '1GB' into an integer" return parse_bytespec(dd_style_byte_specifier) + def to_bytespec(self, + n: int, + dd_style_byte_specifier: str, + fmt = '0.2', + print_sym = True ): + "convert an integer to a byte specifier such as '1GB'" + return int2bytespec(n,dd_style_byte_specifier,fmt,print_sym) + def randhex(self,nbytes='32'): "print 'n' bytes (default 32) of random data in hex format" return get_random(int(nbytes)).hex() diff --git a/mmgen/util.py b/mmgen/util.py index 1573b4ad..2aed8ccd 100755 --- a/mmgen/util.py +++ b/mmgen/util.py @@ -173,29 +173,44 @@ def set_for_type(val,refval,desc,invert_bool=False,src=None): # From 'man dd': # c=1, w=2, b=512, kB=1000, K=1024, MB=1000*1000, M=1024*1024, # GB=1000*1000*1000, G=1024*1024*1024, and so on for T, P, E, Z, Y. +bytespec_map = ( + ('c', 1), + ('w', 2), + ('b', 512), + ('kB', 1000), + ('K', 1024), + ('MB', 1000000), + ('M', 1048576), + ('GB', 1000000000), + ('G', 1073741824), + ('TB', 1000000000000), + ('T', 1099511627776), + ('PB', 1000000000000000), + ('P', 1125899906842624), + ('EB', 1000000000000000000), + ('E', 1152921504606846976), +) + +def int2bytespec(n,spec,fmt,print_sym=True): + def spec2int(spec): + for k,v in bytespec_map: + if k == spec: + return v + else: + die('{spec}: unrecognized bytespec') + return '{:{}f}{}'.format( n / spec2int(spec), fmt, spec if print_sym else '' ) def parse_bytespec(nbytes): - smap = (('c', 1), - ('w', 2), - ('b', 512), - ('kB', 1000), - ('K', 1024), - ('MB', 1000*1000), - ('M', 1024*1024), - ('GB', 1000*1000*1000), - ('G', 1024*1024*1024), - ('TB', 1000*1000*1000*1000), - ('T', 1024*1024*1024*1024)) import re m = re.match(r'([0123456789.]+)(.*)',nbytes) if m: if m.group(2): - for k,v in smap: + for k,v in bytespec_map: if k == m.group(2): from decimal import Decimal return int(Decimal(m.group(1)) * v) else: - msg("Valid byte specifiers: '{}'".format("' '".join([i[0] for i in smap]))) + msg("Valid byte specifiers: '{}'".format("' '".join([i[0] for i in bytespec_map]))) elif '.' in nbytes: raise ValueError('fractional bytes not allowed') else: @@ -347,6 +362,16 @@ def is_ascii(s,enc='ascii'): except: return False else: return True +def check_int_between(n,lo,hi,desc='value'): + import re + m = re.match(r'-{0,1}[0-9]+',str(n)) + if m == None: + raise NotAnInteger(f'{n}: {desc} must be an integer') + n = int(n) + if n < lo or n > hi: + raise IntegerOutOfRange(f'{n}: {desc} must be between {lo} and {hi}') + return n + def match_ext(addr,ext): return addr.split('.')[-1] == ext diff --git a/test/tooltest2.py b/test/tooltest2.py index 992b3329..0b07784a 100755 --- a/test/tooltest2.py +++ b/test/tooltest2.py @@ -277,13 +277,31 @@ tests = { ( ['111111115Q','pad=2'], 'ff' ), ], 'bytespec': [ - ( ['1G'], str(1024*1024*1024) ), - ( ['1234G'], str(1234*1024*1024*1024) ), - ( ['1GB'], str(1000*1000*1000) ), - ( ['1234GB'], str(1234*1000*1000*1000) ), - ( ['1.234MB'], str(1234*1000) ), + ( ['1G'], str(1024*1024*1024) ), + ( ['1GB'], str(1000*1000*1000) ), + ( ['1234GB'], str(1234*1000*1000*1000) ), + ( ['1234G'], str(1234*1024*1024*1024) ), + ( ['1234TB'], str(1234*1000*1000*1000*1000) ), + ( ['1234T'], str(1234*1024*1024*1024*1024) ), + ( ['1234PB'], str(1234*1000*1000*1000*1000*1000) ), + ( ['1234P'], str(1234*1024*1024*1024*1024*1024) ), + ( ['1234EB'], str(1234*1000*1000*1000*1000*1000*1000) ), + ( ['1234E'], str(1234*1024*1024*1024*1024*1024*1024) ), + ( ['1.234MB'], str(1234*1000) ), ( ['1.234567M'], str(int(Decimal('1.234567')*1024*1024)) ), - ( ['1234'], str(1234) ), + ( ['1234'], str(1234) ), + ], + 'to_bytespec': [ + ( [str(1024*1024*1024),'G'], '1.00G' ), + ( [str(1024*1024*1024),'G','fmt=0.0'], '1G' ), + ( [str(1024*1024*1024),'G','fmt=08.5'], '01.00000G' ), + ( [str(1234*1000*1000*1000),'GB'], '1234.00GB' ), + ( [str(1234*1024*1024*1024),'G'], '1234.00G', ), + ( [str(1000*1000*1000*1000*1000),'PB'], '1.00PB' ), + ( [str(1024*1024*1024*1024*1024),'P'], '1.00P' ), + ( [str(1024*1024*1024*1024*1024*1024),'E'], '1.00E' ), + ( [str(int(Decimal('1.234567')*1024*1024)),'M','fmt=0.6'], '1.234567M' ), + ( ['1234','c','fmt=0.0','print_sym=false'], '1234' ), ], 'hash160': [ # TODO: check that hextob58chk(hash160) = pubhex2addr ( ['deadbeef'], 'f04df4c4b30d2b7ac6e1ed2445aeb12a9cb4d2ec' ),