tool: add 'to_bytespec' command; minor changes

This commit is contained in:
The MMGen Project 2020-10-23 14:26:47 +00:00
commit a4ef9ba4ac
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
4 changed files with 72 additions and 19 deletions

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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' ),