core: fixes and optims
This commit is contained in:
parent
7d2c017bc2
commit
73786a090d
|
@ -61,14 +61,13 @@ class Buf(Atom):
|
|||
raise(EltErr('{0} [_chk_val]: val type is {1}, expecting {2}'\
|
||||
.format(self._name, type(val).__name__, self.TYPENAMES)))
|
||||
elif val is not None and self._bl is not None and self._blauto is None:
|
||||
bytelen, bitlen = self._bl>>3, self._bl%8
|
||||
bytelen = self._bl>>3
|
||||
if self._bl%8:
|
||||
bytelen += 1
|
||||
if len(val) < bytelen:
|
||||
raise(EltErr('{0} [_chk_val]: val length underflow, {1} bytes instead of {2}'\
|
||||
.format(self._name, len(val), bytelen)))
|
||||
elif bitlen and len(val) > 1+bytelen:
|
||||
raise(EltErr('{0} [_chk_val]: val length overflow, {1} bytes instead {2} plus {3} bits'\
|
||||
.format(self._name, len(val), bytelen, bitlen)))
|
||||
elif bitlen == 0 and len(val) > bytelen:
|
||||
elif len(val) > bytelen:
|
||||
raise(EltErr('{0} [_chk_val]: val length overflow, {1} bytes instead of {2}'\
|
||||
.format(self._name, len(val), bytelen)))
|
||||
|
||||
|
|
|
@ -121,15 +121,11 @@ class Charpy(object):
|
|||
Returns:
|
||||
bit_str (str): string of 0 and 1
|
||||
"""
|
||||
if self.len_bit() == 0:
|
||||
bitlen = self.len_bit()
|
||||
if bitlen == 0:
|
||||
return ''
|
||||
b = bin(self.to_uint())[2:]
|
||||
# pad with heading zero
|
||||
bitlen = self._len_bit - self._cur
|
||||
if len(b) < bitlen:
|
||||
return (bitlen-len(b))*'0' + b
|
||||
else:
|
||||
return b
|
||||
return uint_to_bitstr(self.to_uint(), bitlen)
|
||||
|
||||
def hex(self):
|
||||
"""Provide an hexadecimal representation of the remaining buffer
|
||||
|
@ -137,29 +133,13 @@ class Charpy(object):
|
|||
Returns:
|
||||
hex_str (str): string of hex character
|
||||
"""
|
||||
if self.len_bit() == 0:
|
||||
bitlen = self.len_bit()
|
||||
if bitlen == 0:
|
||||
return ''
|
||||
uint = self.to_uint()
|
||||
bitlen = self._len_bit - self._cur
|
||||
h = hex(uint)[2:]
|
||||
if h[-1] == 'L':
|
||||
h = h[:-1]
|
||||
dyn = 4*len(h)
|
||||
shift = (bitlen-dyn) % 4
|
||||
if shift:
|
||||
h = hex(uint << (4-shift))[2:]
|
||||
if h[-1] == 'L':
|
||||
h = h[:-1]
|
||||
#
|
||||
niblen = bitlen // 4
|
||||
if bitlen % 4:
|
||||
niblen += 1
|
||||
if len(h) < niblen:
|
||||
return (niblen-len(h))*'0' + h
|
||||
else:
|
||||
return h
|
||||
return uint_to_hex(self.to_uint(), bitlen)
|
||||
|
||||
# _REPR_POS = ('buf', 'bytelist', 'bitlist', 'uint', 'int', 'hex', 'bin')
|
||||
# _REPR_POS = ('buf', 'bytelist', 'bitlist', 'uint', 'int', 'hex', 'bin')
|
||||
def repr(self):
|
||||
"""Provide a printable representation of the remaining buffer
|
||||
|
||||
|
@ -250,15 +230,13 @@ class Charpy(object):
|
|||
def forward(self, bitlen=None):
|
||||
"""Set the charpy instance's cursor foward for the given bit length
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bitlen : None or unsigned integer
|
||||
if None, set the cursor at the end of the charpy instance
|
||||
else, set the cursor forward for the given number of bits
|
||||
Args:
|
||||
bitlen : None or unsigned integer
|
||||
if None, set the cursor at the end of the charpy instance
|
||||
else, set the cursor forward for the given number of bits
|
||||
|
||||
Returns
|
||||
-------
|
||||
None
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
if self._concat: self._pack()
|
||||
if bitlen is None or bitlen > (self._len_bit - self._cur):
|
||||
|
|
|
@ -628,7 +628,7 @@ class Element(object):
|
|||
|
||||
Returns:
|
||||
uint (int) : unsigned integer
|
||||
""".format(self.__class__.__name__)
|
||||
"""
|
||||
return bytes_to_uint(self.to_bytes(), self.get_bl())
|
||||
|
||||
def from_int(self, integ, bl=None):
|
||||
|
@ -667,9 +667,7 @@ class Element(object):
|
|||
Returns:
|
||||
integ (int) : signed integer
|
||||
"""
|
||||
char = Charpy()
|
||||
char.set_bytes(self.to_bytes(), self.get_bl())
|
||||
return char.to_int()
|
||||
return bytes_to_int(self.to_bytes(), self.get_bl())
|
||||
|
||||
if python_version < 3:
|
||||
__str__ = to_bytes
|
||||
|
@ -679,18 +677,24 @@ class Element(object):
|
|||
#--------------------------------------------------------------------------#
|
||||
# representation routines
|
||||
#--------------------------------------------------------------------------#
|
||||
# TODO: bin() and hex() must be optimized
|
||||
# creating a Charpy() instance here is overkill
|
||||
|
||||
def bin(self):
|
||||
char = Charpy()
|
||||
char.set_bytes(self.to_bytes(), self.get_bl())
|
||||
return char.bin()
|
||||
bl = self.get_bl()
|
||||
if bl == 0:
|
||||
return ''
|
||||
else:
|
||||
bs = bytes_to_bitstr(self.to_bytes())
|
||||
if len(bs) > bl:
|
||||
return bs[:bl]
|
||||
else:
|
||||
return bs
|
||||
|
||||
def hex(self):
|
||||
char = Charpy()
|
||||
char.set_bytes(self.to_bytes(), self.get_bl())
|
||||
return char.hex()
|
||||
bl = self.get_bl()
|
||||
if bl == 0:
|
||||
return ''
|
||||
else:
|
||||
return uint_to_hex(bytes_to_uint(self.to_bytes(), bl), bl)
|
||||
|
||||
__bin__ = bin
|
||||
__hex__ = hex
|
||||
|
@ -1304,7 +1308,7 @@ class Atom(Element):
|
|||
else:
|
||||
desc = ''
|
||||
# type of representation to be used
|
||||
val = self.get_val()
|
||||
val = self()
|
||||
if self._rep in (REPR_RAW, REPR_HUM):
|
||||
val_repr = repr(val)
|
||||
elif self._rep == REPR_BIN:
|
||||
|
@ -1488,11 +1492,7 @@ class Envelope(Element):
|
|||
if 'content' in kw:
|
||||
#self._log('Envelope.__init__(content):', kw['content'])
|
||||
for i in kw['content']:
|
||||
try:
|
||||
self.__getitem__(i).set_attr(**kw['content'][i])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__init__] content error for {1}: {2}'\
|
||||
.format(self._name, i, err)))
|
||||
self.__getitem__(i).set_attr(**kw['content'][i])
|
||||
|
||||
# if a val dict is passed as argument
|
||||
# broadcast it to given content items
|
||||
|
@ -1540,20 +1540,11 @@ class Envelope(Element):
|
|||
elif isinstance(vals, (tuple, list)):
|
||||
ind = 0
|
||||
for elt in self.__iter__():
|
||||
try:
|
||||
elt.set_val(vals[ind])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_val] index {1!r}: {2}'\
|
||||
.format(self._name, ind, err)))
|
||||
else:
|
||||
ind += 1
|
||||
elt.set_val(vals[ind])
|
||||
ind += 1
|
||||
elif isinstance(vals, dict):
|
||||
for key, val in vals.items():
|
||||
try:
|
||||
self.__setitem__(key, val)
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_val] index {1!r}: {2}'\
|
||||
.format(self._name, key, err)))
|
||||
self.__setitem__(key, val)
|
||||
elif self._SAFE_STAT:
|
||||
raise(EltErr('{0} [set_val]: vals type is {1}, expecting None, tuple, list or dict'\
|
||||
.format(self._name, type(vals).__name__)))
|
||||
|
@ -1570,10 +1561,7 @@ class Envelope(Element):
|
|||
Raises:
|
||||
EltErr : if one element within the content raises
|
||||
"""
|
||||
try:
|
||||
return [elt.get_val() for elt in self.__iter__()]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [get_val]: {1}'.format(self._name, err)))
|
||||
return [elt() for elt in self.__iter__()]
|
||||
|
||||
def set_bl(self, bl):
|
||||
"""Set the raw bit length to the given elements of the content of self
|
||||
|
@ -1594,20 +1582,11 @@ class Envelope(Element):
|
|||
if isinstance(bl, (tuple, list)):
|
||||
ind = 0
|
||||
for elt in self.__iter__():
|
||||
try:
|
||||
elt.set_bl(bl[ind])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_bl] index {1!r}: {2}'\
|
||||
.format(self._name, ind, err)))
|
||||
else:
|
||||
ind += 1
|
||||
elt.set_bl(bl[ind])
|
||||
ind += 1
|
||||
elif isinstance(bl, dict):
|
||||
for key, val in bl.items():
|
||||
try:
|
||||
self.__getitem__(key).set_bl(val)
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_bl] index {1!r}: {2}'\
|
||||
.format(self._name, key, err)))
|
||||
self.__getitem__(key).set_bl(val)
|
||||
elif self._SAFE_STAT:
|
||||
raise(EltErr('{0} [set_bl]: bl type is {1}, expecting tuple, list '\
|
||||
'or dict'.format(self._name, type(bl).__name__)))
|
||||
|
@ -1627,10 +1606,7 @@ class Envelope(Element):
|
|||
if self.get_trans():
|
||||
return 0
|
||||
else:
|
||||
try:
|
||||
return sum([elt.get_bl() for elt in self.__iter__()])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [get_bl]: {1}'.format(self._name, err)))
|
||||
return sum([elt.get_bl() for elt in self.__iter__()])
|
||||
|
||||
def reautomate(self):
|
||||
"""Reset all attributes of the elements which have an automation within
|
||||
|
@ -1670,12 +1646,7 @@ class Envelope(Element):
|
|||
# especially if these are int / uint on 8, 16, 32, 64 bits
|
||||
if not self.get_trans():
|
||||
for elt in self.__iter__():
|
||||
try:
|
||||
elt._from_char(char)
|
||||
except CharpyErr as err:
|
||||
raise(CharpyErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
||||
elt._from_char(char)
|
||||
|
||||
#--------------------------------------------------------------------------#
|
||||
# copy / cloning routines
|
||||
|
@ -1740,11 +1711,7 @@ class Envelope(Element):
|
|||
#
|
||||
if 'content' in kw:
|
||||
for name, attrs in kw['content'].items():
|
||||
try:
|
||||
self.__getitem__(name).set_attrs(**attrs)
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_attrs] content item {1!r}: {2}'\
|
||||
.format(self._name, name, err)))
|
||||
self.__getitem__(name).set_attrs(**attrs)
|
||||
if 'bl' in kw:
|
||||
self.set_bl(kw['bl'])
|
||||
if 'val' in kw:
|
||||
|
@ -2114,7 +2081,7 @@ class Envelope(Element):
|
|||
class Array(Element):
|
||||
"""
|
||||
Class for arrays: special element which acts as a container for a list of
|
||||
values for a given inmutable element (atom, envelope, array, sequence)
|
||||
values for a given immutable element (atom, envelope, array, sequence)
|
||||
|
||||
class attribute:
|
||||
- GEN: element which is used to build the array template at initialization
|
||||
|
@ -2170,6 +2137,7 @@ class Array(Element):
|
|||
'_tmpl',
|
||||
'_tmpl_val',
|
||||
'_tmpl_bl',
|
||||
'_tmpl_pack',
|
||||
'_val',
|
||||
'_it',
|
||||
'_it_saved')
|
||||
|
@ -2253,8 +2221,9 @@ class Array(Element):
|
|||
.format(self._name, err)))
|
||||
|
||||
# set default value, and values container
|
||||
self._tmpl_val = self._tmpl.get_val()
|
||||
self._tmpl_bl = self._tmpl.get_bl()
|
||||
self._tmpl_val = self._tmpl()
|
||||
self._tmpl_bl = self._tmpl.get_bl()
|
||||
self._tmpl_pack = self._tmpl._to_pack()
|
||||
self._val = []
|
||||
|
||||
# array number of content
|
||||
|
@ -2291,51 +2260,39 @@ class Array(Element):
|
|||
self._val = []
|
||||
#
|
||||
elif isinstance(vals, dict):
|
||||
max_ind = max(vals.keys())
|
||||
if self._SAFE_STAT:
|
||||
# ensure the val dict indexes are valid
|
||||
if not all([isinstance(k, integer_types) for k in vals]):
|
||||
raise(EltErr('{0} [set_val] vals keys are not all integers'\
|
||||
.format(self._name)))
|
||||
# ensure all provided values fit in the template
|
||||
try:
|
||||
[self._tmpl.set_val(v) for v in vals.values() if v != self._tmpl_val]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_val] invalid value for the template: {1}'\
|
||||
.format(self._name, err)))
|
||||
else:
|
||||
self._tmpl.set_val(None)
|
||||
# get the maximum index from the dict and ensure it does not overflow
|
||||
# a fixed number of iteration
|
||||
max_ind = max(vals.keys())
|
||||
if self._SAFE_STAT and self._num is not None and max_ind >= self._num:
|
||||
raise(EltErr('{0} [set_val] vals index {1} overflow (max {2})'\
|
||||
.format(self._name, max_ind, self._num)))
|
||||
# in case the current value self._val does not goes up to the max
|
||||
# val dict index, just extend it with the default value
|
||||
# ensure the max index does not overflow a fixed max size
|
||||
if self._num is not None and max_ind >= self._num:
|
||||
raise(EltErr('{0} [set_val] vals index {1} overflow (max {2})'\
|
||||
.format(self._name, max_ind, self._num)))
|
||||
#
|
||||
# in case the current value self._val does not go up to the max index
|
||||
# just extend it with the default value
|
||||
if len(self._val) <= max_ind:
|
||||
self._val.extend( (1+max_ind-len(self._val)) * (self._tmpl_val, ) )
|
||||
# set the given values at given indexes after ensuring they fit in
|
||||
# the template
|
||||
for i, v in vals.items():
|
||||
self._val[i] = v
|
||||
self._tmpl.set_val(v)
|
||||
self._val[i] = self._tmpl()
|
||||
# reset the template's value
|
||||
self._tmpl.set_val(None)
|
||||
#
|
||||
elif isinstance(vals, (tuple, list)):
|
||||
# ensure the val list is valid
|
||||
if self._SAFE_STAT:
|
||||
# ensure all provided values fit in the template
|
||||
try:
|
||||
[self._tmpl.set_val(v) for v in vals if v != self._tmpl_val]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_val] invalid value for the template: {1}'\
|
||||
.format(self._name, err)))
|
||||
else:
|
||||
self._tmpl.set_val(None)
|
||||
if self._SAFE_STAT and self._num is not None and len(vals) != self._num:
|
||||
# ensure vals length does not overflow a fixed number of iteration
|
||||
if self._num is not None and len(vals) > self._num:
|
||||
raise(EltErr('{0} [set_val] vals length {1} overflow (max {2})'\
|
||||
.format(self._name, len(vals), self._num)))
|
||||
# set the list of values while ensuring they fit in the template
|
||||
self._val = vals
|
||||
raise(EltErr('{0} [set_val] invalid number of values: {1} instead of {2}'\
|
||||
.format(self._name, len(vals), self._num)))
|
||||
#
|
||||
self._val = []
|
||||
for v in vals:
|
||||
self._tmpl.set_val(v)
|
||||
self._val.append(self._tmpl())
|
||||
# reset the template's value
|
||||
self._tmpl.set_val(None)
|
||||
#
|
||||
else:
|
||||
raise(EltErr('{0} [set_val]: vals type is {1}, expecting None, tuple, list or dict'\
|
||||
|
@ -2442,13 +2399,15 @@ class Array(Element):
|
|||
if self.get_trans():
|
||||
return 0
|
||||
else:
|
||||
try:
|
||||
return sum([self._tmpl.get_bl()
|
||||
if (v != self._tmpl_val and self._tmpl.set_val(v) is None) \
|
||||
else self._tmpl_bl \
|
||||
for v in self._val])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [get_bl]: {1}'.format(self._name, err)))
|
||||
ret = []
|
||||
for v in self._val:
|
||||
if v == self._tmpl_val:
|
||||
ret.append(self._tmpl_bl)
|
||||
else:
|
||||
self._tmpl.set_val(v)
|
||||
ret.append(self._tmpl.get_bl())
|
||||
self._tmpl.set_val(None)
|
||||
return sum(ret)
|
||||
|
||||
def reautomate(self):
|
||||
"""Reset all attributes of self and its template which have an automation
|
||||
|
@ -2478,8 +2437,12 @@ class Array(Element):
|
|||
raise(EltErr('{0} [_to_pack] invalid number of values: {1} instead of {2}'\
|
||||
.format(self._name, len(self._val), self._num)))
|
||||
pl = []
|
||||
[pl.extend(self._tmpl._to_pack()) for v in self._val \
|
||||
if self._tmpl.set_val(v) is None ]
|
||||
for v in self._val:
|
||||
if v == self._tmpl_val:
|
||||
pl.extend(self._tmpl_pack)
|
||||
else:
|
||||
self._tmpl.set_val(v)
|
||||
pl.extend(self._tmpl._to_pack())
|
||||
self._tmpl.set_val(None)
|
||||
return pl
|
||||
else:
|
||||
|
@ -2507,14 +2470,9 @@ class Array(Element):
|
|||
self._val = []
|
||||
# 3) consume char and fill in self._val
|
||||
if num is not None:
|
||||
try:
|
||||
[self._val.append(self._tmpl.get_val()) for i in range(num) \
|
||||
if self._tmpl._from_char(char) is None]
|
||||
except CharpyErr as err:
|
||||
raise(CharpyErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
||||
self._tmpl.set_val(None)
|
||||
for i in range(num):
|
||||
self._tmpl._from_char(char)
|
||||
self._val.append(self._tmpl())
|
||||
else:
|
||||
# there is no predefined limit in the number of iteration
|
||||
# consume the charpy instance until its empty and raises
|
||||
|
@ -2526,11 +2484,9 @@ class Array(Element):
|
|||
except CharpyErr as err:
|
||||
char._cur = cur
|
||||
break
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
||||
else:
|
||||
self._val.append(self._tmpl.get_val())
|
||||
self._tmpl.set_val(None)
|
||||
self._val.append(self._tmpl())
|
||||
self._tmpl.set_val(None)
|
||||
|
||||
#--------------------------------------------------------------------------#
|
||||
# copy / cloning routines
|
||||
|
@ -2601,13 +2557,10 @@ class Array(Element):
|
|||
self._chk_trans()
|
||||
#
|
||||
if 'tmpl' in kw:
|
||||
try:
|
||||
self._tmpl.set_attrs(**kw['tmpl'])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_attrs] invalid tmpl: {1}'.format(self._name, err)))
|
||||
else:
|
||||
self._tmpl_val = self._tmpl.get_val()
|
||||
self._tmpl_bl = self._tmpl.get_bl()
|
||||
self._tmpl.set_attrs(**kw['tmpl'])
|
||||
self._tmpl_val = self._tmpl()
|
||||
self._tmpl_bl = self._tmpl.get_bl()
|
||||
self._tmpl_pack = self._tmpl._to_pack()
|
||||
#
|
||||
if 'val' in kw:
|
||||
self.set_val(kw['val'])
|
||||
|
@ -2658,17 +2611,15 @@ class Array(Element):
|
|||
if self._num is not None and len(self._val) == self._num:
|
||||
raise(EltErr('{0} [append] val length {1} overflow (num {2})'\
|
||||
.format(self._name, 1+len(self._val), self._num)))
|
||||
# ensure the new value fits into the template
|
||||
if val != self._tmpl_val:
|
||||
try:
|
||||
self._tmpl.set_val(val)
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [append] invalid value: {2}'.format(self._name, err)))
|
||||
else:
|
||||
self._tmpl.set_val(None)
|
||||
#
|
||||
self._val.append(val)
|
||||
# use the template to format the value
|
||||
if val != self._tmpl_val:
|
||||
self._tmpl.set_val(val)
|
||||
self._val.append(self._tmpl())
|
||||
self._tmpl.set_val(None)
|
||||
else:
|
||||
self._val.append(val)
|
||||
|
||||
# here, .count() is the number of iteration in the array
|
||||
count = get_num
|
||||
|
||||
def extend(self, vals):
|
||||
|
@ -2687,15 +2638,14 @@ class Array(Element):
|
|||
if self._num is not None and len(vals) > (self._num-len(self._val)):
|
||||
raise(EltErr('{0} [extend]: val length {1} overflow (num {2})'\
|
||||
.format(self._name, len(self._val)+len(vals), self._num)))
|
||||
# ensure the new values fit into the template
|
||||
try:
|
||||
[self._tmpl.set_val(v) for v in vals if v != self._tmpl_val]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [extend] invalid value(s): {1}'.format(self._name, err)))
|
||||
# use the template to format the values
|
||||
for val in vals:
|
||||
if val != self._tmpl_val:
|
||||
self._tmpl.set_val(val)
|
||||
self._val.append(self._tmpl())
|
||||
else:
|
||||
self._tmpl.set_val(None)
|
||||
#
|
||||
self._val.extend(vals)
|
||||
self._val.append(val)
|
||||
self._tmpl.set_val(None)
|
||||
|
||||
def index(self, val):
|
||||
"""Provide the index of the first iteration of value `val' within the
|
||||
|
@ -2732,14 +2682,11 @@ class Array(Element):
|
|||
if self._num is not None and len(self._val) == self._num:
|
||||
raise(EltErr('{0} [insert] val length {1} overflow (num {2})'\
|
||||
.format(self._name, 1+len(self._val), self._num)))
|
||||
if val != self._tmpl_val:
|
||||
try:
|
||||
self._tmpl.set_val(val)
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [insert] invalid value: {1}'\
|
||||
.format(self._name, err)))
|
||||
else:
|
||||
self._tmpl.set_val(None)
|
||||
# use the template to format the value
|
||||
if val != self._tmpl_val:
|
||||
self._tmpl.set_val(val)
|
||||
val = self._tmpl()
|
||||
self._tmpl.set_val(None)
|
||||
try:
|
||||
self._val.insert(index, val)
|
||||
except Exception as err:
|
||||
|
@ -2803,15 +2750,11 @@ class Array(Element):
|
|||
ind = self._val.index(old)
|
||||
except:
|
||||
raise(EltErr('{0} [replace] invalid old: {1}'.format(self._name, err)))
|
||||
if self._SAFE_STAT:
|
||||
# ensure the new value fits into the template
|
||||
if new != self._tmpl_val:
|
||||
try:
|
||||
self._tmpl.set_val(new)
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [replace] invalid value: {2}'.format(self._name, err)))
|
||||
else:
|
||||
self._tmpl.set_val(None)
|
||||
# use the template to format the value
|
||||
if new != self._tmpl_val:
|
||||
self._tmpl.set_val(new)
|
||||
new = self._tmpl()
|
||||
self._tmpl.set_val(None)
|
||||
del self._val[ind]
|
||||
self._val.insert(ind, new)
|
||||
|
||||
|
@ -2819,7 +2762,7 @@ class Array(Element):
|
|||
self._it_saved.append(self._it)
|
||||
self._it = 0
|
||||
return self
|
||||
|
||||
|
||||
def __next__(self):
|
||||
if self._it >= len(self._val) or self._tmpl.get_trans():
|
||||
if self._it_saved:
|
||||
|
@ -2839,51 +2782,44 @@ class Array(Element):
|
|||
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, integer_types):
|
||||
try:
|
||||
val = self._val[key]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__getitem__] int item: {1}'\
|
||||
.format(self._name, err)))
|
||||
clone = self._tmpl.clone()
|
||||
try:
|
||||
clone._val = self._val[key]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__getitem__] int item: {1}'.format(self._name, err)))
|
||||
else:
|
||||
return clone
|
||||
clone.set_val(val)
|
||||
return clone
|
||||
elif isinstance(key, slice):
|
||||
slice_env = Array('slice', GEN=self._tmpl.clone())
|
||||
try:
|
||||
slice_env._val = self._val[key]
|
||||
val = self._val[key]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__getitem__] slice item: {1}'.format(self._name, err)))
|
||||
else:
|
||||
return slice_env
|
||||
raise(EltErr('{0} [__getitem__] slice item: {1}'\
|
||||
.format(self._name, err)))
|
||||
slice_env = Array('slice', GEN=self._tmpl.clone())
|
||||
slice_env.set_val(val)
|
||||
return slice_env
|
||||
else:
|
||||
raise(EltErr('{0} [__getitem__]: array item must be int or slice'.format(self._name)))
|
||||
|
||||
def __setitem__(self, key, val):
|
||||
if isinstance(key, integer_types):
|
||||
if self._SAFE_STAT:
|
||||
try:
|
||||
self._tmpl.set_val(val)
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__setitem__] invalid value: {1}'\
|
||||
.format(self._name, err)))
|
||||
else:
|
||||
self._tmpl.set_val(None)
|
||||
if val != self._tmpl_val:
|
||||
self._tmpl.set_val(val)
|
||||
val = self._tmpl()
|
||||
self._tmpl.set_val(None)
|
||||
try:
|
||||
self._val[key] = val
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__setitem__] int item: {1}'.format(self._name, err)))
|
||||
raise(EltErr('{0} [__setitem__] int item: {1}'\
|
||||
.format(self._name, err)))
|
||||
elif isinstance(key, slice):
|
||||
if self._SAFE_STAT:
|
||||
for i, k in enumerate(key):
|
||||
try:
|
||||
[self._tmpl.set_val(v) for v in val if v != self._tmpl_val]
|
||||
except:
|
||||
raise(EltErr('{0} [__setitem__] invalid value: {1}'\
|
||||
self.__setitem__(k, val[i])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__setitem__] slice item: {1}'\
|
||||
.format(self._name, err)))
|
||||
else:
|
||||
self._tmpl.set_val(None)
|
||||
try:
|
||||
self._val[key] = val
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__setitem__] slice item: {1}'.format(self._name, err)))
|
||||
else:
|
||||
raise(EltErr('{0} [__setitem__]: array item must be int or slice'.format(self._name)))
|
||||
|
||||
|
@ -2979,6 +2915,10 @@ class Sequence(Element):
|
|||
|
||||
Sequence provides methods identical to Python list and dict in order to
|
||||
manage Element's instances within its content easily
|
||||
|
||||
Warning: transparency of certain elements within the Sequence's content is not
|
||||
handled. Elements within the content must not be made transparent (e.g. with
|
||||
set_trans()), but must be remove()d instead.
|
||||
"""
|
||||
|
||||
# hardcoded class name
|
||||
|
@ -3126,16 +3066,16 @@ class Sequence(Element):
|
|||
self._content = []
|
||||
#
|
||||
elif isinstance(vals, dict):
|
||||
if self._SAFE_STAT and not all([isinstance(k, integer_types) for k in vals]):
|
||||
# ensure the val dict indexes are valid
|
||||
raise(EltErr('{0} [set_val] vals keys are not all integers'\
|
||||
.format(self._name)))
|
||||
# get the maximum index from the dict and ensure it does not overflow
|
||||
# a fixed number of iteration
|
||||
max_ind = max(vals.keys())
|
||||
if self._SAFE_STAT and self._num is not None and max_ind >= self._num:
|
||||
raise(EltErr('{0} [set_val]: vals index {1} overflow (max {2})'\
|
||||
.format(self._name, max_ind, self._num)))
|
||||
if self._SAFE_STAT:
|
||||
# ensure the val dict indexes are valid
|
||||
if not all([isinstance(k, integer_types) for k in vals]):
|
||||
raise(EltErr('{0} [set_val] vals keys are not all integers'\
|
||||
.format(self._name)))
|
||||
# ensure the max index does not overflow a fixed max size
|
||||
if self._num is not None and max_ind >= self._num:
|
||||
raise(EltErr('{0} [set_val] vals index {1} overflow (max {2})'\
|
||||
.format(self._name, max_ind, self._num)))
|
||||
# in case the current content self._content does not goes up to the max
|
||||
# val dict index, just extend it with the template element
|
||||
if len(self._content) <= max_ind:
|
||||
|
@ -3143,32 +3083,22 @@ class Sequence(Element):
|
|||
# set template's clones with given values at given indexes
|
||||
for i, v in vals.items():
|
||||
clone = self._tmpl.clone()
|
||||
try:
|
||||
clone.set_val(vals[i])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_val] error for index {1}: {2}'\
|
||||
.format(self._name, i, err)))
|
||||
else:
|
||||
self._content[i] = clone
|
||||
clone._env = self
|
||||
clone.set_val(vals[i])
|
||||
self._content[i] = clone
|
||||
clone._env = self
|
||||
#
|
||||
elif isinstance(vals, (tuple, list)):
|
||||
if self._SAFE_STAT and self._num is not None and len(vals) > self._num:
|
||||
# ensure vals length does not overflow a fixed number of iteration
|
||||
raise(EltErr('{0} [set_val]: vals length {1} overflow (max {2})'\
|
||||
raise(EltErr('{0} [set_val] invalid number of values: {1} instead of {2}'\
|
||||
.format(self._name, len(vals), self._num)))
|
||||
self._content, i = [], 0
|
||||
for v in vals:
|
||||
clone = self._tmpl.clone()
|
||||
try:
|
||||
clone.set_val(v)
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [set_val] error for index {1}: {2}'\
|
||||
.format(self._name, i, err)))
|
||||
else:
|
||||
self._content.append(clone)
|
||||
clone._env = self
|
||||
i += 1
|
||||
clone.set_val(v)
|
||||
self._content.append(clone)
|
||||
clone._env = self
|
||||
i += 1
|
||||
#
|
||||
else:
|
||||
raise(EltErr('{0} [set_val]: vals type is {1}, expecting None, tuple, list or dict'\
|
||||
|
@ -3183,7 +3113,7 @@ class Sequence(Element):
|
|||
Returns:
|
||||
value (list) : list of values computed
|
||||
"""
|
||||
return [elt.get_val() for elt in self.__iter__()]
|
||||
return [elt() for elt in self._content]
|
||||
|
||||
def set_num(self, num=None):
|
||||
"""Set the raw number of iteration of the template in the sequence's
|
||||
|
@ -3279,10 +3209,7 @@ class Sequence(Element):
|
|||
if self.get_trans():
|
||||
return 0
|
||||
else:
|
||||
try:
|
||||
return sum([elt.get_bl() for elt in self.__iter__()])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [get_bl]: {1}'.format(self._name, err)))
|
||||
return sum([elt.get_bl() for elt in self._content])
|
||||
|
||||
def reautomate(self):
|
||||
"""Reset all attributes of self, its content and its template which have
|
||||
|
@ -3298,7 +3225,7 @@ class Sequence(Element):
|
|||
del self._trans
|
||||
if self._numauto is not None and self._num is not None:
|
||||
del self._num
|
||||
[elt.reautomate() for elt in self.__iter__() if elt != self._tmpl]
|
||||
[elt.reautomate() for elt in self._content if elt != self._tmpl]
|
||||
self._tmpl.reautomate()
|
||||
|
||||
#--------------------------------------------------------------------------#
|
||||
|
@ -3343,15 +3270,9 @@ class Sequence(Element):
|
|||
if num is not None:
|
||||
for i in range(num):
|
||||
clone = self._tmpl.clone()
|
||||
try:
|
||||
clone._from_char(char)
|
||||
except CharpyErr as err:
|
||||
raise(CharpyErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
||||
else:
|
||||
self._content.append(clone)
|
||||
clone._env = self
|
||||
clone._from_char(char)
|
||||
self._content.append(clone)
|
||||
clone._env = self
|
||||
else:
|
||||
# there is no predefined limit in the number of repeated content
|
||||
# consume the charpy instance until its empty and raises
|
||||
|
@ -3364,8 +3285,6 @@ class Sequence(Element):
|
|||
except CharpyErr as err:
|
||||
char._cur = cur
|
||||
break
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
||||
else:
|
||||
self._content.append(clone)
|
||||
clone._env = self
|
||||
|
@ -3411,7 +3330,7 @@ class Sequence(Element):
|
|||
'transauto': self._transauto,
|
||||
'num' : self._num,
|
||||
'numauto' : self._numauto,
|
||||
'tmpls' : self._content.get_attrs_all(),
|
||||
'tmpl' : self._tmpl.get_attrs_all(),
|
||||
'content' : [elt.get_attrs_all() for elt in self._content]}
|
||||
|
||||
def set_attrs(self, **kw):
|
||||
|
@ -3503,6 +3422,7 @@ class Sequence(Element):
|
|||
self._content.append(elt)
|
||||
elt._env = self
|
||||
|
||||
# here, .count() is the number of iteration in the sequence
|
||||
count = get_num
|
||||
|
||||
def extend(self, elts):
|
||||
|
@ -3688,37 +3608,27 @@ class Sequence(Element):
|
|||
slice_env._content = self._content[key]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__getitem__] slice item: {1}'.format(self._name, err)))
|
||||
else:
|
||||
return slice_env
|
||||
return slice_env
|
||||
else:
|
||||
raise(EltErr('{0} [__getitem__]: sequence item must be int or slice'.format(self._name)))
|
||||
raise(EltErr('{0} [__getitem__]: sequence item must be int or slice'\
|
||||
.format(self._name)))
|
||||
|
||||
def __setitem__(self, key, val):
|
||||
if isinstance(key, integer_types):
|
||||
try:
|
||||
if self._content[key] == self._tmpl:
|
||||
self._content[key] = self._tmpl.clone()
|
||||
self._content[key]._env = self
|
||||
self._content[key].set_val(val)
|
||||
elt = self._content[key]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__setitem__] int item: {1}'.format(self._name, err)))
|
||||
if elt == self._tmpl:
|
||||
self._content[key] = self._tmpl.clone()
|
||||
self._content[key].set_val(val)
|
||||
elif isinstance(key, slice):
|
||||
try:
|
||||
elts = self._content[key]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__setitem__] slice item: {1}'.format(self._name, err)))
|
||||
ind = 0
|
||||
for elt in elts:
|
||||
if elt == self._tmpl:
|
||||
self._content[key.start+ind] = self._tmpl.clone()
|
||||
self._content[key.start+ind] = self
|
||||
elt = self._content[key.start+ind]
|
||||
for i, k in enumerate(key):
|
||||
try:
|
||||
elt.set_val(val[ind])
|
||||
self.__setitem__(k, val[i])
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__setitem__] slice item: {1}'.format(self._name, err)))
|
||||
else:
|
||||
ind += 1
|
||||
raise(EltErr('{0} [__setitem__] slice item: {1}'\
|
||||
.format(self._name, err)))
|
||||
else:
|
||||
raise(EltErr('{0} [__setitem__]: sequence item must be int or slice'\
|
||||
.format(self._name)))
|
||||
|
@ -3732,18 +3642,16 @@ class Sequence(Element):
|
|||
elt = self._content[key]
|
||||
except:
|
||||
raise(EltErr('{0} [__delitem__] int item: {1}'.format(self._name, err)))
|
||||
else:
|
||||
del self._content[key]
|
||||
if elt != self._tmpl:
|
||||
elt._env = None
|
||||
del self._content[key]
|
||||
if elt != self._tmpl:
|
||||
elt._env = None
|
||||
elif isinstance(key, slice):
|
||||
try:
|
||||
elts = self._content[key]
|
||||
except Exception as err:
|
||||
raise(EltErr('{0} [__delitem__] slice item: {1}'.format(self._name, err)))
|
||||
else:
|
||||
[elt.set_env(None) for elt in elts if elt != self._tmpl]
|
||||
del self._content[key]
|
||||
del self._content[key]
|
||||
[elt.set_env(None) for elt in elts if elt != self._tmpl]
|
||||
else:
|
||||
raise(EltErr('{0} [__delitem__]: sequence item must be int or slice'\
|
||||
.format(self._name)))
|
||||
|
@ -3781,7 +3689,7 @@ class Sequence(Element):
|
|||
#
|
||||
return '\n '.join(
|
||||
[self.get_hier_abs()*' ' + '### %s%s%s ###' % (self._name, desc, trans)] + \
|
||||
[elt.show().replace('\n', '\n ') for elt in self.__iter__()])
|
||||
[elt.show().replace('\n', '\n ') for elt in self._content])
|
||||
|
||||
#--------------------------------------------------------------------------#
|
||||
# Python built-ins override
|
||||
|
|
|
@ -45,7 +45,7 @@ def log(msg):
|
|||
print(msg)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# additional bit list functions
|
||||
# additional bit list / str functions
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
def bytelist_to_bitlist(bytelist):
|
||||
|
@ -90,28 +90,34 @@ def bitlist_to_bytelist(bitlist):
|
|||
for i in range(0, len(bitlist), 8)]
|
||||
return ret
|
||||
|
||||
def uint_to_bitlist(uint, bitlen):
|
||||
"""Convert an unsigned integer uint of length bitlen to a list of 0 and 1
|
||||
def bytes_to_bitstr(buf):
|
||||
"""Convert a bytes string to a str of 0 and 1
|
||||
|
||||
Args:
|
||||
uint (unsigned integer)
|
||||
bitlen (unsigned integer)
|
||||
buf (bytes) : bytes string
|
||||
|
||||
Returns:
|
||||
bitlist (list of 0 and 1)
|
||||
bitlstr (str of integer) : str of 0 and 1
|
||||
|
||||
Raises:
|
||||
KeyError : if `s' is not bytes
|
||||
"""
|
||||
# this is crappy
|
||||
bl = list(map(int, bin(uint)[2:]))
|
||||
if len(bl) < bitlen:
|
||||
# extend v
|
||||
bl = [0]*(bitlen-len(bl)) + bl
|
||||
return bl
|
||||
bl = 8*len(buf)
|
||||
return uint_to_bitstr(bytes_to_uint(buf, bl), bl)
|
||||
|
||||
def bitlist_to_uint(bitlist):
|
||||
"""not implemented
|
||||
def bitstr_to_bytes(bitstr):
|
||||
"""Convert a str of 0 and 1 to a bytes string
|
||||
|
||||
Args:
|
||||
bitstr (str of integer) : str of 0 and 1
|
||||
|
||||
Returns:
|
||||
buf (bytes) : bytes string
|
||||
|
||||
Raises:
|
||||
KeyError : if bitstr contains invalid values
|
||||
"""
|
||||
# TODO
|
||||
assert()
|
||||
return uint_to_bytes(bitstr_to_uint(bitstr), len(bitstr))
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Element definition helping routines
|
||||
|
@ -168,27 +174,55 @@ def decompose_uint_sl(sl=8, val=0):
|
|||
# integer functions
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
def bytes_to_int(buf, bitlen=1):
|
||||
"""Convert the leftmost bits of a bytes buffer to a signed integer,
|
||||
2's complement representation with most significant bit leftmost
|
||||
def uint_to_bitstr(uint, bitlen):
|
||||
"""Convert an unsigned integer uint of length bitlen to a str of 0 and 1
|
||||
|
||||
Args:
|
||||
buf (bytes) : bytes string
|
||||
bitlen (integer) : length in bits
|
||||
uint (unsigned integer)
|
||||
bitlen (unsigned integer)
|
||||
|
||||
Returns:
|
||||
int (integer) : signed integer value
|
||||
|
||||
Raises:
|
||||
PycrateErr : if `bitlen' is not strictly positive or if `buf' is not
|
||||
long enough
|
||||
bitstr (str of 0 and 1)
|
||||
"""
|
||||
uint = bytes_to_uint(buf, bitlen)
|
||||
if uint >= 1<<(bitlen-1):
|
||||
# 2's complement
|
||||
return uint - (1<<bitlen)
|
||||
else:
|
||||
return uint
|
||||
bl = bin(uint)[2:]
|
||||
if len(bl) < bitlen:
|
||||
# extend v
|
||||
bl = '0'*(bitlen-len(bl)) + bl
|
||||
return bl
|
||||
|
||||
def bitstr_to_uint(bitstr):
|
||||
"""Convert a str of 0 and 1 to an unsigned integer uint
|
||||
|
||||
Args:
|
||||
bitstr (str of 0 and 1)
|
||||
|
||||
Returns:
|
||||
uint (unsigned integer)
|
||||
"""
|
||||
return int(bitstr, 2)
|
||||
|
||||
def uint_to_bitlist(uint, bitlen):
|
||||
"""Convert an unsigned integer uint of length bitlen to a list of 0 and 1
|
||||
|
||||
Args:
|
||||
uint (unsigned integer)
|
||||
bitlen (unsigned integer)
|
||||
|
||||
Returns:
|
||||
bitlist (list of 0 and 1)
|
||||
"""
|
||||
return [0 if b == '0' else 1 for b in uint_to_bitstr(uint, bitlen)]
|
||||
|
||||
def bitlist_to_uint(bitlist):
|
||||
"""Convert a list of 0 and 1 to an unsigned integer uint
|
||||
|
||||
Args:
|
||||
bitstr (list of 0 and 1)
|
||||
|
||||
Returns:
|
||||
uint (unsigned integer)
|
||||
"""
|
||||
return int(''.join(['1' if b else '0' for b in bitlist]), 2)
|
||||
|
||||
def int_to_bytes(val, bitlen=1):
|
||||
"""Convert a signed integer to a bytes buffer of given length in bits,
|
||||
|
@ -200,13 +234,138 @@ def int_to_bytes(val, bitlen=1):
|
|||
|
||||
Returns:
|
||||
buf (bytes) : bytes string
|
||||
|
||||
Raises:
|
||||
PycrateErr : if `bitlen' is not strictly positive
|
||||
"""
|
||||
if val < 0:
|
||||
# 2's complement
|
||||
return uint_to_bytes((1<<bitlen)+val, bitlen )
|
||||
return uint_to_bytes((1<<bitlen)+val, bitlen)
|
||||
else:
|
||||
return uint_to_bytes(val, bitlen)
|
||||
|
||||
def bytes_to_int(buf, bitlen=1):
|
||||
"""Convert the leftmost bits of a bytes buffer to a signed integer,
|
||||
2's complement representation with most significant bit leftmost
|
||||
|
||||
Args:
|
||||
buf (bytes) : bytes string
|
||||
bitlen (integer) : length in bits
|
||||
|
||||
Returns:
|
||||
val (integer) : signed integer value
|
||||
"""
|
||||
uint = bytes_to_uint(buf, bitlen)
|
||||
if uint >= 1<<(bitlen-1):
|
||||
# 2's complement
|
||||
return uint - (1<<bitlen)
|
||||
else:
|
||||
return uint
|
||||
|
||||
def int_to_bitstr(val, bitlen):
|
||||
"""Convert a signed integer val of length bitlen to a str of 0 and 1
|
||||
|
||||
Args:
|
||||
val (signed integer)
|
||||
bitlen (unsigned integer)
|
||||
|
||||
Returns:
|
||||
bitstr (str of 0 and 1)
|
||||
"""
|
||||
if val < 0:
|
||||
# 2's complement
|
||||
return uint_to_bitstr((1<<bitlen)+val, bitlen)
|
||||
else:
|
||||
return uint_to_bitstr(val, bitlen)
|
||||
|
||||
def bitstr_to_int(bitstr):
|
||||
"""Convert a str of 0 and 1 to a signed integer val
|
||||
|
||||
Args:
|
||||
bitstr (str of 0 and 1)
|
||||
|
||||
Returns:
|
||||
val (signed integer)
|
||||
"""
|
||||
uint = int(bitstr, 2)
|
||||
if uint >= 1<<(bitlen-1):
|
||||
# 2's complement
|
||||
return uint - (1<<bitlen)
|
||||
else:
|
||||
return uint
|
||||
|
||||
def int_to_bitlist(val, bitlen):
|
||||
"""Convert a signed integer val of length bitlen to a list of 0 and 1
|
||||
|
||||
Args:
|
||||
val (signed integer)
|
||||
bitlen (unsigned integer)
|
||||
|
||||
Returns:
|
||||
bitlist (list of 0 and 1)
|
||||
"""
|
||||
if val < 0:
|
||||
# 2's complement
|
||||
return uint_to_bitlist((1<<bitlen)+val, bitlen)
|
||||
else:
|
||||
return uint_to_bitlist(val, bitlen)
|
||||
|
||||
def bitlist_to_int(bitlist):
|
||||
"""Convert a list of 0 and 1 to a signed integer val
|
||||
|
||||
Args:
|
||||
bitstr (str of 0 and 1)
|
||||
|
||||
Returns:
|
||||
val (signed integer)
|
||||
"""
|
||||
uint = bitlist_to_uint(bitlist)
|
||||
if uint >= 1<<(bitlen-1):
|
||||
# 2's complement
|
||||
return uint - (1<<bitlen)
|
||||
else:
|
||||
return uint
|
||||
|
||||
def swap_int(val, bitlen):
|
||||
"""Swap the endianness of the signed integer val of length bitlen
|
||||
|
||||
Args:
|
||||
val (signed integer)
|
||||
bitlen (unsigned integer)
|
||||
|
||||
Returns:
|
||||
ret (signed integer)
|
||||
"""
|
||||
if val < 0:
|
||||
# 2's complement
|
||||
tmp = swap_uint((1<<bitlen)+val, bitlen)
|
||||
else:
|
||||
tmp = swap_uint(val, bitlen)
|
||||
if tmp >= 1<<(bitlen-1):
|
||||
return tmp - (1<<bitlen)
|
||||
else:
|
||||
return tmp
|
||||
|
||||
def uint_to_hex(uint, bitlen):
|
||||
"""Return the string of hexadecimal character representing the unsigned
|
||||
integer uint (big-endian)
|
||||
|
||||
Args:
|
||||
uint (unsigned integer)
|
||||
bitlen (unsigned integer)
|
||||
|
||||
Returns:
|
||||
hex (str of hex chars)
|
||||
"""
|
||||
niblen = bitlen>>2
|
||||
if bitlen % 4:
|
||||
niblen += 1
|
||||
# not nibble-aligned, need to left-shift the uint value
|
||||
uint <<= 4 - (bitlen%4)
|
||||
h = hex(uint)
|
||||
if h[-1] == 'L':
|
||||
h = h[2:-1]
|
||||
else:
|
||||
h = h[2:]
|
||||
if len(h) < niblen:
|
||||
return (niblen-len(h))*'0' + h
|
||||
else:
|
||||
return h
|
||||
|
||||
|
|
|
@ -1149,7 +1149,7 @@ def bitlist_to_bytes(bitlist):
|
|||
if trail:
|
||||
[buf.append(BITTOBYTE_LUT[bitlist[i:i+8]]) \
|
||||
for i in range(0, len(bitlist)-trail, 8)]
|
||||
buf.append( BITTOBYTE_LUT[bitlist[-trail:] + (8-trail) * (0, )] )
|
||||
buf.append(BITTOBYTE_LUT[bitlist[-trail:] + (8-trail) * (0, )] )
|
||||
return b''.join(buf)
|
||||
else:
|
||||
[buf.append(BITTOBYTE_LUT[bitlist[i:i+8]]) \
|
||||
|
@ -1468,6 +1468,29 @@ def decompose_uint(mul=0x100, val=0):
|
|||
dec.append( int(val % mul) )
|
||||
return dec
|
||||
|
||||
def swap_uint(uint, bitlen):
|
||||
"""Swap the endianness of the unsigned integer uint of length bitlen
|
||||
|
||||
Args:
|
||||
uint (unsigned integer)
|
||||
bitlen (unsigned integer)
|
||||
|
||||
Returns:
|
||||
uint (unsigned integer)
|
||||
"""
|
||||
if bitlen < 0 or bitlen % 8:
|
||||
raise(PycrateErr('invalid bitlen of little endian uint: {0}'\
|
||||
.format(bitlen)))
|
||||
len_byte, ret = bitlen>>3, []
|
||||
for i in range(len_byte>>1):
|
||||
bi = 8*i
|
||||
rbi = bitlen-8-bi
|
||||
ret.append( (uint & (0xff<<bi)) << (rbi-bi) )
|
||||
ret.append( (uint & (0xff<<rbi)) >> (rbi-bi) )
|
||||
if len_byte % 2:
|
||||
ret.append( uint & (0xff<<(8*(len_byte>>1))) )
|
||||
return sum(ret)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# concatenation
|
||||
#------------------------------------------------------------------------------#
|
||||
|
|
|
@ -1152,7 +1152,7 @@ def bitlist_to_bytes(bitlist):
|
|||
if trail:
|
||||
[buf.append(BITTOARR_LUT[bitlist[i:i+8]]) \
|
||||
for i in range(0, len(bitlist)-trail, 8)]
|
||||
buf.append( BITTOARR_LUT[bitlist[-trail:] + (8-trail) * (0, )] )
|
||||
buf.append(BITTOARR_LUT[bitlist[-trail:] + (8-trail) * (0, )] )
|
||||
return bytes(buf)
|
||||
else:
|
||||
[buf.append(BITTOARR_LUT[bitlist[i:i+8]]) \
|
||||
|
@ -1439,6 +1439,22 @@ def decompose_uint(mul=0x100, val=0):
|
|||
dec.append( int(val % mul) )
|
||||
return dec
|
||||
|
||||
def swap_uint(uint, bitlen):
|
||||
"""Swap the endianness of the unsigned integer uint of length bitlen
|
||||
|
||||
Args:
|
||||
uint (unsigned integer)
|
||||
bitlen (unsigned integer)
|
||||
|
||||
Returns:
|
||||
uint (unsigned integer)
|
||||
"""
|
||||
if bitlen < 0 or bitlen % 8:
|
||||
raise(PycrateErr('invalid bitlen of little endian uint: {0}'\
|
||||
.format(bitlen)))
|
||||
len_byte = bitlen>>3
|
||||
return int.from_bytes(uint.to_bytes(len_byte, byteorder='little'), byteorder='big')
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# concatenation
|
||||
#------------------------------------------------------------------------------#
|
||||
|
|
Loading…
Reference in New Issue